CFEL - ASG Software Suite  2.5.0
CASS
root_converter.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 Lutz Foucar
2 
3 /**
4  * @file root_converter.cpp file contains definition of processor 2000
5  *
6  * @author Lutz Foucar
7  */
8 
9 #include <sstream>
10 #include <string>
11 #include <vector>
12 #include <stdexcept>
13 #include <iostream>
14 
15 #include <TObject.h>
16 #include <TFile.h>
17 #include <TDirectory.h>
18 #include <TH1.h>
19 #include <TH2.h>
20 
21 #include <QtCore/QDateTime>
22 
23 #include "root_converter.h"
24 #include "result.hpp"
25 #include "cass_settings.h"
26 #include "cass_event.h"
27 #include "rootfile_helper.h"
28 #include "log.h"
29 
30 
31 using namespace cass;
32 using namespace std;
33 
34 namespace cass
35 {
36 /** namespace for ROOT related functions */
37 namespace ROOT
38 {
39 /** function to create a human readable directory name from the eventid
40  *
41  * @param eventid the event id to create the human readable name from
42  *
43  * @author Lutz Foucar
44  */
46 {
47  uint32_t timet(static_cast<uint32_t>((eventid & 0xFFFFFFFF00000000) >> 32));
48  uint32_t eventFiducial = static_cast<uint32_t>((eventid & 0x00000000FFFFFFFF) >> 8);
49  stringstream name;
50  if (timet)
51  {
53  time.setTime_t(timet);
54  name << time.toString(Qt::ISODate).toStdString() <<"_"<<eventFiducial;
55  }
56  else
57  {
58  name << "UnknownTime_"<<eventid;
59  }
60  Log::add(Log::DEBUG4,"eventIdToDirectoryName(): name: '"+ name.str() + "'");
61  return name.str();
62 }
63 
64 /** create a directory if it does not exist and cd into it
65  *
66  * @param file the file in which the directory should be created
67  * @param dirname the directory name that is realtiv to the current directory
68  *
69  * @author Lutz Foucar
70  */
71 void changeDir(TFile* file,const string &dirname)
72 {
73  /** find out wether directory exists */
74  file->cd("/");
75  TDirectory * direc = file->GetDirectory(dirname.c_str());
76  /** if not, create it */
77  if (!direc)
78  {
79  string lhs;
80  string rhs;
81  string tmp = dirname;
82  while (1)
83  {
84  /** if there is no '/' then this is the last sub dir */
85  if (tmp.find("/") == string::npos)
86  {
87  lhs = tmp;
88  }
89  /** otherwise split the string to lefthandside and righthandside of "/" */
90  else
91  {
92  lhs = tmp.substr(0,tmp.find("/"));
93  rhs = tmp.substr(tmp.find("/")+1,tmp.length());
94  }
95 
96  /** check wether subdir exits */
97  direc = gDirectory->GetDirectory(lhs.c_str());
98  /** if so, cd into it */
99  if (direc)
100  gDirectory->cd(lhs.c_str());
101  /** otherwise create it and then cd into it */
102  else
103  {
104  direc = gDirectory->mkdir(lhs.c_str());
105  gDirectory->cd(lhs.c_str());
106  }
107 
108  /** when there is no "/" anymore break */
109  if (tmp.find("/") == string::npos)
110  break;
111 
112  /** the new temp is all that is on the right hand side */
113  tmp = rhs;
114  }
115  }
116  /** make the requested dir the current global dir */
117  direc->cd();
118 }
119 
120 /** function that will copy a histogram to file
121  *
122  * @param casshist the cass histogram that should be written to file
123  * @param valname the name of the histogram in the root file
124  *
125  * @author Lutz Foucar
126  */
127 void copyHistToRootFile(const Processor::result_t &casshist, const string &valname)
128 {
129  TH1 *roothist(0);
130  switch (casshist.dim())
131  {
132  case 0:
133  {
134  roothist = new TH1F(valname.c_str(),valname.c_str(),
135  1,0,1);
136  roothist->SetBinContent(1,casshist.getValue());
137  }
138  break;
139  case 1:
140  {
141  /** create root histogram from cass histogram properties */
143  roothist = new TH1F(valname.c_str(),valname.c_str(),
144  xaxis.nBins, xaxis.low, xaxis.up);
145  /** set up axis */
146  roothist->GetXaxis()->CenterTitle(true);
147  roothist->SetXTitle(xaxis.title.c_str());
148  /** copy histogram contents */
149  for (size_t iX(0); iX<xaxis.nBins;++iX)
150  roothist->SetBinContent(roothist->GetBin(iX+1),casshist[iX]);
151  /** copy over / underflow */
152  size_t OverUnderFlowStart (xaxis.nBins);
153  roothist->SetBinContent(roothist->GetBin(0),casshist[OverUnderFlowStart+Processor::result_t::Underflow]);
154  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1),casshist[OverUnderFlowStart+Processor::result_t::Overflow]);
155  /** copy number of fills (how many shots have been accumulated) */
156  //roothist->SetEntries(casshist.nbrOfFills());
157  }
158  break;
159  case 2:
160  {
161  /** create root histogram from cass histogram properties */
164  roothist = new TH2F(valname.c_str(),valname.c_str(),
165  xaxis.nBins, xaxis.low, xaxis.up,
166  yaxis.nBins, yaxis.low, yaxis.up);
167  /** make sure that the histogram is drawn in color and with color bar */
168  roothist->SetOption("colz");
169  /** set up axis */
170  roothist->SetXTitle(xaxis.title.c_str());
171  roothist->GetXaxis()->CenterTitle(true);
172  roothist->SetYTitle(yaxis.title.c_str());
173  roothist->GetYaxis()->CenterTitle(true);
174  roothist->GetYaxis()->SetTitleOffset(1.5);
175  /** copy histogram contents */
176  for (size_t iY(0); iY<yaxis.nBins;++iY)
177  for (size_t iX(0); iX<xaxis.nBins;++iX)
178  roothist->SetBinContent(roothist->GetBin(iX+1,iY+1),casshist[iX + iY*xaxis.nBins]);
179  /** copy over / underflow */
180  size_t OverUnderFlowStart (xaxis.nBins*yaxis.nBins);
181  roothist->SetBinContent(roothist->GetBin(0,0),casshist[OverUnderFlowStart+Processor::result_t::LowerLeft]);
182  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1,0),casshist[OverUnderFlowStart+Processor::result_t::LowerRight]);
183  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1,yaxis.nBins+1),casshist[OverUnderFlowStart+Processor::result_t::UpperRight]);
184  roothist->SetBinContent(roothist->GetBin(0,yaxis.nBins+1),casshist[OverUnderFlowStart+Processor::result_t::UpperLeft]);
185  roothist->SetBinContent(roothist->GetBin(1,0),casshist[OverUnderFlowStart+Processor::result_t::LowerMiddle]);
186  roothist->SetBinContent(roothist->GetBin(1,yaxis.nBins+1),casshist[OverUnderFlowStart+Processor::result_t::UpperMiddle]);
187  roothist->SetBinContent(roothist->GetBin(xaxis.nBins+1,1),casshist[OverUnderFlowStart+Processor::result_t::Right]);
188  roothist->SetBinContent(roothist->GetBin(0,1),casshist[OverUnderFlowStart+Processor::result_t::Left]);
189  /** copy number of fills (how many shots have been accumulated) */
190  //roothist->SetEntries(casshist.nbrOfFills());
191  }
192  break;
193  default:
194  break;
195  }
196  /** write the histogram to root file */
197  roothist->Write(0,TObject::kOverwrite);
198 }
199 }//end namespace root
200 }//end namespace cass
201 
202 pp2000::pp2000(const name_t &name)
203  : Processor(name)
204 {
205  loadSettings(0);
206 }
207 
209 {
210  throw logic_error("pp2000::result: '"+name()+"' should never be called");
211 }
212 
214 {
215  CASSSettings s;
216  s.beginGroup("Processor");
218  setupGeneral();
219  bool allDepsAreThere(true);
220  int size = s.beginReadArray("Processor");
221  for (int i = 0; i < size; ++i)
222  {
223  s.setArrayIndex(i);
224  string ppname(s.value("Name","Unknown").toString().toStdString());
225  if (ppname == "Unknown")
226  continue;
227  shared_pointer pp(setupDependency("",ppname));
228  allDepsAreThere = pp && allDepsAreThere;
229  string groupname(s.value("GroupName","/").toString().toStdString());
230  string name = pp ? s.value("ValName",QString::fromStdString(pp->name())).toString().toStdString() : "";
231  _ppList.push_back(entry_t(name,groupname,pp));
232  }
233  s.endArray();
234 
235  size = s.beginReadArray("ProcessorSummary");
236  for (int i = 0; i < size; ++i)
237  {
238  s.setArrayIndex(i);
239  string ppname(s.value("Name","Unknown").toString().toStdString());
240  if (ppname == "Unknown")
241  continue;
242  shared_pointer pp(setupDependency("",ppname));
243  allDepsAreThere = pp && allDepsAreThere;
244  string groupname(s.value("GroupName","/").toString().toStdString());
245  string name = pp ? s.value("ValName",QString::fromStdString(pp->name())).toString().toStdString() : "";
246  _ppSummaryList.push_back(entry_t(name,groupname,pp));
247  }
248  s.endArray();
249 
250  bool ret (setupCondition());
251  if (!(ret && allDepsAreThere))
252  {
253  _ppList.clear();
254  _ppSummaryList.clear();
255  return;
256  }
257  _hide = true;
258 
259  string filename(s.value("FileName","output.root").toString().toStdString());
261  if (!_rootfile)
262  throw invalid_argument("pp2000 (" + name() + "): '" + filename +
263  "' could not be opened! Maybe deleting the file helps.");
264  Log::add(Log::INFO,"Processor '" + name() +
265  "' will write all cass histograms with the write flag set " +
266  "to rootfile '" + _rootfile->GetName() + "'. Condition is '" +
267  _condition->name() + "'");
268 }
269 
271 {
272  Log::add(Log::VERBOSEINFO,"pp2000::aboutToQuit() (" + name() +
273  "): Histograms will be written to: '" + _rootfile->GetName() + "'");
274 
275  /** check if something to be written */
276  if (!_ppSummaryList.empty())
277  {
278  /** write all entries to file */
279  list<entry_t>::const_iterator it(_ppSummaryList.begin());
280  list<entry_t>::const_iterator last(_ppSummaryList.end());
281  while(it != last)
282  {
283  /** create and change into dir given by user then write hist with given
284  * name into the file
285  */
286  string folder("/Summary/" + it->groupname);
287  ROOT::changeDir(_rootfile,folder);
288  ROOT::copyHistToRootFile(it->pp->result(),it->name);
289  ++it;
290  }
291 
292  /** go back to original directory and save file */
293  _rootfile->cd("/");
295  }
296 }
297 
299 {
300  if (!_condition->result(evt.id()).isTrue())
301  return;
302 
303  /** check if there is something to be written */
304  if (!_ppList.empty())
305  {
306  QMutexLocker locker(&_lock);
307 
308  /** create the directory name from eventId */
309  string dirname(ROOT::eventIdToDirectoryName(evt.id()));
310 
311  /** write all entries to file */
312  list<entry_t>::const_iterator it(_ppList.begin());
313  list<entry_t>::const_iterator last(_ppList.end());
314  while(it != last)
315  {
316  /** create and change into dir given by user then write hist with given
317  * name into the file
318  */
319  string folder("/" + dirname + "/" + it->groupname);
320  ROOT::changeDir(_rootfile,folder);
321  ROOT::copyHistToRootFile(it->pp->result(evt.id()),it->name);
322  }
323 
324  /** go back to original directory and save file */
325  _rootfile->cd("/");
326  _rootfile->SaveSelf();
327  }
328 }
329 
size_t dim() const
what is the dimension of the result
Definition: result.hpp:503
setArrayIndex(int i)
value_t getValue() const
return the value
Definition: result.hpp:558
Event to store all LCLS Data.
Definition: cass_event.h:32
toString(const QString &format)
const name_t name() const
retrieve the name of this processor
Definition: processor.h:167
void copyHistToRootFile(const Processor::result_t &casshist, const string &valname)
function that will copy a histogram to file
check if FEL is off by checking for bykick which is eventid
file contains declaration of the CASSEvent
Settings for CASS.
Definition: cass_settings.h:30
uint64_t id_t
define the id type
Definition: cass_event.h:52
bool _hide
flag to tell whether this pp should be hidden in the dropdown list
Definition: processor.h:262
STL namespace.
static TFile * create(const std::string &rootfilename, const std::string &options="RECREATE")
create and return an instance of the rootfile
an axis of a more than 0 dimensional container
Definition: result.hpp:29
things written only at end of run H5Dump ProcessorSummary size
QMutex _lock
a lock to make the process reentrant
result classes
file contains declaration of processor 2000
string eventIdToDirectoryName(uint64_t eventid)
function to create a human readable directory name from the eventid
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
fromStdString(const std::string &str)
beginReadArray(const QString &prefix)
base class for processors.
Definition: processor.h:39
std::list< entry_t > _ppSummaryList
container for all pps that should be written when program quits
shared_pointer setupDependency(const std::string &depVarName, const name_t &name="")
setup the dependecy.
Definition: processor.cpp:114
const axis_t & axis() const
read access to the axis
Definition: result.hpp:449
void changeDir(TFile *file, const string &dirname)
create a directory if it does not exist and cd into it
std::list< entry_t > _ppList
container with all pps that contain the histograms to dump to hdf5
pp2000(const name_t &name)
Construct processor for converting histograms to root histograms.
virtual void processEvent(const CASSEvent &)
only a stub does nothing, but needs to be there because its pure virtual in base class ...
id_t & id()
setters
Definition: cass_event.h:64
contains singleton definition for creating root files
value(const QString &key, const QVariant &defaultValue=QVariant()
static void close(TFile *rootfile)
close root file
void setupGeneral()
general setup of the processor
Definition: processor.cpp:85
virtual const result_t & result(const CASSEvent::id_t eventid=0)
overwrite the retrieval of an histogram
file contains specialized class that do the settings for cass
virtual void loadSettings(size_t)
load the settings of this pp
shared_pointer _condition
pointer to the processor that will contain the condition
Definition: processor.h:277
bool setupCondition(bool defaultConditionType=true)
setup the condition.
Definition: processor.cpp:94
TFile * _rootfile
the root file
std::string name_t
define the name type
Definition: processor.h:46
contains a logger for cass
std::tr1::shared_ptr< Processor > shared_pointer
a shared pointer of this
Definition: processor.h:43
virtual void aboutToQuit()
dump all histogram to a root file just before quitting
beginGroup(const QString &prefix)
setTime_t(uint seconds)
struct bundleing info for writing an entry to file