QwAnalysis
QwCompton.cc
Go to the documentation of this file.
1 /*------------------------------------------------------------------------*//*!
2 
3  \defgroup QwCompton QwCompton
4 
5  \section comptonoverview Inclusion of the Compton polarimeter in the Qweak framework
6 
7  Although an existing analysis framework, developed at CMU, was available
8  (and has been successfully used for beam tests at HIgS), we decided that
9  it would be easier to incorporate the Compton polarimeter analysis in the
10  Qweak framework. The main advantages are that parity-type operations are
11  readily available, that delayed helicity reporting is handled transparently
12  to the user (i.e. the detector subsystem analysis writer), and that the
13  particulars of the CODA data structure are abstracted away completely.
14 
15  \section comptonphilosphy Analysis philosophy
16 
17  In the Qweak analysis code all variables (i.e. electronic module channels)
18  can be 'added' and 'subtracted' between helicity states. This makes it
19  easy to get an asymmetry on a helicity multiplet level, but also to get
20  asymmetries or sums between different variables.
21 
22  It might seem funny at first sight that there are functions that define
23  the sum, difference or ratio of two Compton detectors. But, after a
24  moment's thought, that is exactly what you need when you calculate an
25  asymmetry over a helicity multiplet:
26  \f[
27  P_{beam} = \frac{1}{P_{laser}} \frac{N^+ - N^-}{N^+ + N^-}.
28  \f]
29  In this case you perform all three of these operations between the data
30  collected during the different beam helicity states (or alternatively,
31  between the two laser helicity states, which could give us access to
32  systematic differences between the two beam helicity states).
33 
34  The details of how this addition and subtraction is performed have to be
35  specified by the subsystem developer. For example, in the case of the
36  QwComptonPhotonDetector, each helicity window consists of a varying number
37  of sampled photon detector pulses. The goal could be to use the above
38  formula to get an 'asymmety spectrum' of the pulses. In this case, one
39  would have to take care not to add 10 positive helicity events and only
40  8 negative helicity events. The normalization has to be included in the
41  addition and subtraction. The same thing is true in accumulator mode,
42  where the zeroth accumulator (sample counter) should be used to normalize.
43 
44  \subsection comptonphotondetector Photon detector subsystem
45 
46  The only subsystem of the Compton polarimeter that has been implemented
47  (partially) at the moment is the photon detector. The sampling ADC, and
48  integrating ADC/TDC have CODA readout support in the Qweak analysis code,
49  making it easy to take asymmetries of different helicity events.
50 
51  The main difficulty in the code will be to access the laser helicity state
52  through EPICS.
53 
54  \subsection comptonelectrondetector Electron detector subsystem
55 
56  The electron detector has not been implemented yet. The GEM detectors in
57  region 1 of Qweak use the same V1495 boards and are partially implemented.
58 
59 
60 *//*-------------------------------------------------------------------------*/
61 
62 /*------------------------------------------------------------------------*//*!
63 
64  \file QwCompton.cc
65 
66  \ingroup QwCompton
67 
68  \brief Compton data analysis
69 
70 *//*-------------------------------------------------------------------------*/
71 
72 // C and C++ headers
73 #include <iostream>
74 
75 // Boost math library for random number generation
76 #include <boost/random.hpp>
77 
78 // ROOT headers
79 #include <TROOT.h>
80 #include <TFile.h>
81 #include <TTree.h>
82 
83 
84 // Qweak headers
85 #include "QwLog.h"
86 #include "QwRootFile.h"
87 #include "QwOptionsParity.h"
88 #include "QwEventBuffer.h"
89 #include "QwEPICSEvent.h"
90 #include "QwHelicity.h"
91 #include "QwHelicityPattern.h"
92 #include "QwHistogramHelper.h"
93 #include "QwSubsystemArrayParity.h"
94 
95 // Compton headers
96 #include "QwScaler.h"
97 #include "QwBeamLine.h"
100 
101 
102 
103 int main(int argc, char* argv[])
104 {
105  /// Change some default settings for use by the Compton analyzer
108 
109 
110  /// Fill the search paths for the parameter files; this sets a static
111  /// variable within the QwParameterFile class which will be used by
112  /// all instances. The "scratch" directory should be first.
114  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Parity/prminput");
115  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Analysis/prminput");
116 
117 
118  /// Set the command line arguments and the configuration filename
119  gQwOptions.SetCommandLine(argc, argv);
120  /// Define the command line options
122 
123  /// Message logging facilities
125 
126 
127  // Load histogram definitions
128  gQwHists.LoadHistParamsFromFile("compton_hists.in");
129 
130 
131  /// Create the event buffer
132  QwEventBuffer eventbuffer;
133  eventbuffer.ProcessOptions(gQwOptions);
134 
135  /// Start loop over all runs
136  while (eventbuffer.OpenNextStream() == CODA_OK) {
137 
138  /// Begin processing for the first run
139 
140 
141  /// Set the current event number for parameter file lookup
143 
144 
145  /// Create an EPICS event
146  QwEPICSEvent epicsevent;
147  epicsevent.ProcessOptions(gQwOptions);
148  epicsevent.LoadChannelMap("compton_epics_table.map");
149 
150 
151  /// Load the detectors from file
153  detectors.ProcessOptions(gQwOptions);
154 
155  /// Create the helicity pattern
156  QwHelicityPattern helicitypattern(detectors);
157  helicitypattern.ProcessOptions(gQwOptions);
158 
159  // Create a configuration options output
160  QwSubsystemArrayParity configoutput(detectors);
161 
162 
163  // Open the ROOT file
164  QwRootFile* rootfile = new QwRootFile(eventbuffer.GetRunLabel());
165  if (! rootfile) QwError << "QwAnalysis made a boo boo!" << QwLog::endl;
166  rootfile->WriteParamFileList("mapfiles", detectors);
167  // Construct histograms
168  rootfile->ConstructHistograms("mps_histo", detectors);
169  rootfile->ConstructHistograms("hel_histo", helicitypattern);
170 
171  // Construct tree branches
172  rootfile->ConstructTreeBranches("Mps_Tree", "MPS event data tree", detectors);
173  rootfile->ConstructTreeBranches("Hel_Tree", "Helicity event data tree", helicitypattern);
174  rootfile->ConstructTreeBranches("Burst_Tree", "Burst level data tree", helicitypattern.GetBurstYield(),"yield_");
175  rootfile->ConstructTreeBranches("Burst_Tree", "Burst level data tree", helicitypattern.GetBurstAsymmetry(),"asym_");
176  rootfile->ConstructTreeBranches("Burst_Tree", "Burst level data tree", helicitypattern.GetBurstDifference(),"diff_");
177  rootfile->ConstructTreeBranches("Slow_Tree", "EPICS and slow control tree", epicsevent);
178  rootfile->ConstructTreeBranches("Config_Tree","Configuration Tree",configoutput,"conf");
179  // Construct indices to get from one tree to the other
180  rootfile->ConstructIndices("Mps_Tree","Slow_Tree");
181  rootfile->ConstructIndices("Hel_Tree","Slow_Tree");
182  rootfile->ConstructIndices("Mps_Tree","Config_Tree");
183  rootfile->ConstructIndices("Hel_Tree","Config_Tree");
184 
185  // Summarize the ROOT file structure
186  rootfile->PrintTrees();
187  rootfile->PrintDirs();
188 
189 
190  // Clear the running sums
191  helicitypattern.ClearRunningSum();
192  helicitypattern.ClearBurstSum();
193 
194 
195  /// Start loop over events
196  while (eventbuffer.GetNextEvent() == CODA_OK) {
197 
198  // First, do processing of non-physics events...
199  if (eventbuffer.IsROCConfigurationEvent()) {
200  // Send ROC configuration event data to the subsystem objects.
201  eventbuffer.FillSubsystemConfigurationData(configoutput);
202  }
203 
204  // Secondly, process EPICS events
205  if (eventbuffer.IsEPICSEvent()) {
206  eventbuffer.FillEPICSData(epicsevent);
207  if (epicsevent.HasDataLoaded()) {
208  epicsevent.CalculateRunningValues();
209 
210  rootfile->FillTreeBranches(epicsevent);
211  rootfile->FillTree("Slow_Tree");
212  }
213  }
214 
215  // Now, if this is not a physics event, go back and get a new event.
216  if (! eventbuffer.IsPhysicsEvent()) continue;
217 
218 
219 
220  // Fill the subsystem objects with their respective data for this event.
221  eventbuffer.FillSubsystemData(detectors);
222 
223  // Process this events
224  detectors.ProcessEvent();
225 
226  // The event pass the event cut constraints
227  if (detectors.ApplySingleEventCuts()) {
228 
229  // Fill the histograms
230  rootfile->FillHistograms(detectors);
231 
232  // Fill the tree
233  rootfile->FillTreeBranches(detectors);
234  rootfile->FillTree("Mps_Tree");
235 
236 
237  // Somehow test to see if the laser state has changed. If it has,
238  // then calculate and print the running sums so far.
239  // Maybe instead of here, it should be done as soon as we've picked up an
240  // event, instead of waiting to build a complete pattern.
241 
242  if (detectors.CheckForEndOfBurst()){
243  // Do the burst versions of
244  helicitypattern.CalculateRunningAverage();
245  // Maybe we need to clear the burst sums also
246  }
247 
248 
249  // Helicity pattern
250  helicitypattern.LoadEventData(detectors);
251 
252 
253  // TODO We need another check here to test for pattern validity. Right
254  // now the first 24 cycles are also added to the histograms.
255  if (helicitypattern.IsCompletePattern()) {
256 
257  // Calculate the asymmetry
258  helicitypattern.CalculateAsymmetry();
259  if (helicitypattern.IsGoodAsymmetry()) {
260 
261  // Fill histograms
262  rootfile->FillHistograms(helicitypattern);
263 
264  // Fill tree branches
265  rootfile->FillTreeBranches(helicitypattern);
266  rootfile->FillTree("Hel_Tree");
267 
268  // Clear the data
269  helicitypattern.ClearEventData();
270  }
271 
272 
273  // Somehow test to see if the laser state has changed. If it has,
274  // then calculate and print the running sums so far.
275  // Maybe instead of here, it should be done as soon as we've picked up an
276  // event, instead of waiting to build a complete pattern.
277 
278  }
279 
280  } // detectors.ApplySingleEventCuts()
281 
282 
283  // Burst mode
284  if (helicitypattern.IsEndOfBurst()) {
285  helicitypattern.CalculateBurstAverage();
286  helicitypattern.AccumulateRunningBurstSum();
287 
288  // Fill tree branches
289  rootfile->FillTreeBranches(helicitypattern.GetBurstYield());
290  rootfile->FillTreeBranches(helicitypattern.GetBurstAsymmetry());
291  rootfile->FillTreeBranches(helicitypattern.GetBurstDifference());
292  rootfile->FillTree("Burst_Tree");
293 
294  // Clear the data
295  helicitypattern.ClearBurstSum();
296  }
297 
298  } // end of loop over events
299  rootfile->FillTreeBranches(configoutput);
300  rootfile->FillTree("Config_Tree");
301 
302  QwMessage << "Last event processed: "
303  << eventbuffer.GetEventNumber() << QwLog::endl;
304 
305  // Calculate running averages over helicity patterns
306  if (helicitypattern.IsRunningSumEnabled()) {
307  helicitypattern.CalculateRunningAverage();
308  if (helicitypattern.IsBurstSumEnabled()) {
309  helicitypattern.CalculateRunningBurstAverage();
310  }
311  }
312 
313 
314  /* Write to the root file, being sure to delete the old cycles *
315  * which were written by Autosave. *
316  * Doing this will remove the multiple copies of the ntuples *
317  * from the root file. *
318  * *
319  * Then, we need to delete the histograms here. *
320  * If we wait until the subsystem destructors, we get a *
321  * segfault; but in additional to that we should delete them *
322  * here, in case we run over multiple runs at a time. */
323  rootfile->Write(0,TObject::kOverwrite);
324 
325  // Close ROOT file
326  rootfile->Close();
327  delete rootfile; rootfile = 0;
328 
329  // Close data file and print run summary
330  eventbuffer.CloseStream();
331 
332  // Report run summary
333  eventbuffer.ReportRunSummary();
334  eventbuffer.PrintRunTimes();
335 
336  } // end of loop over runs
337 
338  QwMessage << "I have done everything I can do..." << QwLog::endl;
339 
340  return 0;
341 }
void ProcessOptions(QwOptions &options)
Process the configuration options.
Definition: QwEPICSEvent.cc:83
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
static void SetDefaultDataFileStem(const std::string &stem)
Definition: QwEventBuffer.h:36
virtual Bool_t CheckForEndOfBurst() const
static void AppendToSearchPath(const TString &searchdir)
Add a directory to the search path.
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
Bool_t ApplySingleEventCuts()
Apply the single event cuts.
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.
static void SetCurrentRunNumber(const UInt_t runnumber)
Set the current run number for looking up the appropriate parameter file.
void ConstructIndices(const std::string &from, const std::string &to, bool reverse=true)
Construct indices from one tree to another tree.
Definition: QwRootFile.h:574
Int_t CloseStream()
Closes a currently open event stream.
void Close()
Definition: QwRootFile.h:416
QwOptions gQwOptions
Definition: QwOptions.cc:27
void ProcessOptions(QwOptions *options)
Process class options for QwOptions.
Definition: QwLog.cc:108
Bool_t IsBurstSumEnabled()
Status of burst sum calculation flag.
Bool_t IsCompletePattern() const
void ProcessOptions(QwOptions &options)
Process configuration options (default behavior)
QwSubsystemArrayParity & GetBurstDifference()
Int_t FillTree(const std::string &name)
Fill the tree with name.
Definition: QwRootFile.h:359
Int_t GetEventNumber()
Int_t GetNextEvent()
Virtual base class for the parity subsystems.
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()
A logfile class, based on an identical class in the Hermes analyzer.
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
Load the options for the parity subsystems.
void ProcessOptions(QwOptions &options)
Process the configuration options.
static void SetDefaultRootFileStem(const std::string &stem)
Set default ROOT file stem.
Definition: QwRootFile.h:296
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.
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)
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 PrintTrees() const
Print registered trees.
Definition: QwRootFile.h:376
int main(int argc, char **argv)
Definition: QwRoot.cc:20
void LoadHistParamsFromFile(const std::string &filename)
void PrintDirs() const
Print registered histogram directories.
Definition: QwRootFile.h:391
QwLog gQwLog
Definition: QwLog.cc:22
Bool_t IsROCConfigurationEvent()
#define QwError
Predefined log drain for errors.
Definition: QwLog.h:40
void SetCommandLine(int argc, char *argv[], bool default_config_file=true)
Set the command line arguments.
Definition: QwOptions.cc:112