QwAnalysis
QwParity.cc
Go to the documentation of this file.
1 /*------------------------------------------------------------------------*//*!
2 
3  \file QwParity.cc
4 
5  \brief main(...) function for the qwanalysis executable
6 
7 *//*-------------------------------------------------------------------------*/
8 
9 // System headers
10 #include <iostream>
11 #include <fstream>
12 #include <vector>
13 #include <new>
14 
15 // Boost headers
16 #include <boost/shared_ptr.hpp>
17 
18 // ROOT headers
19 #include "Rtypes.h"
20 #include "TROOT.h"
21 #include "TFile.h"
22 
23 // Qweak headers
24 #include "QwLog.h"
25 #include "QwRootFile.h"
26 #include "QwOptionsParity.h"
27 #include "QwEventBuffer.h"
28 #include "QwParityDB.h"
29 #include "QwHistogramHelper.h"
30 #include "QwSubsystemArrayParity.h"
31 #include "QwHelicityPattern.h"
32 #include "QwEventRing.h"
33 #include "QwEPICSEvent.h"
34 #include "QwRegression.h"
35 #include "QwRegressionSubsystem.h"
36 #include "QwPromptSummary.h"
37 
38 // Qweak subsystems
39 // (for correct dependency generation)
40 #include "QwHelicity.h"
41 #include "QwFakeHelicity.h"
42 #include "QwBeamLine.h"
43 #include "QwMainCerenkovDetector.h"
44 #include "QwScanner.h"
45 #include "QwLumi.h"
46 #include "QwBeamMod.h"
47 #include "QwIntegratedRaster.h"
48 
49 
50 
51 Int_t main(Int_t argc, Char_t* argv[])
52 {
53  /// without anything, print usage
54  if(argc == 1){
55  gQwOptions.Usage();
56  exit(0);
57  }
58 
59  /// First, fill the search paths for the parameter files; this sets a
60  /// static variable within the QwParameterFile class which will be used by
61  /// all instances.
62  /// The "scratch" directory should be first.
64  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Parity/prminput");
65  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Analysis/prminput");
66 
67  /// Then, we set the command line arguments and the configuration filename,
68  /// and we define the options that can be used in them (using QwOptions).
69  gQwOptions.AddOptions()("single-output-file", po::value<bool>()->default_bool_value(false), "Write a single output file");
70  gQwOptions.AddOptions()("print-errorcounters", po::value<bool>()->default_bool_value(true), "Print summary of error counters");
71  gQwOptions.AddOptions()("write-promptsummary", po::value<bool>()->default_bool_value(false), "Write PromptSummary");
72 
73  gQwOptions.SetCommandLine(argc, argv);
74  gQwOptions.AddConfigFile("qweak_mysql.conf");
75 
77 
78  /// Define the command line options
80  /// Load command line options for the histogram/tree helper class
82  /// Setup screen and file logging
84 
85 
86  /// Create the event buffer
87  QwEventBuffer eventbuffer;
88  eventbuffer.ProcessOptions(gQwOptions);
89 
90  /// Create the database connection
91  QwParityDB database(gQwOptions);
92 
93 
94  // QwPromptSummary promptsummary;
95 
96  /// Start loop over all runs
97  while (eventbuffer.OpenNextStream() == CODA_OK) {
98 
99  /// Begin processing for the first run
100 
101  Int_t run_number = eventbuffer.GetRunNumber();
102 
103  /// Set the current event number for parameter file lookup
105 
106  // if (gQwOptions.GetValue<bool>("write-promptsummary")) {
107  QwPromptSummary promptsummary(run_number, eventbuffer.GetSegmentNumber());
108  // }
109  /// Create an EPICS event
110  QwEPICSEvent epicsevent;
111  epicsevent.ProcessOptions(gQwOptions);
112  epicsevent.LoadChannelMap("EpicsTable.map");
113 
114  /// Load the detectors from file
116  detectors.ProcessOptions(gQwOptions);
117  detectors.ListPublishedValues();
118 
119  /// Create event-based linear regression subsystem
120  // TString name = "MpsRegression";
121  // QwRegressionSubsystem regress_sub(gQwOptions, detectors, name);
122  // detectors.push_back(regress_sub.GetSharedPointerToStaticObject());
123 
124  /// Create the helicity pattern
125  QwHelicityPattern helicitypattern(detectors);
126  helicitypattern.ProcessOptions(gQwOptions);
127 
128  /// Create the asymmetry-based linear regression
129  QwRegression regression(gQwOptions,helicitypattern);
130  QwRegression running_regression(regression);
131 
132  /// Create the event ring with the subsystem array
133  QwEventRing eventring(gQwOptions,detectors);
134  // Make a copy of the detectors object to hold the
135  // events which pass through the ring.
136  QwSubsystemArrayParity ringoutput(detectors);
137 
138  /// Create the running sum
139  QwSubsystemArrayParity runningsum(detectors);
140 
141 
142  // Initialize the database connection.
143  database.SetupOneRun(eventbuffer);
144 
145  // Open the ROOT file (close when scope ends)
146  QwRootFile *treerootfile = NULL;
147  QwRootFile *burstrootfile = NULL;
148  QwRootFile *historootfile = NULL;
149 
150  TString run_label = eventbuffer.GetRunLabel();
151 
152 
153  if (gQwOptions.GetValue<bool>("single-output-file")) {
154 
155  treerootfile = new QwRootFile(run_label);
156  burstrootfile = historootfile = treerootfile;
157  // Construct a tree which contains map file names which are used to analyze data
158  treerootfile->WriteParamFileList("mapfiles", detectors);
159 
160  } else {
161 
162  treerootfile = new QwRootFile(run_label + ".trees");
163  burstrootfile = new QwRootFile(run_label + ".bursts");
164  historootfile = new QwRootFile(run_label + ".histos");
165 
166  // Construct a tree which contains map file names which are used to analyze data
167  detectors.PrintParamFileList();
168  treerootfile->WriteParamFileList("mapfiles", detectors);
169  burstrootfile->WriteParamFileList("mapfiles", detectors);
170  historootfile->WriteParamFileList("mapfiles", detectors);
171  }
172 
173  if (database.AllowsWriteAccess()) {
174  database.FillParameterFiles(detectors);
175  }
176 
177  // Construct histograms
178  historootfile->ConstructHistograms("mps_histo", ringoutput);
179  historootfile->ConstructHistograms("hel_histo", helicitypattern);
180  detectors.ShareHistograms(ringoutput);
181 
182  // Construct tree branches
183  treerootfile->ConstructTreeBranches("Mps_Tree", "MPS event data tree", ringoutput);
184  treerootfile->ConstructTreeBranches("Hel_Tree", "Helicity event data tree", helicitypattern);
185  treerootfile->ConstructTreeBranches("Hel_Tree_Reg", "Helicity event data tree (regressed)", regression);
186  treerootfile->ConstructTreeBranches("Slow_Tree", "EPICS and slow control tree", epicsevent);
187  burstrootfile->ConstructTreeBranches("Burst_Tree", "Burst level data tree", helicitypattern.GetBurstYield(),"yield_");
188  burstrootfile->ConstructTreeBranches("Burst_Tree", "Burst level data tree", helicitypattern.GetBurstAsymmetry(),"asym_");
189  burstrootfile->ConstructTreeBranches("Burst_Tree", "Burst level data tree", helicitypattern.GetBurstDifference(),"diff_");
190 
191  // Summarize the ROOT file structure
192  //treerootfile->PrintTrees();
193  //treerootfile->PrintDirs();
194 
195 
196  // Clear the single-event running sum at the beginning of the runlet
197  runningsum.ClearEventData();
198  helicitypattern.ClearRunningSum();
199  // Clear the running sum of the burst values at the beginning of the runlet
200  helicitypattern.ClearBurstSum();
201 
202 
203  // Load the blinder seed from the database for this runlet.
204  helicitypattern.UpdateBlinder(&database);
205 
206  // Find the first EPICS event and try to initialize
207  // the blinder.
208  QwMessage << "Finding first EPICS event" << QwLog::endl;
209  while (eventbuffer.GetNextEvent() == CODA_OK) {
210  if (eventbuffer.IsEPICSEvent()) {
211  eventbuffer.FillEPICSData(epicsevent);
212  if (epicsevent.HasDataLoaded()) {
213  helicitypattern.UpdateBlinder(epicsevent);
214  // and break out of this event loop
215  break;
216  }
217  }
218  }
219  epicsevent.ResetCounters();
220  // Rewind stream
221  QwMessage << "Rewinding stream" << QwLog::endl;
222  eventbuffer.ReOpenStream();
223 
224  /// Start loop over events
225  while (eventbuffer.GetNextEvent() == CODA_OK) {
226 
227  // First, do processing of non-physics events...
228  if (eventbuffer.IsROCConfigurationEvent()) {
229  // Send ROC configuration event data to the subsystem objects.
230  eventbuffer.FillSubsystemConfigurationData(detectors);
231  }
232 
233  // Secondly, process EPICS events
234  if (eventbuffer.IsEPICSEvent()) {
235  eventbuffer.FillEPICSData(epicsevent);
236  if (epicsevent.HasDataLoaded()){
237  epicsevent.CalculateRunningValues();
238  helicitypattern.UpdateBlinder(epicsevent);
239 
240  treerootfile->FillTreeBranches(epicsevent);
241  treerootfile->FillTree("Slow_Tree");
242  }
243  }
244 
245 
246  // Now, if this is not a physics event, go back and get a new event.
247  if (! eventbuffer.IsPhysicsEvent()) continue;
248 
249 
250 
251  // Fill the subsystem objects with their respective data for this event.
252  eventbuffer.FillSubsystemData(detectors);
253 
254  // Process the subsystem data
255  detectors.ProcessEvent();
256 
257 
258 
259  // The event pass the event cut constraints
260  if (detectors.ApplySingleEventCuts()) {
261 
262  // // TEST
263  // regress_sub.LinearRegression();
264 
265  // Add event to the ring
266  eventring.push(detectors);
267 
268  // Check to see ring is ready
269  if (eventring.IsReady()) {
270  ringoutput = eventring.pop();
271  ringoutput.IncrementErrorCounters();
272 
273 
274  // Accumulate the running sum to calculate the event based running average
275  runningsum.AccumulateRunningSum(ringoutput);
276 
277  // Fill the histograms
278  historootfile->FillHistograms(ringoutput);
279 
280  // Fill mps tree branches
281  treerootfile->FillTreeBranches(ringoutput);
282  treerootfile->FillTree("Mps_Tree");
283 
284  // Load the event into the helicity pattern
285  helicitypattern.LoadEventData(ringoutput);
286 
287  // Calculate helicity pattern asymmetry
288  if (helicitypattern.IsCompletePattern()) {
289 
290  // Update the blinder if conditions have changed
291  helicitypattern.UpdateBlinder(ringoutput);
292 
293  // Calculate the asymmetry
294  helicitypattern.CalculateAsymmetry();
295  if (helicitypattern.IsGoodAsymmetry()) {
296 
297  // Fill histograms
298  historootfile->FillHistograms(helicitypattern);
299 
300  // Fill helicity tree branches
301  treerootfile->FillTreeBranches(helicitypattern);
302  treerootfile->FillTree("Hel_Tree");
303 
304  // Burst mode
305  if (helicitypattern.IsEndOfBurst()) {
306  helicitypattern.AccumulateRunningBurstSum();
307  helicitypattern.CalculateBurstAverage();
308 
309  // Fill burst tree branches
310  burstrootfile->FillTreeBranches(helicitypattern.GetBurstYield());
311  burstrootfile->FillTreeBranches(helicitypattern.GetBurstAsymmetry());
312  burstrootfile->FillTreeBranches(helicitypattern.GetBurstDifference());
313  burstrootfile->FillTree("Burst_Tree");
314 
315  // Clear the data
316  helicitypattern.ClearBurstSum();
317  }
318 
319  // Linear regression on asymmetries
321  running_regression.AccumulateRunningSum(regression);
322 
323  // Fill regressed tree branches
324  treerootfile->FillTreeBranches(regression);
325  treerootfile->FillTree("Hel_Tree_Reg");
326 
327  // Clear the data
328  helicitypattern.ClearEventData();
329 
330  } // helicitypattern.IsGoodAsymmetry()
331 
332  } // helicitypattern.IsCompletePattern()
333 
334  } // eventring.IsReady()
335 
336  } // detectors.ApplySingleEventCuts()
337 
338  } // end of loop over events
339 
340  // Perform actions at the end of the event loop on the
341  // detectors object, which ought to have handles for the
342  // MPS based histograms.
343  ringoutput.AtEndOfEventLoop();
344 
345  QwMessage << "Number of events processed at end of run: "
346  << eventbuffer.GetEventNumber() << QwLog::endl;
347 
348 
349  // Calculate running averages over helicity patterns
350  if (helicitypattern.IsRunningSumEnabled()) {
351  helicitypattern.CalculateRunningAverage();
352  if (helicitypattern.IsBurstSumEnabled()) {
353  helicitypattern.CalculateRunningBurstAverage();
354  }
355  }
356 
357  running_regression.CalculateRunningAverage();
358  running_regression.PrintValue();
359 
360  // This will calculate running averages over single helicity events
361  runningsum.CalculateRunningAverage();
362  if (gQwOptions.GetValue<bool>("print-runningsum")) {
363  QwMessage << " Running average of events" << QwLog::endl;
364  QwMessage << " =========================" << QwLog::endl;
365  runningsum.PrintValue();
366  }
367 
368 
369  /* Write to the root file, being sure to delete the old cycles *
370  * which were written by Autosave. *
371  * Doing this will remove the multiple copies of the ntuples *
372  * from the root file. *
373  * *
374  * Then, we need to delete the histograms here. *
375  * If we wait until the subsystem destructors, we get a *
376  * segfault; but in addition to that we should delete them *
377  * here, in case we run over multiple runs at a time. */
378  if (treerootfile == historootfile) {
379  treerootfile->Write(0,TObject::kOverwrite);
380  delete treerootfile; treerootfile = 0; burstrootfile = 0; historootfile = 0;
381  } else {
382  treerootfile->Write(0,TObject::kOverwrite);
383  burstrootfile->Write(0,TObject::kOverwrite);
384  historootfile->Write(0,TObject::kOverwrite);
385  delete treerootfile; treerootfile = 0;
386  delete burstrootfile; burstrootfile = 0;
387  delete historootfile; historootfile = 0;
388  }
389 
390  // Print the event cut error summary for each subsystem
391  if (gQwOptions.GetValue<bool>("print-errorcounters")) {
392  QwMessage << " ------------ error counters ------------------ " << QwLog::endl;
393  ringoutput.PrintErrorCounters();
394  }
395 
396  if (gQwOptions.GetValue<bool>("write-promptsummary")) {
397  // runningsum.WritePromptSummary(&promptsummary, "yield");
398  // runningsum.WritePromptSummary(&promptsummary, "asymmetry");
399  // runningsum.WritePromptSummary(&promptsummary, "difference");
400  helicitypattern.WritePromptSummary(&promptsummary);
401  promptsummary.PrintCSV();
402  }
403  // Read from the database
404  database.SetupOneRun(eventbuffer);
405 
406  // Each subsystem has its own Connect() and Disconnect() functions.
407  if (database.AllowsWriteAccess()) {
408  helicitypattern.FillDB(&database);
409  helicitypattern.FillErrDB(&database);
410  epicsevent.FillDB(&database);
411  running_regression.FillDB(&database,"asymmetry");
412  ringoutput.FillDB_MPS(&database, "optics");
413  }
414 
415 
416  //epicsevent.WriteEPICSStringValues();
417 
418  // Close event buffer stream
419  eventbuffer.CloseStream();
420 
421 
422 
423  // Report run summary
424  eventbuffer.ReportRunSummary();
425  eventbuffer.PrintRunTimes();
426  } // end of loop over runs
427 
428  QwMessage << "I have done everything I can do..." << QwLog::endl;
429 
430  return 0;
431 }
432 
void ProcessOptions(QwOptions &options)
Process the configuration options.
Definition: QwEPICSEvent.cc:83
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
QwSubsystemArrayParity & pop()
Return the last subsystem in the ring.
Definition: QwEventRing.cc:121
void PrintValue() const
Print value of all channels.
static void AppendToSearchPath(const TString &searchdir)
Add a directory to the search path.
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
#define default_bool_value(b)
Definition: QwOptions.h:51
Bool_t ApplySingleEventCuts()
Apply the single event cuts.
Int_t GetSegmentNumber() const
Return CODA file segment number.
Definition: QwEventBuffer.h:82
Int_t ReOpenStream()
Int_t WriteParamFileList(const TString &name, T &object)
Definition: QwRootFile.h:736
void ConstructHistograms(const std::string &name, T &object)
Construct the histograms of a generic object.
Definition: QwRootFile.h:706
void DefineOptionsParity(QwOptions &options)
void ProcessOptions(QwOptions &options)
Sets internal flags based on the QwOptions.
Int_t OpenNextStream()
Opens the event stream (file or ET) based on the internal flags.
void AccumulateRunningSum(const QwSubsystemArrayParity &value)
Update the running sums for devices accumulated for the global error non-zero events/patterns.
void AccumulateRunningSum(QwRegression value)
static void SetCurrentRunNumber(const UInt_t runnumber)
Set the current run number for looking up the appropriate parameter file.
Int_t CloseStream()
Closes a currently open event stream.
void WritePromptSummary(QwPromptSummary *ps)
void PrintParamFileList() const
Print list of parameter files.
QwOptions gQwOptions
Definition: QwOptions.cc:27
void CalculateRunningAverage()
Calculate the average for all good events.
void ProcessOptions(QwOptions *options)
Process class options for QwOptions.
Definition: QwLog.cc:108
void UpdateBlinder(QwParityDB *db)
Update the blinder status with new external information.
Bool_t IsBurstSumEnabled()
Status of burst sum calculation flag.
Bool_t IsCompletePattern() const
void ProcessOptions(QwOptions &options)
Process configuration options (default behavior)
QwSubsystemArrayParity & GetBurstDifference()
void LinearRegression(EQwRegType type)
Linear regression.
Int_t FillTree(const std::string &name)
Fill the tree with name.
Definition: QwRootFile.h:359
po::options_description_easy_init AddOptions(const std::string &blockname="Specialized options")
Add an option to a named block or create new block.
Definition: QwOptions.h:164
void FillDB_MPS(QwParityDB *db, TString type)
Fill the database with MPS-based variables Note that most subsystems don&#39;t need to do this...
Int_t GetEventNumber()
void push(QwSubsystemArrayParity &event)
Add the subsystem to the ring.
Definition: QwEventRing.cc:69
Bool_t AllowsWriteAccess()
Definition: QwDatabase.h:56
void CalculateRunningAverage()
Int_t GetNextEvent()
void ProcessOptions(QwOptions &options)
Process the configuration options.
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
void Usage()
Print usage information.
Definition: QwOptions.cc:288
void ListConfigFiles()
List the configuration files.
Definition: QwOptions.h:214
Virtual base class for the parity subsystems.
void FillDB(QwParityDB *db, TString datatype)
A wrapper class for a ROOT file or memory mapped file.
Definition: QwRootFile.h:281
Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Definition: QwRootFile.h:437
QwSubsystemArrayParity & GetBurstYield()
void PrintErrorCounters() const
Report the number of events failed due to HW and event cut failures.
A logfile class, based on an identical class in the Hermes analyzer.
void AddConfigFile(const std::string &configfile)
Add a configuration file.
Definition: QwOptions.h:199
void ConstructTreeBranches(const std::string &name, const std::string &desc, T &object, const std::string &prefix="")
Construct the tree branches of a generic object.
Definition: QwRootFile.h:600
Int_t GetRunNumber() const
Return CODA file run number.
Definition: QwEventBuffer.h:80
void AtEndOfEventLoop()
Perform actions at the end of the event loop.
Load the options for the parity subsystems.
void ProcessOptions(QwOptions &options)
Process the configuration options.
void ListPublishedValues() const
List the published values and description in this subsystem array.
void PrintValue() const
Bool_t IsEPICSEvent()
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
Bool_t FillSubsystemData(QwSubsystemArray &subsystems)
void PrintRunTimes()
Bool_t IsRunningSumEnabled()
Status of running sum calculation flag.
void FillParameterFiles(QwSubsystemArrayParity &subsys)
Definition: QwParityDB.cc:563
void SetupOneRun(QwEventBuffer &qwevt)
Definition: QwParityDB.cc:136
void ShareHistograms(const QwSubsystemArray &source)
Share the histograms with another subsystem.
QwSubsystemArrayParity & GetBurstAsymmetry()
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
void FillTreeBranches(const std::string &name, const T &object)
Fill the tree branches of a generic object by tree name.
Definition: QwRootFile.h:658
void ProcessEvent()
Process the decoded data in this event.
const std::string getenv_safe_string(const char *name)
Definition: QwOptions.h:37
void FillHistograms(T &object)
Fill histograms of the subsystem array.
Definition: QwRootFile.h:329
void LoadEventData(QwSubsystemArrayParity &event)
void FillErrDB(QwParityDB *db)
TString GetRunLabel() const
Returns a string like &lt;run#&gt; or &lt;run#&gt;.&lt;file#&gt;
Bool_t FillEPICSData(QwEPICSEvent &epics)
Bool_t IsPhysicsEvent()
void IncrementErrorCounters()
Update the data elements&#39; error counters based on their internal error flags.
void FillDB(QwParityDB *db)
int main(int argc, char **argv)
Definition: QwRoot.cc:20
QwLog gQwLog
Definition: QwLog.cc:22
Bool_t IsROCConfigurationEvent()
Bool_t IsReady()
Return the read status of the ring.
Definition: QwEventRing.cc:138
void SetCommandLine(int argc, char *argv[], bool default_config_file=true)
Set the command line arguments.
Definition: QwOptions.cc:112