Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 1008, column 4
Description:Potential leak of memory pointed to by 'c'

Annotated Source Code

1// $Id$
2// $HeadURL$
3//
4// File: JEventSource_EVIO.cc
5// Created: Tue Aug 7 15:22:29 EDT 2012
6// Creator: davidl (on Darwin harriet.jlab.org 11.4.0 i386)
7//
8
9// See comments in JEventSource_EVIO.h for overview description
10
11#include <unistd.h>
12#include <stdint.h>
13
14#include <string>
15#include <cmath>
16#include <iomanip>
17using namespace std;
18
19
20// This flag allows us to switch back and forth from using HDEVIO and
21// the CODA-supplied EVIO
22#define USE_HDEVIO1 1
23
24//#define ENABLE_UPSAMPLING
25
26#ifdef HAVE_EVIO1
27
28#if USE_HDEVIO1 == 0
29#include <evioFileChannel.hxx>
30#endif
31
32extern "C" uint32_t *swap_int32_t(uint32_t *data, unsigned int length, uint32_t *dest);
33#endif // HAVE_EVIO
34
35#ifdef HAVE_ET
36//#include <evioETChannel.hxx>
37#include <et.h>
38#endif // HAVE_ET
39
40#include "JEventSourceGenerator_EVIO.h"
41//#include "JFactoryGenerator_DAQ.h"
42#include "JEventSource_EVIO.h"
43using namespace jana;
44
45#include <DANA/DStatusBits.h>
46#include <TTAB/DTranslationTable.h>
47#include <TTAB/DTranslationTable_factory.h>
48
49#define _DBG_DAQ(A)cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<
49<<" 0x"<<hex<<A<<" cntrl:0x"<<
(A&0xF0000000)<<dec<<" slot:"<<((A>>
22)&0x1F)<<endl
cerr<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__49<<" 0x"<<hex<<A<<" cntrl:0x"<<(A&0xF0000000)<<dec<<" slot:"<<((A>>22)&0x1F)<<endl
50
51// Make us a plugin
52#include <JANA/JApplication.h>
53//extern "C"{
54// void InitPlugin(JApplication *app){
55// InitJANAPlugin(app);
56// app->AddEventSourceGenerator(new JEventSourceGenerator_EVIO());
57// app->AddFactoryGenerator(new JFactoryGenerator_DAQ());
58// }
59//} // "C"
60
61
62set<uint32_t> ROCIDS_TO_PARSE;
63
64// Naomi's CDC timing algortihm
65#include <fa125algo.h>
66
67//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
68// If EVIO support is not available, define dummy methods
69#ifndef HAVE_EVIO1
70JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name){
71 cerr << endl;
72 cerr << "You are trying to use code requiring EVIO when support" << endl;
73 cerr << "for EVIO was not built into this binary. Set your" << endl;
74 cerr << "EVIOROOT *and* your ETROOT environment variables to" << endl;
75 cerr << "point to your EVIO installation and recompile." << endl;
76 cerr << endl;
77 exit(-1);
78}
79 JEventSource_EVIO::~JEventSource_EVIO(){}
80jerror_t JEventSource_EVIO::GetEvent(jana::JEvent &event){return NOERROR;}
81 void JEventSource_EVIO::FreeEvent(jana::JEvent &event){}
82jerror_t JEventSource_EVIO::GetObjects(jana::JEvent &event, jana::JFactory_base *factory){return NOERROR;}
83jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buf){return NOERROR;}
84//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
85
86#else // HAVE_EVIO
87
88//----------------
89// Constructor
90//----------------
91JEventSource_EVIO::JEventSource_EVIO(const char* source_name):JEventSource(source_name)
92{
93 // Initialize connection objects and flags to NULL
94 et_connected = false;
95 //chan = NULL;
96 hdevio = NULL__null;
97 source_type = kNoSource;
98 quit_on_next_ET_timeout = false;
99
100 // Initialize dedicated JStreamLog used for debugging messages
101 evioout.SetTag("--- EVIO ---: ");
102 evioout.SetTimestampFlag();
103 evioout.SetThreadstampFlag();
104
105 // Define base set of status bits
106 if(japp) DStatusBits::SetStatusBitDescriptions(japp);
107
108 // Get configuration parameters
109 AUTODETECT_MODULE_TYPES = true;
110 DUMP_MODULE_MAP = false;
111 MAKE_DOM_TREE = true;
112 PARSE_EVIO_EVENTS = true;
113 PARSE_F250 = true;
114 PARSE_F125 = true;
115 PARSE_F1TDC = true;
116 PARSE_CAEN1290TDC = true;
117 PARSE_CONFIG = true;
118 PARSE_BOR = true;
119 PARSE_EPICS = true;
120 PARSE_EVENTTAG = true;
121 PARSE_TRIGGER = true;
122 BUFFER_SIZE = 20000000; // in bytes
123 ET_STATION_NEVENTS = 10;
124 ET_STATION_CREATE_BLOCKING = false;
125 ET_DEBUG_WORDS_TO_DUMP = 0;
126 LOOP_FOREVER = false;
127 VERBOSE = 0;
128 TIMEOUT = 2.0;
129 MODTYPE_MAP_FILENAME = "modtype.map";
130 ENABLE_DISENTANGLING = true;
131
132 F250_PI_EMULATION_MODE = kEmulationAuto;
133 F250_PT_EMULATION_MODE = kEmulationAuto;
134 F250_PP_EMULATION_MODE = kEmulationAuto;
135 F250_EMULATION_MIN_SWING = 20; // Formerly F250_EMULATION_THRESHOLD
136 F250_THRESHOLD = 120;
137 F250_SPARSIFICATION_THRESHOLD = 0; // =0 is equivalent to no threshold
138 F250_NSA = 50;
139 F250_NSB = 5;
140 F250_NSPED = 4;
141
142 F125_PI_EMULATION_MODE = kEmulationAuto;
143 F125_PT_EMULATION_MODE = kEmulationAuto;
144 F125_PP_EMULATION_MODE = kEmulationAuto;
145 F125_EMULATION_MIN_SWING = 20; // Formerly F125_EMULATION_THRESHOLD
146 F125_THRESHOLD = 80;
147 F125_SPARSIFICATION_THRESHOLD = 0;
148 F125_NSA = 40;
149 F125_NSB = 3;
150 F125_NSA_CDC = 80;
151 F125_NSB_CDC = 5;
152 F125_NSPED = 16;
153 F125_TIME_UPSAMPLE = true;
154
155 F125_CDC_WS = 46; // hit window start - must be >= F125_CDC_NP
156 F125_CDC_WE = 150; // hit window end - must be at least 20 less than number of samples available
157 F125_CDC_IE = 200; // end integration at the earlier of WE, or this many samples after threshold crossing of TH
158 F125_CDC_NP = 16; // # samples used for pedestal used to find hit. 2**integer
159 F125_CDC_NP2 = 16; // # samples used for pedestal calculated just before hit. 2**integer
160 F125_CDC_PG = 4; // # samples between hit threshold crossing and local pedestal sample
161 F125_CDC_H = 125; // 5 sigma hit threshold
162 F125_CDC_TH = 100; // 4 sigma high timing threshold
163 F125_CDC_TL = 25; // 1 sigma low timing threshold
164
165 F125_FDC_WS = 30; // hit window start - must be >= F125_FDC_NP
166 F125_FDC_WE = 52; // hit window end - must be at least 20 less than number of samples available
167 F125_FDC_IE = 10; // end integration at the earlier of WE, or this many samples after threshold crossing of TH
168 F125_FDC_NP = 16; // # samples used for pedestal used to find hit. 2**integer
169 F125_FDC_NP2 = 16; // # samples used for pedestal calculated just before hit. 2**integer
170 F125_FDC_PG = 4; // # samples between hit threshold crossing and local pedestal sample
171 F125_FDC_H = 125; // 5 sigma hit threshold
172 F125_FDC_TH = 100; // 4 sigma high timing threshold
173 F125_FDC_TL = 25; // 1 sigma low timing threshold
174
175 USER_RUN_NUMBER = 0;
176 F125PULSE_NUMBER_FILTER = 1000;
177 F250PULSE_NUMBER_FILTER = 1000;
178
179 if(gPARMS){
180 // JANA doesn't know about EmulationModeType so we use temporary variables
181 uint32_t f250_pi_emulation_mode = F250_PI_EMULATION_MODE;
182 uint32_t f250_pt_emulation_mode = F250_PT_EMULATION_MODE;
183 uint32_t f250_pp_emulation_mode = F250_PP_EMULATION_MODE;
184 uint32_t f125_pi_emulation_mode = F125_PI_EMULATION_MODE;
185 uint32_t f125_pt_emulation_mode = F125_PT_EMULATION_MODE;
186 uint32_t f125_pp_emulation_mode = F125_PP_EMULATION_MODE;
187
188 gPARMS->SetDefaultParameter("EVIO:AUTODETECT_MODULE_TYPES", AUTODETECT_MODULE_TYPES, "Try and guess the module type tag,num values for which there is no module map entry.");
189 gPARMS->SetDefaultParameter("EVIO:DUMP_MODULE_MAP", DUMP_MODULE_MAP, "Write module map used to file when source is destroyed. n.b. If more than one input file is used, the map file will be overwritten!");
190 gPARMS->SetDefaultParameter("EVIO:MAKE_DOM_TREE", MAKE_DOM_TREE, "Set this to 0 to disable generation of EVIO DOM Tree and parsing of event. (for benchmarking/debugging)");
191 gPARMS->SetDefaultParameter("EVIO:PARSE_EVIO_EVENTS", PARSE_EVIO_EVENTS, "Set this to 0 to disable parsing of event but still make the DOM tree, so long as MAKE_DOM_TREE isn't set to 0. (for benchmarking/debugging)");
192 gPARMS->SetDefaultParameter("EVIO:PARSE_F250", PARSE_F250, "Set this to 0 to disable parsing of data from F250 ADC modules (for benchmarking/debugging)");
193 gPARMS->SetDefaultParameter("EVIO:PARSE_F125", PARSE_F125, "Set this to 0 to disable parsing of data from F125 ADC modules (for benchmarking/debugging)");
194 gPARMS->SetDefaultParameter("EVIO:PARSE_F1TDC", PARSE_F1TDC, "Set this to 0 to disable parsing of data from F1TDC modules (for benchmarking/debugging)");
195 gPARMS->SetDefaultParameter("EVIO:PARSE_CAEN1290TDC", PARSE_CAEN1290TDC, "Set this to 0 to disable parsing of data from CAEN 1290 TDC modules (for benchmarking/debugging)");
196 gPARMS->SetDefaultParameter("EVIO:PARSE_CONFIG", PARSE_CONFIG, "Set this to 0 to disable parsing of ROC configuration data in the data stream (for benchmarking/debugging)");
197 gPARMS->SetDefaultParameter("EVIO:PARSE_BOR", PARSE_BOR, "Set this to 0 to disable parsing of BOR events from the data stream (for benchmarking/debugging)");
198 gPARMS->SetDefaultParameter("EVIO:PARSE_EPICS", PARSE_EPICS, "Set this to 0 to disable parsing of EPICS events from the data stream (for benchmarking/debugging)");
199 gPARMS->SetDefaultParameter("EVIO:PARSE_EVENTTAG", PARSE_EVENTTAG, "Set this to 0 to disable parsing of event tag data in the data stream (for benchmarking/debugging)");
200 gPARMS->SetDefaultParameter("EVIO:PARSE_TRIGGER", PARSE_TRIGGER, "Set this to 0 to disable parsing of the built trigger bank from CODA (for benchmarking/debugging)");
201
202 gPARMS->SetDefaultParameter("EVIO:BUFFER_SIZE", BUFFER_SIZE, "Size in bytes to allocate for holding a single EVIO event.");
203 gPARMS->SetDefaultParameter("EVIO:ET_STATION_NEVENTS", ET_STATION_NEVENTS, "Number of events to use if we have to create the ET station. Ignored if station already exists.");
204 gPARMS->SetDefaultParameter("EVIO:ET_STATION_CREATE_BLOCKING", ET_STATION_CREATE_BLOCKING, "Set this to 0 to create station in non-blocking mode (default is to create it in blocking mode). Ignored if station already exists.");
205 gPARMS->SetDefaultParameter("EVIO:ET_DEBUG_WORDS_TO_DUMP", ET_DEBUG_WORDS_TO_DUMP, "Number of words to dump to screen from ET buffer (useful for debugging only).");
206 gPARMS->SetDefaultParameter("EVIO:LOOP_FOREVER", LOOP_FOREVER, "If reading from EVIO file, keep re-opening file and re-reading events forever (only useful for debugging) If reading from ET, this is ignored.");
207 gPARMS->SetDefaultParameter("EVIO:VERBOSE", VERBOSE, "Set verbosity level for processing and debugging statements while parsing. 0=no debugging messages. 10=all messages");
208 gPARMS->SetDefaultParameter("ET:TIMEOUT", TIMEOUT, "Set the timeout in seconds for each attempt at reading from ET system (repeated attempts will still be made indefinitely until program quits or the quit_on_et_timeout flag is set.");
209 gPARMS->SetDefaultParameter("EVIO:MODTYPE_MAP_FILENAME", MODTYPE_MAP_FILENAME, "Optional module type conversion map for use with files generated with the non-standard module types");
210 gPARMS->SetDefaultParameter("EVIO:ENABLE_DISENTANGLING", ENABLE_DISENTANGLING, "Enable/disable disentangling of multi-block events. Enabled by default. Set to 0 to disable.");
211
212 gPARMS->SetDefaultParameter("EVIO:F250_PI_EMULATION_MODE", f250_pi_emulation_mode, "Set f250 pulse integral emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
213 gPARMS->SetDefaultParameter("EVIO:F250_PT_EMULATION_MODE", f250_pt_emulation_mode, "Set f250 pulse time emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
214 gPARMS->SetDefaultParameter("EVIO:F250_PP_EMULATION_MODE", f250_pp_emulation_mode, "Set f250 pulse pedestal emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
215 gPARMS->SetDefaultParameter("EVIO:F250_EMULATION_MIN_SWING", F250_EMULATION_MIN_SWING, "Minimum difference between min and max sample required for emulation of f250.");
216 gPARMS->SetDefaultParameter("EVIO:F250_THRESHOLD", F250_THRESHOLD, "Identified pulse threshold used during emulation of f250.");
217 gPARMS->SetDefaultParameter("EVIO:F250_SPARSIFICATION_THRESHOLD", F250_SPARSIFICATION_THRESHOLD, "Sparsification threshold used during emulation of f250.");
218 gPARMS->SetDefaultParameter("EVIO:F250_NSA", F250_NSA, "For f250PulseIntegral object. NSA value for emulation from window raw data and for pulse integral pedestal normalization.");
219 gPARMS->SetDefaultParameter("EVIO:F250_NSB", F250_NSB, "For f250PulseIntegral object. NSB value for emulation from window raw data and for pulse integral pedestal normalization.");
220 gPARMS->SetDefaultParameter("EVIO:F250_NSPED", F250_NSPED, "For f250PulseIntegral object. Number of pedestal samples value for emulation from window raw data and for pulse integral normalization.");
221
222 gPARMS->SetDefaultParameter("EVIO:F125_PI_EMULATION_MODE", f125_pi_emulation_mode, "Set f125 pulse integral emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
223 gPARMS->SetDefaultParameter("EVIO:F125_PT_EMULATION_MODE", f125_pt_emulation_mode, "Set f125 pulse time emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
224 gPARMS->SetDefaultParameter("EVIO:F125_PP_EMULATION_MODE", f125_pp_emulation_mode, "Set f125 pulse pedestal emulation mode. 0=no emulation, 1=always, 2=auto. Default is 2 (auto).");
225 gPARMS->SetDefaultParameter("EVIO:F125_EMULATION_MIN_SWING", F125_EMULATION_MIN_SWING, "Minimum difference between min and max sample required for emulation of f125.");
226 gPARMS->SetDefaultParameter("EVIO:F125_THRESHOLD", F125_THRESHOLD, "Identified pulse threshold used during emulation of f125.");
227 gPARMS->SetDefaultParameter("EVIO:F125_SPARSIFICATION_THRESHOLD", F125_SPARSIFICATION_THRESHOLD, "Sparsification threshold used during emulation of f125.");
228 gPARMS->SetDefaultParameter("EVIO:F125_NSA", F125_NSA, "For f125PulseIntegral object. NSA value for emulation from window raw data and for pulse integral pedestal normalization.");
229 gPARMS->SetDefaultParameter("EVIO:F125_NSB", F125_NSB, "For f125PulseIntegral object. NSB value for emulation from window raw data and for pulse integral pedestal normalization.");
230 gPARMS->SetDefaultParameter("EVIO:F125_NSA_CDC", F125_NSA_CDC, "For f125PulseIntegral object. NSA value for emulation from window raw data and for pulse integral pedestal normalization. This is applied to rocid 24-28 only!");
231 gPARMS->SetDefaultParameter("EVIO:F125_NSB_CDC", F125_NSB_CDC, "For f125PulseIntegral object. NSB value for emulation from window raw data and for pulse integral pedestal normalization. This is applied to rocid 24-28 only!");
232 gPARMS->SetDefaultParameter("EVIO:F125_NSPED", F125_NSPED, "For f125PulseIntegral object. Number of pedestal samples value for emulation from window raw data and for pulse integral normalization.");
233 gPARMS->SetDefaultParameter("EVIO:F125_TIME_UPSAMPLE", F125_TIME_UPSAMPLE, "If true, then use the CMU upsampling algorithm to determine times for the DF125PulseTime objects when using emulaton. Set to zero to use the f250 algorithm that was in f125 firmware for 2014 commissioning data.");
234
235 gPARMS->SetDefaultParameter("EVIO:RUN_NUMBER", USER_RUN_NUMBER, "User-supplied run number. Override run number from other sources with this.(will be ignored if set to zero)");
236 gPARMS->SetDefaultParameter("EVIO:F125PULSE_NUMBER_FILTER", F125PULSE_NUMBER_FILTER, "Ignore data for DF125XXX objects with a pulse number equal or greater than this.");
237 gPARMS->SetDefaultParameter("EVIO:F250PULSE_NUMBER_FILTER", F250PULSE_NUMBER_FILTER, "Ignore data for DF250XXX objects with a pulse number equal or greater than this.");
238
239
240 gPARMS->SetDefaultParameter("EVIO:F125_CDC_WS", F125_CDC_WS, "FA125 emulation: CDC hit window start.");
241 gPARMS->SetDefaultParameter("EVIO:F125_CDC_WE", F125_CDC_WE, "FA125 emulation: CDC hit window end.");
242 gPARMS->SetDefaultParameter("EVIO:F125_CDC_IE", F125_CDC_IE, "FA125 emulation: CDC number of integrated samples, unless WE is reached.");
243 gPARMS->SetDefaultParameter("EVIO:F125_CDC_NP", F125_CDC_NP, "FA125 emulation: CDC number of samples in initial pedestal window.");
244 gPARMS->SetDefaultParameter("EVIO:F125_CDC_NP2", F125_CDC_NP2, "FA125 emulation: CDC number of samples in local pedestal window.");
245 gPARMS->SetDefaultParameter("EVIO:F125_CDC_PG", F125_CDC_PG, "FA125 emulation: CDC gap between pedestal and hit threshold crossing.");
246 gPARMS->SetDefaultParameter("EVIO:F125_CDC_H", F125_CDC_H, "FA125 emulation: CDC hit threshold.");
247 gPARMS->SetDefaultParameter("EVIO:F125_CDC_TH", F125_CDC_TH, "FA125 emulation: CDC high timing threshold.");
248 gPARMS->SetDefaultParameter("EVIO:F125_CDC_TL", F125_CDC_TL, "FA125 emulation: CDC low timing threshold.");
249
250 gPARMS->SetDefaultParameter("EVIO:F125_FDC_WS", F125_FDC_WS, "FA125 emulation: FDC hit window start.");
251 gPARMS->SetDefaultParameter("EVIO:F125_FDC_WE", F125_FDC_WE, "FA125 emulation: FDC hit window end.");
252 gPARMS->SetDefaultParameter("EVIO:F125_FDC_IE", F125_FDC_IE, "FA125 emulation: FDC number of integrated samples, unless WE is reached.");
253 gPARMS->SetDefaultParameter("EVIO:F125_FDC_NP", F125_FDC_NP, "FA125 emulation: FDC number of samples in initial pedestal window.");
254 gPARMS->SetDefaultParameter("EVIO:F125_FDC_NP2", F125_FDC_NP2, "FA125 emulation: FDC number of samples in local pedestal window.");
255 gPARMS->SetDefaultParameter("EVIO:F125_FDC_PG", F125_FDC_PG, "FA125 emulation: FDC gap between pedestal and hit threshold crossing.");
256 gPARMS->SetDefaultParameter("EVIO:F125_FDC_H", F125_FDC_H, "FA125 emulation: FDC hit threshold.");
257 gPARMS->SetDefaultParameter("EVIO:F125_FDC_TH", F125_FDC_TH, "FA125 emulation: FDC high timing threshold.");
258 gPARMS->SetDefaultParameter("EVIO:F125_FDC_TL", F125_FDC_TL, "FA125 emulation: FDC low timing threshold.");
259
260
261 F250_PI_EMULATION_MODE = (EmulationModeType)f250_pi_emulation_mode;
262 F250_PT_EMULATION_MODE = (EmulationModeType)f250_pt_emulation_mode;
263 F250_PP_EMULATION_MODE = (EmulationModeType)f250_pp_emulation_mode;
264 F125_PI_EMULATION_MODE = (EmulationModeType)f125_pi_emulation_mode;
265 F125_PT_EMULATION_MODE = (EmulationModeType)f125_pt_emulation_mode;
266 F125_PP_EMULATION_MODE = (EmulationModeType)f125_pp_emulation_mode;
267 }
268
269 // Try to open the file.
270 try {
271
272 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as EVIO file..." <<endl;
273
274#if USE_HDEVIO1
275 //---------- HDEVIO ------------
276 hdevio = new HDEVIO(this->source_name);
277 if( ! hdevio->is_open ) throw std::exception(); // throw exception if unable to open
278#else // USE_HDEVIO
279 //-------- CODA EVIO -----------
280 jerr << "You are attempting to use the CODA Channels library for reading" << endl;
281 jerr << "and EVIO file and this mechanism has been disabled from in the" << endl;
282 jerr << "DAQ library. Contact davidl@jlab.org if you need this to be" << endl;
283 jerr << "reinstated." << endl;
284 quit(0);
285 //chan = new evioFileChannel(this->source_name, "r", BUFFER_SIZE);
286 //chan->open(); // open the file. Throws exception if not successful
287
288#endif // USE_HDEVIO
289
290 source_type = kFileSource;
291
292 } catch (std::exception &e) {
293
294#ifdef HAVE_ET
295 // Could not open file. Check if name starts with "ET:"
296 //chan = NULL;
297 if(this->source_name.substr(0,3) == "ET:"){
298 if(VERBOSE>0) evioout << "Attempting to open \""<<this->source_name<<"\" as ET (network) source..." <<endl;
299 ConnectToET(source_name);
300 }
301
302 if(!et_connected) throw JException("Failed to open ET system: " + this->source_name);
303
304 // open the channel. Throws exception if not successful
305 // chan->open(); // evioETchannel no longer used
306 source_type = kETSource;
307
308#else // HAVE_ET
309
310 // No ET and the file didn't work so re-throw the exception
311 if(this->source_name.substr(0,3) == "ET:"){
312 cerr << endl;
313 cerr << "=== ERROR: ET source specified and this was compiled without ===" << endl;
314 cerr << "=== ET support. You need to install ET and set your ===" << endl;
315 cerr << "=== ETROOT environment variable appropriately before ===" << endl;
316 cerr << "=== recompiling. ===" << endl;
317 cerr << endl;
318 }
319 throw e;
320
321#endif // HAVE_ET
322 }
323 if(VERBOSE>0) evioout << "Success opening event source \"" << this->source_name << "\"!" <<endl;
324
325
326 // Create list of data types this event source can provide
327 // (must match what is returned by JObject::className() )
328 // n.b. there is an ugly hack down in GetObjects that will
329 // probably also need a line added for each data type added
330 // here.
331 event_source_data_types.insert("Df250Config");
332 event_source_data_types.insert("Df250PulseIntegral");
333 event_source_data_types.insert("Df250StreamingRawData");
334 event_source_data_types.insert("Df250WindowSum");
335 event_source_data_types.insert("Df250PulseRawData");
336 event_source_data_types.insert("Df250TriggerTime");
337 event_source_data_types.insert("Df250PulseTime");
338 event_source_data_types.insert("Df250PulsePedestal");
339 event_source_data_types.insert("Df250WindowRawData");
340 event_source_data_types.insert("Df125Config");
341 event_source_data_types.insert("Df125PulseIntegral");
342 event_source_data_types.insert("Df125TriggerTime");
343 event_source_data_types.insert("Df125PulseTime");
344 event_source_data_types.insert("Df125PulsePedestal");
345 event_source_data_types.insert("Df125WindowRawData");
346 event_source_data_types.insert("Df125CDCPulse");
347 event_source_data_types.insert("Df125FDCPulse");
348 event_source_data_types.insert("DF1TDCConfig");
349 event_source_data_types.insert("DF1TDCHit");
350 event_source_data_types.insert("DF1TDCTriggerTime");
351 event_source_data_types.insert("DCAEN1290TDCConfig");
352 event_source_data_types.insert("DCAEN1290TDCHit");
353 event_source_data_types.insert("DCODAEventInfo");
354 event_source_data_types.insert("DCODAROCInfo");
355 event_source_data_types.insert("DEPICSvalue");
356 event_source_data_types.insert("DEventTag");
357
358 // Read in optional module type translation map if it exists
359 ReadOptionalModuleTypeTranslation();
360
361 last_run_number = 0;
362 filename_run_number = 0;
363 current_event_count = 0;
364
365 // Try extracting the run number from the filename. (This is
366 // only used if the run number is not found in the EVIO data.)
367 size_t pos2 = this->source_name.find_last_of('_');
368 if(pos2 != string::npos){
369 size_t pos1 = this->source_name.find_last_of('_', pos2-1);
370 if(pos1 != string::npos){
371 pos1++;
372 string runstr = this->source_name.substr(pos1, pos2-pos1);
373 if(runstr.length()>0) filename_run_number = atoi(runstr.c_str());
374 }
375 }
376
377 pthread_mutex_init(&evio_buffer_pool_mutex, NULL__null);
378 pthread_mutex_init(&stored_events_mutex, NULL__null);
379 pthread_mutex_init(&current_event_count_mutex, NULL__null);
380 pthread_rwlock_init(&BOR_lock, NULL__null);
381}
382
383//----------------
384// Destructor
385//----------------
386JEventSource_EVIO::~JEventSource_EVIO()
387{
388 // close event source here
389// if(chan){
390// if(VERBOSE>0) evioout << "Closing event source \"" << this->source_name << "\"" <<endl;
391// chan->close();
392// delete chan;
393// }
394
395#ifdef HAVE_ET
396 if(et_connected){
397 if(VERBOSE>0) evioout << "Closing ET connection \"" << this->source_name << "\"" <<endl;
398 et_close(sys_id);
399 et_connected = false;
400 }
401#endif
402
403 if(hdevio){
404 if(VERBOSE>0) evioout << "Closing hdevio event source \"" << this->source_name << "\"" <<endl;
405 hdevio->PrintStats();
406 delete hdevio;
407 }
408
409 // Release memory used for the event buffer pool
410 while(!evio_buffer_pool.empty()){
411 free(evio_buffer_pool.front());
412 evio_buffer_pool.pop_front();
413 }
414
415 // Delete any BOR config objects
416 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
417 BORobjs.clear();
418
419 // Optionally dump the module map
420 if(DUMP_MODULE_MAP)DumpModuleMap();
421}
422
423//---------------------------------
424// ReadOptionalModuleTypeTranslation
425//---------------------------------
426void JEventSource_EVIO::ReadOptionalModuleTypeTranslation(void)
427{
428 // Some data may be taken with bad ROLs or drivers that
429 // write module type values that are non-standard. This
430 // allows the user to specify a simple text file that
431 // can be read in to translate the types found in the
432 // file to another type so that they can be properly parsed.
433 ifstream ifs(MODTYPE_MAP_FILENAME.c_str());
434 if(!ifs.is_open()) return;
435
436 cout << "Opened JLab module type translation map: " << endl;
437 cout << " " << MODTYPE_MAP_FILENAME << endl;
438 while(ifs.good()){
439 char line[256];
440 ifs.getline(line, 256);
441 if(ifs.gcount() < 1) break;
442 if(line[0] == '#') continue;
443
444 stringstream ss(line);
445 uint32_t from=10000, to=10000;
446 ss >> from >> to; // from=evio to=TT
447 if( to==10000 ){
448 if( from!=10000){
449 cout << "unable to convert line:" << endl;
450 cout << " " << line;
451 }
452 }else{
453 modtype_translate[(MODULE_TYPE)from] = (MODULE_TYPE)to;
454 }
455 }
456 ifs.close();
457
458 cout << " Read " << modtype_translate.size() << " entries" << endl;
459 map<MODULE_TYPE,MODULE_TYPE>::iterator iter;
460 for(iter=modtype_translate.begin(); iter != modtype_translate.end(); iter++){
461 cout << " type " << iter->first << " -> type " << iter->second << endl;
462 }
463}
464
465//----------------
466// ConnectToET
467//----------------
468void JEventSource_EVIO::ConnectToET(const char* source_name)
469{
470#ifdef HAVE_ET
471
472 /// Format for ET source strings is:
473 ///
474 /// ET:session:station:host:port
475 ///
476 /// The session is used to form the filename of the ET
477 /// system. For example, if an session of "eb" is specified,
478 /// then a file named "/tmp/et_sys_eb" is assumed to be
479 /// what should be opened. If no session is specified (or
480 /// an empty session name) then "none" is used as the session.
481 ///
482 /// If the station name specified does not exist, it will
483 /// be created. If it does exist, the existing station will
484 /// be used. If no station is specified, then the station
485 /// name "DANA" will be used. Any station created will be
486 /// set to "blocking" *unless* the configuration paramter
487 /// EVIO:ET_STATION_CREATE_BLOCKING is set to "0"
488 /// in which case it will be set to non-blocking.
489 ///
490 /// If the host is specified, then an attempt will be made
491 /// to open that system. If it is not specified, then
492 /// it will attempt to open an ET system on the local machine.
493 ///
494 /// If port is specified, it is used as the TCP port number
495 /// on the remote host to attach to. If the host is not
496 /// specified (i.e. by having two colons and therefore
497 /// an empty string) then the port is ignored. If the
498 /// port is omitted or specified as "0", then the default
499 /// port is used.
500 ///
501
502 // Split source name into session, station, etc...
503 vector<string> fields;
504 string str = source_name;
505 size_t startpos=0, endpos=0;
506 while((endpos = str.find(":", startpos)) != str.npos){
507 size_t len = endpos-startpos;
508 fields.push_back(len==0 ? "":str.substr(startpos, len));
509 startpos = endpos+1;
510 }
511 if(startpos<str.length()) fields.push_back(str.substr(startpos, str.npos));
512
513 string session = fields.size()>1 ? fields[1]:"";
514 string station = fields.size()>2 ? fields[2]:"";
515 string host = fields.size()>3 ? fields[3]:"localhost";
516 int port = fields.size()>4 ? atoi(fields[4].c_str()):ET_SERVER_PORT;
517
518 if(session == "") session = "none";
519 if(station == "") station = "DANA";
520 if(host == "") host = "localhost";
521 string fname = session.at(0)=='/' ? session:(string("/tmp/et_sys_") + session);
522
523 // Report to user what we're doing
524 jout << " Opening ET system:" << endl;
525 if(session!=fname) jout << " session: " << session << endl;
526 jout << " station: " << station << endl;
527 jout << " system file: " << fname << endl;
528 jout << " host: " << host << endl;
529 if(port !=0) jout << " port: " << port << endl;
530
531 // connect to the ET system
532 et_openconfig openconfig;
533 et_open_config_init(&openconfig);
534 if(host != ""){
535 if(host.find("239.")==0){
536 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__536<<" Configuring input ET for multicast" << endl;
537 et_open_config_setcast(openconfig, ET_MULTICAST);
538 et_open_config_addmulticast(openconfig, host.c_str());
539 et_open_config_sethost(openconfig, ET_HOST_ANYWHERE);
540 et_open_config_setport(openconfig, port);
541 struct timespec tspec={5,5};
542 et_open_config_settimeout(openconfig, tspec);
543 et_open_config_setwait(openconfig, ET_OPEN_WAIT);
544 }else{
545 cout<<__FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__545<<" Configuring input ET for direct connection" << endl;
546 et_open_config_setcast(openconfig, ET_DIRECT);
547 et_open_config_setmode(openconfig, ET_HOST_AS_LOCAL); // ET_HOST_AS_LOCAL or ET_HOST_AS_REMOTE
548 et_open_config_sethost(openconfig, host.c_str());
549 et_open_config_setport(openconfig, ET_BROADCAST_PORT);
550 if(port != 0)et_open_config_setserverport(openconfig, port);
551 }
552 }
553 int err = et_open(&sys_id,fname.c_str(),openconfig);
554 if(err != ET_OK){
555 cerr << __FILE__"libraries/DAQ/JEventSource_EVIO.cc"<<":"<<__LINE__555<<" Problem opening ET system"<<endl;
556 cerr << et_perror(err);
557 return;
558 }
559
560 // create station config in case no station exists
561 et_statconfig et_station_config;
562 et_station_config_init(&et_station_config);
563 et_station_config_setblock(et_station_config, ET_STATION_CREATE_BLOCKING ? ET_STATION_BLOCKING:ET_STATION_NONBLOCKING);
564 et_station_config_setselect(et_station_config,ET_STATION_SELECT_ALL);
565 et_station_config_setuser(et_station_config,ET_STATION_USER_MULTI);
566 et_station_config_setrestore(et_station_config,ET_STATION_RESTORE_OUT);
567 et_station_config_setcue(et_station_config,ET_STATION_NEVENTS);
568 et_station_config_setprescale(et_station_config,1);
569 cout<<"ET station configured\n";
570
571 // create station if not already created
572 int status=et_station_create(sys_id,&sta_id,station.c_str(),et_station_config);
573 if((status!=ET_OK)&&(status!=ET_ERROR_EXISTS)) {
574 et_close(sys_id);
575 cerr << "Unable to create station " << station << endl;
576 cerr << et_perror(status);
577
578 // Check that the number of events in the ET system is not
579 // less than the number of events we specified for the station CUE.
580 int Nevents = 0;
581 et_system_getnumevents(sys_id, &Nevents);
582 if(Nevents <= ET_STATION_NEVENTS){
583 jerr << "NOTE: The number of events specified for the station cue is equal to" << endl;
584 jerr << "or greater than the number of events in the entire ET system:" << endl;
585 jerr << endl;
586 jerr << " " << ET_STATION_NEVENTS << " >= " << Nevents << endl;
587 jerr << endl;
588 jerr << "Try re-running with: " << endl;
589 jerr << endl;
590 jerr << " -PEVIO:ET_STATION_NEVENTS=" << (Nevents+1)/2 << endl;
591 jerr << endl;
592 }
593 return;
594 }
595 if(status==ET_ERROR_EXISTS){
596 jout << " Using existing ET station " << station << endl;
597 }else{
598 jout << " ET station " << station << " created\n";
599 }
600
601 // Attach to the ET station
602 status=et_station_attach(sys_id,sta_id,&att_id);
603 if(status!=ET_OK) {
604 et_close(sys_id);
605 jerr << "Unable to attach to station " << station << endl;
606 return;
607 }
608
609 jout << "...now connected to ET system: " << fname
610 << ", station: " << station << " (station id=" << sta_id << ", attach id=" << att_id <<")" << endl;
611
612 et_connected = true;
613 // chan = new evioETChannel(sys_id, att_id);
614
615 // Make sure the size of event buffers we will allocate are at least as big
616 // as the event size used in the ET system
617 size_t eventsize;
618 et_system_geteventsize(sys_id, &eventsize);
619 if((uint32_t)eventsize > BUFFER_SIZE){
620 jout<<" Events in ET system are larger than currently set buffer size:"<<endl;
621 jout<<" "<<eventsize<<" > "<<BUFFER_SIZE<<endl;
622 jout<<" Setting BUFFER_SIZE to "<<eventsize<<endl;
623 BUFFER_SIZE = (uint32_t)eventsize;
624 }else{
625 jout<<" ET system event size:"<<eventsize<<" JEventSource_EVIO.BUFFER_SIZE:"<<BUFFER_SIZE<<endl;
626 }
627
628#else
629 jerr << endl;
630 jerr << "You are attempting to connect to an ET system using a binary that" <<endl;
631 jerr << "was compiled without ET support. Please reconfigure and recompile" <<endl;
632 jerr << "To get ET support." << endl;
633 jerr << endl;
634 throw exception();
635#endif // HAVE_ET
636}
637
638//----------------
639// Cleanup
640//----------------
641void JEventSource_EVIO::Cleanup(void)
642{
643 /// This is called internally by the JEventSource_EVIO class
644 /// once all events have been read in. Its purpose is to
645 /// free the hidden memory in all of the container class
646 /// members of the JEventSource_EVIO class. This is needed
647 /// for jobs that process a lot of input files and therefore
648 /// create a lot JEventSource_EVIO objects. JANA does not delete
649 /// these objects until the end of the job so this tends to
650 /// act like a memory leak. The data used can be substantial
651 /// (nearly 1GB per JEventSource_EVIO object).
652 if(hdevio) delete hdevio;
653 hdevio = NULL__null;
654 //if(chan) delete chan;
655 //chan = NULL;
656#ifdef HAVE_ET
657 if(et_connected) et_close(sys_id);
658 et_connected = false;
659#endif // HAVE_ET
660
661 module_type.clear();
662 modtype_translate.clear();
663
664 for(uint32_t i=0; i<hit_objs.size(); i++) hit_objs[i].resize(0);
665 hit_objs.resize(0);
666
667 while(!stored_events.empty()){
668 delete stored_events.front();
669 stored_events.pop();
670 }
671 while(!evio_buffer_pool.empty()) {
672 delete evio_buffer_pool.back();
673 evio_buffer_pool.pop_back();
674 }
675 while(!event_source_data_types.empty()){
676 event_source_data_types.erase(event_source_data_types.begin());
677 }
678}
679
680//----------------
681// GetEvent
682//----------------
683jerror_t JEventSource_EVIO::GetEvent(JEvent &event)
684{
685 if(VERBOSE>1) evioout << "GetEvent called for &event = " << hex << &event << dec << endl;
686
687 // If we couldn't even open the source, then there's nothing to do
688 bool no_source = true;
689#if USE_HDEVIO1
690 if(source_type==kFileSource && hdevio->is_open) no_source = false;
691#endif
692 if(source_type==kETSource && et_connected) no_source = false;
693 if(no_source)throw JException(string("Unable to open EVIO channel for \"") + source_name + "\"");
694
695
696 // This may not be a long term solution, but here goes:
697 // We need to write single events out in EVIO format, possibly
698 // with new information attached. The easiest way to do this
699 // is to keep the DOM tree when the event is read in and modify
700 // it if needed before writing it out. The complication comes
701 // in that entangled events will not have a dedicated DOM tree
702 // for every event. This is only an issue if disentangling is
703 // not done upstream. How this is handled now is that the DOM
704 // tree pointer is copied into the ObjList object for the first
705 // physics event found in the DAQ event. The DOM tree is freed
706 // in FreeEvent (if the pointer is non-NULL). Note that for
707 // single event blocks (i.e. already disentangled events) the
708 // stored_events list will always be empty so "evt" is always
709 // set.
710
711 // Check for event stored from parsing a previously read in
712 // DAQ event
713 ObjList *objs_ptr = NULL__null;
714 pthread_mutex_lock(&stored_events_mutex);
715 if(!stored_events.empty()){
716 objs_ptr = stored_events.front();
717 stored_events.pop();
718
719 // If this is a stored event then it almost certainly
720 // came from a multi-event block of physics events.
721 // Set the physics event status bit.
722 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
723 }
724 pthread_mutex_unlock(&stored_events_mutex);
725
726 // If no events are currently stored in the buffer, then
727 // read in another event block.
728 if(objs_ptr == NULL__null){
729 uint32_t *buff = NULL__null; // ReadEVIOEvent will allocate memory from pool for this
730 jerror_t err = ReadEVIOEvent(buff);
731 if(err != NOERROR) return err;
732 if(buff == NULL__null) return MEMORY_ALLOCATION_ERROR;
733 uint32_t buff_size = ((*buff) + 1)*4; // first word in EVIO buffer is total bank size in words
734
735 objs_ptr = new ObjList();
736 objs_ptr->eviobuff = buff;
737 objs_ptr->eviobuff_size = buff_size;
738 objs_ptr->run_number = FindRunNumber(buff);
739 objs_ptr->event_number = FindEventNumber(buff);
740
741 // Increment counter that keeps track of how many events
742 // are currently being processed.
743 pthread_mutex_lock(&current_event_count_mutex);
744 current_event_count++;
745 pthread_mutex_unlock(&current_event_count_mutex);
746 }
747
748 // Store a pointer to the ObjList object for this event in the
749 // JEvent as the Reference value. Parsing will be done later
750 // in GetObjects() -> ParseEvents() using the eviobuff pointer.
751 event.SetJEventSource(this);
752 event.SetEventNumber((uint64_t)objs_ptr->event_number);
753 event.SetRunNumber(objs_ptr->run_number);
754 event.SetRef(objs_ptr);
755 event.SetStatusBit(kSTATUS_EVIO);
756 if( source_type == kFileSource ) event.SetStatusBit(kSTATUS_FROM_FILE);
757 if( source_type == kETSource ) event.SetStatusBit(kSTATUS_FROM_ET);
758 if(objs_ptr)
759 if(objs_ptr->eviobuff) FindEventType(objs_ptr->eviobuff, event);
760
761 // EPICS and BOR events are barrier events
762 if(event.GetStatusBit(kSTATUS_EPICS_EVENT) || event.GetStatusBit(kSTATUS_BOR_EVENT) ){
763 event.SetSequential();
764 }
765
766 Nevents_read++;
767
768 return NOERROR;
769}
770
771//----------------
772// FreeEvent
773//----------------
774void JEventSource_EVIO::FreeEvent(JEvent &event)
775{
776 if(VERBOSE>1) evioout << "FreeEvent called for event: " << event.GetEventNumber() << endl;
777
778 ObjList *objs_ptr = (ObjList*)event.GetRef();
779 if(objs_ptr){
780
781 // If a DAQ event was read in but GetObjects never called
782 // then the buffer will never have been parsed. Since the
783 // DAQ event could hold multiple Physics events, we parse
784 // it now to ensure all physics events are presented by
785 // the event source. The ParseEvents call will copy the
786 // first event's parameters into our objs_ptr object, but
787 // any additional ones will be placed in stored_events.
788 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
789
790 if(objs_ptr->own_objects){
791
792 for(unsigned int i=0; i<objs_ptr->hit_objs.size(); i++){
793 delete objs_ptr->hit_objs[i];
794 }
795
796 for(unsigned int i=0; i<objs_ptr->config_objs.size(); i++){
797 delete objs_ptr->config_objs[i];
798 }
799
800 for(unsigned int i=0; i<objs_ptr->misc_objs.size(); i++){
801 delete objs_ptr->misc_objs[i];
802 }
803 }
804
805 if(objs_ptr->DOMTree != NULL__null) delete objs_ptr->DOMTree;
806 if(objs_ptr->eviobuff){
807
808 // If we have not already stopped reading events from
809 // the source then return this buffer to the pool. Otherwise,
810 // delete the buffer.
811 if(hdevio){
812 // Return EVIO buffer to pool for recycling
813 pthread_mutex_lock(&evio_buffer_pool_mutex);
814 evio_buffer_pool.push_front(objs_ptr->eviobuff);
815 pthread_mutex_unlock(&evio_buffer_pool_mutex);
816 }else{
817 free(objs_ptr->eviobuff);
818 }
819 }
820
821 delete objs_ptr;
822
823 // Decrement counter that keeps track of how many events
824 // are currently being processed.
825 pthread_mutex_lock(&current_event_count_mutex);
826 current_event_count--;
827 bool last_event = (hdevio==NULL__null) && (current_event_count==0);
828 pthread_mutex_unlock(&current_event_count_mutex);
829
830 // If we are the last event, then clean up as much memory as
831 // possible.
832 if(last_event) Cleanup();
833 }
834}
835
836//----------------
837// ParseEvents
838//----------------
839jerror_t JEventSource_EVIO::ParseEvents(ObjList *objs_ptr)
840{
841 /// This is the high-level entry point for parsing the
842 /// DAQ event in order to create one or more Physics
843 /// events. It will be called from either GetObjects
844 /// or FreeEvent, the latter being done only if needed
845 /// to ensure the event does eventually get parsed.
846 /// The grunt work of actually parsing the data starts
847 /// in ParseEVIOEvent().
848 ///
849 /// This method is here so that the DOM Tree creation
850 /// and data parsing can be deferred from the EventBuffer
851 /// thread (of which there is only one) to an event
852 /// processor thread (or which there may be many). Since
853 /// the DOM tree creating and data parsing represent the
854 /// larger time cost of getting the event into memory,
855 /// a siginificant performance increase can be gained
856 /// using this slightly more complicated method.
857
858 if(VERBOSE>2) evioout << " Entering ParseEvents() with objs_ptr=" << hex << objs_ptr << dec << endl;
1
Taking false branch
859
860 // Double check that we're not re-parsing an event
861 if(objs_ptr->eviobuff_parsed){
2
Taking false branch
862 jerr << " DAQ event already parsed!! Bug in code. Contact davidl@jlab.org" << endl;
863 return UNKNOWN_ERROR;
864 }
865
866 // Bomb-proof against getting a NULL buffer
867 uint32_t *buff = objs_ptr->eviobuff;
868 if(buff == NULL__null){
3
Taking false branch
869 jerr << " Bad buffer pointer passed to JEventSource_EVIO::ParseEvent()!!" << endl;
870 return RESOURCE_UNAVAILABLE;
871 }
872
873 // This container will be used to hold all of the individual
874 // Physics (L1 triggered) events for this DAQ event. This includes
875 // both dientangling multi-event blocks and separating multi-event
876 // ET events.
877 list<ObjList*> full_events;
878
879 // Setup up iptr and iend to point to the start of the first event
880 // and the word just after the end of the last event respectively.
881 // Initialize them for the case of reading from a file and not a
882 // CODA-produced ET event
883 uint32_t *iptr = &buff[0];
884 uint32_t *iend = &buff[buff[0]+1]; // EVIO length word is exclusive so +1
885
886 // If the "event" was read from ET, then it may (and likely
887 // will) contain several DAQ events. (Each DAQ event may itself
888 // contain many L1 trigger events.) In addition, the ET event
889 // will have a Network Transport Header (NTH) that must be skipped
890 // but only if read from CODA. Events put into the ET system
891 // by other means will not include the NTH. To decide whether
892 // there is an NTH, we look at the magic word and the header length.
893 // Note that byteswapping should already have occured.
894 if(source_type==kETSource && buff[7]==0xc0da0100 && buff[2]==8){
895 // This buffer read from ET. Redefine iptr and iend
896 iptr = &buff[8];
897 iend = &buff[buff[0]]; // EVIO length word in NTH is inclusive so don't add 1
898 }
899
900 if(VERBOSE>5) evioout << " Looping event stack with " << *iptr << " words" << endl;
4
Taking false branch
901
902 // Loop over events in buffer until entire buffer is parsed.
903 // When reading from a file, this loop should only get executed once.
904 int Nevents_in_stack=0;
905 while(iptr < iend){
5
Assuming 'iptr' is >= 'iend'
6
Loop condition is false. Execution continues on line 955
906
907 // Make a evioDOMTree for this DAQ event
908 evioDOMTree *evt = NULL__null;
909 if(MAKE_DOM_TREE){
910 try{
911 evt = new evioDOMTree(iptr);
912 }catch(evioException &e){
913 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<913<<" "
<< "Problem creating EVIO DOM Tree!!" << endl;
914 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<914<<" "
<< e.what() << endl;
915 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<915<<" "
<< "Binary dump of first 160 words follows:" << endl;
916 DumpBinary(iptr, iend, 160);
917 exit(-1);
918 }
919 }
920
921 if(evt){
922 // Parse event, making other ObjList objects
923 list<ObjList*> my_full_events;
924 //bool skipped_parsing = true;
925 if(PARSE_EVIO_EVENTS){
926 try{
927 //skipped_parsing = false;
928 ParseEVIOEvent(evt, my_full_events);
929 }catch(JException &jexception){
930 jerr << "Exception thrown from ParseEVIOEvent!" << endl;
931 jerr << jexception.toString() << endl;
932 }
933 }
934
935 // Append physics events found for this DAQ event to the list of all physics events
936 if(!my_full_events.empty()) {
937 my_full_events.front()->DOMTree = evt; // keep DOMTree pointer with first event from this DAQ event
938 full_events.insert( full_events.end(), my_full_events.begin(), my_full_events.end() );
939 }else{
940 delete evt;
941 }
942 }else{
943 // No DOM tree made for this buffer. Insert an empty event into
944 // the list so we can keep track of the number of events seen
945 // even when DOMTree creation is turned off.
946 ObjList *objs = new ObjList;
947 full_events.push_back(objs);
948 }
949
950 // Advance pointer to next event in buffer
951 iptr += iptr[0]+1;
952 Nevents_in_stack++; // number of events processed in this buffer (for debugging)
953 }
954
955 if(VERBOSE>5) evioout << " Loop finished. " << full_events.size() << " events total found (" << Nevents_in_stack << " events in stack)" << endl;
7
Taking false branch
956
957 // At this point, we have parsed the DAQ event and extracted all physics
958 // events into the full_events list. In the case of a prestart or go event
959 // read from an EVIO file, the full_events list may actually be empty at
960 // this point. For these cases, we need to add an empty event for the
961 // current thread to "process".
962 bool empty_event = full_events.empty();
963 if(empty_event) full_events.push_back(new ObjList());
8
Assuming 'empty_event' is 0
9
Taking false branch
964
965 // Whether we actually parsed the events or not, we mark them as being
966 // parsed since it is really just used as a flag to tell whether this
967 // method should be called or not.
968 list<ObjList*>::iterator iter = full_events.begin();
969 for( ; iter != full_events.end(); iter++ ) (*iter)->eviobuff_parsed = true;
10
Loop condition is false. Execution continues on line 972
970
971 // Copy the first event's objects obtained from parsing into this event's ObjList
972 ObjList *objs = full_events.front();
973 full_events.pop_front();
974 //objs_ptr->run_number = empty_event ? objs_ptr->run_number:objs->run_number;
975 objs_ptr->own_objects = objs->own_objects;
976 objs_ptr->hit_objs = objs->hit_objs;
977 objs_ptr->config_objs = objs->config_objs;
978 objs_ptr->misc_objs = objs->misc_objs;
979 objs_ptr->eviobuff_parsed = objs->eviobuff_parsed;
980 //objs_ptr->eviobuff = objs->eviobuff; // Don't copy this! (it causes memory leak)
981 //objs_ptr->eviobuff_size = objs->eviobuff_size;
982 objs_ptr->DOMTree = objs->DOMTree;
983 delete objs;
984
985 // Config objects come from banks that are created when a block
986 // of events is read out. Thus, a single set of config. objects
987 // will be created when parsing a multi-event block. Here, we duplicate
988 // all config objects for the first event for every other event in the
989 // block. To make this a little more compact and maintainable, we use a
990 // #define. This allows us to write the class type once and guarantee
991 // that it shows up the same in all places. For example, using
992 // CloneConfigObject(Df125Config) will expand to something like:
993 //
994 // if(confobj->className() == string("Df125Config")){
995 // c = new Df125Config(confobj->rocid,confobj->slot_mask);
996 // *((Df125Config*)c) = *((Df125Config*)confobj);
997 // }
998#define CloneConfigObject(T){ if(confobj->className() == string("T")){ c = new T(confobj
->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);
} }
{ if(confobj->className() == string(#T)){ c = new T(confobj->rocid,confobj->slot_mask); *((T*)c) = *((T*)confobj);} }
999 list<ObjList*>::iterator feiter = full_events.begin();
1000 for(; feiter!=full_events.end(); feiter++){
11
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
15
Loop condition is true. Entering loop body
1001 ObjList *objs = *feiter;
1002 for(uint32_t j=0; j<objs_ptr->config_objs.size(); j++){
12
Loop condition is false. Execution continues on line 1000
14
Loop condition is false. Execution continues on line 1000
16
Loop condition is true. Entering loop body
1003 DDAQConfig *confobj = objs_ptr->config_objs[j];
1004 DDAQConfig *c = NULL__null;
1005 CloneConfigObject(Df250Config){ if(confobj->className() == string("Df250Config")){ c = new
Df250Config(confobj->rocid,confobj->slot_mask); *((Df250Config
*)c) = *((Df250Config*)confobj);} }
;
1006 CloneConfigObject(Df125Config){ if(confobj->className() == string("Df125Config")){ c = new
Df125Config(confobj->rocid,confobj->slot_mask); *((Df125Config
*)c) = *((Df125Config*)confobj);} }
;
1007 CloneConfigObject(DF1TDCConfig){ if(confobj->className() == string("DF1TDCConfig")){ c = new
DF1TDCConfig(confobj->rocid,confobj->slot_mask); *((DF1TDCConfig
*)c) = *((DF1TDCConfig*)confobj);} }
;
17
Within the expansion of the macro 'CloneConfigObject':
a
Memory is allocated
1008 CloneConfigObject(DCAEN1290TDCConfig){ if(confobj->className() == string("DCAEN1290TDCConfig"))
{ c = new DCAEN1290TDCConfig(confobj->rocid,confobj->slot_mask
); *((DCAEN1290TDCConfig*)c) = *((DCAEN1290TDCConfig*)confobj
);} }
;
18
Within the expansion of the macro 'CloneConfigObject':
a
Potential leak of memory pointed to by 'c'
1009 if(c)objs->config_objs.push_back(c);
1010 }
1011 }
1012
1013 // Copy remaining events into the stored_events container
1014 pthread_mutex_lock(&stored_events_mutex);
1015 while(!full_events.empty()){
1016 objs = full_events.front();
1017 full_events.pop_front();
1018 stored_events.push(objs);
1019
1020 // Copy run number from first event
1021 objs->run_number = objs_ptr->run_number;
1022 }
1023 pthread_mutex_unlock(&stored_events_mutex);
1024
1025 if(VERBOSE>2) evioout << " Leaving ParseEvents()" << endl;
1026
1027 return NOERROR;
1028}
1029
1030//----------------
1031// ReadEVIOEvent
1032//----------------
1033jerror_t JEventSource_EVIO::ReadEVIOEvent(uint32_t* &buff)
1034{
1035 /// This method will read an event from the source (file or ET system)
1036 /// copying the data into "buff". No parsing of the data is done at
1037 /// this level except that if the event comes from ET and needs to be
1038 /// byte-swapped, the byte swapping is done during the copy.
1039 ///
1040 /// This is called from the GetEvent method and therefore run in
1041 /// the event reader thread. Events read from ET may contain several DAQ
1042 /// events in a single buffer (and each of those may contain several
1043 /// physics events if read in multi-event blocks). Separating the multiple
1044 /// DAQ events is left to the ParseEvents method which gets called later
1045 /// from the event processing threads to improve efficiency.
1046
1047 if(VERBOSE>1) evioout << " ReadEVIOEvent() called with &buff=" << hex << &buff << dec << endl;
1048
1049 // Get buffer from pool or allocate new one if needed
1050 pthread_mutex_lock(&evio_buffer_pool_mutex);
1051 if(evio_buffer_pool.empty()){
1052 // Allocate new block of memory
1053 if(VERBOSE>5) evioout << " evio_buffer_pool empty. Allocating new buffer of size: " << BUFFER_SIZE << " bytes" << endl;
1054 buff = (uint32_t*)malloc(BUFFER_SIZE);
1055 }else{
1056 if(VERBOSE>5) evioout << " evio_buffer_pool not empty(size=" << evio_buffer_pool.size() << "). using buffer from pool" << endl;
1057 buff = evio_buffer_pool.front();
1058 evio_buffer_pool.pop_front();
1059 }
1060 pthread_mutex_unlock(&evio_buffer_pool_mutex);
1061
1062 try{
1063 if(source_type==kFileSource){
1064 if(VERBOSE>3) evioout << " attempting read from EVIO file source ..." << endl;
1065
1066#if USE_HDEVIO1
1067
1068 bool done = false;
1069 uint32_t buff_size = BUFFER_SIZE;
1070 while(!done){
1071 if(hdevio->read(buff, buff_size)){
1072 done = true;
1073 }else{
1074 string mess = hdevio->err_mess.str();
1075
1076 switch(hdevio->err_code){
1077 case HDEVIO::HDEVIO_OK:
1078 done = true;
1079 break;
1080 case HDEVIO::HDEVIO_USER_BUFFER_TOO_SMALL:
1081 if(VERBOSE>0) evioout << "EVIO buffer too small (" << buff_size << " bytes) . Reallocating to " << hdevio->last_event_len<< endl;
1082 if(buff) delete[] buff;
1083 buff_size = hdevio->last_event_len;
1084 buff = new uint32_t[buff_size];
1085 continue;
1086 break;
1087 case HDEVIO::HDEVIO_EVENT_BIGGER_THAN_BLOCK:
1088 case HDEVIO::HDEVIO_BANK_TRUNCATED:
1089 case HDEVIO::HDEVIO_UNKNOWN_BANK_TYPE:
1090 if(VERBOSE>0) cout << endl << mess << endl;
1091 continue;
1092 break;
1093 case HDEVIO::HDEVIO_EOF:
1094 if(hdevio) delete hdevio;
1095 hdevio = NULL__null;
1096 if(LOOP_FOREVER && Nevents_read>=1){
1097 cout << "LOOP_FOREVER: reopening " << this->source_name <<endl;
1098 hdevio = new HDEVIO(this->source_name);
1099 if( hdevio->is_open ) continue;
1100 }
1101 return NO_MORE_EVENTS_IN_SOURCE;
1102 break;
1103 default:
1104 cout << endl << "err_code=" << hdevio->err_code << endl;
1105 cout << endl << mess << endl;
1106 if(hdevio) delete hdevio;
1107 hdevio = NULL__null;
1108 return NO_MORE_EVENTS_IN_SOURCE;
1109 break;
1110 }
1111 }
1112 } // while(!done)
1113
1114#else
1115// if(!chan->read(buff, BUFFER_SIZE)){
1116// if(LOOP_FOREVER){
1117// if(Nevents_read<1){
1118// // User asked us to loop forever, but we couldn't find even 1 event!
1119// jerr << "No events in file!!" << endl;
1120// return NO_MORE_EVENTS_IN_SOURCE;
1121// }else{
1122//
1123// // close file
1124// if(VERBOSE>0) evioout << "Closing \""<<this->source_name<<"\"" <<endl;
1125// chan->close();
1126// delete chan;
1127//
1128// // re-open file
1129// evioout << "Re-opening EVIO file \""<<this->source_name<<"\"" <<endl;
1130// chan = new evioFileChannel(this->source_name, "r", BUFFER_SIZE);
1131//
1132// // open the file and read first event (assume it will be successful again)
1133// chan->open();
1134// chan->read(buff, BUFFER_SIZE);
1135// }
1136// }else{
1137// return NO_MORE_EVENTS_IN_SOURCE;
1138// }
1139// }
1140#endif // USE_HDEVIO
1141
1142 }else if(source_type==kETSource){
1143
1144#ifdef HAVE_ET
1145
1146 if(VERBOSE>3) evioout << " attempting read from EVIO ET source ..." << endl;
1147
1148
1149 // Loop until we get an event or are told to stop
1150 struct timespec timeout;
1151 timeout.tv_sec = (unsigned int)floor(TIMEOUT); // set ET timeout
1152 timeout.tv_nsec = (unsigned int)floor(1.0E9*(TIMEOUT-(float)timeout.tv_sec));
1153 et_event *pe=NULL__null;
1154 while(! japp->GetQuittingStatus() ){
1155 int err = et_event_get(sys_id, att_id, &pe, ET_TIMED , &timeout);
1156
1157 if( err == ET_OK && pe!=NULL__null) break; // got an event. break out of while loop
1158
1159 if( err == ET_OK && pe==NULL__null){
1160 evioout << " !!! ET returned no error, but event pointer is NULL!!!" << endl;
1161 return NO_MORE_EVENTS_IN_SOURCE;
1162 }
1163
1164 if( err==ET_ERROR_TIMEOUT ){
1165 if(quit_on_next_ET_timeout)return NO_MORE_EVENTS_IN_SOURCE;
1166 }else if( err!=ET_OK){
1167 evioout << " Error reading from ET. This probably means the ET" << endl;
1168 evioout << "system has gone away (possibly due to run ending or" << endl;
1169 evioout << "DAQ crashing). At any rate, we are quitting now as this" << endl;
1170 evioout << "error is currently unrecoverable." << endl;
1171 return NO_MORE_EVENTS_IN_SOURCE;
1172 }
1173
1174 usleep(10);
1175 }
1176
1177 if(japp->GetQuittingStatus() && pe==NULL__null) return NO_MORE_EVENTS_IN_SOURCE;
1178
1179 // Get pointer to event buffer in the ET-owned memory
1180 uint32_t *et_buff=NULL__null;
1181 et_event_getdata(pe, (void**)&et_buff);
1182 if(et_buff == NULL__null){
1183 jerr << " Got event from ET, but pointer to data is NULL!" << endl;
1184 return NO_MORE_EVENTS_IN_SOURCE;
1185 }
1186
1187 // If user specified to dump words from ET event, do it right away
1188 if(ET_DEBUG_WORDS_TO_DUMP) DumpBinary(et_buff, &et_buff[ET_DEBUG_WORDS_TO_DUMP], ET_DEBUG_WORDS_TO_DUMP, NULL__null);
1189
1190 // Check byte order of event by looking at magic #
1191 bool swap_needed = false;
1192 uint32_t magic = et_buff[7];
1193 switch(magic){
1194 case 0xc0da0100: swap_needed = false; break;
1195 case 0x0001dac0: swap_needed = true; break;
1196 default:
1197 evioout << "EVIO magic word not present!" << endl;
1198 return NO_MORE_EVENTS_IN_SOURCE;
1199 }
1200 uint32_t len = et_buff[0];
1201 if(swap_needed) len = EVIO_SWAP32(len)( (((len) >> 24) & 0x000000FF) | (((len) >> 8
) & 0x0000FF00) | (((len) << 8) & 0x00FF0000) |
(((len) << 24) & 0xFF000000) )
;
1202 if(VERBOSE>3){
1203 evioout << "Swapping is " << (swap_needed ? "":"not ") << "needed" << endl;
1204 evioout << " Num. words in EVIO buffer: "<<len<<endl;
1205 }
1206
1207 // Chop off NTH header
1208 len -= 8;
1209
1210 // Size of events in bytes
1211 uint32_t bufsize_bytes = (len +1)*sizeof(uint32_t); // +1 is for buffer length word
1212 if(bufsize_bytes > BUFFER_SIZE){
1213 jerr<<" ET event larger than our BUFFER_SIZE!!!"<<endl;
1214 jerr<<" " << bufsize_bytes << " > " << BUFFER_SIZE << endl;
1215 jerr<<" Will stop reading from this source now. Try restarting"<<endl;
1216 jerr<<" with -PEVIO:BUFFER_SIZE=X where X is greater than "<<bufsize_bytes<<endl;
1217 if(VERBOSE>3){
1218 evioout << "First few words in case you are trying to debug:" << endl;
1219 for(unsigned int j=0; j<3; j++){
1220 char str[512];
1221 for(unsigned int i=0; i<5; i++){
1222 sprintf(str, " %08x", et_buff[i+j*5]);
1223 evioout << str;
1224 }
1225 evioout << endl;
1226 }
1227 }
1228 return NO_MORE_EVENTS_IN_SOURCE;
1229 }
1230
1231 // Copy event into "buff", byte swapping if needed.
1232 // The evioswap routine will not handle the NTH correctly
1233 // so we need to swap that separately and then swap each
1234 // event in the stack using evioswap so that the different
1235 // bank types are handled properly. If no swapping is
1236 // needed, we just copy it all over in one go.
1237 if(!swap_needed){
1238
1239 // Copy NTH and all events without swapping
1240 memcpy(buff, &et_buff[8], bufsize_bytes);
1241
1242 }else{
1243
1244 // Swap+copy NTH
1245 //swap_int32_t(et_buff, 8, buff);
1246
1247 // Loop over events in stack
1248 int Nevents_in_stack=0;
1249 uint32_t idx = 8;
1250 while(idx<len){
1251 uint32_t mylen = EVIO_SWAP32(et_buff[idx])( (((et_buff[idx]) >> 24) & 0x000000FF) | (((et_buff
[idx]) >> 8) & 0x0000FF00) | (((et_buff[idx]) <<
8) & 0x00FF0000) | (((et_buff[idx]) << 24) & 0xFF000000
) )
;
1252 if(VERBOSE>7) evioout <<" swapping event: idx=" << idx <<" mylen="<<mylen<<endl;
1253 if( (idx+mylen) > (len+8) ){
1254 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1254<<" "
<< "Bad word count while swapping events in ET event stack!" << endl;
1255 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1255<<" "
<< "idx="<<idx<<" mylen="<<mylen<<" len="<<len<<endl;
1256 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1256<<" "
<< "This indicates a problem either with the DAQ system"<<endl;
1257 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1257<<" "
<< "or this parser code! Contact davidl@jlab.org x5567 " <<endl;
1258 break;
1259 }
1260 swap_int32_t(&et_buff[idx], mylen+1, &buff[idx-8]);
1261 idx += mylen+1;
1262 Nevents_in_stack++;
1263 }
1264
1265 if(VERBOSE>3) evioout << " Found " << Nevents_in_stack << " events in the ET event stack." << endl;
1266 }
1267
1268 // Put ET event back since we're done with it
1269 et_event_put(sys_id, att_id, pe);
1270
1271#else // HAVE_ET
1272
1273 japp->Quit();
1274 evioout << "Attempting to read from ET system using binary that" << endl;
1275 evioout << "does not have ET support built in! Try recompiling" << endl;
1276 evioout << "programs/Utilities/plugins/DAQ with ETROOT defined" << endl;
1277 evioout << "and pointing to an ET installation." << endl;
1278
1279#endif //HAVE_ET
1280
1281 }
1282 } catch (evioException &e) {
1283 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<1283<<" "
<<e.what()<<endl;
1284 if(e.type == S_EVFILE_TRUNC0x40730001){
1285 jerr << "-- Event buffer truncated --" <<endl;
1286 jerr << "---- this could be because the events are too large " << endl;
1287 jerr << "---- for the buffer provided (" << BUFFER_SIZE << " bytes)" <<endl;
1288 jerr << "---- you can try giving a larger buffer size by setting" << endl;
1289 jerr << "---- the EVIO:BUFFER_SIZE configuration parameter by " << endl;
1290 jerr << "---- adding this argument to your command line:" << endl;
1291 jerr << "---- -PEVIO:BUFFER_SIZE=X (where X is in bytes)" << endl;
1292 }
1293 }
1294
1295 if(VERBOSE>2) evioout << " Leaving ReadEVIOEvent()" << endl;
1296
1297 return NOERROR;
1298}
1299
1300//----------------
1301// GetObjects
1302//----------------
1303jerror_t JEventSource_EVIO::GetObjects(JEvent &event, JFactory_base *factory)
1304{
1305 if(VERBOSE>2) evioout << " GetObjects() called for &event = " << hex << &event << dec << endl;
1306
1307 // This will get called when the first object of the event is
1308 // requested (regardless of the type of object). Instead of
1309 // pulling out objects only of the type requested, we instead
1310 // take the data for all objects and copy them into the respective
1311 // factories. Subsequent requests for objects for this same
1312 // event will get them from the factories. Thus, this should
1313 // only get called once per event.
1314 // O.K. that is not actually true. If objects of a type we don't
1315 // supply are requested, then the corresponding factory's evnt_called
1316 // flag will not have been set and it will come here first to see
1317 // if the source can supply those objects. In those cases, we should
1318 // just return OBJECT_NOT_AVAILABLE so it can revert to the factory
1319 // algorithm. We use the "own_objects" flag here to test if we have
1320 // already copied the low-level objects to the factories and so
1321 // should return right away.
1322 ObjList *objs_ptr = (ObjList*)event.GetRef();
1323 if(!objs_ptr)return RESOURCE_UNAVAILABLE;
1324 if(!objs_ptr->own_objects) return OBJECT_NOT_AVAILABLE; // if objects were already copied ...
1325
1326 // If any translation tables exist, we will use them at the end of this
1327 // method. However, the TTab plugin has an option to specify parsing of
1328 // only certain detector systems. It does this by copying values into
1329 // this JEventSource_EVIO object via the AddROCIDtoParseList method
1330 // while in the brun method. The brun method won't get called until
1331 // we ask for the DTranslationTable objects, thus, we must ask for them
1332 // here, prior to calling ParseEvents.
1333 // Note that we have to use the GetFromFactory() method here since
1334 // if we just use Get() or GetSingle(), it will call us (the event
1335 // source) again in an infinite loop!
1336 // Also note that we use static_cast here instead of dynamic_cast
1337 // since the latter requires that the type_info structure for
1338 // the DTranslationTable_factory be present. It is not in this
1339 // plugin (it is in the TTab plugin). Thus, with dynamic_cast there
1340 // is an unresolved symbol error if the TTab plugin is not also
1341 // present. (Make sense?)
1342 vector<const DTranslationTable*> translationTables;
1343 JEventLoop *loop = event.GetJEventLoop();
1344 DTranslationTable_factory *ttfac = static_cast<DTranslationTable_factory*>(loop->GetFactory("DTranslationTable"));
1345 if(ttfac) ttfac->Get(translationTables);
1346
1347 // We use a deferred parsing scheme for efficiency. If the event
1348 // is not flagged as having already been parsed, then parse it
1349 // now, creating objects for one or more events. The first event's
1350 // parameters will be copied into our ObjList object and any additional
1351 // ones stored in the stored_events queue.
1352 if(!objs_ptr->eviobuff_parsed) ParseEvents(objs_ptr);
1353
1354 // Get name of class which is actually being requested by caller
1355 string dataClassName = (factory==NULL__null ? "N/A":factory->GetDataClassName());
1356
1357 // Make list of data(hit) types we have. Keep list of
1358 // pointers to hit objects of each type
1359 map<string, vector<JObject*> > hit_objs_by_type;
1360 vector<DDAQAddress*> &hit_objs = objs_ptr->hit_objs;
1361 for(unsigned int i=0; i<hit_objs.size(); i++){
1362 JObject *hit_obj = hit_objs[i];
1363 hit_objs_by_type[hit_obj->className()].push_back(hit_obj);
1364 }
1365
1366 // Make list of config objects of each type
1367 map<string, vector<JObject*> > config_objs_by_type;
1368 vector<DDAQConfig*> &config_objs = objs_ptr->config_objs;
1369 for(unsigned int i=0; i<config_objs.size(); i++){
1370 JObject *config_obj = config_objs[i];
1371 config_objs_by_type[config_obj->className()].push_back(config_obj);
1372 }
1373
1374 // Make list of misc objects of each type
1375 map<string, vector<JObject*> > misc_objs_by_type;
1376 vector<JObject*> &misc_objs = objs_ptr->misc_objs;
1377 for(unsigned int i=0; i<misc_objs.size(); i++){
1378 JObject *jobj = misc_objs[i];
1379 misc_objs_by_type[jobj->className()].push_back(jobj);
1380 }
1381
1382 // In order for the janadot plugin to properly display the callgraph, we need to
1383 // make entries for each of the object types that we generated from data in the file.
1384 // Actually, we need to do it for all of the data objects we supply, but if any objects
1385 // are emulated (e.g. Df250PulseIntegral) they need to be added differently so the correct
1386 // dependence is shown. The first step is to add entries for all of the hit objects we
1387 // actually did find in the file. Do that here.
1388 map<string, vector<JObject*> >::iterator hoiter;
1389 for(hoiter=hit_objs_by_type.begin(); hoiter!=hit_objs_by_type.end(); hoiter++){
1390 AddSourceObjectsToCallStack(loop, hoiter->first);
1391 }
1392
1393 // Get references to various objects
1394 vector<JObject*> &f250_wrd_objs = hit_objs_by_type["Df250WindowRawData"];
1395 vector<JObject*> &f250_pt_objs = hit_objs_by_type["Df250PulseTime"];
1396 vector<JObject*> &f250_pp_objs = hit_objs_by_type["Df250PulsePedestal"];
1397 vector<JObject*> &f250_pi_objs = hit_objs_by_type["Df250PulseIntegral"];
1398
1399 vector<JObject*> &f125_wrd_objs = hit_objs_by_type["Df125WindowRawData"];
1400 vector<JObject*> &f125_pt_objs = hit_objs_by_type["Df125PulseTime"];
1401 vector<JObject*> &f125_pp_objs = hit_objs_by_type["Df125PulsePedestal"];
1402 vector<JObject*> &f125_pi_objs = hit_objs_by_type["Df125PulseIntegral"];
1403 vector<JObject*> &f125_cp_objs = hit_objs_by_type["Df125CDCPulse"];
1404 vector<JObject*> &f125_fp_objs = hit_objs_by_type["Df125FDCPulse"];
1405
1406 // Emulate PulseTime and PulsePedestal
1407 // Emulation of pulse time and pulse pedestal are done at
1408 // the same time since that's how the original firmware
1409 // does it. The EmulateDf250PulseTime() method will check
1410 // the value of F250_PT_EMULATION_MODE and
1411 // F250_PP_EMULATION_MODE and modify the f250_pt_objs and f250_pp_objs
1412 // vectors as appropriate (possibly deleting some objects).
1413 if( (F250_PT_EMULATION_MODE != kEmulationNone) || (F250_PP_EMULATION_MODE != kEmulationNone) ){
1414 EmulateDf250PulseTime(f250_wrd_objs, f250_pt_objs, f250_pp_objs);
1415 }
1416
1417 // Repeat for f125 Pulse Time and Pulse Pedestal
1418 if( (F125_PT_EMULATION_MODE != kEmulationNone) || (F125_PP_EMULATION_MODE != kEmulationNone) ){
1419 EmulateDf125PulseTime(f125_wrd_objs, f125_pt_objs, f125_pp_objs, f125_cp_objs, f125_fp_objs);
1420 }
1421
1422 // Emulate PulseIntegral
1423 // Similar to above, EmulateDf250PulseIntegral() will modify
1424 // f250_pi_objs by adding/deleting objects based on the value of
1425 // F250_PI_EMULATION_MODE.
1426 if(F250_PI_EMULATION_MODE != kEmulationNone){
1427 EmulateDf250PulseIntegral(f250_wrd_objs, f250_pi_objs);
1428 }
1429
1430 // Repeat for f125 Pulse Integral
1431 if(F125_PI_EMULATION_MODE != kEmulationNone){
1432 EmulateDf125PulseIntegral(f125_wrd_objs, f125_pi_objs, f125_pt_objs, f125_cp_objs, f125_fp_objs);
1433 }
1434
1435 // Make PulseTime, PulsePedstal, and PulseIntegral objects associated objects of one another
1436 vector<Df250PulseIntegral*> f250_ppi_objs;
1437 vector<Df250PulseTime*> f250_ppt_objs;
1438 vector<Df250PulsePedestal*> f250_ppp_objs;
1439 CopyContainerElementsWithCast(f250_pi_objs, f250_ppi_objs);
1440 CopyContainerElementsWithCast(f250_pt_objs, f250_ppt_objs);
1441 CopyContainerElementsWithCast(f250_pp_objs, f250_ppp_objs);
1442 LinkAssociationsWithPulseNumber(f250_ppt_objs, f250_ppi_objs);
1443 LinkAssociationsWithPulseNumber(f250_ppp_objs, f250_ppi_objs);
1444 LinkAssociationsWithPulseNumber(f250_ppp_objs, f250_ppt_objs);
1445
1446 vector<Df125WindowRawData*> f125_pwrd_objs;
1447 vector<Df125PulseIntegral*> f125_ppi_objs;
1448 vector<Df125PulseTime*> f125_ppt_objs;
1449 vector<Df125PulsePedestal*> f125_ppp_objs;
1450 vector<Df125CDCPulse*> f125_pcp_objs;
1451 vector<Df125FDCPulse*> f125_pfp_objs;
1452 CopyContainerElementsWithCast(f125_wrd_objs, f125_pwrd_objs);
1453 CopyContainerElementsWithCast(f125_pi_objs, f125_ppi_objs);
1454 CopyContainerElementsWithCast(f125_pt_objs, f125_ppt_objs);
1455 CopyContainerElementsWithCast(f125_pp_objs, f125_ppp_objs);
1456 CopyContainerElementsWithCast(f125_cp_objs, f125_pcp_objs);
1457 CopyContainerElementsWithCast(f125_fp_objs, f125_pfp_objs);
1458 LinkAssociationsWithPulseNumber(f125_ppt_objs, f125_ppi_objs);
1459 LinkAssociationsWithPulseNumber(f125_ppp_objs, f125_ppi_objs);
1460 LinkAssociationsWithPulseNumber(f125_ppp_objs, f125_ppt_objs);
1461 LinkAssociations(f125_pcp_objs, f125_pwrd_objs);
1462 LinkAssociations(f125_pfp_objs, f125_pwrd_objs);
1463
1464 // To make JANA aware of the correct association between
1465 // emulated objects and the Window Raw Data objects, we
1466 // have to explicitly tell it. This is tricky since, for
1467 // example, not all PulseIntegral objects may be emulated.
1468 // The best we can do is check if any objects are emulated
1469 // and if so, add the association.
1470 // F250 -----------
1471 if(!f250_wrd_objs.empty()){
1472 for(uint32_t i=0; i<f250_ppi_objs.size(); i++){
1473 if(f250_ppi_objs[i]->emulated){
1474 AddEmulatedObjectsToCallStack(loop, "Df250PulseIntegral", "Df250WindowRawData");
1475 break;
1476 }
1477 }
1478 for(uint32_t i=0; i<f250_ppt_objs.size(); i++){
1479 if(f250_ppt_objs[i]->emulated){
1480 AddEmulatedObjectsToCallStack(loop, "Df250PulseTime", "Df250WindowRawData");
1481 break;
1482 }
1483 }
1484 for(uint32_t i=0; i<f250_ppp_objs.size(); i++){
1485 if(f250_ppp_objs[i]->emulated){
1486 AddEmulatedObjectsToCallStack(loop, "Df250PulsePedestal", "Df250WindowRawData");
1487 break;
1488 }
1489 }
1490 }
1491
1492 // F125 -----------
1493 if(!f125_wrd_objs.empty()){
1494 for(uint32_t i=0; i<f125_ppi_objs.size(); i++){
1495 if(f125_ppi_objs[i]->emulated){
1496 AddEmulatedObjectsToCallStack(loop, "Df125PulseIntegral", "Df125WindowRawData");
1497 break;
1498 }
1499 }
1500 for(uint32_t i=0; i<f125_ppt_objs.size(); i++){
1501 if(f125_ppt_objs[i]->emulated){
1502 AddEmulatedObjectsToCallStack(loop, "Df125PulseTime", "Df125WindowRawData");
1503 break;
1504 }
1505 }
1506 for(uint32_t i=0; i<f125_ppp_objs.size(); i++){
1507 if(f125_ppp_objs[i]->emulated){
1508 AddEmulatedObjectsToCallStack(loop, "Df125PulsePedestal", "Df125WindowRawData");
1509 break;
1510 }
1511 }
1512 }
1513
1514 // Now, add data objects to call stack for the classes we can provide, but for which
1515 // there are no objects for this event. Again, this is so janadot will display things
1516 // properly.
1517 set<string>::iterator siter;
1518 for(siter=event_source_data_types.begin(); siter!=event_source_data_types.end(); siter++){
1519 if(hit_objs_by_type.find(*siter) == hit_objs_by_type.end()){
1520 AddSourceObjectsToCallStack(loop, *siter);
1521 }
1522 }
1523
1524 // Associate any DDAQConfig objects with hit objects to which they should apply.
1525 for(unsigned int j=0; j<config_objs.size(); j++){
1526 DDAQConfig *config = config_objs[j];
1527 for(unsigned int i=0; i<hit_objs.size(); i++){
1528 DDAQAddress *hit = hit_objs[i];
1529 if(hit->rocid != config->rocid) continue;
1530 if( (1<<hit->slot) & config->slot_mask){
1531 hit->AddAssociatedObject(config);
1532 }
1533 }
1534 }
1535
1536 // The f125 firmware used for the 2014 and Spring 2015 commissioning
1537 // data was hardwired to report pedestals that were an average of
1538 // 4 samples. Since only the average was reported, the number of
1539 // samples used for this data was always "1". For the firmware
1540 // implemented in late 2015, configuration parameters were introduced
1541 // to allow a different number of samples to be used for the pedestal
1542 // and a different divisor as well. Here, we need to replace the
1543 // nsamples field of the PulsePedestal objects (which should be set to
1544 // a default value of "1") with values determined by the config.
1545 // parameters. We use the value NPED which should be calculated in
1546 // the coda_config code on the ROCs when the data was taken.
1547 vector<JObject*> &vpp125 = hit_objs_by_type["Df125PulsePedestal"];
1548 for(unsigned int i=0; i<vpp125.size(); i++){
1549 Df125PulsePedestal *pp = (Df125PulsePedestal*)vpp125[i];
1550 if(!pp->emulated){
1551 const Df125Config*conf = NULL__null;
1552 pp->GetSingle(conf);
1553 if(conf!=NULL__null){
1554 if(conf->NPED != 0xFFFF){
1555 pp->nsamples = conf->NPED;
1556 }
1557 }
1558 }
1559 }
1560
1561 // Initially, the F250, F125 firmware does not include the
1562 // pedestal measurement in the pulse integral data
1563 // (it is an add-on Pulse Pedestal word) We want the
1564 // pedestal field of the Df250PulseIntegral objects
1565 // to contain the measured pedestals in both cases.
1566 // Check all Df250PulseIntegral objects for an associated
1567 // Df250PulsePedestal object. If it has one, copy the
1568 // pedestal from it into the Df250PulseIntegral.
1569 vector<JObject*> &vpi250 = hit_objs_by_type["Df250PulseIntegral"];
1570 for(unsigned int i=0; i<vpi250.size(); i++){
1571
1572 Df250PulseIntegral *pi = (Df250PulseIntegral*)vpi250[i];
1573 const Df250Config*conf = NULL__null;
1574 const Df250PulsePedestal*pp = NULL__null;
1575 pi->GetSingle(conf);
1576 pi->GetSingle(pp);
1577
1578 // If a Df250PulsePedestal object is associated with this
1579 // then copy its pedestal into the pedestal member of this
1580 // pulse integral object. Furthermore, if the pedestal is
1581 // *not* emulated and we have a configuration parameter from
1582 // the datastream for the number of samples the pedestal
1583 // represents, then copy this into the nsamples_pedestal.
1584 if(pp){
1585 pi->pedestal = pp->pedestal;
1586 if(!pp->emulated){
1587 if(conf!=NULL__null){
1588 if(conf->NPED != 0xFFFF){
1589 pi->nsamples_pedestal = conf->NPED;
1590 }
1591 }
1592 }
1593 }
1594
1595 // If this pulse integral is *not* emulated AND there is
1596 // a configuration object from the data stream associated,
1597 // then copy the number of samples for the integral from it.
1598 if(!pi->emulated){
1599 if(conf){
1600 pi->nsamples_integral = conf->NSA_NSB;
1601 }
1602 }
1603 }
1604 vector<JObject*> &vpi125 = hit_objs_by_type["Df125PulseIntegral"];
1605 for(unsigned int i=0; i<vpi125.size(); i++){
1606
1607 Df125PulseIntegral *pi = (Df125PulseIntegral*)vpi125[i];
1608 const Df125Config*conf = NULL__null;
1609 const Df125PulsePedestal*pp = NULL__null;
1610 pi->GetSingle(conf);
1611 pi->GetSingle(pp);
1612
1613 // If a Df125PulsePedestal object is associated with this
1614 // then copy its pedestal into the pedestal member of this
1615 // pulse integral object. Furthermore, if the pedestal is
1616 // *not* emulated then copy the number of pedestal samples.
1617 // (n.b. the value of nsamples should have been set based
1618 // on the configuration parameter in a separate loop over
1619 // Df125PulsePedestal objects above.)
1620 if(pp){
1621 pi->pedestal = pp->pedestal;
1622 if(!pp->emulated) pi->nsamples_pedestal = pp->nsamples;
1623 }
1624
1625 // If this pulse integral is *not* emulated AND there is
1626 // a configuration object from the data stream associated,
1627 // then copy the number of samples for the integral from it.
1628 if(!pi->emulated){
1629 if(conf){
1630 pi->nsamples_integral = conf->NSA_NSB;
1631 }
1632 }
1633 }
1634 vector<JObject*> &vcdcp125 = hit_objs_by_type["Df125CDCPulse"];
1635 for(unsigned int i=0; i<vcdcp125.size(); i++){
1636
1637 Df125CDCPulse *cdcp = (Df125CDCPulse*)vcdcp125[i];
1638 const Df125Config*conf = NULL__null;
1639 cdcp->GetSingle(conf);
1640
1641 // If this CDCpulse is *not* emulated AND there is
1642 // a configuration object from the data stream associated,
1643 // then copy the number of samples for the integral from it.
1644 if(!cdcp->emulated){
1645 if(conf){
1646 //cdcp->nsamples_integral = conf->NSA_NSB;
1647 int TC = (int)cdcp->le_time/10+1;
1648 //int PG = conf->PG; does not yet work
1649 int PG = 4;
1650 int END = ( (TC-PG+conf->IE) > (conf->NW - 20) ) ? (conf->NW - 20) : (TC-PG + conf->IE) ;
1651 int nsamp = END - (TC-PG);
1652 if (nsamp>0){
1653 cdcp->nsamples_integral = nsamp;
1654 } else {
1655 cdcp->nsamples_integral = 1;
1656 }
1657 }
1658 }
1659 }
1660
1661 vector<JObject*> &vfdcp125 = hit_objs_by_type["Df125FDCPulse"];
1662 for(unsigned int i=0; i<vfdcp125.size(); i++){
1663
1664 Df125FDCPulse *fdcp = (Df125FDCPulse*)vfdcp125[i];
1665 const Df125Config*conf = NULL__null;
1666 fdcp->GetSingle(conf);
1667
1668 // If this FDCpulse is *not* emulated AND there is
1669 // a configuration object from the data stream associated,
1670 // then copy the number of samples for the integral from it.
1671 if(!fdcp->emulated){
1672 if(conf){
1673 //fdcp->nsamples_integral = conf->NSA_NSB;
1674 int TC = (int)fdcp->le_time/10+1;
1675 //int PG = conf->PG; does not yet work
1676 int PG = 4;
1677 int END = ( (TC-PG+conf->IE) > (conf->NW - 20) ) ? (conf->NW - 20) : (TC-PG + conf->IE) ;
1678 int nsamp = END - (TC-PG);
1679 if (nsamp>0){
1680 fdcp->nsamples_integral = nsamp;
1681 } else {
1682 fdcp->nsamples_integral = 1;
1683 }
1684 }
1685 }
1686 }
1687
1688 // Loop over types of config objects, copying to appropriate factory
1689 map<string, vector<JObject*> >::iterator config_iter = config_objs_by_type.begin();
1690 for(; config_iter!=config_objs_by_type.end(); config_iter++){
1691 JFactory_base *fac = loop->GetFactory(config_iter->first, "", false); // false= don't allow default tag replacement
1692 if(fac) fac->CopyTo(config_iter->second);
1693 }
1694
1695 // Loop over types of hit objects, copying to appropriate factory
1696 map<string, vector<JObject*> >::iterator iter = hit_objs_by_type.begin();
1697 for(; iter!=hit_objs_by_type.end(); iter++){
1698 JFactory_base *fac = loop->GetFactory(iter->first, "", false); // false= don't allow default tag replacement
1699 fac->CopyTo(iter->second);
1700 }
1701
1702 // Loop over types of misc objects, copying to appropriate factory
1703 map<string, vector<JObject*> >::iterator misc_iter = misc_objs_by_type.begin();
1704 for(; misc_iter!=misc_objs_by_type.end(); misc_iter++){
1705 JFactory_base *fac = loop->GetFactory(misc_iter->first, "", false); // false= don't allow default tag replacement
1706 fac->CopyTo(misc_iter->second);
1707 }
1708 objs_ptr->own_objects = false;
1709
1710 // Copy pointers to BOR objects
1711 CopyBOR(loop, hit_objs_by_type);
1712
1713 // Returning OBJECT_NOT_AVAILABLE tells JANA that this source cannot
1714 // provide the type of object requested and it should try and generate
1715 // it via a factory algorithm. Returning NOERROR on the other hand
1716 // tells JANA that we can provide this type of object and any that
1717 // are present have already been copied into the appropriate factory.
1718 jerror_t err = OBJECT_NOT_AVAILABLE;
1719 if(strlen(factory->Tag()) == 0){ // We do not supply any tagged factory data here
1720 if(event_source_data_types.find(dataClassName) != event_source_data_types.end()) err = NOERROR;
1721 }
1722
1723 // If it turns out there are no objects of one of the types we supply
1724 // then the CopyTo method for that factory never gets called and subsequent
1725 // requests for that object type will end up calling this method again.
1726 // (For the case when this is done from the ApplyTranslationTable call
1727 // below, it results in an infinite loop!). To prevent this, we need to
1728 // mark all factories of the data types we supply as having had their
1729 // evnt method called.
1730 set<string>::iterator dtiter = event_source_data_types.begin();
1731 for(; dtiter!=event_source_data_types.end(); dtiter++){
1732 JFactory_base *fac = loop->GetFactory(*dtiter);
1733 if(fac) {
1734 // The DAQ_WRD2PI plugin wants to generate some objects from
1735 // the waveform data, overiding anything found in the file.
1736 // It this case, the factory's use_factory flag is set and
1737 // we should NOT mark the factory as having it's event method
1738 // called. Furthermore, we should delete any objects in the
1739 // factory.
1740 // Now, another complication is that the only way to check
1741 // the use_factory flag is to have a pointer to the JFactory
1742 // not the JFactory_base. This means we have to check the data
1743 // type of the factory and make the appropriate cast
1744 string dataClassName = fac->GetDataClassName();
1745 int checkSourceFirst = 1;
1746 if( dataClassName == "Df250Config") checkSourceFirst = ((JFactory<Df250Config >*)fac)->GetCheckSourceFirst();
1747 else if(dataClassName == "Df250PulseIntegral") checkSourceFirst = ((JFactory<Df250PulseIntegral >*)fac)->GetCheckSourceFirst();
1748 else if(dataClassName == "Df250StreamingRawData") checkSourceFirst = ((JFactory<Df250StreamingRawData>*)fac)->GetCheckSourceFirst();
1749 else if(dataClassName == "Df250WindowSum") checkSourceFirst = ((JFactory<Df250WindowSum >*)fac)->GetCheckSourceFirst();
1750 else if(dataClassName == "Df250PulseRawData") checkSourceFirst = ((JFactory<Df250PulseRawData >*)fac)->GetCheckSourceFirst();
1751 else if(dataClassName == "Df250TriggerTime") checkSourceFirst = ((JFactory<Df250TriggerTime >*)fac)->GetCheckSourceFirst();
1752 else if(dataClassName == "Df250PulseTime") checkSourceFirst = ((JFactory<Df250PulseTime >*)fac)->GetCheckSourceFirst();
1753 else if(dataClassName == "Df250PulsePedestal") checkSourceFirst = ((JFactory<Df250PulsePedestal >*)fac)->GetCheckSourceFirst();
1754 else if(dataClassName == "Df250WindowRawData") checkSourceFirst = ((JFactory<Df250WindowRawData >*)fac)->GetCheckSourceFirst();
1755 else if(dataClassName == "Df125Config") checkSourceFirst = ((JFactory<Df125Config >*)fac)->GetCheckSourceFirst();
1756 else if(dataClassName == "Df125PulseIntegral") checkSourceFirst = ((JFactory<Df125PulseIntegral >*)fac)->GetCheckSourceFirst();
1757 else if(dataClassName == "Df125TriggerTime") checkSourceFirst = ((JFactory<Df125TriggerTime >*)fac)->GetCheckSourceFirst();
1758 else if(dataClassName == "Df125PulseTime") checkSourceFirst = ((JFactory<Df125PulseTime >*)fac)->GetCheckSourceFirst();
1759 else if(dataClassName == "Df125PulsePedestal") checkSourceFirst = ((JFactory<Df125PulsePedestal >*)fac)->GetCheckSourceFirst();
1760 else if(dataClassName == "Df125WindowRawData") checkSourceFirst = ((JFactory<Df125WindowRawData >*)fac)->GetCheckSourceFirst();
1761 else if(dataClassName == "Df125CDCPulse") checkSourceFirst = ((JFactory<Df125CDCPulse >*)fac)->GetCheckSourceFirst();
1762 else if(dataClassName == "Df125FDCPulse") checkSourceFirst = ((JFactory<Df125FDCPulse >*)fac)->GetCheckSourceFirst();
1763 else if(dataClassName == "DF1TDCConfig") checkSourceFirst = ((JFactory<DF1TDCConfig >*)fac)->GetCheckSourceFirst();
1764 else if(dataClassName == "DF1TDCHit") checkSourceFirst = ((JFactory<DF1TDCHit >*)fac)->GetCheckSourceFirst();
1765 else if(dataClassName == "DF1TDCTriggerTime") checkSourceFirst = ((JFactory<DF1TDCTriggerTime >*)fac)->GetCheckSourceFirst();
1766 else if(dataClassName == "DCAEN1290TDCConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCConfig >*)fac)->GetCheckSourceFirst();
1767 else if(dataClassName == "DCAEN1290TDCHit") checkSourceFirst = ((JFactory<DCAEN1290TDCHit >*)fac)->GetCheckSourceFirst();
1768 else if(dataClassName == "DCODAEventInfo") checkSourceFirst = ((JFactory<DCODAEventInfo >*)fac)->GetCheckSourceFirst();
1769 else if(dataClassName == "DCODAROCInfo") checkSourceFirst = ((JFactory<DCODAROCInfo >*)fac)->GetCheckSourceFirst();
1770 else if(dataClassName == "Df250BORConfig") checkSourceFirst = ((JFactory<Df250BORConfig >*)fac)->GetCheckSourceFirst();
1771 else if(dataClassName == "Df125BORConfig") checkSourceFirst = ((JFactory<Df125BORConfig >*)fac)->GetCheckSourceFirst();
1772 else if(dataClassName == "DF1TDCBORConfig") checkSourceFirst = ((JFactory<DF1TDCBORConfig >*)fac)->GetCheckSourceFirst();
1773 else if(dataClassName == "DCAEN1290TDCBORConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCBORConfig>*)fac)->GetCheckSourceFirst();
1774
1775 if(checkSourceFirst) {
1776 fac->Set_evnt_called();
1777 }else{
1778 // Factory wants to generate these so delete any read
1779 // from source.
1780 fac->Reset();
1781 }
1782 }
1783 }
1784
1785 // If a translation table object is available, use it to create
1786 // detector hits from the low-level DAQ objects we just created.
1787 for(unsigned int i=0; i<translationTables.size(); i++){
1788 translationTables[i]->ApplyTranslationTable(loop);
1789 if(translationTables[i]->IsSuppliedType(dataClassName))
1790 if(strlen(factory->Tag()) == 0)err = NOERROR; // Don't allow tagged factories from Translation table
1791 }
1792
1793 if(VERBOSE>2) evioout << " Leaving GetObjects()" << endl;
1794
1795 return err;
1796}
1797
1798//----------------
1799// CopyBOR
1800//----------------
1801void JEventSource_EVIO::CopyBOR(JEventLoop *loop, map<string, vector<JObject*> > &hit_objs_by_type)
1802{
1803 /// Copy pointers to BOR (Beginning Of Run) objects into the
1804 /// appropriate factories for this event. The objects are flagged
1805 /// so that the factories won't delete them and the objects
1806 /// may be reused on subsequent events.
1807
1808 pthread_rwlock_rdlock(&BOR_lock);
1809
1810 // Make list of BOR objects of each type
1811 map<string, vector<JObject*> > bor_objs_by_type;
1812 for(unsigned int i=0; i<BORobjs.size(); i++){
1813 JObject *jobj = BORobjs[i];
1814 bor_objs_by_type[jobj->className()].push_back(jobj);
1815 }
1816
1817 // Loop over types of BOR objects, copying to appropriate factory
1818 map<string, vector<JObject*> >::iterator iter = bor_objs_by_type.begin();
1819 for(; iter!=bor_objs_by_type.end(); iter++){
1820 const string &bor_obj_name = iter->first;
1821 vector<JObject*> &bors = iter->second;
1822 JFactory_base *fac = loop->GetFactory(bor_obj_name, "", false); // false= don't allow default tag replacement
1823 if(fac){
1824 fac->CopyTo(bors);
1825 fac->SetFactoryFlag(JFactory_base::NOT_OBJECT_OWNER);
1826 }
1827
1828 // Associate with hit objects from this type of module
1829 if(bor_obj_name == "Df250BORConfig"){
1830 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["Df250PulseIntegral"]);
1831 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulsePedestal>(bors, hit_objs_by_type["Df250PulsePedestal"]);
1832 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250PulseTime>(bors, hit_objs_by_type["Df250PulseTime"]);
1833 LinkAssociationsModuleOnlyWithCast<Df250BORConfig,Df250WindowRawData>(bors, hit_objs_by_type["Df250WindowRawData"]);
1834 }
1835 if(bor_obj_name == "Df125BORConfig"){
1836 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125CDCPulse>(bors, hit_objs_by_type["Df250PulseIntegral"]);
1837 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125FDCPulse>(bors, hit_objs_by_type["Df250PulsePedestal"]);
1838 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulseIntegral>(bors, hit_objs_by_type["Df250PulseTime"]);
1839 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulsePedestal>(bors, hit_objs_by_type["Df250WindowRawData"]);
1840 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125PulseTime>(bors, hit_objs_by_type["Df250WindowRawData"]);
1841 LinkAssociationsModuleOnlyWithCast<Df125BORConfig,Df125WindowRawData>(bors, hit_objs_by_type["Df250WindowRawData"]);
1842 }
1843 if(bor_obj_name == "DF1TDCBORConfig"){
1844 LinkAssociationsModuleOnlyWithCast<DF1TDCBORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["DF1TDCHit"]);
1845 }
1846 if(bor_obj_name == "DCAEN1290TDCBORConfig"){
1847 LinkAssociationsModuleOnlyWithCast<DCAEN1290TDCBORConfig,Df250PulseIntegral>(bors, hit_objs_by_type["DCAEN1290TDCHit"]);
1848 }
1849 }
1850
1851 pthread_rwlock_unlock(&BOR_lock);
1852}
1853
1854//----------------
1855// AddSourceObjectsToCallStack
1856//----------------
1857void JEventSource_EVIO::AddSourceObjectsToCallStack(JEventLoop *loop, string className)
1858{
1859 /// This is used to give information to JANA regarding the origin of objects
1860 /// that *should* come from the source. We add them in explicitly because
1861 /// the file may not have any, but factories may ask for them. We want those
1862 /// links to indicate that the "0" objects in the factory came from the source
1863 /// so that janadot draws these objects correctly.
1864
1865 JEventLoop::call_stack_t cs;
1866 cs.caller_name = "<ignore>"; // tells janadot this object wasn't actually requested by anybody
1867 cs.caller_tag = "";
1868 cs.callee_name = className;
1869 cs.callee_tag = "";
1870 cs.start_time = 0.0;
1871 cs.end_time = 0.0;
1872 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1873 loop->AddToCallStack(cs);
1874}
1875
1876//----------------
1877// AddEmulatedObjectsToCallStack
1878//----------------
1879void JEventSource_EVIO::AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
1880{
1881 /// This is used to give information to JANA regarding the relationship and
1882 /// origin of some of these data objects. This is really just needed so that
1883 /// the janadot program can be used to produce the correct callgraph. Because
1884 /// of how this plugin works, JANA can't record the correct call stack (at
1885 /// least not easily!) Therefore, we have to give it a little help here.
1886
1887 JEventLoop::call_stack_t cs;
1888 cs.caller_name = caller;
1889 cs.callee_name = callee;
1890 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1891 loop->AddToCallStack(cs);
1892 cs.callee_name = cs.caller_name;
1893 cs.caller_name = "<ignore>";
1894 cs.data_source = JEventLoop::DATA_FROM_FACTORY;
1895 loop->AddToCallStack(cs);
1896}
1897
1898
1899//----------------
1900// EmulateDf250PulseIntegral
1901//----------------
1902void JEventSource_EVIO::EmulateDf250PulseIntegral(vector<JObject*> &wrd_objs, vector<JObject*> &pi_objs)
1903{
1904 if(VERBOSE>3) evioout << " Entering EmulateDf250PulseIntegral ..." <<endl;
1905
1906 // If emulation is being forced, then delete any existing objects.
1907 // We take extra care to check that we don't delete any existing
1908 // emulated objects. (I don't think there actually can be any at
1909 // this point, but this may protect against future upgrades to
1910 // the code.)
1911 if(F250_PI_EMULATION_MODE==kEmulationAlways){
1912 vector<JObject*> emulated_pi_objs;
1913 for(uint32_t j=0; j<pi_objs.size(); j++){
1914 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1915 if(pi->emulated){
1916 emulated_pi_objs.push_back(pi);
1917 }else{
1918 delete pi;
1919 }
1920 }
1921 pi_objs = emulated_pi_objs;
1922 }
1923
1924 uint32_t pulse_number = 0;
1925 uint32_t quality_factor = 0;
1926
1927 // Loop over all window raw data objects
1928 for(unsigned int i=0; i<wrd_objs.size(); i++){
1929 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
1930
1931 // If in auto mode then check if any pulse time objects already
1932 // exist for this channel and clear the emulate_pi flag if so.
1933 bool emulate_pi = true;
1934 if(F250_PI_EMULATION_MODE == kEmulationAuto){
1935 for(uint32_t j=0; j<pi_objs.size(); j++){
1936 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1937 if(pi->rocid == f250WindowRawData->rocid){
1938 if(pi->slot == f250WindowRawData->slot){
1939 if(pi->channel == f250WindowRawData->channel){
1940 if(pi->emulated){
1941 jerr << "Emulating channel that already has emulated objects!" << endl;
1942 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1943 jerr << "PulseIntegral250: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
1944 jerr << "please report error to davidl@jlab.org" << endl;
1945 exit(-1);
1946 }
1947 emulate_pi = false;
1948 break;
1949 }
1950 }
1951 }
1952 }
1953 }
1954
1955 // If we're not emulating a pulse integral here then no need to proceed.
1956 if(!emulate_pi) continue;
1957
1958 // Get a vector of the samples for this channel
1959 const vector<uint16_t> &samplesvector = f250WindowRawData->samples;
1960 uint32_t nsamples=samplesvector.size();
1961 uint32_t signalsum = 0;
1962
1963 // variables to store the sample numbers
1964 uint32_t sn_min = 0, sn_max = 0;
1965 uint32_t min = samplesvector[sn_min];
1966 uint32_t max = samplesvector[sn_max];
1967
1968 // get max and min information to decide on which algorithm to use
1969 for (uint32_t c_samp=1; c_samp<nsamples; c_samp++) {
1970 if (samplesvector[c_samp] > max) {
1971 max = samplesvector[c_samp];
1972// sn_max = c_samp;
1973 }
1974 if (samplesvector[c_samp] < min) {
1975 min = samplesvector[c_samp];
1976// sn_min = c_samp;
1977 }
1978 }
1979 // if no signal, don't process further
1980 if (max-min < F250_EMULATION_MIN_SWING) {
1981 if(VERBOSE>4) evioout << " EmulateDf250PulseIntergral: object " << i << " max - min < "
1982 << F250_EMULATION_MIN_SWING <<endl;
1983 continue;
1984 }
1985 // if the min and max are reasonable compared to the threshold then use the requested threshold
1986 // otherwise adjust it to work better.
1987 uint32_t threshold = 0;
1988 if (min < F250_THRESHOLD-5 && max > F250_THRESHOLD+5) {
1989 threshold = F250_THRESHOLD;
1990 } else {
1991 threshold = (min + max)/2;
1992 quality_factor = 1;
1993 }
1994 // find the threshold crossing
1995 uint32_t first_sample_over_threshold = 0;
1996 for (uint32_t c_samp=0; c_samp<nsamples; c_samp++) {
1997 if(VERBOSE>5) evioout << c_samp << " " << samplesvector[c_samp] << " " << threshold <<endl;
1998 if (samplesvector[c_samp] > threshold) {
1999 first_sample_over_threshold = c_samp;
2000 if(VERBOSE>4) evioout << " EmulateDf250PulseIntegral: object " << i << " found value over "
2001 << threshold << " at samp " << c_samp << " with value " << samplesvector[c_samp] <<endl;
2002 break;
2003 }
2004 }
2005
2006 // calculate integral from relevant samples
2007 uint32_t start_sample = first_sample_over_threshold - F250_NSB;
2008 uint32_t end_sample = first_sample_over_threshold + F250_NSA; // first sample past where we should sum
2009 uint32_t nsamples_used = 0;
2010 if (F250_NSB > first_sample_over_threshold) start_sample=0;
2011 if (end_sample > nsamples) end_sample=nsamples;
2012 for (uint32_t c_samp=start_sample; c_samp<end_sample; c_samp++) {
2013 signalsum += samplesvector[c_samp];
2014 nsamples_used++;
2015 }
2016
2017 // Apply sparsification threshold
2018 if(signalsum < F250_SPARSIFICATION_THRESHOLD) continue;
2019
2020 // create new Df250PulseIntegral object
2021 Df250PulseIntegral *myDf250PulseIntegral = new Df250PulseIntegral;
2022 myDf250PulseIntegral->rocid =f250WindowRawData->rocid;
2023 myDf250PulseIntegral->slot = f250WindowRawData->slot;
2024 myDf250PulseIntegral->channel = f250WindowRawData->channel;
2025 myDf250PulseIntegral->itrigger = f250WindowRawData->itrigger;
2026 myDf250PulseIntegral->pulse_number = pulse_number;
2027 myDf250PulseIntegral->quality_factor = quality_factor;
2028 myDf250PulseIntegral->integral = signalsum;
2029 myDf250PulseIntegral->pedestal = 0;
2030 myDf250PulseIntegral->nsamples_integral = nsamples_used;
2031 myDf250PulseIntegral->nsamples_pedestal = 1;
2032 myDf250PulseIntegral->emulated = true;
2033
2034 // Add the Df250WindowRawData object as an associated object
2035 myDf250PulseIntegral->AddAssociatedObject(f250WindowRawData);
2036 pi_objs.push_back(myDf250PulseIntegral);
2037 }
2038
2039 if(VERBOSE>3) evioout << " Leaving EmulateDf250PulseIntegral" <<endl;
2040}
2041
2042//----------------
2043// EmulateDf125PulseIntegral
2044//----------------
2045void JEventSource_EVIO::EmulateDf125PulseIntegral(vector<JObject*> &wrd_objs, vector<JObject*> &pi_objs,
2046 vector<JObject*> &pt_objs,
2047 vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2048{
2049 if(VERBOSE>3) evioout << " Entering EmulateDf125PulseIntegral ..." <<endl;
2050
2051 // If emulation is being forced, then delete any existing objects.
2052 // We take extra care to check that we don't delete any existing
2053 // emulated objects. (I don't think there actually can be any at
2054 // this point, but this may protect against future upgrades to
2055 // the code.)
2056 if(F125_PI_EMULATION_MODE==kEmulationAlways){
2057 vector<JObject*> emulated_pi_objs;
2058 for(uint32_t j=0; j<pi_objs.size(); j++){
2059 Df125PulseIntegral *pi = (Df125PulseIntegral*)pi_objs[j];
2060 if(pi->emulated){
2061 emulated_pi_objs.push_back(pi);
2062 }else{
2063 delete pi;
2064 }
2065 }
2066 pi_objs = emulated_pi_objs;
2067 }
2068
2069 uint32_t pulse_number = 0;
2070 uint32_t quality_factor = 0;
2071 // Loop over all window raw data objects
2072 for(unsigned int i=0; i<wrd_objs.size(); i++){
2073 const Df125WindowRawData *wrd = (Df125WindowRawData*)wrd_objs[i];
2074
2075 // If in auto mode then check if any pulse time objects already
2076 // exist for this channel and clear the emulate_pi flag if so.
2077 bool emulate_pi = true;
2078 if(F125_PI_EMULATION_MODE == kEmulationAuto){
2079 for(uint32_t j=0; j<pi_objs.size(); j++){
2080 Df125PulseIntegral *pi = (Df125PulseIntegral*)pi_objs[j];
2081 if(pi->rocid == wrd->rocid){
2082 if(pi->slot == wrd->slot){
2083 if(pi->channel == wrd->channel){
2084 if(pi->emulated){
2085 jerr << "Emulating channel that already has emulated objects!" << endl;
2086 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2087 jerr << "PulseIntegral125: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
2088 jerr << "please report error to davidl@jlab.org" << endl;
2089 exit(-1);
2090 }
2091 emulate_pi = false;
2092 break;
2093 }
2094 }
2095 }
2096 }
2097
2098 //switch off PI emulation if CDC pulse time objects are found
2099 for(uint32_t j=0; j<cp_objs.size(); j++){
2100 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2101 if(cp->rocid == wrd->rocid){
2102 if(cp->slot == wrd->slot){
2103 if(cp->channel == wrd->channel){
2104 emulate_pi = false;
2105 break;
2106 }
2107 }
2108 }
2109 }
2110
2111 //switch off PI emulation if FDC pulse time objects are found
2112 for(uint32_t j=0; j<fp_objs.size(); j++){
2113 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2114 if(fp->rocid == wrd->rocid){
2115 if(fp->slot == wrd->slot){
2116 if(fp->channel == wrd->channel){
2117 emulate_pi = false;
2118 break;
2119 }
2120 }
2121 }
2122 }
2123 }
2124
2125 // If we're not emulating a pulse integral here then no need to proceed.
2126 if(!emulate_pi) continue;
2127
2128 // Find pulse time for this channel
2129 const Df125PulseTime *T = NULL__null;
2130 for (unsigned int k=0; k<pt_objs.size(); k++){
2131 const Df125PulseTime *t = (Df125PulseTime*)pt_objs[k];
2132 if( t->rocid == wrd->rocid ){
2133 if( t->slot == wrd->slot ) {
2134 if( t->channel == wrd->channel ){
2135 T = t;
2136 break;
2137 }
2138 }
2139 }
2140 }
2141
2142 // Choose value of NSA and NSB based on rocid (eechh!)
2143 uint32_t NSA = F125_NSA;
2144 uint32_t NSB = F125_NSB;
2145 if(wrd->rocid>=24 && wrd->rocid<=28){
2146 NSA = F125_NSA_CDC;
2147 NSB = F125_NSB_CDC;
2148 }
2149
2150 // Get a vector of the samples for this channel
2151 const vector<uint16_t> &samplesvector = wrd->samples;
2152 uint32_t nsamples=samplesvector.size();
2153 uint32_t signalsum = 0;
2154
2155 // loop over all samples to calculate integral
2156 uint32_t nsamples_used = 0;
2157
2158 uint32_t BinTC = T==NULL__null ? 0:(T->time >> 6);
2159 uint32_t StartSample = BinTC - NSB;
2160 if( NSB > BinTC) {
2161 StartSample = 0;
2162 }
2163 uint32_t EndSample = BinTC + NSA;
2164 if (EndSample>nsamples-1){
2165 EndSample = nsamples;
2166 }
2167 for (uint32_t c_samp=StartSample; c_samp<EndSample; c_samp++) {
2168 if(c_samp>=samplesvector.size()){
2169 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<2169<<" "
<< "Sample number outside of range of samples (c_samp="<<c_samp<<" >= samplesvector.size()="<<samplesvector.size()<<")" << endl;
2170 break;
2171 }
2172 signalsum += samplesvector[c_samp];
2173 nsamples_used++;
2174 }
2175
2176 // Apply sparsification threshold
2177 if(signalsum < F125_SPARSIFICATION_THRESHOLD) continue;
2178
2179 // create new Df125PulseIntegral object
2180 Df125PulseIntegral *myDf125PulseIntegral = new Df125PulseIntegral;
2181 myDf125PulseIntegral->rocid =wrd->rocid;
2182 myDf125PulseIntegral->slot = wrd->slot;
2183 myDf125PulseIntegral->channel = wrd->channel;
2184 myDf125PulseIntegral->itrigger = wrd->itrigger;
2185 myDf125PulseIntegral->pulse_number = pulse_number;
2186 myDf125PulseIntegral->quality_factor = quality_factor;
2187 myDf125PulseIntegral->integral = signalsum;
2188 myDf125PulseIntegral->pedestal = 0; // This will be replaced by the one from Df125PulsePedestal in GetObjects
2189 myDf125PulseIntegral->nsamples_integral = nsamples_used;
2190 myDf125PulseIntegral->nsamples_pedestal = 1;
2191 myDf125PulseIntegral->emulated = true;
2192
2193 // Add the Df125WindowRawData object as an associated object
2194 myDf125PulseIntegral->AddAssociatedObject(wrd);
2195 pi_objs.push_back(myDf125PulseIntegral);
2196 }
2197
2198 if(VERBOSE>3) evioout << " Leaving EmulateDf125PulseIntegral" <<endl;
2199}
2200
2201//----------------
2202// EmulateDf250PulseTime
2203//----------------
2204void JEventSource_EVIO::EmulateDf250PulseTime(vector<JObject*> &wrd_objs, vector<JObject*> &pt_objs, vector<JObject*> &pp_objs)
2205{
2206 if(VERBOSE>3) evioout << " Entering EmulateDf250PulseTime ..." <<endl;
2207
2208 // If emulation is being forced, then delete any existing objects.
2209 // We take extra care to check that we don't delete any existing
2210 // emulated objects. (I don't think there actually can be any at
2211 // this point, but this may protect against future upgrades to
2212 // the code.)
2213 if(F250_PT_EMULATION_MODE==kEmulationAlways){
2214 vector<JObject*> emulated_pt_objs;
2215 for(uint32_t j=0; j<pt_objs.size(); j++){
2216 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
2217 if(pt->emulated){
2218 emulated_pt_objs.push_back(pt);
2219 }else{
2220 delete pt;
2221 }
2222 }
2223 pt_objs = emulated_pt_objs;
2224 }
2225 if(F250_PP_EMULATION_MODE==kEmulationAlways){
2226 vector<JObject*> emulated_pp_objs;
2227 for(uint32_t j=0; j<pp_objs.size(); j++){
2228 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
2229 if(pp->emulated){
2230 emulated_pp_objs.push_back(pp);
2231 }else{
2232 delete pp;
2233 }
2234 }
2235 pp_objs = emulated_pp_objs;
2236 }
2237
2238
2239 // Loop over all window raw data objects
2240 for(unsigned int i=0; i<wrd_objs.size(); i++){
2241 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
2242
2243 // If in auto mode then check if any pulse time objects already
2244 // exists for this channel and clear the emulate_pt flag if so.
2245 bool emulate_pt = true;
2246 if(F250_PT_EMULATION_MODE == kEmulationAuto){
2247 for(uint32_t j=0; j<pt_objs.size(); j++){
2248 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
2249 if(pt->rocid == f250WindowRawData->rocid){
2250 if(pt->slot == f250WindowRawData->slot){
2251 if(pt->channel == f250WindowRawData->channel){
2252 if(pt->emulated){
2253 jerr << "Emulating channel that already has emulated objects!" << endl;
2254 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2255 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
2256 jerr << "please report error to davidl@jlab.org" << endl;
2257 exit(-1);
2258 }
2259 emulate_pt = false;
2260 break;
2261 }
2262 }
2263 }
2264 }
2265 }
2266
2267 // Ditto for pulse pedestal objects
2268 bool emulate_pp = true;
2269 if(F250_PP_EMULATION_MODE == kEmulationAuto){
2270 for(uint32_t j=0; j<pp_objs.size(); j++){
2271 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
2272 if(pp->rocid == f250WindowRawData->rocid){
2273 if(pp->slot == f250WindowRawData->slot){
2274 if(pp->channel == f250WindowRawData->channel){
2275 if(pp->emulated){
2276 jerr << "Emulating channel that already has emulated objects!" << endl;
2277 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2278 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
2279 jerr << "please report error to davidl@jlab.org" << endl;
2280 exit(-1);
2281 }
2282 emulate_pp = false;
2283 break;
2284 }
2285 }
2286 }
2287 }
2288 }
2289
2290 // Skip to next wrd if nothing is to be emulated
2291 if( (!emulate_pt) && (!emulate_pp) ) continue;
2292
2293 // Get a vector of the samples for this channel
2294 const vector<uint16_t> &samplesvector = f250WindowRawData->samples;
2295 uint32_t nsamples=samplesvector.size();
2296
2297 // variables to store the sample numbers
2298 uint32_t sn_min = 0, sn_max = 0;
2299 uint32_t min = samplesvector[sn_min];
2300 uint32_t max = samplesvector[sn_max];
2301
2302 // get max and min information to decide on which algorithm to use
2303 for (uint32_t c_samp=1; c_samp<nsamples; c_samp++) {
2304 if (samplesvector[c_samp] > max) {
2305 max = samplesvector[c_samp];
2306// sn_max = c_samp;
2307 }
2308 if (samplesvector[c_samp] < min) {
2309 min = samplesvector[c_samp];
2310// sn_min = c_samp;
2311 }
2312 }
2313 // if no signal, don't process further
2314 if (max-min < F250_EMULATION_MIN_SWING) {
2315 if(VERBOSE>4) evioout << " EmulateDf250PulseIntergral: object " << i << " max - min < "
2316 << F250_EMULATION_MIN_SWING <<endl;
2317 continue;
2318 }
2319 // if the min and max are reasonable compared to the threshold then use the requested threshold
2320 // otherwise adjust it to work better
2321 uint32_t threshold = 0;
2322 if (min < F250_THRESHOLD-5 && max > F250_THRESHOLD+5) {
2323 threshold = F250_THRESHOLD;
2324 } else {
2325 threshold = (min + max)/2;
2326 }
2327 // find the threshold crossing
2328 int32_t first_sample_over_threshold = -1000;
2329 for (uint32_t c_samp=0; c_samp<nsamples; c_samp++) {
2330 if (samplesvector[c_samp] > threshold) {
2331 first_sample_over_threshold = c_samp;
2332 if(VERBOSE>4) evioout << " EmulateDf250PulseTime: object " << i << " found value over " << threshold << " at samp "
2333 << c_samp << " with value " << samplesvector[c_samp] <<endl;
2334 break;
2335 }
2336 }
2337 // Define the variables for the time extraction (named as in the f250 documentation)
2338 uint32_t VPEAK = 0, VMIN = 0, VMID = 0;
2339 uint32_t VN1=0, VN2=0;
2340 double time_fraction = -1000;
2341
2342 // loop over the first F250_NSPED samples to calculate pedestal
2343 uint32_t pedestalsum = 0;
2344 for (uint32_t c_samp=0; c_samp<F250_NSPED; c_samp++) {
2345 pedestalsum += samplesvector[c_samp];
2346 }
2347 uint32_t pedestalavg = ( F250_NSPED==0 ? 0:(pedestalsum/F250_NSPED) );
2348 VMIN = pedestalavg;
2349
2350 uint32_t time = 0;
2351 uint32_t mid_sample = 0;
2352 if (VMIN > threshold) { // firmware requires VMIN < F250_THRESHOLD
2353 time_fraction = 0;
2354 }
2355 if (first_sample_over_threshold == 0) {
2356 time_fraction = 1;
2357 }
2358 if (time_fraction < 0) {
2359 // Find maximum by looking for signal downturn
2360 for (uint32_t c_samp=first_sample_over_threshold; c_samp<nsamples; c_samp++) {
2361 if (samplesvector[c_samp] > VPEAK) {
2362 VPEAK = samplesvector[c_samp];
2363 } else {
2364 // we found the downturn
2365 break;
2366 }
2367 }
2368 VMID = (VPEAK + VMIN)/2;
2369
2370 // find the adjacent samples that straddle the VMID crossing
2371 for (uint32_t c_samp=0; c_samp<nsamples; c_samp++) {
2372 if (samplesvector[c_samp] > VMID) {
2373 if (c_samp==0) {
2374 // evioout << " EmulateDf250PulseTime: object " << i << " c_samp=" << c_samp
2375 // << " samplesvector[c_samp]=" << samplesvector[c_samp] << " VMID=" << VMID << endl;
2376 // evioout << " EmulateDf250PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2377 // << " mid_sample=" << mid_sample << " max_sample=" << max_sample
2378 // << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2379 // << " time=" << time << " sample_over=" << first_sample_over_threshold <<endl;
2380 } else {
2381 VN2 = samplesvector[c_samp];
2382 VN1 = samplesvector[c_samp-1];
2383 mid_sample = c_samp-1;
2384 break;
2385 }
2386 }
2387 }
2388 }
2389 time_fraction = mid_sample + ((double)(VMID-VN1))/((double)(VN2-VN1));
2390 time = time_fraction*64;
2391 if(VERBOSE>4) evioout << " EmulateDf250PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2392 << " mid_sample=" << mid_sample << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2393 << " time=" << time << " sample_over=" << first_sample_over_threshold << endl;
2394
2395 // create new Df250PulseTime object
2396 if(emulate_pt){
2397 Df250PulseTime *myDf250PulseTime = new Df250PulseTime;
2398 myDf250PulseTime->rocid =f250WindowRawData->rocid;
2399 myDf250PulseTime->slot = f250WindowRawData->slot;
2400 myDf250PulseTime->channel = f250WindowRawData->channel;
2401 myDf250PulseTime->itrigger = f250WindowRawData->itrigger;
2402 myDf250PulseTime->pulse_number = 0;
2403 myDf250PulseTime->quality_factor = 0;
2404 myDf250PulseTime->time = time;
2405 myDf250PulseTime->emulated = true;
2406 myDf250PulseTime->AddAssociatedObject(f250WindowRawData);
2407 pt_objs.push_back(myDf250PulseTime);
2408 }
2409
2410 // create new Df250PulsePedestal object
2411 if(emulate_pp){
2412 Df250PulsePedestal *myDf250PulsePedestal = new Df250PulsePedestal;
2413 myDf250PulsePedestal->rocid =f250WindowRawData->rocid;
2414 myDf250PulsePedestal->slot = f250WindowRawData->slot;
2415 myDf250PulsePedestal->channel = f250WindowRawData->channel;
2416 myDf250PulsePedestal->itrigger = f250WindowRawData->itrigger;
2417 myDf250PulsePedestal->pulse_number = 0;
2418 myDf250PulsePedestal->pedestal = pedestalavg; // Return the average pedestal. This is what the firmware will do.
2419 myDf250PulsePedestal->pulse_peak = VPEAK;
2420 myDf250PulsePedestal->emulated = true;
2421 myDf250PulsePedestal->AddAssociatedObject(f250WindowRawData);
2422 pp_objs.push_back(myDf250PulsePedestal);
2423 }
2424 }
2425
2426 // PulseTime and PulsePedestal objects are associated to one another in GetObjects
2427
2428 if(VERBOSE>3) evioout << " Leaving EmulateDf250PulseTime" <<endl;
2429}
2430
2431//----------------
2432// EmulateDf125PulseTime
2433//----------------
2434void JEventSource_EVIO::EmulateDf125PulseTime(vector<JObject*> &wrd_objs, vector<JObject*> &pt_objs, vector<JObject*> &pp_objs, vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2435{
2436 /// Emulation of the f125 can be done in one of two ways. The first
2437 /// implements an upsampling technique developed by Naomi Jarvis at
2438 /// CMU. This was not implemented in the firmware for the 2014 commissioning
2439 /// run, but was implemented for later runs. The second algorithm is
2440 /// supposed to match the firmware algorithm used in the f125 during the
2441 /// 2014 commissioning run. This is a copy of the f250 algorithm. At the
2442 /// time I'm writing this, it does not appear to give identical, or even
2443 /// terribly close results to what the actual firmware reported. To select
2444 /// using this second algorithm (the "f250 algorithm") set the
2445 /// EVIO:F125_TIME_UPSAMPLE config. parameter to "0". To turn
2446 /// on emulation for data that actually has hits in the data stream from
2447 /// the firmware, set the EVIO:F125_PT_EMULATION_MODE config. parameter
2448 /// to 1.
2449 ///
2450 /// NOTE: The upsampling algorithm here currently converts the value reported
2451 /// into units of 1/64 of a sample to match the units of the firmware
2452 /// version used for 2014 commissioning data. When the upsampling algorithm
2453 /// is implemented in firmware, the units reported by the firmware will
2454 /// change to 1/10 of a sample! 2/9/2014 DL
2455 ///
2456 /// Changed the units to 1/10 sample to match the firmware 3 Nov 2015 NSJ.
2457
2458
2459 if(VERBOSE>3) evioout << " Entering EmulateDf125PulseTime ..." <<endl;
2460
2461 // If emulation is being forced, then delete any existing objects.
2462 // We take extra care to check that we don't delete any existing
2463 // emulated objects. (I don't think there actually can be any at
2464 // this point, but this may protect against future upgrades to
2465 // the code.)
2466 if(F125_PT_EMULATION_MODE==kEmulationAlways){
2467 vector<JObject*> emulated_pt_objs;
2468 for(uint32_t j=0; j<pt_objs.size(); j++){
2469 Df125PulseTime *pt = (Df125PulseTime*)pt_objs[j];
2470 if(pt->emulated){
2471 emulated_pt_objs.push_back(pt);
2472 }else{
2473 delete pt;
2474 }
2475 }
2476 pt_objs = emulated_pt_objs;
2477 }
2478 if(F125_PP_EMULATION_MODE==kEmulationAlways){
2479 vector<JObject*> emulated_pp_objs;
2480 for(uint32_t j=0; j<pp_objs.size(); j++){
2481 Df125PulsePedestal *pp = (Df125PulsePedestal*)pp_objs[j];
2482 if(pp->emulated){
2483 emulated_pp_objs.push_back(pp);
2484 }else{
2485 delete pp;
2486 }
2487 }
2488 pp_objs = emulated_pp_objs;
2489 }
2490
2491 uint32_t Nped_samples = 4; // number of samples to use for pedestal calculation (PED_SAMPLE)
2492 uint32_t Nsamples = 14; // Number of samples used to define leading edge (was NSAMPLES in Naomi's code)
2493
2494 // Loop over all window raw data objects
2495 for(unsigned int i=0; i<wrd_objs.size(); i++){
2496 const Df125WindowRawData *f125WindowRawData = (Df125WindowRawData*)wrd_objs[i];
2497
2498 // If in auto mode then check if any pulse time objects already
2499 // exists for this channel and clear the emulate_pt flag if so.
2500 bool emulate_pt = true;
2501 if(F125_PT_EMULATION_MODE == kEmulationAuto){
2502 for(uint32_t j=0; j<pt_objs.size(); j++){
2503 Df125PulseTime *pt = (Df125PulseTime*)pt_objs[j];
2504 if(pt->rocid == f125WindowRawData->rocid){
2505 if(pt->slot == f125WindowRawData->slot){
2506 if(pt->channel == f125WindowRawData->channel){
2507 if(pt->emulated){
2508 jerr << "Emulating channel that already has emulated objects!" << endl;
2509 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2510 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
2511 jerr << "please report error to davidl@jlab.org" << endl;
2512 exit(-1);
2513 }
2514 emulate_pt = false;
2515 break;
2516 }
2517 }
2518 }
2519 }
2520
2521 //switch off PT auto-emulation if CDCPulse is found
2522 for(uint32_t j=0; j<cp_objs.size(); j++){
2523 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2524 if(cp->rocid == f125WindowRawData->rocid){
2525 if(cp->slot == f125WindowRawData->slot){
2526 if(cp->channel == f125WindowRawData->channel){
2527 emulate_pt = false;
2528 break;
2529 }
2530 }
2531 }
2532 }
2533
2534 //switch off PT auto-emulation if FDCPulse is found
2535 for(uint32_t j=0; j<fp_objs.size(); j++){
2536 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2537 if(fp->rocid == f125WindowRawData->rocid){
2538 if(fp->slot == f125WindowRawData->slot){
2539 if(fp->channel == f125WindowRawData->channel){
2540 emulate_pt = false;
2541 break;
2542 }
2543 }
2544 }
2545 }
2546 }
2547
2548 // Ditto for pulse pedestal objects
2549 bool emulate_pp = true;
2550 if(F125_PP_EMULATION_MODE == kEmulationAuto){
2551 for(uint32_t j=0; j<pp_objs.size(); j++){
2552 Df125PulsePedestal *pp = (Df125PulsePedestal*)pp_objs[j];
2553 if(pp->rocid == f125WindowRawData->rocid){
2554 if(pp->slot == f125WindowRawData->slot){
2555 if(pp->channel == f125WindowRawData->channel){
2556 if(pp->emulated){
2557 jerr << "Emulating channel that already has emulated objects!" << endl;
2558 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2559 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
2560 jerr << "please report error to davidl@jlab.org" << endl;
2561 exit(-1);
2562 }
2563 emulate_pp = false;
2564 break;
2565 }
2566 }
2567 }
2568 }
2569
2570 //switch off PP auto-emulation if CDCPulse is found
2571 for(uint32_t j=0; j<cp_objs.size(); j++){
2572 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2573 if(cp->rocid == f125WindowRawData->rocid){
2574 if(cp->slot == f125WindowRawData->slot){
2575 if(cp->channel == f125WindowRawData->channel){
2576 emulate_pp = false;
2577 break;
2578 }
2579 }
2580 }
2581 }
2582
2583 //switch off PP auto-emulation if FDCPulse is found
2584 for(uint32_t j=0; j<fp_objs.size(); j++){
2585 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2586 if(fp->rocid == f125WindowRawData->rocid){
2587 if(fp->slot == f125WindowRawData->slot){
2588 if(fp->channel == f125WindowRawData->channel){
2589 emulate_pp = false;
2590 break;
2591 }
2592 }
2593 }
2594 }
2595
2596 }
2597
2598 int rocid = f125WindowRawData->rocid;
2599
2600 // Get a vector of the samples for this channel
2601 const vector<uint16_t> &samplesvector = f125WindowRawData->samples;
2602 uint32_t Nsamples_all = samplesvector.size(); // (was NADCBUFFER in Naomi's code)
2603 if(Nsamples_all < (Nped_samples+Nsamples)){
2604 static int Nwarn=0;
2605 if(Nwarn<10){
2606 char str[256];
2607 sprintf(str, "Too few samples in Df125WindowRawData for pulse time extraction! Nsamples_all=%d, (Nped_samples+Nsamples)=%d", Nsamples_all, (Nped_samples+Nsamples));
2608 jerr << str << endl;
2609 if(++Nwarn==10) jerr << "--- Last Warning! ---" <<endl;
2610 }
2611 return;
2612// throw JException(str);
2613 }
2614
2615 bool found_hit = false;
2616 uint32_t time = 0;
2617 uint32_t quality_factor = 0;
2618 uint32_t pedestalavg = 0;
2619 uint32_t pulse_peak = 0;
2620 uint32_t overflows = 0;
2621
2622 // loop over the first ped_samples samples to calculate pedestal
2623 int32_t pedestalsum = 0;
2624 for (uint32_t c_samp=0; c_samp<Nped_samples; c_samp++) {
2625 pedestalsum += samplesvector[c_samp];
2626 }
2627 pedestalavg = pedestalsum / Nped_samples;
2628
2629 if(F125_TIME_UPSAMPLE){
2630 fa125_algos_data_t fa125_algos_data;
2631 //fa125_algos(rocid, samplesvector, fa125_algos_data);
2632 fa125_algos(rocid, samplesvector, fa125_algos_data, F125_CDC_WS, F125_CDC_WE, F125_CDC_IE, F125_CDC_NP, F125_CDC_NP2, F125_CDC_PG, F125_CDC_H, F125_CDC_TH, F125_CDC_TL, F125_FDC_WS, F125_FDC_WE, F125_FDC_IE, F125_FDC_NP, F125_FDC_NP2, F125_FDC_PG, F125_FDC_H, F125_FDC_TH, F125_FDC_TL);
2633
2634 time = fa125_algos_data.time;
2635 quality_factor = fa125_algos_data.q_code;
2636 pedestalavg = fa125_algos_data.pedestal;
2637 pulse_peak = fa125_algos_data.maxamp;
2638 overflows = fa125_algos_data.overflows;
2639
2640 // The upsampling algorithm reports times in units of 1/10 of a
2641 // sample while the f250 algorithm reports it in units of 1/64
2642 // of a sample. Convert to units of 1/64 of a sample here to
2643 // make this consistent with the other algorithms.
2644 // time = (time*64)/10; //removed 4Nov2015 NSJ
2645
2646 // In Naomi's original code, she checked if maxamp was >0 to decide
2647 // whether to add the value to the tree. Note that this ignored the
2648 // "hitfound" variable in the cdc_algos2 code. We follow her example
2649 // here. DL
2650 found_hit = pulse_peak > 0;
2651
2652 }else{ // not F125_TIME_UPSAMPLE
2653
2654 //----------F250 algorithm ----------
2655 // variables to store the sample numbers
2656 uint32_t sn_min = 0, sn_max = 0;
2657 uint32_t min = samplesvector[sn_min];
2658 uint32_t max = samplesvector[sn_max];
2659
2660 // get max and min information to decide on which algorithm to use
2661 for (uint32_t c_samp=1; c_samp<Nsamples_all; c_samp++) {
2662 if (samplesvector[c_samp] > max) {
2663 max = samplesvector[c_samp];
2664// sn_max = c_samp;
2665 }
2666 if (samplesvector[c_samp] < min) {
2667 min = samplesvector[c_samp];
2668// sn_min = c_samp;
2669 }
2670 }
2671 // if no signal, don't process further
2672 if (max-min < F125_EMULATION_MIN_SWING) {
2673 if(VERBOSE>4) evioout << " EmulateDf125PulseTime: object " << i << " max - min < " << F250_EMULATION_MIN_SWING <<endl;
2674 continue;
2675 }
2676 // if the min and max are reasonable compared to the threshold then use the requested threshold
2677 // otherwise adjust it to work better
2678 uint32_t threshold = 0;
2679 if (min < F125_THRESHOLD-5 && max > F125_THRESHOLD+5) {
2680 threshold = F125_THRESHOLD;
2681 } else {
2682 threshold = (min + max)/2;
2683 }
2684 // find the threshold crossing
2685 int32_t first_sample_over_threshold = -1000;
2686 for (uint32_t c_samp=0; c_samp<Nsamples_all; c_samp++) {
2687 if (samplesvector[c_samp] > threshold) {
2688 first_sample_over_threshold = c_samp;
2689 if(VERBOSE>4) evioout << " EmulateDf125PulseTime: object " << i << " found value over " << threshold << " at samp "
2690 << c_samp << " with value " << samplesvector[c_samp] <<endl;
2691 break;
2692 }
2693 }
2694 // Define the variables for the time extraction (named as in the f250 documentation)
2695 uint32_t VPEAK = 0, VMIN = pedestalavg, VMID = 0;
2696 uint32_t VN1=0, VN2=0;
2697 double time_fraction = -1000;
2698
2699
2700 uint32_t mid_sample = 0;
2701 if (VMIN > threshold) { // firmware requires VMIN < F125_THRESHOLD
2702 time_fraction = 0;
2703 }
2704 if (first_sample_over_threshold == 0) {
2705 time_fraction = 1;
2706 }
2707 if (time_fraction < 0) {
2708 // Find maximum by looking for signal downturn
2709 for (uint32_t c_samp=first_sample_over_threshold; c_samp<Nsamples_all; c_samp++) {
2710 if (samplesvector[c_samp] > VPEAK) {
2711 pulse_peak = VPEAK = samplesvector[c_samp];
2712 } else {
2713 // we found the downturn
2714 break;
2715 }
2716 }
2717 VMID = (VPEAK + VMIN)/2;
2718
2719 // find the adjacent samples that straddle the VMID crossing
2720 for (uint32_t c_samp=0; c_samp<Nsamples_all; c_samp++) {
2721 if (samplesvector[c_samp] > VMID) {
2722 if (c_samp==0) {
2723 // evioout << " EmulateDf125PulseTime: object " << i << " c_samp=" << c_samp
2724 // << " samplesvector[c_samp]=" << samplesvector[c_samp] << " VMID=" << VMID << endl;
2725 // evioout << " EmulateDf125PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2726 // << " mid_sample=" << mid_sample << " max_sample=" << max_sample
2727 // << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2728 // << " time=" << time << " sample_over=" << first_sample_over_threshold <<endl;
2729 } else {
2730 VN2 = samplesvector[c_samp];
2731 VN1 = samplesvector[c_samp-1];
2732 mid_sample = c_samp-1;
2733 break;
2734 }
2735 }
2736 }
2737 }
2738 time_fraction = mid_sample + ((double)(VMID-VN1))/((double)(VN2-VN1));
2739 time = time_fraction*64;
2740 quality_factor = 1;
2741 found_hit = true;
2742 if(VERBOSE>4)
2743 evioout << " EmulateDf125PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2744 << " mid_sample=" << mid_sample << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2745 << " time=" << time << " sample_over=" << first_sample_over_threshold << endl;
2746
2747
2748 } // F125_TIME_UPSAMPLE
2749
2750 // At this point we know we have a hit and will be able to extract a time.
2751 // Go ahead and make the PulseTime object, filling in the "rough" time.
2752 // and corresponding quality factor. The time and quality factor
2753 // will be updated later when and if we can calculate a more accurate one.
2754
2755 if(found_hit){
2756
2757 // create new Df125PulseTime object
2758 if(emulate_pt){
2759 Df125PulseTime *myDf125PulseTime = new Df125PulseTime;
2760 myDf125PulseTime->rocid =f125WindowRawData->rocid;
2761 myDf125PulseTime->slot = f125WindowRawData->slot;
2762 myDf125PulseTime->channel = f125WindowRawData->channel;
2763 myDf125PulseTime->itrigger = f125WindowRawData->itrigger;
2764 myDf125PulseTime->pulse_number = 0;
2765 myDf125PulseTime->quality_factor = quality_factor;
2766 myDf125PulseTime->time = time;
2767 myDf125PulseTime->overflows = overflows;
2768 myDf125PulseTime->emulated = true;
2769 myDf125PulseTime->AddAssociatedObject(f125WindowRawData);
2770 pt_objs.push_back(myDf125PulseTime);
2771
2772 // The following is empirical from the first BCAL/CDC cosmic data
2773 //myDf125PulseTime->time -= 170.0;
2774 if(myDf125PulseTime->time > 10000){
2775 // If calculated time is <170.0, then the unsigned int is problematic. Flag this if it happens
2776 myDf125PulseTime->time = 0;
2777 myDf125PulseTime->quality_factor = 2;
2778 }
2779 }
2780
2781 // create new Df125PulsePedestal object
2782 if(emulate_pp){
2783 Df125PulsePedestal *myDf125PulsePedestal = new Df125PulsePedestal;
2784 myDf125PulsePedestal->rocid =f125WindowRawData->rocid;
2785 myDf125PulsePedestal->slot = f125WindowRawData->slot;
2786 myDf125PulsePedestal->channel = f125WindowRawData->channel;
2787 myDf125PulsePedestal->itrigger = f125WindowRawData->itrigger;
2788 myDf125PulsePedestal->pulse_number = 0;
2789 myDf125PulsePedestal->pedestal = pedestalavg;
2790 myDf125PulsePedestal->pulse_peak = pulse_peak;
2791 myDf125PulsePedestal->emulated = true;
2792 myDf125PulsePedestal->AddAssociatedObject(f125WindowRawData);
2793 pp_objs.push_back(myDf125PulsePedestal);
2794 }
2795 } // found_hit
2796 } // i loop over wrd_objs.size()
2797
2798 // Add PulseTime and PulsePedestal objects as associate objects of one another
2799 vector<Df125PulseTime*> ppt_objs;
2800 vector<Df125PulsePedestal*> ppp_objs;
2801 CopyContainerElementsWithCast(pt_objs, ppt_objs);
2802 CopyContainerElementsWithCast(pp_objs, ppp_objs);
2803 LinkAssociationsWithPulseNumber(ppt_objs, ppp_objs);
2804
2805 if(VERBOSE>3) evioout << " Leaving EmulateDf125PulseTime" <<endl;
2806}
2807
2808//----------------
2809// GetRunNumber
2810//----------------
2811int32_t JEventSource_EVIO::GetRunNumber(evioDOMTree *evt)
2812{
2813 // Note: This is currently not used. Preference is
2814 // now given to the run number found in FindRunNumber
2815 // which is called from GetEvent. This makes things
2816 // a little simpler and ensures the run number originally
2817 // presented to the processor/factory does not change.
2818 // 2/15/2016 DL
2819
2820 // This is called during event parsing to get the
2821 // run number for the event.
2822 // Look through event to try and extract the run number.
2823 // We do this by looking for all uint64_t nodes. Then
2824 // check for a parent with one of the magic values for
2825 // the tag indicating it has run number information.
2826 if(USER_RUN_NUMBER>0) return USER_RUN_NUMBER;
2827 if(!evt) return last_run_number;
2828
2829 evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
2830 evioDOMNodeList::iterator iter = bankList->begin();
2831 const uint64_t *run_number_and_type = NULL__null;
2832 for(; iter!=bankList->end(); iter++){
2833 evioDOMNodeP bankPtr = *iter;
2834 evioDOMNodeP physics_event_built_trigger_bank = bankPtr->getParent();
2835 if(physics_event_built_trigger_bank == NULL__null) continue;
2836 uint32_t tag = physics_event_built_trigger_bank->tag;
2837 const vector<uint64_t> *vec;
2838 switch(tag){
2839 case 0xFF22:
2840 case 0xFF23:
2841 case 0xFF26:
2842 case 0xFF27:
2843 vec = bankPtr->getVector<uint64_t>();
2844 if(!vec) continue;
2845 if(vec->size()<1) continue;
2846 run_number_and_type = &((*vec)[vec->size()-1]);
2847 break;
2848 }
2849 if(run_number_and_type != NULL__null) break;
2850 }
2851
2852 if(run_number_and_type != NULL__null) last_run_number = (*run_number_and_type)>>32;
2853
2854 return last_run_number;
2855}
2856
2857//----------------
2858// FindRunNumber
2859//----------------
2860int32_t JEventSource_EVIO::FindRunNumber(uint32_t *iptr)
2861{
2862 /// This is called from GetEvent() to quickly look for the run number
2863 /// at the time the event is read in so it can be passed into
2864 /// JEvent. It is what will be used for accessing the CCDB.
2865 /// from this event. If a bank containing the run number is found,
2866 /// use it to provide the run number. Otherwise, return whatever run
2867 /// number we were able to extract from the file name.
2868
2869 if(VERBOSE>1) evioout << " .. Searching for run number ..." <<endl;
2870 if(USER_RUN_NUMBER>0){
2871 if(VERBOSE>1) evioout << " returning user-supplied run number: " << USER_RUN_NUMBER << endl;
2872 return USER_RUN_NUMBER;
2873 }
2874
2875 // Assume first word is number of words in bank
2876 uint32_t *iend = &iptr[*iptr - 1];
2877 if(*iptr > 256) iend = &iptr[256];
2878 bool has_timestamps = false;
2879 while(iptr<iend){
2880 iptr++;
2881 switch((*iptr)>>16){
2882 case 0xFF10:
2883 case 0xFF11:
2884 case 0xFF20:
2885 case 0xFF21:
2886 case 0xFF24:
2887 case 0xFF25:
2888 case 0xFF30:
2889 // These Trigger Bank Tag values have no run number info in them
2890 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does not contain run number" <<endl;
2891 return filename_run_number;
2892 case 0xFF23:
2893 case 0xFF27:
2894 has_timestamps = true;
2895 case 0xFF22:
2896 case 0xFF26:
2897 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does contain run number" <<endl;
2898// Nrocs = (*iptr) & 0x0F;
2899 break;
2900 default:
2901 continue;
2902 }
2903 iptr++;
2904 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2905 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2906 if(VERBOSE>2) evioout << " ... Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2907 iptr++;
2908 uint64_t *iptr64 = (uint64_t*)iptr;
2909
2910 uint64_t event_num = *iptr64;
2911 iptr64++;
2912 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2913 if(VERBOSE>3) evioout << " .... Event num: " << event_num <<endl;
2914
2915 // I'm not sure I fully understand this, but if we read from
2916 // ET, then the run number is in the low 32 bits of *iptr64.
2917 // If we are reading from a file, it is in the high 32 bits.
2918 // No byte swapping is needed (it has already been done, though
2919 // perhaps incorrectly). We handle this here by checking if
2920 // this is an ET source or not.
2921 uint64_t run64 = (*iptr64)>>32;
2922 if(source_type==kETSource){
2923 run64 = (*iptr64)&0xffffffff;
2924 }
2925 int32_t run = (int32_t)run64;
2926 if(VERBOSE>1) evioout << " .. Found run number: " << run <<endl;
2927
2928 return run;
2929 }
2930
2931 return filename_run_number;
2932}
2933
2934//----------------
2935// FindEventNumber
2936//----------------
2937uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
2938{
2939 /// This is called from GetEvent() to quickly look for the event number
2940 /// at the time the event is read in so it can be passed into JEvent.
2941 /// (See comments for FindRunNumber above.)
2942 if(*iptr < 6) return Nevents_read+1;
2943
2944 // Check header of Trigger bank
2945 uint32_t mask = 0xFF202000;
2946 if( (iptr[3]&mask) != mask ) return Nevents_read+1;
2947
2948 uint64_t loevent_num = iptr[5];
2949 uint64_t hievent_num = iptr[6];
2950 if(source_type==kETSource) {
2951 loevent_num = iptr[6];
2952 hievent_num = iptr[5];
2953 }
2954 uint64_t event_num = loevent_num + (hievent_num<<32);
2955
2956 return event_num;
2957}
2958
2959//----------------
2960// FindEventType
2961//----------------
2962void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
2963{
2964 /// This is called from GetEvent to quickly determine the type of
2965 /// event this is (Physics, EPICS, SYNC, BOR, ...)
2966 uint32_t head = iptr[1];
2967 if( (head & 0xff000f) == 0x600001){
2968 event.SetStatusBit(kSTATUS_EPICS_EVENT);
2969 }else if( (head & 0xffffffff) == 0x00700E01){
2970 event.SetStatusBit(kSTATUS_BOR_EVENT);
2971 }else if( (head & 0xffffff00) == 0xff501000){
2972 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2973 }else if( (head & 0xffffff00) == 0xff701000){
2974 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2975 }else if( (head & 0xfff000ff) == 0xffd00000){
2976 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
2977 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
2978 }else{
2979 DumpBinary(iptr, &iptr[16]);
2980 }
2981}
2982
2983//----------------
2984// MergeObjLists
2985//----------------
2986void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
2987{
2988 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
2989 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
2990 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
2991
2992 /// Merge the events referenced in events2 into the events1 list.
2993 ///
2994 /// This will append the object lists for each type of data object
2995 /// stored in events2 onto the appropriate list in events1. It does this
2996 /// event-by-event. The idea being that each entry in the queue represents a
2997 /// partial list of the objects for the event. The two queues are most likely
2998 /// filled from different EVIO banks orginiating from different ROCs.
2999 ///
3000 /// Before the merging is done, it is checked that both lists either have the
3001 /// same number of events, or one list is empty. One list is allowed to be
3002 /// empty since it is possible it was "filled" from a bank that contains no
3003 /// data at all which may not neccessarily be an error. If both queues have
3004 /// at least one event, but they do not contain an equal number of events,
3005 /// then an exception is thrown.
3006 ///
3007 /// The contents of event2 will be erased before returning. Ownership of all
3008 /// ObjList objects pointed to by event2 upon entry should be considered
3009 /// owned by event1 upon return.
3010
3011 // Allow a list of 1 event with only config objects in test below
3012 bool justconfig = false;
3013 if(events1.size()==1){
3014 ObjList *objs1 = events1.front();
3015 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
3016 }else if(events2.size()==1){
3017 ObjList *objs2 = events2.front();
3018 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
3019 }
3020
3021 // Check number of events and throw exception if appropriate
3022 unsigned int Nevents1 = events1.size();
3023 unsigned int Nevents2 = events2.size();
3024 if(Nevents1>0 && Nevents2>0 && !justconfig){
3025 if(Nevents1 != Nevents2){
3026 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
3027 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
3028 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
3029 }
3030 }
3031
3032 // Handle cases when one or both lists are empty
3033 if(Nevents1==0 && Nevents2==0)return;
3034 if(Nevents1==0){
3035 events1 = events2;
3036 events2.clear(); // clear queue
3037 return;
3038 }
3039 if(Nevents2==0)return;
3040
3041 // If we get here it means both events1 and events2 have events
3042 list<ObjList*>::iterator iter = events1.begin();
3043 for(; iter!=events1.end(); iter++){
3044 if(events2.empty()) break; // in case one has just config objects in a single event
3045 ObjList *objs1 = *iter;
3046 ObjList *objs2 = events2.front();
3047 events2.pop_front();
3048
3049 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
3050 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
3051 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
3052
3053 // Delete the objs2 container
3054 delete objs2;
3055 }
3056
3057 // Clear out any references to objects in event2 (this should be redundant)
3058 events2.clear(); // clear queue
3059
3060 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
3061}
3062
3063//----------------
3064// ParseEVIOEvent
3065//----------------
3066void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
3067{
3068 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
3069
3070 if(!evt)throw RESOURCE_UNAVAILABLE;
3071
3072 // Since each bank contains parts of many events, have them fill in
3073 // the "tmp_events" list and then merge those into the "full_events".
3074 // It is done this way so each bank can grow tmp_events to the appropriate
3075 // size to hold the number of events it discovers in the bank. A check
3076 // can then be made that this is consistent with the number of event
3077 // fragments found in the other banks.
3078 //list<ObjList*> full_events;
3079 list<ObjList*> tmp_events;
3080
3081 // The Physics Event bank is the outermost bank of the event and
3082 // it is a bank of banks. One of those banks is the
3083 // "Built Trigger Bank" which is a bank of segments. The others
3084 // are the "Data Bank" banks which in turn contain the
3085 // "Data Block Bank" banks which hold the actual data. For the
3086 // mc2coda generated data files (and presumably the real data)
3087 // these Data Block Banks are banks of ints. More specifically,
3088 // uint32_t.
3089 //
3090 // The "Physics Event's Built Trigger Bank" is a bank of segments.
3091 // This contains 3 segments, one each of type uint64, uint16, and
3092 // unit32. The first two are "common data" which contains information
3093 // common to all rocs. The last (uint32) has information specific to each
3094 // event and for each ROC.
3095 //
3096 // For now, we skip parseing the Built Trigger Bank and just
3097 // look for Data Block Banks. We do this by getting a list of
3098 // all uint32_t banks in the enitries DOM Tree (at all levels
3099 // of the heirachy) and checking the parent banks for depth
3100 // and additional info.
3101
3102 // Loop over list of all EVIO banks at all levels of the tree and parse
3103 // them, creating data objects and adding them to the overall list.
3104 evioDOMNodeListP bankList = evt->getNodeList();
3105 evioDOMNodeList::iterator iter = bankList->begin();
3106 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
3107 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
3108
3109 if(VERBOSE>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
3110
3111 // The data banks we want should have exactly two parents:
3112 // - Data Bank bank <-- parent
3113 // - Physics Event bank <-- grandparent
3114 //
3115 // other types of events may be inserted in the datastream though so we
3116 // check for those first.
3117
3118 // BOR event
3119 // BOR events will have an outermost
3120 // bank with tag=0x70 and num=1. If this is the outermost bank of
3121 // a BOR event, then parse it. If it is a inner BOR bank then ignore it.
3122 evioDOMNodeP outermostBankPtr = *iter;
3123 while(outermostBankPtr->getParent()) outermostBankPtr = outermostBankPtr->getParent();
3124 if(outermostBankPtr->tag==0x70 && outermostBankPtr->num==1){
3125 // This is a BOR bank
3126 if(VERBOSE>9) evioout << " bank is part of BOR event ... " << endl;
3127 if(outermostBankPtr == *iter){
3128 if(VERBOSE>9) evioout << " bank is outermost EVIO bank. Parsing BOR event ..." << endl;
3129 ParseBORevent(outermostBankPtr);
3130 }else{
3131 if(VERBOSE>9) evioout << " bank is not outermost EVIO bankin BOR event skipping ..." << endl;
3132 }
3133 continue; // no further processing of this bank is needed
3134 }
3135
3136 // EPICS event
3137 evioDOMNodeP bankPtr = *iter;
3138 evioDOMNodeP data_bank = bankPtr->getParent();
3139 if( data_bank==NULL__null ) {
3140
3141 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
3142 if(bankPtr->tag==96 && bankPtr->num==1){
3143 // This looks like an EPICS event. Hand it over to EPICS parser
3144 ParseEPICSevent(bankPtr, full_events);
3145 }else{
3146 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
3147 }
3148
3149 continue;
3150 }
3151
3152 // Trigger Bank
3153 evioDOMNodeP physics_event_bank = data_bank->getParent();
3154 if( physics_event_bank==NULL__null ){
3155 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
3156
3157 // Check if this is a CODA Reserved Bank Tag. If it is, then
3158 // this probably is part of the built trigger bank and not
3159 // the ROC data we're looking to parse here.
3160 if((bankPtr->tag & 0xFF00) == 0xFF00){
3161 if(VERBOSE>6) evioout << " Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range and has correct lineage. Assuming it's a built trigger bank."<< endl;
3162 ParseBuiltTriggerBank(bankPtr, tmp_events);
3163 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
3164 MergeObjLists(full_events, tmp_events);
3165
3166 // Check if this is a DEventTag bank
3167 }else if(bankPtr->tag == 0x0056){
3168 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
3169 if(vec){
3170 const uint32_t *iptr = &(*vec)[0];
3171 const uint32_t *iend = &(*vec)[vec->size()];
3172 ParseEventTag(iptr, iend, tmp_events);
3173 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
3174 MergeObjLists(full_events, tmp_events);
3175 }
3176 }
3177
3178 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
3179 }
3180 if( physics_event_bank->getParent() != NULL__null ){
3181 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
3182 continue; // physics event bank should have no parent!
3183 }
3184 if(VERBOSE>9){
3185 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
3186 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
3187 }
3188
3189 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
3190
3191 // Check if this is a CODA Reserved Bank Tag.
3192 if((data_bank->tag & 0xFF00) == 0xFF00){
3193 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
3194 continue;
3195 }
3196
3197 // Check if this is a TS Bank.
3198 if((bankPtr->tag & 0xFF00) == 0xEE00){
3199 if(VERBOSE>6) evioout << " TS bank tag="<<hex<<data_bank->tag<<dec<<" (not currently handled so skip to next bank)"<< endl;
3200 continue;
3201 }
3202
3203 // Get data from bank in the form of a vector of uint32_t
3204 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
3205 if(!vec){
3206 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
3207 continue;
3208 }
3209 const uint32_t *iptr = &(*vec)[0];
3210 const uint32_t *iend = &(*vec)[vec->size()];
3211 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
3212
3213 // Extract ROC id (crate number) from bank's parent
3214 uint32_t rocid = data_bank->tag & 0x0FFF;
3215
3216 // If there are rocid's specified that we wish to parse, make sure this one
3217 // is in the list. Otherwise, skip it.
3218 if(!ROCIDS_TO_PARSE.empty()){
3219 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
3220 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
3221 }
3222
3223 // The number of events in block is stored in lower 8 bits
3224 // of header word (aka the "num") of Data Bank. This should
3225 // be at least 1.
3226 uint32_t NumEvents = data_bank->num & 0xFF;
3227 if( NumEvents<1 ){
3228 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
3229 continue;
3230 }
3231
3232 // At this point iptr and iend indicate the data that came
3233 // from the ROC itself (all CODA headers have been stripped
3234 // away). Here, we need to decide what type of data this
3235 // bank contains. All JLab modules have a common block
3236 // header format and so are handled in a common way. Other
3237 // modules (e.g. CAEN) will have to appear in their own
3238 // EVIO bank and should be identified by their own det_id
3239 // value in the Data Block Bank.
3240 //
3241 // Current, preliminary thinking includes writing the type
3242 // of data into the 12-bit detector id contained in the
3243 // Data Block Bank of the DAQ group's "Event Building EVIO
3244 // Scheme". (This is the lower 12 bits of the "tag"). We
3245 // use this to decide if it is JLab module data or somehting
3246 // else.
3247 uint32_t det_id = bankPtr->tag & 0x0FFF;
3248 // Call appropriate parsing method
3249 bool bank_parsed = true; // will be set to false if default case is entered
3250 switch(det_id){
3251 case 0:
3252 case 1:
3253 case 3:
3254 case 6: // flash 250 module, MMD 2014/2/4
3255 case 16: // flash 125 module (CDC), DL 2014/6/19
3256 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
3257 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
3258 break;
3259
3260 case 20:
3261 ParseCAEN1190(rocid, iptr, iend, tmp_events);
3262 break;
3263
3264 case 0x55:
3265 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
3266 break;
3267
3268 case 5:
3269 // Beni's original CDC ROL used for the stand-alone CDC DAQ
3270 // had the following for the TS readout list (used in the TI):
3271 // *dma_dabufp++ = 0xcebaf111;
3272 // *dma_dabufp++ = tsGetIntCount();
3273 // *dma_dabufp++ = 0xdead;
3274 // *dma_dabufp++ = 0xcebaf222;
3275 // We skip this here, but put in the case so that we avoid errors
3276 break;
3277
3278
3279 default:
3280 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
3281 bank_parsed = false;
3282 if(VERBOSE>5){
3283 cerr << endl;
3284 cout << "----- First few words to help with debugging -----" << endl;
3285 cout.flush(); cerr.flush();
3286 int i=0;
3287 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
3288 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3288<<" "
<< "0x" << hex << *iiptr << dec << endl;
3289 if(i>=8) break;
3290 }
3291
3292 }
3293 }
3294
3295 // Merge this bank's partial events into the full events
3296 if(bank_parsed){
3297 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
3298 MergeObjLists(full_events, tmp_events);
3299 }
3300 }
3301
3302 // The following disabled in preference for keeping the
3303 // run number found by FindRunNumber called from
3304 // GetEvent() 2/15/2016
3305
3306// // Set the run number for all events
3307// uint32_t run_number = GetRunNumber(evt);
3308// list<ObjList*>::iterator evt_iter = full_events.begin();
3309// for(; evt_iter!=full_events.end(); evt_iter++){
3310// ObjList *objs = *evt_iter;
3311// objs->run_number = run_number;
3312// }
3313
3314 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
3315}
3316
3317//----------------
3318// ParseBuiltTriggerBank
3319//----------------
3320void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
3321{
3322 if(!PARSE_TRIGGER) return;
3323
3324 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
3325
3326 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
3327 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
3328 evioDOMNodeP physics_event_bank = trigbank->getParent();
3329 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
3330
3331 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
3332
3333 // Some values to fill in while parsing the banks that will be used later to create objects
3334 vector<uint64_t> avg_timestamps;
3335 uint32_t run_number = 0;
3336 uint32_t run_type = 0;
3337 uint64_t first_event_num = 1;
3338 vector<uint16_t> event_types;
3339 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
3340 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
3341
3342 // Loop over children of built trigger bank
3343 evioDOMNodeListP bankList = trigbank->getChildren();
3344 evioDOMNodeList::iterator iter = bankList->begin();
3345 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
3346
3347 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
3348
3349 evioDOMNodeP bankPtr = *iter;
3350
3351 // The "Physics Event's Built Trigger Bank" is a bank of segments that
3352 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
3353 // The uint64_t contains the first event number, average timestamps, and
3354 // run number & types. The uint16_t contains the event type(s). The
3355 // uint32_t contains the optional ROC specific meta data starting with
3356 // the specific timestamp for each event. All of these have some options
3357 // on exactly what info is contained in the bank. The first check here is
3358 // on the data type the bank contains. At most, one of the following pointers
3359 // should be non-zero.
3360 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
3361 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
3362 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
3363
3364 // unit64_t = common data (1st part)
3365 if(vec64){
3366
3367 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
3368
3369 // In addition to the first event number (1st word) there are three
3370 // additional pieces of information that may be present:
3371 // t = average timestamp
3372 // r = run number and type
3373 // d = run specific data
3374 //
3375 // The last one ("d") comes in the form of multiple uint32_t banks
3376 // so is not included in vec64. The other two have their presence
3377 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
3378 // also deduce this from the bank length.)
3379
3380 if(vec64->size() == 0) continue; // need debug message here!
3381
3382 first_event_num = (*vec64)[0];
3383
3384 // Hi and lo 32bit words in 64bit numbers seem to be
3385 // switched for events read from ET, but not read from
3386 // file. Not sure if this is in the swapping routine
3387 if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
3388
3389 uint32_t Ntimestamps = vec64->size()-1;
3390 if(Ntimestamps==0) continue; // no more words of interest
3391 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
3392 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
3393
3394 // run number and run type
3395 if(trigbank->tag & 0x02){
3396 run_number = (*vec64)[vec64->size()-1] >> 32;
3397 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
3398 }
3399 }
3400
3401 // uint16_t = common data (2nd part)
3402 if(vec16){
3403
3404 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
3405
3406 for(uint32_t i=0; i<Mevents; i++){
3407 if(i>=vec16->size()) break;
3408 event_types.push_back((*vec16)[i]);
3409 }
3410 }
3411
3412 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
3413 if(vec32){
3414
3415 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
3416
3417 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
3418 uint32_t rocid = (uint32_t)bankPtr->tag;
3419 uint32_t Nwords_per_event = vec32->size()/Mevents;
3420 if(vec32->size() != Mevents*Nwords_per_event){
3421 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3421<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
3422 exit(-1);
3423 }
3424
3425 uint32_t *iptr = &(*vec32)[0];
3426 for(uint32_t ievent=0; ievent<Mevents; ievent++){
3427
3428 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
3429 codarocinfo->rocid = rocid;
3430
3431 uint64_t ts_low = *iptr++;
3432 uint64_t ts_high = *iptr++;
3433 codarocinfo->timestamp = (ts_high<<32) + ts_low;
3434 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
3435
3436 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
3437 rocinfos[ievent].push_back(codarocinfo);
3438 }
3439 }
3440 }
3441
3442 // Check that we have agreement on the number of events this data represents
3443 bool Nevent_mismatch = false;
3444 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
3445 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
3446 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
3447 if(Nevent_mismatch){
3448 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3448<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
3449 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3449<<" "
<<" Mevents="<<Mevents<<endl;
3450 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3450<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
3451 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3451<<" "
<<" event_types.size()="<<event_types.size()<<endl;
3452 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3452<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3453 exit(-1);
3454 }
3455
3456 // Copy all objects into events
3457 for(uint32_t i=0; i<Mevents; i++){
3458 while(events.size()<=i){
3459 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3460 events.push_back(new ObjList);
3461 }
3462 ObjList *objs = events.back();
3463
3464 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3465 codaeventinfo->run_number = run_number;
3466 codaeventinfo->run_type = run_type;
3467 codaeventinfo->event_number = first_event_num + i;
3468 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3469 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3470 objs->misc_objs.push_back(codaeventinfo);
3471 objs->event_number = codaeventinfo->event_number;
3472
3473 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3474 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3475 }
3476
3477 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3478 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3479}
3480
3481//----------------
3482// ParseModuleConfiguration
3483//----------------
3484void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3485{
3486 if(!PARSE_CONFIG){ iptr = iend; return; }
3487
3488 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3489
3490 /// Parse a bank of module configuration data. These are configuration values
3491 /// programmed into the module at the beginning of the run that may be needed
3492 /// in the offline. For example, the number of samples to sum in a FADC pulse
3493 /// integral.
3494 ///
3495 /// The bank has one or more sections, each describing parameters applicable
3496 /// to a number of modules as indicated by a 24bit slot mask.
3497 ///
3498 /// This bank should appear only once per DAQ event which, if in multi-event
3499 /// block mode, may have multiple L1 events. The parameters here will apply
3500 /// to all L1 events in the block. This method will put the config objects
3501 /// in the first event of "events", creating it if needed. The config objects
3502 /// are duplicated for all other events in the block later, after all event
3503 /// parsing is finished and the total number of events is known.
3504 /// (See the end of ParseEvents() .)
3505
3506 while(iptr < iend){
3507 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3508 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3509 iptr++;
3510
3511 Df250Config *f250config = NULL__null;
3512 Df125Config *f125config = NULL__null;
3513 DF1TDCConfig *f1tdcconfig = NULL__null;
3514 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3515
3516 // Loop over all parameters in this section
3517 for(uint32_t i=0; i< Nvals; i++){
3518 if( iptr >= iend){
3519 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3519<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3520 exit(-1);
3521 }
3522
3523 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3524 uint16_t val = (*iptr) & 0xFFFF;
3525
3526 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3527
3528 // Create config object of correct type if needed and copy
3529 // parameter value into it.
3530 switch(ptype>>8){
3531
3532 // f250
3533 case 0x05:
3534 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3535 switch(ptype){
3536 case kPARAM250_NSA : f250config->NSA = val; break;
3537 case kPARAM250_NSB : f250config->NSB = val; break;
3538 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3539 case kPARAM250_NPED : f250config->NPED = val; break;
3540 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3540<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3541 }
3542 break;
3543
3544 // f125
3545 case 0x0F:
3546 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3547 switch(ptype){
3548 case kPARAM125_NSA : f125config->NSA = val; break;
3549 case kPARAM125_NSB : f125config->NSB = val; break;
3550 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3551 case kPARAM125_NPED : f125config->NPED = val; break;
3552 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3553 case kPARAM125_PL : f125config->PL = val; break;
3554 case kPARAM125_NW : f125config->NW = val; break;
3555 case kPARAM125_NPK : f125config->NPK = val; break;
3556 case kPARAM125_P1 : f125config->P1 = val; break;
3557 case kPARAM125_P2 : f125config->P2 = val; break;
3558 case kPARAM125_PG : f125config->PG = val; break;
3559 case kPARAM125_IE : f125config->IE = val; break;
3560 case kPARAM125_H : f125config->H = val; break;
3561 case kPARAM125_TH : f125config->TH = val; break;
3562 case kPARAM125_TL : f125config->TL = val; break;
3563 case kPARAM125_IBIT : f125config->IBIT = val; break;
3564 case kPARAM125_ABIT : f125config->ABIT = val; break;
3565 case kPARAM125_PBIT : f125config->PBIT = val; break;
3566 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3566<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3567 }
3568 break;
3569
3570 // F1TDC
3571 case 0x06:
3572 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3573 switch(ptype){
3574 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3575 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3576 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3577 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3578 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3579 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3580 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3580<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3581 }
3582 break;
3583
3584 // caen1290
3585 case 0x10:
3586 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3587 switch(ptype){
3588 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3589 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3590 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3590<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3591 }
3592 break;
3593
3594 default:
3595 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3595<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3596 exit(-1);
3597 }
3598
3599#if 0
3600 // Create config object of correct type if needed. (Only one type
3601 // should be created per section!)
3602 switch(ptype>>8){
3603 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3604 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3605 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3606 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3607 default:
3608 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3608<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3609 exit(-1);
3610 }
3611
3612 // Copy parameter into config. object
3613 switch(ptype){
3614 case kPARAM250_NSA : f250config->NSA = val; break;
3615 case kPARAM250_NSB : f250config->NSB = val; break;
3616 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3617 case kPARAM250_NPED : f250config->NPED = val; break;
3618
3619 case kPARAM125_NSA : f125config->NSA = val; break;
3620 case kPARAM125_NSB : f125config->NSB = val; break;
3621 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3622 case kPARAM125_NPED : f125config->NPED = val; break;
3623 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3624 case kPARAM125_PL : f125config->PL = val; break;
3625 case kPARAM125_NW : f125config->NW = val; break;
3626 case kPARAM125_NPK : f125config->NPK = val; break;
3627 case kPARAM125_P1 : f125config->P1 = val; break;
3628 case kPARAM125_P2 : f125config->P2 = val; break;
3629 case kPARAM125_PG : f125config->PG = val; break;
3630 case kPARAM125_IE : f125config->IE = val; break;
3631 case kPARAM125_H : f125config->H = val; break;
3632 case kPARAM125_TH : f125config->TH = val; break;
3633 case kPARAM125_TL : f125config->TL = val; break;
3634 case kPARAM125_IBIT : f125config->IBIT = val; break;
3635 case kPARAM125_ABIT : f125config->ABIT = val; break;
3636 case kPARAM125_PBIT : f125config->PBIT = val; break;
3637
3638 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3639 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3640 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3641 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3642 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3643 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3644
3645 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3646 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3647
3648 default:
3649 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3649<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3650 }
3651#endif
3652
3653 iptr++;
3654 }
3655
3656 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3657 // so there is at least one DDAQConfig object we need to store. Get pointer to
3658 // first event's ObjList, creating it if needed.
3659 if(events.empty()) events.push_back(new ObjList());
3660 ObjList *objs = *(events.begin());
3661
3662 if(f250config ) objs->config_objs.push_back(f250config );
3663 if(f125config ) objs->config_objs.push_back(f125config );
3664 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3665 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3666 }
3667
3668 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3669}
3670
3671//----------------
3672// ParseEventTag
3673//----------------
3674void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3675{
3676 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3677
3678 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3679
3680 // Make sure there is one event in the event container
3681 // and get pointer to it.
3682 if(events.empty()) events.push_back(new ObjList());
3683 ObjList *objs = *(events.begin());
3684
3685
3686 DEventTag *etag = new DEventTag;
3687
3688 // event_status
3689 uint64_t lo = *iptr++;
3690 uint64_t hi = *iptr++;
3691 etag->event_status = (hi<<32) + lo;
3692
3693 // L3_status
3694 lo = *iptr++;
3695 hi = *iptr++;
3696 etag->L3_status = (hi<<32) + lo;
3697
3698 // L3_decision
3699 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3700
3701 // L3_algorithm
3702 etag->L3_algorithm = *iptr++;
3703
3704 objs->misc_objs.push_back(etag);
3705
3706
3707 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3708}
3709
3710//----------------
3711// ParseJLabModuleData
3712//----------------
3713void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3714{
3715 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3716
3717 /// Parse a bank of data coming from one or more JLab modules.
3718 /// The data are assumed to follow the standard JLab format for
3719 /// block headers. If multiple modules are read out in a single
3720 /// chain block transfer, then the data will all be placed in
3721 /// a single EVIO bank and this will loop over the modules.
3722 while(iptr < iend){
3723
3724 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3725
3726 // This was observed in some CDC data. Not sure where it came from ...
3727 if(*iptr == 0xF800FAFA){
3728 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3729 iptr++;
3730 continue;
3731 }
3732
3733 // Get module type from next word (bits 18-21)
3734 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3735
3736 // The enum defined in DModuleType.h MUST be kept in alignment
3737 // with the DAQ group's definitions for modules types!
3738 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3739 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3740
3741 if(modtype_translate.find(type) != modtype_translate.end()){
3742 type = modtype_translate[type];
3743 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3744 }
3745
3746 // Parse buffer depending on module type
3747 // (Note that each of the ParseXXX routines called below will
3748 // update the "iptr" variable to point to the next word
3749 // after the block it parsed.)
3750 list<ObjList*> tmp_events;
3751 const uint32_t *istart=iptr; // just for UNKNOWN case below
3752 bool module_parsed = true;
3753 switch(type){
3754 case DModuleType::FADC250:
3755 Parsef250Bank(rocid, iptr, iend, tmp_events);
3756 break;
3757
3758 case DModuleType::FADC125:
3759 Parsef125Bank(rocid, iptr, iend, tmp_events);
3760 break;
3761
3762 case DModuleType::F1TDC32:
3763 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3764 break;
3765
3766 case DModuleType::F1TDC48:
3767 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3768 break;
3769
3770 case DModuleType::JLAB_TS:
3771 ParseTSBank(rocid, iptr, iend, tmp_events);
3772 break;
3773
3774 case DModuleType::TID:
3775 ParseTIBank(rocid, iptr, iend, tmp_events);
3776 break;
3777
3778 case DModuleType::UNKNOWN:
3779 default:
3780 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
3781
3782 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
3783 iptr++; // advance past JLab block trailer
3784 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
3785 module_parsed = false;
3786 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
3787 break;
3788 }
3789
3790 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
3791
3792 if(module_parsed){
3793 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
3794 MergeObjLists(events, tmp_events);
3795 }
3796 }
3797
3798 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
3799}
3800
3801//----------------
3802// Parsef250Bank
3803//----------------
3804void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3805{
3806 /// Parse data from a single FADC250 module.
3807
3808 if(!PARSE_F250){ iptr = iend; return; }
3809
3810 // This will get updated to point to a newly allocated object when an
3811 // event header is encountered. The existing value (if non-NULL) is
3812 // added to the events queue first though so all events are kept.
3813 ObjList *objs = NULL__null;
3814
3815 // From the Block Header
3816 uint32_t slot=0;
3817 //uint32_t Nblock_events;
3818 //uint32_t iblock;
3819
3820 // From the Block Trailer
3821 //uint32_t slot_trailer;
3822 //uint32_t Nwords_in_block;
3823
3824 // From Event header
3825 //uint32_t slot_event_header;
3826 uint32_t itrigger = -1;
3827 uint32_t last_itrigger = -2;
3828
3829 // Loop over data words
3830 for(; iptr<iend; iptr++){
3831
3832 // Skip all non-data-type-defining words at this
3833 // level. When we do encounter one, the appropriate
3834 // case block below should handle parsing all of
3835 // the data continuation words and advance the iptr.
3836 if(((*iptr>>31) & 0x1) == 0)continue;
3837
3838 // Variables used inside of switch, but cannot be declared inside
3839 uint64_t t = 0L;
3840 uint32_t channel = 0;
3841 uint32_t sum = 0;
3842 uint32_t pulse_number = 0;
3843 uint32_t quality_factor = 0;
3844 uint32_t pulse_time = 0;
3845 uint32_t pedestal = 0;
3846 uint32_t pulse_peak = 0;
3847 uint32_t nsamples_integral = 0;
3848 uint32_t nsamples_pedestal = 0;
3849 bool overflow = false;
3850
3851 bool found_block_trailer = false;
3852 uint32_t data_type = (*iptr>>27) & 0x0F;
3853 switch(data_type){
3854 case 0: // Block Header
3855 slot = (*iptr>>22) & 0x1F;
3856 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<endl;
3857 //iblock= (*iptr>>8) & 0x03FF;
3858 //Nblock_events= (*iptr>>0) & 0xFF;
3859 break;
3860 case 1: // Block Trailer
3861 //slot_trailer = (*iptr>>22) & 0x1F;
3862 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3863 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<endl;
3864 found_block_trailer = true;
3865 break;
3866 case 2: // Event Header
3867 //slot_event_header = (*iptr>>22) & 0x1F;
3868 itrigger = (*iptr>>0) & 0x3FFFFF;
3869 if(VERBOSE>7) evioout << " FADC250 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
3870 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3871 if(ENABLE_DISENTANGLING){
3872 if(objs){
3873 events.push_back(objs);
3874 objs = NULL__null;
3875 }
3876 }
3877 if(!objs) objs = new ObjList;
3878 last_itrigger = itrigger;
3879 }
3880 break;
3881 case 3: // Trigger Time
3882 t = ((*iptr)&0xFFFFFF)<<0;
3883 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<endl;
3884 iptr++;
3885 if(((*iptr>>31) & 0x1) == 0){
3886 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3887 }else{
3888 iptr--;
3889 }
3890 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
3891 break;
3892 case 4: // Window Raw Data
3893 // iptr passed by reference and so will be updated automatically
3894 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<endl;
3895 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
3896 break;
3897 case 5: // Window Sum
3898 channel = (*iptr>>23) & 0x0F;
3899 sum = (*iptr>>0) & 0x3FFFFF;
3900 overflow = (*iptr>>22) & 0x1;
3901 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<endl;
3902 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
3903 break;
3904 case 6: // Pulse Raw Data
3905 // iptr passed by reference and so will be updated automatically
3906 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<endl;
3907 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
3908 break;
3909 case 7: // Pulse Integral
3910 channel = (*iptr>>23) & 0x0F;
3911 pulse_number = (*iptr>>21) & 0x03;
3912 quality_factor = (*iptr>>19) & 0x03;
3913 sum = (*iptr>>0) & 0x7FFFF;
3914 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3915 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3916 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3917 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<endl;
3918 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3919 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3920 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3921 }
3922 break;
3923 case 8: // Pulse Time
3924 channel = (*iptr>>23) & 0x0F;
3925 pulse_number = (*iptr>>21) & 0x03;
3926 quality_factor = (*iptr>>19) & 0x03;
3927 pulse_time = (*iptr>>0) & 0x7FFFF;
3928 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<endl;
3929 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) && (F250_PT_EMULATION_MODE!=kEmulationAlways)) {
3930 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3931 }
3932 break;
3933 case 9: // Streaming Raw Data
3934 // This is marked "reserved for future implementation" in the current manual (v2).
3935 // As such, we don't try handling it here just yet.
3936 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<endl;
3937 break;
3938 case 10: // Pulse Pedestal
3939 channel = (*iptr>>23) & 0x0F;
3940 pulse_number = (*iptr>>21) & 0x03;
3941 pedestal = (*iptr>>12) & 0x1FF;
3942 pulse_peak = (*iptr>>0) & 0xFFF;
3943 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<endl;
3944 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) && (F250_PP_EMULATION_MODE!=kEmulationAlways)) {
3945 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
3946 }
3947 break;
3948 case 13: // Event Trailer
3949 // This is marked "suppressed for normal readout – debug mode only" in the
3950 // current manual (v2). It does not contain any data so the most we could do here
3951 // is return early. I'm hesitant to do that though since it would mean
3952 // different behavior for debug mode data as regular data.
3953 case 14: // Data not valid (empty module)
3954 case 15: // Filler (non-data) word
3955 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<endl;
3956 break;
3957 }
3958
3959 // Once we find a block trailer, assume that is it for this module.
3960 if(found_block_trailer){
3961 iptr++; // iptr is still pointing to block trailer. Jump to next word.
3962 break;
3963 }
3964 }
3965
3966 // Chop off filler words
3967 for(; iptr<iend; iptr++){
3968 if(((*iptr)&0xf8000000) != 0xf8000000) break;
3969 }
3970
3971 // Add last event in block to list
3972 if(objs)events.push_back(objs);
3973
3974 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
3975 // objects to each other so it is easier to get to these downstream without having to
3976 // make nested loops. This is the most efficient place to do it since the ObjList objects
3977 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
3978 // worth.)
3979 list<ObjList*>::iterator iter = events.begin();
3980 for(; iter!=events.end(); iter++){
3981
3982 // Sort list of objects into type-specific lists
3983 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
3984 vector<Df250TriggerTime*> vtrigt;
3985 vector<Df250WindowRawData*> vwrd;
3986 vector<Df250WindowSum*> vws;
3987 vector<Df250PulseRawData*> vprd;
3988 vector<Df250PulseIntegral*> vpi;
3989 vector<Df250PulseTime*> vpt;
3990 vector<Df250PulsePedestal*> vpp;
3991 for(unsigned int i=0; i<hit_objs.size(); i++){
3992 AddIfAppropriate(hit_objs[i], vtrigt);
3993 AddIfAppropriate(hit_objs[i], vwrd);
3994 AddIfAppropriate(hit_objs[i], vws);
3995 AddIfAppropriate(hit_objs[i], vprd);
3996 AddIfAppropriate(hit_objs[i], vpi);
3997 AddIfAppropriate(hit_objs[i], vpt);
3998 AddIfAppropriate(hit_objs[i], vpp);
3999 }
4000
4001 // Connect Df250PulseIntegral, Df250PulseTime, and
4002 // Df250PulsePedestal with Df250PulseRawData
4003 // (n.b. the associations between pi, pt, and pp are
4004 // done in GetObjects where emulated objects are
4005 // also available.)
4006 LinkAssociationsWithPulseNumber(vprd, vpi);
4007 LinkAssociationsWithPulseNumber(vprd, vpt);
4008 LinkAssociationsWithPulseNumber(vprd, vpp);
4009
4010 // Connect Df250WindowSum and Df250WindowRawData
4011 LinkAssociations(vwrd, vws);
4012
4013 // Connect Df250TriggerTime to everything
4014 LinkAssociationsModuleOnly(vtrigt, vwrd);
4015 LinkAssociationsModuleOnly(vtrigt, vws);
4016 LinkAssociationsModuleOnly(vtrigt, vprd);
4017 LinkAssociationsModuleOnly(vtrigt, vpi);
4018 LinkAssociationsModuleOnly(vtrigt, vpt);
4019 LinkAssociationsModuleOnly(vtrigt, vpp);
4020 }
4021}
4022
4023//----------------
4024// MakeDf250WindowRawData
4025//----------------
4026void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4027{
4028 uint32_t channel = (*iptr>>23) & 0x0F;
4029 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4030
4031 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
4032
4033 for(uint32_t isample=0; isample<window_width; isample +=2){
4034
4035 // Advance to next word
4036 iptr++;
4037
4038 // Make sure this is a data continuation word, if not, stop here
4039 if(((*iptr>>31) & 0x1) != 0x0){
4040 iptr--; // calling method expects us to point to last word in block
4041 break;
4042 }
4043
4044 bool invalid_1 = (*iptr>>29) & 0x1;
4045 bool invalid_2 = (*iptr>>13) & 0x1;
4046 uint16_t sample_1 = 0;
4047 uint16_t sample_2 = 0;
4048 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4049 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4050
4051 // Sample 1
4052 wrd->samples.push_back(sample_1);
4053 wrd->invalid_samples |= invalid_1;
4054 wrd->overflow |= (sample_1>>12) & 0x1;
4055
4056 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4057
4058 // Sample 2
4059 wrd->samples.push_back(sample_2);
4060 wrd->invalid_samples |= invalid_2;
4061 wrd->overflow |= (sample_2>>12) & 0x1;
4062 }
4063
4064 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4065 // This will happen if a Window Raw Data block is encountered before an event header.
4066 // For these cases, we still want to try parsing the data so that the iptr is updated
4067 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4068 // the list. Otherwise, delete it now.
4069 if(objs){
4070 objs->hit_objs.push_back(wrd);
4071 }else{
4072 delete wrd;
4073 }
4074}
4075
4076//----------------
4077// MakeDf250PulseRawData
4078//----------------
4079void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4080{
4081 const uint32_t *istart = iptr;
4082 uint32_t channel = (*iptr>>23) & 0x0F;
4083 uint32_t pulse_number = (*iptr>>21) & 0x0003;
4084 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4085
4086 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
4087
4088 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4089
4090 // This loop needs to break when it hits a non-continuation word
4091 for(uint32_t isample=0; isample<1000; isample +=2){
4092
4093 // Advance to next word
4094 iptr++;
4095
4096 // Make sure this is a data continuation word, if not, stop here
4097 if(((*iptr>>31) & 0x1) != 0x0)break;
4098
4099 bool invalid_1 = (*iptr>>29) & 0x1;
4100 bool invalid_2 = (*iptr>>13) & 0x1;
4101 uint16_t sample_1 = 0;
4102 uint16_t sample_2 = 0;
4103 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4104 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4105
4106 // Sample 1
4107 prd->samples.push_back(sample_1);
4108 prd->invalid_samples |= invalid_1;
4109 prd->overflow |= (sample_1>>12) & 0x1;
4110
4111 bool last_word = (iptr[1]>>31) & 0x1;
4112 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4113
4114 // Sample 2
4115 prd->samples.push_back(sample_2);
4116 prd->invalid_samples |= invalid_2;
4117 prd->overflow |= (sample_2>>12) & 0x1;
4118 }
4119
4120 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
4121
4122 // When should get here because the loop above stopped when it found
4123 // a data defining word (bit 31=1). The method calling this one will
4124 // assume iptr is pointing to the last word of this block and it will
4125 // advance to the first word of the next block. We need to back up one
4126 // word so that it is pointing to the last word of this block.
4127 iptr--;
4128
4129 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4130 // This will happen if a Window Raw Data block is encountered before an event header.
4131 // For these cases, we still want to try parsing the data so that the iptr is updated
4132 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4133 // the list. Otherwise, delete it now.
4134 if(objs){
4135 objs->hit_objs.push_back(prd);
4136 }else{
4137 delete prd;
4138 }
4139}
4140
4141//----------------
4142// Parsef125Bank
4143//----------------
4144void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4145{
4146 /// Parse data from a single FADC125 module.
4147 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
4148 /// data formats follow what is in the file:
4149 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
4150
4151 if(!PARSE_F125){ iptr = iend; return; }
4152
4153 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
4154
4155 // This will get updated to point to a newly allocated object when an
4156 // event header is encountered. The existing value (if non-NULL) is
4157 // added to the events queue first though so all events are kept.
4158 ObjList *objs = NULL__null;
4159
4160 // From the Block Header
4161 uint32_t slot=0;
4162 //uint32_t Nblock_events;
4163 //uint32_t iblock;
4164
4165 // From the Block Trailer
4166 //uint32_t slot_trailer;
4167 //uint32_t Nwords_in_block;
4168
4169 // From Event header
4170 //uint32_t slot_event_header;
4171 uint32_t itrigger = -1;
4172 uint32_t last_itrigger = -2;
4173 uint32_t last_pulse_time_channel=0;
4174 uint32_t last_slot = -1;
4175 uint32_t last_channel = -1;
4176
4177 // Loop over data words
4178 for(; iptr<iend; iptr++){
4179
4180 // Skip all non-data-type-defining words at this
4181 // level. When we do encounter one, the appropriate
4182 // case block below should handle parsing all of
4183 // the data continuation words and advance the iptr.
4184 if(((*iptr>>31) & 0x1) == 0)continue;
4185
4186 // Variables used inside of switch, but cannot be declared inside
4187 uint64_t t = 0L;
4188 uint32_t channel = 0;
4189 uint32_t sum = 0;
4190 uint32_t pulse_number = 0;
4191 uint32_t pulse_time = 0;
4192 uint32_t quality_factor = 0;
4193 uint32_t overflow_count = 0;
4194 uint32_t pedestal = 0;
4195 uint32_t pulse_peak = 0;
4196 uint32_t peak_time = 0;
4197 uint32_t nsamples_integral = 0;
4198 uint32_t nsamples_pedestal = 0;
4199 uint32_t word1=0;
4200 uint32_t word2=0;
4201
4202 bool found_block_trailer = false;
4203 uint32_t data_type = (*iptr>>27) & 0x0F;
4204 switch(data_type){
4205 case 0: // Block Header
4206 slot = (*iptr>>22) & 0x1F;
4207 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
4208 //iblock= (*iptr>>8) & 0x03FF;
4209 //Nblock_events= (*iptr>>0) & 0xFF;
4210 break;
4211 case 1: // Block Trailer
4212 //slot_trailer = (*iptr>>22) & 0x1F;
4213 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
4214 found_block_trailer = true;
4215 break;
4216 case 2: // Event Header
4217 //slot_event_header = (*iptr>>22) & 0x1F;
4218 itrigger = (*iptr>>0) & 0x3FFFFFF;
4219 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
4220 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
4221 if(ENABLE_DISENTANGLING){
4222 if(objs){
4223 events.push_back(objs);
4224 objs = NULL__null;
4225 }
4226 }
4227 if(!objs) objs = new ObjList;
4228 last_itrigger = itrigger;
4229 }
4230 break;
4231 case 3: // Trigger Time
4232 t = ((*iptr)&0xFFFFFF)<<0;
4233 iptr++;
4234 if(((*iptr>>31) & 0x1) == 0){
4235 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4236 }else{
4237 iptr--;
4238 }
4239 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
4240 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
4241 break;
4242 case 4: // Window Raw Data
4243 // iptr passed by reference and so will be updated automatically
4244 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
4245 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
4246 break;
4247
4248 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
4249
4250 // Word 1:
4251 word1 = *iptr;
4252 channel = (*iptr>>20) & 0x7F;
4253 pulse_number = (*iptr>>15) & 0x1F;
4254 pulse_time = (*iptr>>4 ) & 0x7FF;
4255 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4256 overflow_count = (*iptr>>0 ) & 0x7;
4257 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
4258 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4259
4260 // Word 2:
4261 ++iptr;
4262 if(iptr>=iend){
4263 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
4264 continue;
4265 }
4266 if( ((*iptr>>31) & 0x1) != 0 ){
4267 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
4268 continue;
4269 }
4270 word2 = *iptr;
4271 pedestal = (*iptr>>23) & 0xFF;
4272 sum = (*iptr>>9 ) & 0x3FFF;
4273 pulse_peak = (*iptr>>0 ) & 0x1FF;
4274 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
4275 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
4276
4277 // Create hit objects
4278 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4279 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4280
4281 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4282 // n.b. This is were we might apply a check on whether we are
4283 // only producing emulated objects. If so, then we shouldn't
4284 // create the Df125CDCPulse. At this point in time though,
4285 // there are 3 config. parameters that control this because
4286 // the original firmware produced 3 separate data types as
4287 // opposed to the new firmware that puts the same infomation
4288 // into a single data type. The emulation framework is also
4289 // being revamped.
4290 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
4291 , pulse_number // NPK
4292 , pulse_time // le_time
4293 , quality_factor // time_quality_bit
4294 , overflow_count // overflow_count
4295 , pedestal // pedestal
4296 , sum // integral
4297 , pulse_peak // first_max_amp
4298 , word1 // word1
4299 , word2 // word2
4300 , nsamples_pedestal // nsamples_pedestal
4301 , nsamples_integral // nsamples_integral
4302 , false) // emulated
4303 );
4304 }
4305
4306 // n.b. We don't record last_slot, last_channel, etc... here since those
4307 // are only used by data types corresponding to older firmware that did
4308 // not write out data type 5.
4309 break;
4310
4311 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
4312
4313 // Word 1:
4314 word1 = *iptr;
4315 channel = (*iptr>>20) & 0x7F;
4316 pulse_number = (*iptr>>15) & 0x1F;
4317 pulse_time = (*iptr>>4 ) & 0x7FF;
4318 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4319 overflow_count = (*iptr>>0 ) & 0x7;
4320 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
4321 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4322
4323 // Word 2:
4324 ++iptr;
4325 if(iptr>=iend){
4326 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4327 continue;
4328 }
4329 if( ((*iptr>>31) & 0x1) != 0 ){
4330 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4331 continue;
4332 }
4333 word2 = *iptr;
4334 pulse_peak = 0;
4335 sum = (*iptr>>19) & 0xFFF;
4336 peak_time = (*iptr>>11) & 0xFF;
4337 pedestal = (*iptr>>0 ) & 0x7FF;
4338 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
4339 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4340
4341 // Create hit objects
4342 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4343 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4344
4345 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4346 // n.b. This is were we might apply a check on whether we are
4347 // only producing emulated objects. If so, then we shouldn't
4348 // create the Df125FDCPulse. At this point in time though,
4349 // there are 3 config. parameters that control this because
4350 // the original firmware produced 3 separate data types as
4351 // opposed to the new firmware that puts the same infomation
4352 // into a single data type. The emulation framework is also
4353 // being revamped.
4354 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4355 , pulse_number // NPK
4356 , pulse_time // le_time
4357 , quality_factor // time_quality_bit
4358 , overflow_count // overflow_count
4359 , pedestal // pedestal
4360 , sum // integral
4361 , pulse_peak // peak_amp
4362 , peak_time // peak_time
4363 , word1 // word1
4364 , word2 // word2
4365 , nsamples_pedestal // nsamples_pedestal
4366 , nsamples_integral // nsamples_integral
4367 , false) // emulated
4368 );
4369 }
4370
4371 // n.b. We don't record last_slot, last_channel, etc... here since those
4372 // are only used by data types corresponding to older firmware that did
4373 // not write out data type 6.
4374 break;
4375
4376 case 7: // Pulse Integral
4377 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
4378 channel = (*iptr>>20) & 0x7F;
4379 sum = (*iptr>>0) & 0xFFFFF;
4380 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4381 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4382 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
4383 if (last_slot == slot && last_channel == channel) pulse_number = 1;
4384 last_slot = slot;
4385 last_channel = channel;
4386 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4387 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
4388 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
4389 }
4390 break;
4391 case 8: // Pulse Time
4392 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
4393 channel = (*iptr>>20) & 0x7F;
4394 pulse_number = (*iptr>>18) & 0x03;
4395 pulse_time = (*iptr>>0) & 0xFFFF;
4396 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) && (F125_PT_EMULATION_MODE!=kEmulationAlways) ) {
4397 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
4398 }
4399 last_pulse_time_channel = channel;
4400 break;
4401
4402 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
4403
4404 // Word 1:
4405 word1 = *iptr;
4406 channel = (*iptr>>20) & 0x7F;
4407 pulse_number = (*iptr>>15) & 0x1F;
4408 pulse_time = (*iptr>>4 ) & 0x7FF;
4409 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4410 overflow_count = (*iptr>>0 ) & 0x7;
4411 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
4412 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4413
4414 // Word 2:
4415 ++iptr;
4416 if(iptr>=iend){
4417 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4418 continue;
4419 }
4420 if( ((*iptr>>31) & 0x1) != 0 ){
4421 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4422 continue;
4423 }
4424 word2 = *iptr;
4425 pulse_peak = (*iptr>>19) & 0xFFF;
4426 sum = 0;
4427 peak_time = (*iptr>>11) & 0xFF;
4428 pedestal = (*iptr>>0 ) & 0x7FF;
4429 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
4430 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4431
4432 // Create hit objects
4433 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4434 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4435
4436 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4437 // n.b. This is were we might apply a check on whether we are
4438 // only producing emulated objects. If so, then we shouldn't
4439 // create the Df125FDCPulse. At this point in time though,
4440 // there are 3 config. parameters that control this because
4441 // the original firmware produced 3 separate data types as
4442 // opposed to the new firmware that puts the same infomation
4443 // into a single data type. The emulation framework is also
4444 // being revamped.
4445 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4446 , pulse_number // NPK
4447 , pulse_time // le_time
4448 , quality_factor // time_quality_bit
4449 , overflow_count // overflow_count
4450 , pedestal // pedestal
4451 , sum // integral
4452 , pulse_peak // peak_amp
4453 , peak_time // peak_time
4454 , word1 // word1
4455 , word2 // word2
4456 , nsamples_pedestal // nsamples_pedestal
4457 , nsamples_integral // nsamples_integral
4458 , false) // emulated
4459 );
4460 }
4461
4462 // n.b. We don't record last_slot, last_channel, etc... here since those
4463 // are only used by data types corresponding to older firmware that did
4464 // not write out data type 6.
4465 break;
4466
4467 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4468 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4469 //channel = (*iptr>>20) & 0x7F;
4470 channel = last_pulse_time_channel; // not enough bits to hold channel number so rely on proximity to Pulse Time in data stream (see "FADC125 dataformat 250 modes.docx")
4471 pulse_number = (*iptr>>21) & 0x03;
4472 pedestal = (*iptr>>12) & 0x1FF;
4473 pulse_peak = (*iptr>>0) & 0xFFF;
4474 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4475 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) && (F125_PP_EMULATION_MODE!=kEmulationAlways) ) {
4476 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4477 }
4478 break;
4479
4480 case 13: // Event Trailer
4481 case 14: // Data not valid (empty module)
4482 case 15: // Filler (non-data) word
4483 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4484 break;
4485 }
4486
4487 // Once we find a block trailer, assume that is it for this module.
4488 if(found_block_trailer){
4489 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4490 break;
4491 }
4492 }
4493
4494 // Chop off filler words
4495 for(; iptr<iend; iptr++){
4496 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4497 }
4498
4499 // Add last event in block to list
4500 if(objs)events.push_back(objs);
4501
4502 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4503 // objects to each other so it is easier to get to these downstream without having to
4504 // make nested loops. This is the most efficient place to do it since the ObjList objects
4505 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4506 // worth.)
4507 list<ObjList*>::iterator iter = events.begin();
4508 for(; iter!=events.end(); iter++){
4509
4510 // Sort list of objects into type-specific lists
4511 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4512 vector<Df125TriggerTime*> vtrigt;
4513 vector<Df125WindowRawData*> vwrd;
4514 vector<Df125PulseRawData*> vprd;
4515 vector<Df125PulseIntegral*> vpi;
4516 vector<Df125PulseTime*> vpt;
4517 vector<Df125PulsePedestal*> vpp;
4518 for(unsigned int i=0; i<hit_objs.size(); i++){
4519 AddIfAppropriate(hit_objs[i], vtrigt);
4520 AddIfAppropriate(hit_objs[i], vwrd);
4521 AddIfAppropriate(hit_objs[i], vprd);
4522 AddIfAppropriate(hit_objs[i], vpi);
4523 AddIfAppropriate(hit_objs[i], vpt);
4524 AddIfAppropriate(hit_objs[i], vpp);
4525 }
4526
4527 // Connect Df125PulseIntegral with Df125PulseTime
4528 LinkAssociationsWithPulseNumber(vprd, vpi);
4529 LinkAssociationsWithPulseNumber(vprd, vpt);
4530 LinkAssociationsWithPulseNumber(vprd, vpp);
4531 LinkAssociationsWithPulseNumber(vpi, vpt);
4532 LinkAssociationsWithPulseNumber(vpi, vpp);
4533 LinkAssociationsWithPulseNumber(vpt, vpp);
4534
4535 // Connect Df125TriggerTime to everything
4536 LinkAssociationsModuleOnly(vtrigt, vwrd);
4537 LinkAssociationsModuleOnly(vtrigt, vprd);
4538 LinkAssociationsModuleOnly(vtrigt, vpi);
4539 LinkAssociationsModuleOnly(vtrigt, vpt);
4540 LinkAssociationsModuleOnly(vtrigt, vpp);
4541 }
4542
4543 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4544}
4545
4546//----------------
4547// MakeDf125WindowRawData
4548//----------------
4549void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4550{
4551 uint32_t channel = (*iptr>>20) & 0x7F;
4552 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4553
4554 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4555
4556 for(uint32_t isample=0; isample<window_width; isample +=2){
4557
4558 // Advance to next word
4559 iptr++;
4560
4561 // Make sure this is a data continuation word, if not, stop here
4562 if(((*iptr>>31) & 0x1) != 0x0)break;
4563
4564 bool invalid_1 = (*iptr>>29) & 0x1;
4565 bool invalid_2 = (*iptr>>13) & 0x1;
4566 uint16_t sample_1 = 0;
4567 uint16_t sample_2 = 0;
4568 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4569 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4570
4571 // Sample 1
4572 wrd->samples.push_back(sample_1);
4573 wrd->invalid_samples |= invalid_1;
4574 wrd->overflow |= (sample_1>>12) & 0x1;
4575
4576 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4577
4578 // Sample 2
4579 wrd->samples.push_back(sample_2);
4580 wrd->invalid_samples |= invalid_2;
4581 wrd->overflow |= (sample_2>>12) & 0x1;
4582 }
4583
4584 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4585
4586 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4587 // This will happen if a Window Raw Data block is encountered before an event header.
4588 // For these cases, we still want to try parsing the data so that the iptr is updated
4589 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4590 // the list. Otherwise, delete it now.
4591 if(objs){
4592 objs->hit_objs.push_back(wrd);
4593 }else{
4594 delete wrd;
4595 }
4596}
4597
4598//----------------
4599// MakeDf125PulseRawData
4600//----------------
4601void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4602{
4603 uint32_t channel = (*iptr>>23) & 0x0F;
4604 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4605 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4606
4607 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4608
4609 // This loop needs to break when it hits a non-continuation word
4610 for(uint32_t isample=0; isample<1000; isample +=2){
4611
4612 // Advance to next word
4613 iptr++;
4614
4615 // Make sure this is a data continuation word, if not, stop here
4616 if(((*iptr>>31) & 0x1) != 0x0)break;
4617
4618 bool invalid_1 = (*iptr>>29) & 0x1;
4619 bool invalid_2 = (*iptr>>13) & 0x1;
4620 uint16_t sample_1 = 0;
4621 uint16_t sample_2 = 0;
4622 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4623 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4624
4625 // Sample 1
4626 prd->samples.push_back(sample_1);
4627 prd->invalid_samples |= invalid_1;
4628 prd->overflow |= (sample_1>>12) & 0x1;
4629
4630 bool last_word = (iptr[1]>>31) & 0x1;
4631 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4632
4633 // Sample 2
4634 prd->samples.push_back(sample_2);
4635 prd->invalid_samples |= invalid_2;
4636 prd->overflow |= (sample_2>>12) & 0x1;
4637 }
4638
4639
4640 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4641 // This will happen if a Window Raw Data block is encountered before an event header.
4642 // For these cases, we still want to try parsing the data so that the iptr is updated
4643 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4644 // the list. Otherwise, delete it now.
4645 if(objs){
4646 objs->hit_objs.push_back(prd);
4647 }else{
4648 delete prd;
4649 }
4650}
4651
4652//----------------
4653// ParseF1TDCBank
4654//----------------
4655void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4656{
4657 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4658 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4659 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4660
4661 if(!PARSE_F1TDC){ iptr = iend; return; }
4662
4663 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4664
4665 const uint32_t *istart = iptr;
4666
4667 // Some early data had a marker word at just before the actual F1 data
4668 if(*iptr == 0xf1daffff) iptr++;
4669
4670 // Block header word
4671 // Double check that block header is set
4672 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4673 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4674 }
4675
4676 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4677 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4678 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4679 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4680 if(VERBOSE>2) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4681
4682 // Advance to next word
4683 iptr++;
4684
4685 // Loop over events
4686 ObjList *objs = NULL__null;
4687 while(iptr<iend){
4688
4689 // Event header
4690 // Double check that event header is set
4691 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4692 if(VERBOSE>10){
4693 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4693<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4694 DumpBinary(istart, iend, 0, iptr);
4695 }
4696 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4697 }
4698
4699 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4700 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4701 if(VERBOSE>2) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4702
4703 // Make sure slot number from event header matches block header
4704 if(slot_event_header != slot_block_header){
4705 char str[256];
4706 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4707 throw JException(str);
4708 }
4709
4710 // Advance to timestamp word
4711 iptr++;
4712 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4713
4714 // The most recent documentation says that the first time stamp
4715 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4716 // the second word is optional.
4717 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4718 if(VERBOSE>2) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4719 iptr++;
4720 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4721 if(((*iptr>>31) & 0x1) == 0){
4722 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4723 if(VERBOSE>2) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4724 }else{
4725 iptr--; // second time word not present, back up pointer
4726 }
4727
4728 // Create a new object list (i.e. new event)
4729 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4730 events.push_back(objs);
4731 objs = NULL__null;
4732 }
4733 if(!objs) objs = new ObjList;
4734
4735 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4736
4737 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4738 iptr++;
4739
4740 // Loop over F1 data words
4741 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
4742 while( iptr<iend && ((*iptr)>>31)==0x1 ){
4743
4744 bool done = false;
4745
4746 uint32_t chip, chan_on_chip, time;
4747 uint32_t channel;
4748 DF1TDCHit *hit=NULL__null;
4749 switch( (*iptr) & 0xF8000000 ){
4750 case 0xC0000000: // F1 Header
4751 chip_f1header = ((*iptr)>> 3) & 0x07;
4752 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
4753 itrigger_f1header = ((*iptr)>>16) & 0x3F;
4754 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
4755 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
4756 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
4757 break;
4758 case 0xB8000000: // F1 Data
4759 chip = (*iptr>>19) & 0x07;
4760 chan_on_chip = (*iptr>>16) & 0x07;
4761 time = (*iptr>> 0) & 0xFFFF;
4762 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
4763 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
4764 channel = F1TDC_channel(chip, chan_on_chip, modtype);
4765 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
4766 if(objs)objs->hit_objs.push_back(hit);
4767 break;
4768 case 0xF8000000: // Filler word
4769 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
4770 break;
4771 case 0x80000000: // JLab block header (handled in outer loop)
4772 case 0x88000000: // JLab block trailer (handled in outer loop)
4773 case 0x90000000: // JLab event header (handled in outer loop)
4774 case 0x98000000: // Trigger time (handled in outer loop)
4775 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
4776 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
4777 done = true;
4778 break;
4779 default:
4780 cerr<<endl;
4781 cout.flush(); cerr.flush();
4782 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4782<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
4783 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
4784 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4784<<" "
<<"0x"<<hex<<*iiptr<<dec;
4785 if(iiptr == iptr)cerr<<" <----";
4786 switch( (*iiptr) & 0xF8000000 ){
4787 case 0x80000000: cerr << " F1 Block Header"; break;
4788 case 0x90000000: cerr << " F1 Event Header"; break;
4789 case 0x98000000: cerr << " F1 Trigger time"; break;
4790 case 0xC0000000: cerr << " F1 Header"; break;
4791 case 0xB8000000: cerr << " F1 Data"; break;
4792 case 0x88000000: cerr << " F1 Block Trailer"; break;
4793 case 0xF8000000: cerr << " Filler word"; break;
4794 case 0xF0000000: cerr << " <module has no valid data>"; break;
4795 default: break;
4796 }
4797 cerr<<endl;
4798 if(iiptr > (iptr+4)) break;
4799 }
4800
4801 throw JException("Unexpected word type in F1TDC block!");
4802 }
4803
4804 if(done)break;
4805
4806 // Advance to next data word
4807 iptr++;
4808
4809 } // end loop over data words in this event
4810
4811 // If the current word is a JLab block trailer, then we are done
4812 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
4813
4814 } // end loop over events
4815
4816 // Add hits for last event to list of events.
4817 if(objs)events.push_back(objs);
4818
4819 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
4820 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
4821 }
4822
4823 // Advance past JLab block trailer
4824 iptr++;
4825
4826 // Skip filler words
4827 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
4828
4829 // Double check that we found all of the events we were supposed to
4830 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
4831 if(events.size() != Nevents_block_header){
4832 stringstream ss;
4833 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
4834 DumpBinary(istart, iend, 128);
4835 throw JException(ss.str());
4836 }
4837
4838 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4839
4840}
4841
4842//----------------
4843// F1TDC_channel
4844//----------------
4845uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
4846{
4847 /// Convert a F1TDC chip number and channel on the chip to the
4848 /// front panel channel number. This is based on "Input Channel Mapping"
4849 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
4850
4851 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
4852 switch(modtype){
4853 case DModuleType::F1TDC32:
4854 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
4855 case DModuleType::F1TDC48:
4856 return (chip <<3) | chan_on_chip;
4857 default:
4858 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4858<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
4859 throw JException("F1TDC_channel called for non-F1TDC module type");
4860 }
4861 return 1000000; // (should never get here)
4862}
4863
4864//----------------
4865// ParseTSBank
4866//----------------
4867void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4868{
4869 cout << "<><><><><> !! Parsing of JLab TS module requested !! <><><>" << endl;
4870 cout << "<><><><><> !! TS parsing not yet supported !! <><><>" << endl;
4871 iptr = iend;
4872}
4873
4874//----------------
4875// ParseTIBank
4876//----------------
4877void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4878{
4879 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4880 iptr++; // advance past JLab block trailer
4881 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4882 //iptr = iend;
4883}
4884
4885//----------------
4886// ParseCAEN1190
4887//----------------
4888void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4889{
4890 /// Parse data from a CAEN 1190 or 1290 module
4891 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
4892
4893 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
4894
4895 uint32_t slot = 0;
4896 uint32_t event_count = 0;
4897 uint32_t word_count = 0;
4898 uint32_t trigger_time_tag = 0;
4899 uint32_t tdc_num = 0;
4900 uint32_t event_id = 0;
4901 uint32_t bunch_id = 0;
4902
4903 // We need to accomodate multi-event blocks where
4904 // events are entangled (i.e. hits from event 1
4905 // are mixed inbetween those of event 2,3,4,
4906 // etc... With CAEN modules, we only know which
4907 // event a hit came from by looking at the event_id
4908 // in the TDC header. This value is only 12 bits
4909 // and could roll over within an event block. This
4910 // means we need to keep track of the order we
4911 // encounter them in so it is maintained in the
4912 // "events" container. The event_id order is kept
4913 // in the "event_id_order" vector.
4914 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
4915 vector<uint32_t> event_id_order;
4916
4917 while(iptr<iend){
4918
4919 // This word appears to be appended to the data.
4920 // Probably in the ROL. Ignore it if found.
4921 if(*iptr == 0xd00dd00d) {
4922 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
4923 iptr++;
4924 continue;
4925 }
4926
4927 uint32_t type = (*iptr) >> 27;
4928 uint32_t edge = 0; // 1=trailing, 0=leading
4929 uint32_t channel = 0;
4930 uint32_t tdc = 0;
4931 uint32_t error_flags = 0;
4932 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
4933 map<uint32_t, ObjList*>::iterator iter;
4934 switch(type){
4935 case 0b01000: // Global Header
4936 slot = (*iptr) & 0x1f;
4937 event_count = ((*iptr)>>5) & 0xffffff;
4938 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
4939 break;
4940 case 0b10000: // Global Trailer
4941 slot = (*iptr) & 0x1f;
4942 word_count = ((*iptr)>>5) & 0x7ffff;
4943 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
4944 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
4945 break;
4946 case 0b10001: // Global Trigger Time Tag
4947 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
4948 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
4949 break;
4950 case 0b00001: // TDC Header
4951 tdc_num = ((*iptr)>>24) & 0x03;
4952 event_id = ((*iptr)>>12) & 0x0fff;
4953 bunch_id = (*iptr) & 0x0fff;
4954 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
4955 event_id_order.push_back(event_id);
4956 }
4957 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
4958 break;
4959 case 0b00000: // TDC Measurement
4960 edge = ((*iptr)>>26) & 0x01;
4961 channel = ((*iptr)>>21) & 0x1f;
4962 tdc = ((*iptr)>>0) & 0x1fffff;
4963 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
4964
4965 // Create DCAEN1290TDCHit object
4966 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
4967 hits_by_event_id[event_id].push_back(caen1290tdchit);
4968 break;
4969 case 0b00100: // TDC Error
4970 error_flags = (*iptr) & 0x7fff;
4971 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
4972 break;
4973 case 0b00011: // TDC Trailer
4974 tdc_num = ((*iptr)>>24) & 0x03;
4975 event_id = ((*iptr)>>12) & 0x0fff;
4976 word_count = ((*iptr)>>0) & 0x0fff;
4977 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
4978 tdc_num = event_id = bunch_id = 0;
4979 break;
4980 case 0b11000: // Filler Word
4981 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
4982 break;
4983 default:
4984 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
4985 }
4986
4987 iptr++;
4988 }
4989
4990 // If disentagling is disabled, then lump all hits into single event
4991 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
4992 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
4993 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
4994 for(uint32_t i=1; i<event_id_order.size(); i++){
4995 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
4996 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
4997 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
4998 }
4999 }
5000
5001 // Add hits for each event to the events container, creating ObjList's as needed
5002 for(uint32_t i=0; i<event_id_order.size(); i++){
5003
5004 // Make sure there are enough event containers to hold this event
5005 while(events.size() <= i) events.push_back(new ObjList);
5006 list<ObjList*>::iterator it = events.begin();
5007 advance(it, i);
5008 ObjList *objs = *it;
5009
5010 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
5011 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
5012
5013 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
5014 }
5015
5016}
5017
5018//----------------
5019// ParseBORevent
5020//----------------
5021void JEventSource_EVIO::ParseBORevent(evioDOMNodeP bankPtr)
5022{
5023 if(!PARSE_BOR) return;
5024
5025 // This really shouldn't be needed
5026 pthread_rwlock_wrlock(&BOR_lock);
5027
5028 // Delete any existing BOR config objects. BOR events should
5029 // be flagged as sequential (or barrier) events so all threads
5030 // that were using these should be done with them now.
5031 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
5032 BORobjs.clear();
5033
5034 evioDOMNodeListP bankList = bankPtr->getChildren();
5035 evioDOMNodeList::iterator iter = bankList->begin();
5036 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in BOR event" << endl;
5037 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
5038 evioDOMNodeP childBank = *iter;
5039
5040 if(childBank->tag==0x71){
5041// uint32_t rocid = childBank->num;
5042 evioDOMNodeListP bankList = childBank->getChildren();
5043 evioDOMNodeList::iterator iter = bankList->begin();
5044 for(; iter!=bankList->end(); iter++){
5045 evioDOMNodeP dataBank = *iter;
5046// uint32_t slot = dataBank->tag>>5;
5047 uint32_t modType = dataBank->tag&0x1f;
5048
5049 const vector<uint32_t> *vec = dataBank->getVector<uint32_t>();
5050
5051 const uint32_t *src = &(*vec)[0];
5052 uint32_t *dest = NULL__null;
5053 uint32_t sizeof_dest = 0;
5054
5055 Df250BORConfig *f250conf = NULL__null;
5056 Df125BORConfig *f125conf = NULL__null;
5057 DF1TDCBORConfig *F1TDCconf = NULL__null;
5058 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
5059
5060 switch(modType){
5061 case DModuleType::FADC250: // f250
5062 f250conf = new Df250BORConfig;
5063 dest = (uint32_t*)&f250conf->rocid;
5064 sizeof_dest = sizeof(f250config);
5065 break;
5066 case DModuleType::FADC125: // f125
5067 f125conf = new Df125BORConfig;
5068 dest = (uint32_t*)&f125conf->rocid;
5069 sizeof_dest = sizeof(f125config);
5070 break;
5071
5072 case DModuleType::F1TDC32: // F1TDCv2
5073 case DModuleType::F1TDC48: // F1TDCv3
5074 F1TDCconf = new DF1TDCBORConfig;
5075 dest = (uint32_t*)&F1TDCconf->rocid;
5076 sizeof_dest = sizeof(F1TDCconfig);
5077 break;
5078
5079 case DModuleType::CAEN1190: // CAEN 1190 TDC
5080 case DModuleType::CAEN1290: // CAEN 1290 TDC
5081 caen1190conf = new DCAEN1290TDCBORConfig;
5082 dest = (uint32_t*)&caen1190conf->rocid;
5083 sizeof_dest = sizeof(caen1190config);
5084 break;
5085 }
5086
5087 // Check that the bank size and data structure size match.
5088 // If they do, then copy the data and add the object to
5089 // the event. If not, then delete the object and print
5090 // a warning message.
5091 if( vec->size() == (sizeof_dest/sizeof(uint32_t)) ){
5092
5093 // Copy bank data, assuming format is the same
5094 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
5095
5096 // Store object for use in this and subsequent events
5097 if(f250conf) BORobjs.push_back(f250conf);
5098 if(f125conf) BORobjs.push_back(f125conf);
5099 if(F1TDCconf) BORobjs.push_back(F1TDCconf);
5100 if(caen1190conf) BORobjs.push_back(caen1190conf);
5101
5102 }else if(sizeof_dest>0){
5103 if(f250conf) delete f250conf;
5104 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5104<<" "
<< "BOR bank size does not match structure! " << vec->size() <<" != " << (sizeof_dest/sizeof(uint32_t)) << endl;
5105 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5105<<" "
<< "sizeof(f250config)="<<sizeof(f250config)<<endl;
5106 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5106<<" "
<< "sizeof(f125config)="<<sizeof(f125config)<<endl;
5107 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5107<<" "
<< "sizeof(F1TDCconfig)="<<sizeof(F1TDCconfig)<<endl;
5108 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5108<<" "
<< "sizeof(caen1190config)="<<sizeof(caen1190config)<<endl;
5109 }
5110 }
5111 }
5112 }
5113
5114 pthread_rwlock_unlock(&BOR_lock);
5115
5116}
5117
5118//----------------
5119// ParseEPICSevent
5120//----------------
5121void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
5122{
5123 if(!PARSE_EPICS) return;
5124
5125 time_t timestamp=0;
5126
5127 ObjList *objs = NULL__null;
5128
5129 evioDOMNodeListP bankList = bankPtr->getChildren();
5130 evioDOMNodeList::iterator iter = bankList->begin();
5131 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
5132 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
5133 evioDOMNodeP childBank = *iter;
5134
5135 if(childBank->tag == 97){
5136 // timestamp bank
5137 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
5138 if(vec) {
5139 timestamp = (time_t)(*vec)[0];
5140 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
5141 }
5142 }else if(childBank->tag==98){
5143 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
5144 if(vec){
5145 string nameval = (const char*)&((*vec)[0]);
5146 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
5147 if(VERBOSE>7) evioout << " " << nameval << endl;
5148
5149 if(!objs){
5150 if(events.empty()) events.push_back(new ObjList);
5151 objs = *(events.begin());
5152 }
5153 objs->misc_objs.push_back(epicsval);
5154 }
5155 }
5156 }
5157}
5158
5159//----------------
5160// DumpBinary
5161//----------------
5162void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
5163{
5164 /// This is used for debugging. It will print to the screen the words
5165 /// starting at the address given by iptr and ending just before iend
5166 /// or for MaxWords words, whichever comes first. If iend is NULL,
5167 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
5168 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
5169 /// only the word at iptr is printed.
5170
5171 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
5172
5173 if(iend==NULL__null && MaxWords==0) MaxWords=1;
5174 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
5175
5176 uint32_t Nwords=0;
5177 while(iptr!=iend && Nwords<MaxWords){
5178
5179 // line1 is hex and line2 is decimal
5180 stringstream line1, line2;
5181
5182 // print words in columns 8 words wide. First part is
5183 // reserved for word number
5184 uint32_t Ncols = 8;
5185 line1 << setw(5) << Nwords;
5186 line2 << string(5, ' ');
5187
5188 // Loop over columns
5189 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
5190
5191 if(iptr == iend) break;
5192 if(Nwords>=MaxWords) break;
5193
5194 stringstream iptr_hex;
5195 iptr_hex << hex << "0x" << *iptr;
5196
5197 string mark = (iptr==imark ? "*":" ");
5198
5199 line1 << setw(12) << iptr_hex.str() << mark;
5200 line2 << setw(12) << *iptr << mark;
5201 }
5202
5203 cout << line1.str() << endl;
5204 cout << line2.str() << endl;
5205 cout << endl;
5206 }
5207}
5208
5209#endif // HAVE_EVIO
5210
5211#if 0
5212//----------------
5213// GuessModuleType
5214//----------------
5215MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
5216{
5217 /// Try parsing through the information in the given data buffer
5218 /// to determine which type of module produced the data.
5219
5220 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
5221 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
5222 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
5223 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
5224 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
5225
5226
5227 // Couldn't figure it out...
5228 return DModuleType::UNKNOWN;
5229}
5230
5231//----------------
5232// IsFADC250
5233//----------------
5234bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
5235{
5236 //---- Check for f250
5237 // This will check if the first word appears to be a block header.
5238 // If so, it loops over all words looking for a block trailer.
5239 // If the slot number in the block trailer matches that in the
5240 // block header AND the number of words in the block matches that
5241 // specified in the block trailer, then it is assumed to be a f250.
5242 if(((*istart>>31) & 0x1) == 1){
5243 uint32_t data_type = (*istart>>27) & 0x0F;
5244 if(data_type == 0){ // Block Header
5245 uint32_t slot_header = (*istart>>22) & 0x1F;
5246 uint32_t Nwords = 1;
5247 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
5248 if(((*iptr>>31) & 0x1) == 1){
5249 uint32_t data_type = (*iptr>>27) & 0x0F;
5250 if(data_type == 1){ // Block Trailer
5251 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
5252 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
5253
5254 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
5255 return true;
5256 }else{
5257 return false;
5258 }
5259 }
5260 }
5261 }
5262 }
5263 }
5264
5265 // either first word was not a block header or no block trailer was found
5266 return false;
5267}
5268
5269//----------------
5270// IsF1TDC
5271//----------------
5272bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
5273{
5274 //---- Check for F1TDC
5275 // This will check for consistency in the slot numbers for all words
5276 // in the buffer. The slot number of data words are checked against
5277 // the slot number of the most recently encountered header word.
5278 uint32_t slot_header = 1000;
5279 uint32_t slot_trailer = 1000;
5280
5281 const uint32_t *iptr=istart;
5282
5283 // skip first word which appears to be ROL marker for F1TDC data
5284 if(*istart == 0xf1daffff)iptr++
5285
5286 // There is no distinction between header and trailer
5287 // words other than the order that they appear. We keep
5288 // track by flipping this value
5289 bool looking_for_header = true;
5290
5291 // Keep track of the number of valid blocks of F1TDC data we find
5292 // (i.e. ones where the header and trailer words were found
5293 int Nvalid = 0;
5294
5295 for(; iptr<iend; iptr++){
5296
5297 // ROL end of data marker (only in test setup data)
5298 if(*iptr == 0xda0000ff)break;
5299
5300 uint32_t slot = (*iptr>>27) & 0x1F;
5301
5302 // if slot is 0 or 30, we are supposed to ignore the data.
5303 if(slot == 30 || slot ==0)continue;
5304
5305 if(((*iptr>>23) & 0x1) == 0){
5306 // header/trailer word
5307 if(looking_for_header){
5308 slot_header = slot;
5309 looking_for_header = false;
5310 }else{
5311 slot_trailer = slot;
5312 if(slot_trailer != slot_header)return false;
5313 looking_for_header = true;
5314 Nvalid++;
5315 }
5316 }else{
5317 // data word
5318
5319 // if we encounter a data word when we are expecting
5320 // a header word, then the current word is not from
5321 // an F1TDC. However, if we did find at least one valid
5322 // block at the begining, of the buffer, claim the buffer
5323 // points to F1TDC data. We check for as many valid F1TDC
5324 // blocks as possible to help ensure that is what the data
5325 // is.
5326 if(looking_for_header)return Nvalid>0;
5327
5328 // If the slot number does not match, then this is
5329 // not valid F1TDC data
5330 if(slot != slot_header)return false;
5331 }
5332 }
5333
5334 return Nvalid>0;
5335}
5336
5337//----------------
5338// DumpModuleMap
5339//----------------
5340void JEventSource_EVIO::DumpModuleMap(void)
5341{
5342 // Open output file
5343 string fname = "module_map.txt";
5344 ofstream ofs(fname.c_str());
5345 if(!ofs.is_open()){
5346 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
5347 return;
5348 }
5349
5350 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
5351
5352 // Write header
5353 time_t now = time(NULL__null);
5354 ofs<<"# Autogenerated module map"<<endl;
5355 ofs<<"# Created: "<<ctime(&now);
5356 ofs<<"#"<<endl;
5357
5358 // Write known module types in header
5359 vector<DModuleType> modules;
5360 DModuleType::GetModuleList(modules);
5361 ofs<<"# Known module types:"<<endl;
5362 ofs<<"# ----------------------"<<endl;
5363 for(unsigned int i=0; i<modules.size(); i++){
5364 string name = modules[i].GetName();
5365 string space(12-name.size(), ' ');
5366 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5367 }
5368 ofs<<"#"<<endl;
5369 ofs<<"#"<<endl;
5370
5371 // Write module map
5372 ofs<<"# Format is:"<<endl;
5373 ofs<<"# tag num type"<<endl;
5374 ofs<<"#"<<endl;
5375
5376 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5377 for(; iter!=module_type.end(); iter++){
5378
5379 tagNum tag_num = iter->first;
5380 MODULE_TYPE type = iter->second;
5381 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5382 }
5383 ofs<<endl;
5384
5385 // Close output file
5386 ofs.close();
5387}
5388#endif