QwAnalysis
QwTracking.cc
Go to the documentation of this file.
1 /*------------------------------------------------------------------------*//*!
2 
3  \file QwTracking.cc
4  \ingroup QwTracking
5 
6  \brief This is the main executable for the tracking analysis.
7 
8 *//*-------------------------------------------------------------------------*/
9 
10 // C and C++ headers
11 #include <sys/time.h>
12 
13 // Qweak headers
14 #include "QwLog.h"
15 #include "QwRootFile.h"
16 #include "QwOptionsTracking.h"
17 #include "QwEventBuffer.h"
18 #include "QwHistogramHelper.h"
19 #include "QwEPICSEvent.h"
20 #include "QwTrackingWorker.h"
21 #include "QwEvent.h"
22 #include "QwHitContainer.h"
23 #include "QwHitRootContainer.h"
24 #include "QwRunCondition.h"
25 
26 
27 // Qweak tracking subsystems
29 #include "QwSciFiDetector.h"
30 #include "QwDriftChamberHDC.h"
31 #include "QwDriftChamberVDC.h"
32 #include "QwTriggerScintillator.h"
33 #include "QwMainDetector.h"
34 #include "QwScanner.h"
35 #include "QwRaster.h"
36 
37 
38 // Qweak parity subsystems
39 #include "QwSubsystemArrayParity.h"
40 #include "QwHelicity.h"
41 #include "QwBeamLine.h"
42 #include "QwScaler.h"
43 
44 
45 // Main function
46 Int_t main(Int_t argc, Char_t* argv[])
47 {
48  /// without anything, print usage
49  if(argc == 1){
50  gQwOptions.Usage();
51  exit(0);
52  }
53  /// First, fill the search paths for the parameter files; this sets a static
54  /// variable within the QwParameterFile class which will be used by
55  /// all instances.
56  /// The "scratch" directory should be first.
58  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Tracking/prminput");
59  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Parity/prminput");
60  QwParameterFile::AppendToSearchPath(getenv_safe_string("QWANALYSIS") + "/Analysis/prminput");
61 
62  /// Then, we set the command line arguments and the configuration filename,
63  /// and we define the options that can be used in them (using QwOptions).
64 
65  gQwOptions.SetCommandLine(argc, argv);
67 
68  /// TODO: I have disabled the AddConfigFile("qweak_mysql.conf")
69  /// line below, because the standard version contains
70  /// options which are not defined in the basic QwDatabase
71  /// DefineOptions function. We should figure out something
72  /// better...
73  /// gQwOptions.AddConfigFile("qweak_mysql.conf");
74  /// Define the command line options
76  /// Load command line options for the histogram/tree helper class
77  //gQwHists.ProcessOptions(gQwOptions);
78  /// Setup screen and file logging
80 
81 
82  /// Create the event buffer
83  QwEventBuffer eventbuffer;
84  eventbuffer.ProcessOptions(gQwOptions);
85 
86 
87 
88  Bool_t enablemapfile = gQwOptions.GetValue<bool>("enable-mapfile");
89  gQwHists.LoadHistParamsFromFile("parity_hist.in");
90  gQwHists.LoadHistParamsFromFile("qweak_tracking_hists.in");
91 
92 
93  /// Start loop over all runs
94  while (eventbuffer.OpenNextStream() == CODA_OK) {
95 
96  /// Begin processing for the first run.
97 
98 
99  /// Set the current event number for parameter file lookup
101 
102  /// Clear options to pick up run number specific config files
103  gQwOptions.Parse(true);
104 
105  /// Create an EPICS event
106  QwEPICSEvent epics;
107  epics.LoadChannelMap("EpicsTable.map");
108 
109 
110  /// Load the tracking detectors from file
111  QwSubsystemArrayTracking tracking_detectors(gQwOptions);
112  tracking_detectors.ProcessOptions(gQwOptions);
113  /// Get detector geometry
114  QwGeometry geometry = tracking_detectors.GetGeometry();
115  QwVerbose << geometry << QwLog::endl;
116 
117  /// Load the parity detectors from file
118  QwSubsystemArrayParity parity_detectors(gQwOptions);
119  parity_detectors.ProcessOptions(gQwOptions);
120 
121  /// Create the tracking worker
122  QwTrackingWorker *trackingworker = new QwTrackingWorker(gQwOptions, geometry);
123 
124 
125  // Loop until first EPICS event if no magnetic field is set
126  bool current_from_epics = false;
127  if (fabs(trackingworker->GetMagneticFieldCurrent()) < 100.0) {
128 
129  QwMessage << "Finding first EPICS event" << QwLog::endl;
130  while (eventbuffer.GetNextEvent() == CODA_OK) {
131 
132  // First, do quick processing of non-physics events...
133  if (eventbuffer.IsEPICSEvent()) {
134  eventbuffer.FillEPICSData(epics);
135  if (epics.HasDataLoaded()) {
136 
137  // Get magnetic field current
138  Double_t current = epics.GetDataValue("qw:qt_mps_i_set");
139  if (current > 0.0) {
140  QwMessage << "Setting magnetic field current to "
141  << current << "A " << QwLog::endl;
142  trackingworker->SetMagneticFieldCurrent(current);
143  current_from_epics = true;
144  }
145  // and break out of this event loop
146  break;
147  }
148  }
149  }
150 
151  // Rewind stream
152  QwMessage << "Rewinding stream" << QwLog::endl;
153  eventbuffer.ReOpenStream();
154 
155  // Check whether we found the magnetic field
156  if (fabs(trackingworker->GetMagneticFieldCurrent()) < 100.0) {
157  QwError << "Error: no magnetic field specified and no EPICS events in range!"
158  << QwLog::endl;
159  }
160  }
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 
167  //
168  // Construct a Tree which contains map file names which are used to analyze data
169  //
170  rootfile->WriteParamFileList("mapfiles", tracking_detectors);
171 
172  // Create dummy event for branch creation (memory leak when using null)
173  QwEvent* event = new QwEvent();
174  event->LoadBeamProperty("beam_property.map");
175 
176  if (not enablemapfile) {
177  // Create the tracking object branches
178  rootfile->NewTree("event_tree", "QwTracking Event-based Tree");
179  rootfile->GetTree("event_tree")->Branch("events", "QwEvent", &event);
180 
181  // Create the subsystem branches
182  rootfile->ConstructTreeBranches("event_tree", "QwTracking Event-based Tree", tracking_detectors);
183  rootfile->ConstructTreeBranches("Mps_Tree", "QwParity Helicity-based Tree", parity_detectors);
184  rootfile->ConstructTreeBranches("Slow_Tree", "EPICS and slow control tree", epics);
185  // Construct indices to get from one tree to the other
186  rootfile->ConstructIndices("event_tree","Slow_Tree");
187  rootfile->ConstructIndices("event_tree","Mps_Tree");
188  }
189 
190  // Delete dummy event again
191  delete event; event = 0;
192 
193  // Create the subsystem histograms
194  rootfile->ConstructHistograms("tracking_histo", tracking_detectors);
195  rootfile->ConstructHistograms("parity_histo", parity_detectors);
196 
197  // Summarize the ROOT file structure
198  rootfile->PrintTrees();
199  rootfile->PrintDirs();
200 
201 
202  // Loop over events in this CODA file
203  Int_t nevents = 0;
204  while (eventbuffer.GetNextEvent() == CODA_OK) {
205 
206  // First, do processing of non-physics events...
207  if (eventbuffer.IsEPICSEvent()) {
208  eventbuffer.FillEPICSData(epics);
209  if (epics.HasDataLoaded()) {
210 
211  // Get magnetic field current
212  Double_t current = epics.GetDataValue("qw:qt_mps_i_set");
213  if (current_from_epics && current > 0.0) {
214  QwMessage << "Setting magnetic field current to "
215  << current << "A " << QwLog::endl;
216  trackingworker->SetMagneticFieldCurrent(current);
217  }
218 
219  epics.CalculateRunningValues();
220 
221  rootfile->FillTreeBranches(epics);
222  rootfile->FillTree("Slow_Tree");
223  }
224  }
225 
226  // Send ROC configuration event data to the subsystem objects.
227  if (eventbuffer.IsROCConfigurationEvent()) {
228  eventbuffer.FillSubsystemConfigurationData(tracking_detectors);
229  eventbuffer.FillSubsystemConfigurationData(parity_detectors);
230  }
231 
232  // Now, if this is not a physics event, go back and get a new event.
233  if (! eventbuffer.IsPhysicsEvent()) {
234  continue;
235  }
236 
237  // Fill the subsystem objects with their respective data for this event.
238  eventbuffer.FillSubsystemData(tracking_detectors);
239  eventbuffer.FillSubsystemData(parity_detectors);
240 
241  // Process the event
242  tracking_detectors.ProcessEvent();
243  parity_detectors.ProcessEvent();
244 
245  // Fill the tree
246  rootfile->FillTreeBranches(tracking_detectors);
247  rootfile->FillTreeBranches(parity_detectors);
248 
249  // Fill the histograms for the subsystem objects.
250  rootfile->FillHistograms(tracking_detectors);
251  rootfile->FillHistograms(parity_detectors);
252 
253 
254  /// Create a new event structure
255  event = new QwEvent();
256 
257  // Create the event header with the run and event number
258  QwEventHeader header(eventbuffer.GetRunNumber(),eventbuffer.GetEventNumber());
259  // Assign the event header to the event
260  event->SetEventHeader(header);
261 
262  // Create and fill hit list
263  QwHitContainer* hitlist = new QwHitContainer();
264  tracking_detectors.GetHitList(hitlist);
265 
266  // Sorting the hit list
267  hitlist->sort();
268 
269  // and fill into the event
270  event->AddHitContainer(hitlist);
271 
272  // Track reconstruction
273  trackingworker->ProcessEvent(&tracking_detectors, event);
274 
275 
276  // Fill the event tree
277  rootfile->FillTree("event_tree");
278  rootfile->FillTree("Mps_Tree");
279 
280  // Delete objects
281  if (hitlist) delete hitlist; hitlist = 0;
282  if (event) delete event; event = 0;
283 
284  nevents++;
285 
286  } // end of loop over events
287 
288  // Write F1TDC errors histograms into rootfile
289  // Print F1TDC errors summary into screen
290  // Must be executed before delete a rootfile.
291 
292  tracking_detectors.FillHardwareErrorSummary();
293 
294  // Print summary information
295  QwMessage << "Total number of events processed: " << nevents << QwLog::endl;
296  QwMessage << "Number of good partial tracks: "
297  << trackingworker->ngood << QwLog::endl;
298 
299  /* Write to the root file, being sure to delete the old cycles *
300  * which were written by Autosave. *
301  * Doing this will remove the multiple copies of the ntuples *
302  * from the root file. */
303  // if (rootfile != NULL) rootfile->Write(0, TObject::kOverwrite);
304 
305  // Write and close file (after last access to ROOT tree)
306  rootfile->Write(0, TObject::kOverwrite);
307 
308  // Close CODA file
309  eventbuffer.CloseStream();
310 
311  // Close ROOT file
312  rootfile->Close();
313  // Note: Closing rootfile too early causes segfaults when deleting histos
314 
315  // Delete objects (this is confusing: the if only applies to the delete)
316  if (rootfile) delete rootfile; rootfile = 0;
317 
318  // Print run summary information
319  eventbuffer.ReportRunSummary();
320  eventbuffer.PrintRunTimes();
321 
322  // Delete objects
323  if (trackingworker) delete trackingworker; trackingworker = 0;
324 
325  } // end of loop over runs
326 
327  QwMessage << "I have done everything I can do..." << QwLog::endl;
328 
329  return 0;
330 }
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
static void AppendToSearchPath(const TString &searchdir)
Add a directory to the search path.
Bool_t FillSubsystemConfigurationData(QwSubsystemArray &subsystems)
double GetMagneticFieldCurrent() const
Get the magnetic field current.
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
TTree * GetTree(const std::string &name)
Get the tree with name.
Definition: QwRootFile.h:353
Double_t GetDataValue(const string &tag) const
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.
Contains header information of a tracked event.
Definition: QwEvent.h:37
Load the options for the tracking subsystems.
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.
Controls all the routines involved in finding tracks in an event.
This is the main executable for the tracking analysis.
#define QwVerbose
Predefined log drain for verbose messages.
Definition: QwLog.h:55
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
void ProcessOptions(QwOptions &options)
Process configuration options (default behavior)
void ProcessEvent(const QwSubsystemArrayTracking *detectors, QwEvent *event)
Process the hit list and construct the event.
Int_t FillTree(const std::string &name)
Fill the tree with name.
Definition: QwRootFile.h:359
Int_t GetEventNumber()
void GetHitList(QwHitContainer &hitlist)
Int_t GetNextEvent()
T GetValue(const std::string &key)
Get a templated value.
Definition: QwOptions.h:240
Controls all the routines involved in finding tracks in an event.
Contains a tracked event, i.e. all information from hits to tracks.
Definition: QwEvent.h:156
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.
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
A logfile class, based on an identical class in the Hermes analyzer.
Int_t LoadChannelMap(TString mapfile)
Definition: QwEPICSEvent.cc:90
void Parse(bool force=false)
Parse all sources of options.
Definition: QwOptions.h:222
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 SetMagneticFieldCurrent(const double current)
Set the magnetic field current.
void NewTree(const std::string &name, const std::string &desc)
Create a new tree with name and description.
Definition: QwRootFile.h:341
Bool_t IsEPICSEvent()
QwHistogramHelper gQwHists
Globally defined instance of the QwHistogramHelper class.
Bool_t FillSubsystemData(QwSubsystemArray &subsystems)
void PrintRunTimes()
Bool_t HasDataLoaded() const
Definition: QwEPICSEvent.h:68
const QwGeometry GetGeometry()
Get the detector info for all detectors.
int ngood
number of good events
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
Collection of QwDetectorInfo pointers that specifies an experimental geometry.
Definition: QwGeometry.h:27
void FillHistograms(T &object)
Fill histograms of the subsystem array.
Definition: QwRootFile.h:329
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 DefineOptionsTracking(QwOptions &options)
void CalculateRunningValues()
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