CFEL - ASG Software Suite  2.5.0
CASS
histo_updater.cpp
Go to the documentation of this file.
1 //Copyright (C) 2011 Lutz Foucar
2 
3 /**
4  * @file histo_updater.cpp file contains the classes that update histograms
5  *
6  * @author Lutz Foucar
7  */
8 
9 #include <cmath>
10 #include <limits>
11 #include <iostream>
12 #include <sstream>
13 #include <stdexcept>
14 #include <algorithm>
15 #include <list>
16 
17 #include <TObject.h>
18 #include <TH1.h>
19 #include <TH2.h>
20 #include <TDirectory.h>
21 #include <TROOT.h>
22 #include <TList.h>
23 #include <TSeqCollection.h>
24 #include <TPad.h>
25 #include <TCanvas.h>
26 #include <TCollection.h>
27 #include <TFile.h>
28 
29 #include "histo_updater.h"
30 
31 #include "tcpclient.h"
32 #include "result.hpp"
33 
34 using namespace lucassview;
35 using namespace std;
36 
38 
39 namespace lucassview
40 {
41  /** update the contents of the canvases
42  *
43  * recursively iterate through lists if object is a pad, update it and
44  * iterate through its primitives.
45  *
46  * @param list the list of TObjects to iterate through
47  *
48  * @author Lutz Foucar
49  */
50  void updateCanvases(TSeqCollection* list)
51  {
52  TIter next(list);
53  TObject *obj(0);
54  while ((obj = next()))
55  {
56 // cout << "Obj: "<< obj->GetName() <<" " << obj->InheritsFrom("TPad")<<endl;
57  if (obj->InheritsFrom("TPad"))
58  {
59  static_cast<TPad*>(obj)->Modified();
60  static_cast<TPad*>(obj)->Update();
61  updateCanvases(static_cast<TPad*>(obj)->GetListOfPrimitives());
62  }
63  }
64  }
65 
66  /** delete all root histograms that are not on the list
67  *
68  * go through the list of objects in memory and erase it if it not on the list
69  * @author Lutz Foucar
70  */
72  {
73  /** constructor
74  *
75  * @param allkeys all available keys on the server
76  */
77  deleteObsoleteHistogram(const list<string> &allkeys)
78  :_allkeys(allkeys)
79  {}
80 
81  /** the operator
82  *
83  * if the object is a TH1 and its name is not on the allkeys list, check if
84  * the title is the same as the name of the object. If so it is most likely
85  * a cass histogram, that is not on the list anymore, so delete it.
86  *
87  * @param obj The object that potentially will be deleted
88  */
89  void operator()(TObject *obj) const
90  {
91  if (obj->InheritsFrom("TH1"))
92  {
93  if (find(_allkeys.begin(),_allkeys.end(),obj->GetName()) == _allkeys.end())
94  {
95  if (string(obj->GetName()) == string(obj->GetTitle()))
96  {
97  cout<<"deleteObsoleteHistogram(): delete '"<< obj->GetName()<<"' it is not on the casshistogram list"<<endl;
98  obj->Delete();
99  }
100  }
101  }
102  }
103 
104  /** the list with all cass histogram keys */
105  const list<string> &_allkeys;
106  };
107 
108  /** iteratively go through canvas list and find histgrams
109  *
110  * when a histogram is found add it to the updateList, if it is another pad,
111  * iterate through its primatives
112  *
113  * @param list The list of TObjects to iterate through
114  * @param updateList The list containg the names of the found histgrams
115  *
116  * @author Lutz Foucar
117  */
118  void iterateListAndAddDisplayedHistograms(TSeqCollection* list, std::list<string>& updateList)
119  {
120  TIter next(list);
121  TObject *obj(0);
122  while ((obj = next()))
123  {
124 // cout << "Obj: "<< obj->GetName() <<" " << obj->InheritsFrom("TPad")<<endl;
125  if (obj->InheritsFrom("TPad"))
126  iterateListAndAddDisplayedHistograms(static_cast<TCanvas*>(obj)->GetListOfPrimitives(),
127  updateList);
128  else if(obj->InheritsFrom("TH1"))
129  {
130  updateList.push_back(obj->GetName());
131  }
132  }
133  }
134 
135  /** create the list of updateable histograms from all available keys
136  *
137  * First add all cass histograms that are not present as root histograms.
138  * Then go through all canvases and add the histograms that are shown in them
139  * and add them to the list returned. For this one must go through all
140  * canvases and the pads within the canvases. The pads contain the histograms.
141  *
142  * @return list of keys that need to be updated
143  * @param allkeys all available keys on the server
144  *
145  * @author Lutz Foucar
146  */
147  list<string> checkList(const list<string> &allkeys)
148  {
149  list<string> updateList;
150  for (list<string>::const_iterator it(allkeys.begin()); it!=allkeys.end(); ++ it)
151  if (!gDirectory->FindObjectAny((*it).c_str()))
152  updateList.push_back((*it));
153  iterateListAndAddDisplayedHistograms(gROOT->GetListOfCanvases(),updateList);
154 // TIter next(gROOT->GetListOfCanvases());
155 // TObject * canv(0);
156 // while ((canv = next()))
157 // {
158 // cout << "Canv: "<< canv->GetName() <<" " << canv->InheritsFrom("TPad")<<endl;
159 // TIter next2(static_cast<TCanvas*>(canv)->GetListOfPrimitives());
160 // TObject * pad(0);
161 // while ((pad = next2()))
162 // {
163 // cout << " Pad: "<< pad->GetName()<<" " << pad->InheritsFrom("TPad") <<endl;
164 // TIter next3(static_cast<TPad*>(pad)->GetListOfPrimitives());
165 // TObject * hist(0);
166 // while ((hist = next3()))
167 // {
168 // if (hist->InheritsFrom("TH1"))
169 // updateList.push_back(hist->GetName());
170 // }
171 // }
172 // }
173  return updateList;
174  }
175 
176  /** write the object to file
177  *
178  * @author Lutz Foucar
179  */
180  struct writeObject
181  {
182  /** the file to write the object to */
183  TFile * _file;
184 
185  /** constructor
186  *
187  * set the file
188  *
189  * @param filename filename of the file to write the histograms to
190  */
191  writeObject(const std::string & filename)
192  :_file(TFile::Open(filename.c_str(),"RECREATE"))
193  {}
194 
195  /** destructor
196  *
197  * saves and closes the file
198  */
200  {
201  _file->SaveSelf();
202  _file->Close();
203  }
204 
205  /** the operator
206  *
207  * check if the object is a histogram, if so write it to the file
208  *
209  * @param obj The object that potentially gets written to file
210  */
211  void operator()(TObject *obj)
212  {
213  if (obj->InheritsFrom("TH1"))
214  {
215  cout<<"writeObject(): writing '"<< obj->GetName()<<"' to '"<<_file->GetName()<<"'"<<endl;
216  _file->cd();
217  obj->Write(0,TObject::kOverwrite);
218  }
219  }
220  };
221 
222  /** comapre axis for equalitiy
223  *
224  * check whether the cass histogram axis and the root histogram axis are the
225  * same. Test for number of bins, low and high ends and the title of the axis.
226  *
227  * @return true when both axis are the same
228  * @param ca the axis of the cass histogram
229  * @param ra the axis of the root histogram
230  *
231  * @author Lutz Foucar
232  */
233  bool operator== (const cass::Result<float>::axe_t &ca, const TAxis &ra)
234  {
235  return (static_cast<int>(ca.nBins) == ra.GetNbins() &&
236  fabs(ca.low - ra.GetXmin()) < sqrt(numeric_limits<double>::epsilon()) &&
237  fabs(ca.up - ra.GetXmax()) < sqrt(numeric_limits<double>::epsilon()) &&
238  ca.title == ra.GetTitle());
239  }
240 
241  /** comapre axis for inequality
242  *
243  * @return the inverse of opertator==
244  * @param ca the axis of the cass histogram
245  * @param ra the axis of the root histogram
246  *
247  * @author Lutz Foucar
248  */
249  bool operator!= (const cass::Result<float>::axe_t &ca, const TAxis &ra)
250  {
251  return !(ca==ra);
252  }
253 
254  /** create the list of updateable histograms from all available keys
255  *
256  * @author Lutz Foucar
257  */
258  struct updateHist
259  {
260  /** the client for the server */
262 
263  /** constructor
264  *
265  * @param client the client to connecto to the server
266  */
267  updateHist(const TCPClient &client)
268  :_client(client)
269  {}
270 
271  /** update the histogram with key
272  *
273  * retrieve the cass histogram for key. Then try to get the root histogram
274  * that has the name "key". Find out what dimension the cass histogram has.
275  * Depending on that one treats the histograms differently. In case of the
276  * 2D histogram one checks whether the root histogram already exists (the
277  * returned pointer is non Zero). If it does exist, check whether the axis
278  * properties are the same. When they differ then set the root axis
279  * properties to be the same as the properties that the cass histogram has.
280  * When the root histogram does not exist, create it from the cass histogram
281  * properties.\n
282  * Now copy the histogram contents from the cass histogram to the root
283  * histogram. After that copy the over and underflow quadrants and the
284  * number of fills to the root histogram.
285  *
286  * In case the histogram is a 1D histogram make the same procedure as you
287  * did with the 2D histogram, just only for the x-axis. When then histogram
288  * is a 0D histogram or has a different dimension ignore it.
289  *
290  * @param key The key that the histogram has on the server
291  */
292  void operator() (const string& key)const
293  {
294  using namespace cass;
295  using namespace tr1;
296  try
297  {
298 // cout << "updateHist(): copy information of "<<key<<endl;
299  Result<float>::shared_pointer result(_client(key));
300  TH1 * roothist(dynamic_cast<TH1*>(gDirectory->FindObjectAny(key.c_str())));
301  switch (result->dim())
302  {
303  case 2:
304  {
305  const Result<float>::axe_t &xaxis(result->axis(Result<float>::xAxis));
306  const Result<float>::axe_t &yaxis(result->axis(Result<float>::yAxis));
307  if(!roothist)
308  {
309  cout << "updateHist(): '"<<key<<"' create roothist with X("<<xaxis.title<<") '"<<xaxis.nBins<<" "<<xaxis.low<<" "<<xaxis.up<<"' "
310  "Y("<<yaxis.title<<") '"<<yaxis.nBins<<" "<<yaxis.low<<" "<<yaxis.up<<"'"<<endl;
311  roothist = new TH2F(key.c_str(),key.c_str(),
312  xaxis.nBins, xaxis.low, xaxis.up,
313  yaxis.nBins, yaxis.low, yaxis.up);
314  roothist->SetOption("colz");
315  }
316  const TAxis &rxaxis(*roothist->GetXaxis());
317  const TAxis &ryaxis(*roothist->GetYaxis());
318  if(xaxis != rxaxis || yaxis != ryaxis)
319  {
320  cout << "updateHist(): '"<<key<<"' resize because axis differs: roothist: "<<xaxis.nBins<<"<->"<<rxaxis.GetNbins()<<" "<<xaxis.low<<"<->"<<rxaxis.GetXmin()<<" "<<xaxis.up<<"<->"<<rxaxis.GetXmax()<<" "
321  <<yaxis.nBins<<"<->"<<ryaxis.GetNbins()<<" "<<yaxis.low<<"<->"<<ryaxis.GetXmin()<<" "<<yaxis.up<<"<->"<<ryaxis.GetXmax()<<endl;
322  roothist->SetBins(xaxis.nBins, xaxis.low, xaxis.up,
323  yaxis.nBins, yaxis.low, yaxis.up);
324  roothist->SetXTitle(xaxis.title.c_str());
325  roothist->GetXaxis()->CenterTitle(true);
326  roothist->SetYTitle(yaxis.title.c_str());
327  roothist->GetYaxis()->CenterTitle(true);
328  roothist->GetYaxis()->SetTitleOffset(1.5);
329  }
330  /** copy histogram contents */
331  for (size_t iY(0); iY<yaxis.nBins;++iY)
332  for (size_t iX(0); iX<xaxis.nBins;++iX)
333  {
334  const double histvalue((*result)[iX + iY*xaxis.nBins]);
335  const float value = (std::tr1::isnan(histvalue)) ?
336  0. : (*result)[iX + iY*xaxis.nBins];
337  roothist->SetBinContent(roothist->GetBin(iX+1,iY+1),value);
338  }
339  /** copy over / underflow */
340  size_t OverUnderFlowStart (xaxis.nBins*yaxis.nBins);
341  roothist->SetBinContent(roothist->GetBin(0,0),(*result)[OverUnderFlowStart+Result<float>::LowerLeft]);
342  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1,0),(*result)[OverUnderFlowStart+Result<float>::LowerRight]);
343  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1,yaxis.nBins+1),(*result)[OverUnderFlowStart+Result<float>::UpperRight]);
344  roothist->SetBinContent(roothist->GetBin(0,yaxis.nBins+1),(*result)[OverUnderFlowStart+Result<float>::UpperLeft]);
345  roothist->SetBinContent(roothist->GetBin(1,0),(*result)[OverUnderFlowStart+Result<float>::LowerMiddle]);
346  roothist->SetBinContent(roothist->GetBin(1,yaxis.nBins+1),(*result)[OverUnderFlowStart+Result<float>::UpperMiddle]);
347  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1,1),(*result)[OverUnderFlowStart+Result<float>::Right]);
348  roothist->SetBinContent(roothist->GetBin(0,1),(*result)[OverUnderFlowStart+Result<float>::Left]);
349  /** copy number of fills (how many shots have been accumulated) */
350 // roothist->SetEntries(result->nbrOfFills());
351  }
352  break;
353  case 1:
354  {
355  const Result<float>::axe_t &xaxis(result->axis(Result<float>::xAxis));
356  if(!roothist)
357  {
358  cout << "updateHist(): '"<<key<<"' create roothist with X("<<xaxis.title<<"):'"<<xaxis.nBins<<" "<<xaxis.low<<" "<<xaxis.up<<"'"<<endl;
359  roothist = new TH1F(key.c_str(),key.c_str(),
360  xaxis.nBins, xaxis.low, xaxis.up);
361  roothist->GetXaxis()->CenterTitle(true);
362  }
363  const TAxis &rxaxis(*roothist->GetXaxis());
364  if(xaxis != rxaxis)
365  {
366  cout << "updateHist(): '"<<key<<"' resize because axis differs: roothist: "<<xaxis.nBins<<"<->"<<rxaxis.GetNbins()<<" "<<xaxis.low<<"<->"<<rxaxis.GetXmin()<<" "<<xaxis.up<<"<->"<<rxaxis.GetXmax()<<endl;
367  roothist->SetBins(xaxis.nBins, xaxis.low, xaxis.up);
368  roothist->SetXTitle(xaxis.title.c_str());
369  }
370  /** copy histogram contents */
371  for (size_t iX(0); iX<xaxis.nBins;++iX)
372  {
373  const double histvalue((*result)[iX]);
374  const float value = (std::tr1::isnan(histvalue)) ? 0. : (*result)[iX];
375  roothist->SetBinContent(roothist->GetBin(iX+1),value);
376  }
377  /** copy over / underflow */
378  size_t OverUnderFlowStart (xaxis.nBins);
379  roothist->SetBinContent(roothist->GetBin(0),(*result)[OverUnderFlowStart+Result<float>::Underflow]);
380  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1),(*result)[OverUnderFlowStart+Result<float>::Overflow]);
381  /** copy number of fills (how many shots have been accumulated) */
382 // roothist->SetEntries(result->nbrOfFills());
383  }
384  break;
385  case 0:
386  {
387  if(!roothist)
388  {
389  cout << "updateHist(): '"<<key<<"' create roothist with for 0D histogram"<<endl;
390  roothist = new TH1F(key.c_str(),key.c_str(),1,0,1);
391  }
392  const double histvalue(result->getValue());
393  const float value = (std::tr1::isnan(histvalue)) ? 0. : histvalue;
394  roothist->SetBinContent(1,value);
395 // roothist->SetEntries(result->nbrOfFills());
396  }
397  break;
398  default:
399  break;
400  }
401 // cout << "updateHist(): done with "<<key<<endl;
402  }
403  catch (const runtime_error& error)
404  {
405  cout << "updateHist(): "<< error.what()<<endl;
406  }
407  }
408  };
409 }
410 
411 HistogramUpdater::HistogramUpdater(const string &server, int port)
412  :_server(server),
413  _port(port),
414  _timer(new TTimer()),
415  _updateCanv(false)
416 {
417  _timer->Connect("Timeout()", "HistogramUpdater",this, "syncHistograms()");
418 }
419 
420 void HistogramUpdater::autoSync(double freq)
421 {
422  if(freq < sqrt(numeric_limits<double>::epsilon()))
423  _timer->Stop();
424  else
425  {
426  _timer->Start(static_cast<int>(1.e3/freq));
427  }
428 }
429 
431 {
432  try
433  {
434  stringstream serveradress;
435  serveradress << _server << ":" << _port;
436  TCPClient client (serveradress.str());
437  list<string> allkeylist(client());
438  list<string> updatableHistsList(checkList(allkeylist));
439  for_each(updatableHistsList.begin(),updatableHistsList.end(), updateHist(client));
440 // TIter it(gDirectory->GetList());
441 // for_each(it.Begin(),TIter::End(),deleteObsoleteHistogram(allkeylist));
442  TIter next(gDirectory->GetList());
443  const deleteObsoleteHistogram removeUnusedHist(allkeylist);
444  TObject *obj(0);
445  while ((obj = next()))
446  removeUnusedHist(obj);
447  if (_updateCanv)
448  updateCanvases(gROOT->GetListOfCanvases());
449  }
450  catch (const runtime_error &error)
451  {
452  cout << "HistogramUpdater::updateHistograms(): "<<error.what()<<endl;
453  }
454 }
455 
456 void HistogramUpdater::syncHistogram(const string &name)
457 {
458  try
459  {
460  stringstream serveradress;
461  serveradress << _server << ":" << _port;
462  TCPClient client (serveradress.str());
463  updateHist updater = updateHist(client);
464  updater(name);
465  }
466  catch (const runtime_error &error)
467  {
468  cout << "HistogramUpdater::updateHistogram(): "<<error.what()<<endl;
469  }
470 }
471 
472 void HistogramUpdater::writeRootFile(const std::string& name)
473 {
474  try
475  {
476  stringstream serveradress;
477  serveradress << _server << ":" << _port;
478  TCPClient client (serveradress.str());
479  list<string> allkeylist(client());
480  for_each(allkeylist.begin(),allkeylist.end(), updateHist(client));
481 // TIter it(gDirectory->GetList());
482 // for_each(it.Begin(),TIter::End(),writeObject(name));
483  TIter next(gDirectory->GetList());
484  writeObject writeObj(name);
485  TObject *obj(0);
486  while ((obj = next()))
487  writeObj(obj);
488  gROOT->cd();
489  }
490  catch (const runtime_error &error)
491  {
492  cout << "HistogramUpdater::writeRootFile(): "<<error.what()<<endl;
493  }
494 }
495 
497 {
498  try
499  {
500  stringstream serveradress;
501  serveradress << _server << ":" << _port;
502  TCPClient client (serveradress.str());
503  client.reloadIni();
504  }
505  catch (const runtime_error &error)
506  {
507  cout << "HistogramUpdater::reloadIni(): "<<error.what()<<endl;
508  }
509 }
510 
511 void HistogramUpdater::controlCalibration(const std::string& command)
512 {
513  try
514  {
515  stringstream serveradress;
516  serveradress << _server << ":" << _port;
517  TCPClient client(serveradress.str());
518  client.controlCalibration(command);
519  }
520  catch (const runtime_error &error)
521  {
522  cout << "HistogramUpdater::controlDarkcal(): "<<error.what()<<endl;
523  }
524 }
void updateCanvases(TSeqCollection *list)
update the contents of the canvases
bool operator==(const cass::Result< float >::axe_t &ca, const TAxis &ra)
comapre axis for equalitiy
size_t dim() const
what is the dimension of the result
Definition: result.hpp:503
void operator()(TObject *obj) const
the operator
value_t getValue() const
return the value
Definition: result.hpp:558
create the list of updateable histograms from all available keys
STL namespace.
an axis of a more than 0 dimensional container
Definition: result.hpp:29
std::string title
the title of the axis
Definition: result.hpp:296
result classes
writeObject(const std::string &filename)
constructor
size_t nBins
the number of bins in this axis
Definition: result.hpp:287
write the object to file
void reloadIni() const
reload .ini file
void writeRootFile(const std::string &name)
write all histograms to a root file
std::auto_ptr< TTimer > _timer
the timer for auto update
Definition: histo_updater.h:97
const axis_t & axis() const
read access to the axis
Definition: result.hpp:449
delete all root histograms that are not on the list
A result of a processor.
Definition: result.hpp:30
HistogramUpdater(const std::string &server, int port)
constructor
void autoSync(double freq)
automaticly update
deleteObsoleteHistogram(const list< string > &allkeys)
constructor
bool _updateCanv
flag whether after updating the histogram the canvas should also update
void controlCalibration(const std::string &command="startDarkcal")
control the dark calibration
void operator()(TObject *obj)
the operator
void controlCalibration(const std::string &command) const
reload .ini file
void syncHistograms()
update the shown histograms
list< string > checkList(const list< string > &allkeys)
create the list of updateable histograms from all available keys
bool operator!=(const cass::Result< float >::axe_t &ca, const TAxis &ra)
comapre axis for inequality
HistogramUpdater * gCASSClient(0)
void iterateListAndAddDisplayedHistograms(TSeqCollection *list, std::list< string > &updateList)
iteratively go through canvas list and find histgrams
int _port
the server port
Definition: histo_updater.h:94
value_t low
lower end of the axis
Definition: result.hpp:290
void syncHistogram(const std::string &name)
copy a single result into a histogram
value_t up
upper end of the axis
Definition: result.hpp:293
TFile * _file
the file to write the object to
const list< string > & _allkeys
the list with all cass histogram keys
void reloadIni()
tell the server reload the .ini parameters
the tcp client that connects to the cass server
file contains the classes connect to cass
updateHist(const TCPClient &client)
constructor
file contains the classes that update histograms
check if there is some light in the chamber based upon the GMD value
std::string _server
the server
Definition: histo_updater.h:91
const TCPClient & _client
the client for the server