Bug Summary

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