Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 1025, 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);} }
;
1023 CloneConfigObject(Df125Config){ if(confobj->className() == string("Df125Config")){ c = new
Df125Config(confobj->rocid,confobj->slot_mask); *((Df125Config
*)c) = *((Df125Config*)confobj);} }
;
1024 CloneConfigObject(DF1TDCConfig){ if(confobj->className() == string("DF1TDCConfig")){ c = new
DF1TDCConfig(confobj->rocid,confobj->slot_mask); *((DF1TDCConfig
*)c) = *((DF1TDCConfig*)confobj);} }
;
17
Within the expansion of the macro 'CloneConfigObject':
a
Memory is allocated
1025 CloneConfigObject(DCAEN1290TDCConfig){ if(confobj->className() == string("DCAEN1290TDCConfig"))
{ c = new DCAEN1290TDCConfig(confobj->rocid,confobj->slot_mask
); *((DCAEN1290TDCConfig*)c) = *((DCAEN1290TDCConfig*)confobj
);} }
;
18
Within the expansion of the macro 'CloneConfigObject':
a
Potential leak of memory pointed to by 'c'
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(!WARN_USER_RUN_FILENAME) {
3028 jout << "WARNING: setting run number " << filename_run_number << " based on file name" << endl;
3029 WARN_USER_RUN_FILENAME = true;
3030 }
3031
3032 return last_run_number = filename_run_number;
3033}
3034
3035//----------------
3036// EpicQuestForRunNumber
3037//----------------
3038int32_t JEventSource_EVIO::EpicQuestForRunNumber(void)
3039{
3040 /// This is called when an event is encountered that does
3041 /// not have a run number in it. (e.g. a BOR event encountered
3042 /// in FindRunNumber() ). This is a last hope of finding the
3043 /// run number in the file by looking for other events that
3044 /// may contain it. Specifically, EPICS or PHYSICS events.
3045 /// This only works if it is a file source so that it can open
3046 /// the file and read in past the first event.
3047 ///
3048 /// Note that this is extremely inefficient so should not be
3049 /// called very often. As a precaution, this will look to see
3050 /// if last_run_number is not set to 0 first and will just
3051 /// return it if it is. Only if it is not will the epic quest
3052 /// commence.
3053
3054 if(source_type!=kFileSource) return 0;
3055 if(last_run_number != 0) return last_run_number;
3056
3057 uint32_t buff_len = 4000000;
3058 uint32_t *buff = new uint32_t[buff_len];
3059 HDEVIO *hdevio = new HDEVIO(source_name);
3060 while(hdevio->read(buff, buff_len)){
3061
3062 // Assume first word is number of words in bank
3063 uint32_t *iptr = buff;
3064 uint32_t *iend = &iptr[*iptr - 1];
3065 if(*iptr > 2048) iend = &iptr[2048];
3066 bool has_timestamps = false;
3067 while(iptr<iend){
3068 iptr++;
3069
3070 // EPICS event
3071 if( (*iptr & 0xff000f) == 0x600001){
3072 if(VERBOSE>2) evioout << " Found EPICS header. Looking for HD:coda:daq:run_number ..." << endl;
3073 const char *cptr = (const char*)&iptr[1];
3074 const char *cend = (const char*)iend;
3075 const char *needle = "HD:coda:daq:run_number=";
3076 while(cptr<cend){
3077 if(VERBOSE>4) evioout << " \""<<cptr<<"\"" << endl;
3078 if(!strncmp(cptr, needle, strlen(needle))){
3079 if(VERBOSE>2) evioout << " Found it!" << endl;
3080 if(hdevio) delete hdevio;
3081 if(buff) delete[] buff;
3082 return atoi(&cptr[strlen(needle)]);
3083 }
3084 cptr+=4; // should only start on 4-byte boundary!
3085 }
3086 }
3087
3088 // BOR event
3089 if( (*iptr & 0xffffffff) == 0x00700E01) continue;
3090
3091 // PHYSICS event
3092 bool not_in_this_buffer = false;
3093 switch((*iptr)>>16){
3094 case 0xFF10:
3095 case 0xFF11:
3096 case 0xFF20:
3097 case 0xFF21:
3098 case 0xFF24:
3099 case 0xFF25:
3100 case 0xFF30:
3101 not_in_this_buffer = true;
3102 break;
3103 case 0xFF23:
3104 case 0xFF27:
3105 has_timestamps = true;
3106 case 0xFF22:
3107 case 0xFF26:
3108 break;
3109 default:
3110 continue;
3111 }
3112
3113 if(not_in_this_buffer) break; // go to next EVIO buffer
3114
3115 iptr++;
3116 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
3117 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
3118 if(VERBOSE>2) evioout << " ...(epic quest) Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
3119 iptr++;
3120 uint64_t *iptr64 = (uint64_t*)iptr;
3121
3122 uint64_t event_num = *iptr64;
3123 if(source_type==kETSource) event_num = ((*iptr64)>>32) | ((*iptr64)<<32);
3124 if(VERBOSE>3) evioout << " ....(epic quest) Event num: " << event_num <<endl;
3125 iptr64++;
3126 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
3127
3128 // I'm not sure I fully understand this, but if we read from
3129 // ET, then the run number is in the low 32 bits of *iptr64.
3130 // If we are reading from a file, it is in the high 32 bits.
3131 // No byte swapping is needed (it has already been done, though
3132 // perhaps incorrectly). We handle this here by checking if
3133 // this is an ET source or not.
3134 uint64_t run64 = (*iptr64)>>32;
3135 if(source_type==kETSource){
3136 run64 = (*iptr64)&0xffffffff;
3137 }
3138 int32_t run = (int32_t)run64;
3139 if(VERBOSE>1) evioout << " .. (epic quest) Found run number: " << run <<endl;
3140
3141 if(hdevio) delete hdevio;
3142 if(buff) delete[] buff;
3143 return run;
3144
3145 } // while(iptr<iend)
3146
3147 if(hdevio->Nevents > 500) break;
3148 } // while(hdevio->read(buff, buff_len))
3149
3150 if(hdevio) delete hdevio;
3151 if(buff) delete[] buff;
3152
3153 return 0;
3154}
3155
3156//----------------
3157// FindEventNumber
3158//----------------
3159uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
3160{
3161 /// This is called from GetEvent() to quickly look for the event number
3162 /// at the time the event is read in so it can be passed into JEvent.
3163 /// (See comments for FindRunNumber above.)
3164 if(VERBOSE>1) evioout << " .. Searching for event number ..." <<endl;
3165
3166 if(*iptr < 6){
3167 if(VERBOSE>1) evioout << " Word count(="<<*iptr<<")<6. Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
3168 return Nevents_read+1;
3169 }
3170
3171 // Check header of Trigger bank
3172 uint32_t mask = 0xFF202000;
3173 if( (iptr[3]&mask) != mask ){
3174 if(VERBOSE>1){
3175 evioout << " iptr[3]=" << hex << iptr[3] << " does not look like trigger bank tag (" << (iptr[3]&mask) << " != " << mask << ")" << dec <<endl;
3176 evioout << " Returning Nevents_read+1(=" << Nevents_read+1 << ") as event number" <<endl;
3177 }
3178 return Nevents_read+1;
3179 }
3180
3181 uint64_t loevent_num = iptr[5];
3182 uint64_t hievent_num = iptr[6];
3183 if(source_type==kETSource) {
3184 loevent_num = iptr[6];
3185 hievent_num = iptr[5];
3186 }
3187 uint64_t event_num = loevent_num + (hievent_num<<32);
3188 if(VERBOSE>1) evioout << " .. Found event number: " << event_num <<endl;
3189
3190 return event_num;
3191}
3192
3193//----------------
3194// FindEventType
3195//----------------
3196void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
3197{
3198 /// This is called from GetEvent to quickly determine the type of
3199 /// event this is (Physics, EPICS, SYNC, BOR, ...)
3200 uint32_t head = iptr[1];
3201 if( (head & 0xff000f) == 0x600001){
3202 event.SetStatusBit(kSTATUS_EPICS_EVENT);
3203 }else if( (head & 0xffffffff) == 0x00700E01){
3204 event.SetStatusBit(kSTATUS_BOR_EVENT);
3205 }else if( (head & 0xffffff00) == 0xff501000){
3206 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
3207 }else if( (head & 0xffffff00) == 0xff701000){
3208 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
3209 }else if( (head & 0xfff000ff) == 0xffd00000){
3210 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
3211 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
3212 }else{
3213 DumpBinary(iptr, &iptr[16]);
3214 }
3215}
3216
3217//----------------
3218// MergeObjLists
3219//----------------
3220void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
3221{
3222 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
3223 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
3224 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
3225
3226 /// Merge the events referenced in events2 into the events1 list.
3227 ///
3228 /// This will append the object lists for each type of data object
3229 /// stored in events2 onto the appropriate list in events1. It does this
3230 /// event-by-event. The idea being that each entry in the queue represents a
3231 /// partial list of the objects for the event. The two queues are most likely
3232 /// filled from different EVIO banks orginiating from different ROCs.
3233 ///
3234 /// Before the merging is done, it is checked that both lists either have the
3235 /// same number of events, or one list is empty. One list is allowed to be
3236 /// empty since it is possible it was "filled" from a bank that contains no
3237 /// data at all which may not neccessarily be an error. If both queues have
3238 /// at least one event, but they do not contain an equal number of events,
3239 /// then an exception is thrown.
3240 ///
3241 /// The contents of event2 will be erased before returning. Ownership of all
3242 /// ObjList objects pointed to by event2 upon entry should be considered
3243 /// owned by event1 upon return.
3244
3245 // Allow a list of 1 event with only config objects in test below
3246 bool justconfig = false;
3247 if(events1.size()==1){
3248 ObjList *objs1 = events1.front();
3249 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
3250 }else if(events2.size()==1){
3251 ObjList *objs2 = events2.front();
3252 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
3253 }
3254
3255 // Check number of events and throw exception if appropriate
3256 unsigned int Nevents1 = events1.size();
3257 unsigned int Nevents2 = events2.size();
3258 if(Nevents1>0 && Nevents2>0 && !justconfig){
3259 if(Nevents1 != Nevents2){
3260 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
3261 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
3262 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
3263 }
3264 }
3265
3266 // Handle cases when one or both lists are empty
3267 if(Nevents1==0 && Nevents2==0)return;
3268 if(Nevents1==0){
3269 events1 = events2;
3270 events2.clear(); // clear queue
3271 return;
3272 }
3273 if(Nevents2==0)return;
3274
3275 // If we get here it means both events1 and events2 have events
3276 list<ObjList*>::iterator iter = events1.begin();
3277 for(; iter!=events1.end(); iter++){
3278 if(events2.empty()) break; // in case one has just config objects in a single event
3279 ObjList *objs1 = *iter;
3280 ObjList *objs2 = events2.front();
3281 events2.pop_front();
3282
3283 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
3284 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
3285 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
3286
3287 // Delete the objs2 container
3288 delete objs2;
3289 }
3290
3291 // Clear out any references to objects in event2 (this should be redundant)
3292 events2.clear(); // clear queue
3293
3294 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
3295}
3296
3297//----------------
3298// ParseEVIOEvent
3299//----------------
3300void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
3301{
3302 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
3303
3304 if(!evt)throw RESOURCE_UNAVAILABLE;
3305
3306 // Since each bank contains parts of many events, have them fill in
3307 // the "tmp_events" list and then merge those into the "full_events".
3308 // It is done this way so each bank can grow tmp_events to the appropriate
3309 // size to hold the number of events it discovers in the bank. A check
3310 // can then be made that this is consistent with the number of event
3311 // fragments found in the other banks.
3312 //list<ObjList*> full_events;
3313 list<ObjList*> tmp_events;
3314
3315 // The Physics Event bank is the outermost bank of the event and
3316 // it is a bank of banks. One of those banks is the
3317 // "Built Trigger Bank" which is a bank of segments. The others
3318 // are the "Data Bank" banks which in turn contain the
3319 // "Data Block Bank" banks which hold the actual data. For the
3320 // mc2coda generated data files (and presumably the real data)
3321 // these Data Block Banks are banks of ints. More specifically,
3322 // uint32_t.
3323 //
3324 // The "Physics Event's Built Trigger Bank" is a bank of segments.
3325 // This contains 3 segments, one each of type uint64, uint16, and
3326 // unit32. The first two are "common data" which contains information
3327 // common to all rocs. The last (uint32) has information specific to each
3328 // event and for each ROC.
3329 //
3330 // For now, we skip parseing the Built Trigger Bank and just
3331 // look for Data Block Banks. We do this by getting a list of
3332 // all uint32_t banks in the enitries DOM Tree (at all levels
3333 // of the heirachy) and checking the parent banks for depth
3334 // and additional info.
3335
3336 // Loop over list of all EVIO banks at all levels of the tree and parse
3337 // them, creating data objects and adding them to the overall list.
3338 evioDOMNodeListP bankList = evt->getNodeList();
3339 evioDOMNodeList::iterator iter = bankList->begin();
3340 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
3341 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
3342
3343 if(VERBOSE>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
3344
3345 // The data banks we want should have exactly two parents:
3346 // - Data Bank bank <-- parent
3347 // - Physics Event bank <-- grandparent
3348 //
3349 // other types of events may be inserted in the datastream though so we
3350 // check for those first.
3351
3352 // BOR event
3353 // BOR events will have an outermost
3354 // bank with tag=0x70 and num=1. If this is the outermost bank of
3355 // a BOR event, then parse it. If it is a inner BOR bank then ignore it.
3356 evioDOMNodeP outermostBankPtr = *iter;
3357 while(outermostBankPtr->getParent()) outermostBankPtr = outermostBankPtr->getParent();
3358 if(outermostBankPtr->tag==0x70 && outermostBankPtr->num==1){
3359 // This is a BOR bank
3360 if(VERBOSE>9) evioout << " bank is part of BOR event ... " << endl;
3361 if(outermostBankPtr == *iter){
3362 if(VERBOSE>9) evioout << " bank is outermost EVIO bank. Parsing BOR event ..." << endl;
3363 ParseBORevent(outermostBankPtr);
3364 }else{
3365 if(VERBOSE>9) evioout << " bank is not outermost EVIO bankin BOR event skipping ..." << endl;
3366 }
3367 continue; // no further processing of this bank is needed
3368 }
3369
3370 // EPICS event
3371 evioDOMNodeP bankPtr = *iter;
3372 evioDOMNodeP data_bank = bankPtr->getParent();
3373 if( data_bank==NULL__null ) {
3374
3375 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
3376 if(bankPtr->tag==96 && bankPtr->num==1){
3377 // This looks like an EPICS event. Hand it over to EPICS parser
3378 ParseEPICSevent(bankPtr, full_events);
3379 }else{
3380 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
3381 }
3382
3383 continue;
3384 }
3385
3386 // Trigger Bank
3387 evioDOMNodeP physics_event_bank = data_bank->getParent();
3388
3389 // TS scalers for SYNC events. Currently us phys event tag
3390 // Don't use the parent tag in the future, to be checked
3391 if((physics_event_bank != NULL__null) && (bankPtr != NULL__null)){
3392 if( (physics_event_bank->tag == 0xff70) && (bankPtr->tag == 0xEE02)){
3393 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
3394 if(vec->size() < 102){
3395 evioout << " TS record for SYNC event is inconsistent. Don't parse " << endl;
3396 } else {
3397 ParseTSSync(bankPtr, full_events);
3398// MergeObjLists(full_events, tmp_events);
3399 }
3400 }
3401 }
3402
3403
3404 if( physics_event_bank==NULL__null ){
3405 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
3406
3407 // Check if this is a CODA Reserved Bank Tag. If it is, then
3408 // this probably is part of the built trigger bank and not
3409 // the ROC data we're looking to parse here.
3410 if((bankPtr->tag & 0xFF00) == 0xFF00){
3411 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;
3412 ParseBuiltTriggerBank(bankPtr, tmp_events);
3413 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
3414 MergeObjLists(full_events, tmp_events);
3415
3416 // Check if this is a DEventTag bank
3417 }else if(bankPtr->tag == 0x0056){
3418 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
3419 if(vec){
3420 const uint32_t *iptr = &(*vec)[0];
3421 const uint32_t *iend = &(*vec)[vec->size()];
3422 ParseEventTag(iptr, iend, tmp_events);
3423 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
3424 MergeObjLists(full_events, tmp_events);
3425 }
3426 }
3427
3428 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
3429 }
3430 if( physics_event_bank->getParent() != NULL__null ){
3431 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
3432 continue; // physics event bank should have no parent!
3433 }
3434 if(VERBOSE>9){
3435 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
3436 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
3437 }
3438
3439 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
3440
3441 // Extract ROC id (crate number) from bank's parent
3442 uint32_t rocid = data_bank->tag & 0x0FFF;
3443
3444 // Get data from bank in the form of a vector of uint32_t
3445 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
3446 if(!vec){
3447 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
3448 continue;
3449 }
3450 const uint32_t *iptr = &(*vec)[0];
3451 const uint32_t *iend = &(*vec)[vec->size()];
3452 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
3453
3454 // If there are rocid's specified that we wish to parse, make sure this one
3455 // is in the list. Otherwise, skip it.
3456 if(!ROCIDS_TO_PARSE.empty()){
3457 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
3458 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
3459 }
3460
3461 // Check if this is a CODA Reserved Bank Tag.
3462 if((data_bank->tag & 0xFF00) == 0xFF00){
3463 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
3464 continue;
3465 }
3466
3467 // Check if this is a TS Bank.
3468 if(bankPtr->tag == 0xEE02){
3469 if(VERBOSE>4) evioout << " TS bank tag="<<hex<<bankPtr->tag<<dec<< endl;
3470 ParseTSBank(rocid, iptr, iend, full_events);
3471 continue;
3472 }
3473
3474 // Check if this is a f250 Pedestal Bank.
3475 if(bankPtr->tag == 0xEE05){
3476 if(VERBOSE>6) evioout << " SYNC event - f250 pedestals not currently handled"<< endl;
3477 continue;
3478 }
3479
3480 // The number of events in block is stored in lower 8 bits
3481 // of header word (aka the "num") of Data Bank. This should
3482 // be at least 1.
3483 uint32_t NumEvents = data_bank->num & 0xFF;
3484 if( NumEvents<1 ){
3485 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
3486 continue;
3487 }
3488
3489 // At this point iptr and iend indicate the data that came
3490 // from the ROC itself (all CODA headers have been stripped
3491 // away). Here, we need to decide what type of data this
3492 // bank contains. All JLab modules have a common block
3493 // header format and so are handled in a common way. Other
3494 // modules (e.g. CAEN) will have to appear in their own
3495 // EVIO bank and should be identified by their own det_id
3496 // value in the Data Block Bank.
3497 //
3498 // Current, preliminary thinking includes writing the type
3499 // of data into the 12-bit detector id contained in the
3500 // Data Block Bank of the DAQ group's "Event Building EVIO
3501 // Scheme". (This is the lower 12 bits of the "tag"). We
3502 // use this to decide if it is JLab module data or somehting
3503 // else.
3504 uint32_t det_id = bankPtr->tag & 0x0FFF;
3505 // Call appropriate parsing method
3506 bool bank_parsed = true; // will be set to false if default case is entered
3507 switch(det_id){
3508 case 0:
3509 case 1:
3510 case 3:
3511 case 6: // flash 250 module, MMD 2014/2/4
3512 case 16: // flash 125 module (CDC), DL 2014/6/19
3513 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
3514 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
3515 break;
3516
3517 case 20:
3518 ParseCAEN1190(rocid, iptr, iend, tmp_events);
3519 break;
3520
3521 case 0x55:
3522 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
3523 break;
3524
3525 case 5:
3526 // Beni's original CDC ROL used for the stand-alone CDC DAQ
3527 // had the following for the TS readout list (used in the TI):
3528 // *dma_dabufp++ = 0xcebaf111;
3529 // *dma_dabufp++ = tsGetIntCount();
3530 // *dma_dabufp++ = 0xdead;
3531 // *dma_dabufp++ = 0xcebaf222;
3532 // We skip this here, but put in the case so that we avoid errors
3533 break;
3534
3535
3536 default:
3537 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
3538 bank_parsed = false;
3539 if(VERBOSE>5){
3540 cerr << endl;
3541 cout << "----- First few words to help with debugging -----" << endl;
3542 cout.flush(); cerr.flush();
3543 int i=0;
3544 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
3545 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3545<<" "
<< "0x" << hex << *iiptr << dec << endl;
3546 if(i>=8) break;
3547 }
3548
3549 }
3550 }
3551
3552 // Merge this bank's partial events into the full events
3553 if(bank_parsed){
3554 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
3555 MergeObjLists(full_events, tmp_events);
3556 }
3557 }
3558
3559 // The following disabled in preference for keeping the
3560 // run number found by FindRunNumber called from
3561 // GetEvent() 2/15/2016
3562
3563// // Set the run number for all events
3564// uint32_t run_number = GetRunNumber(evt);
3565// list<ObjList*>::iterator evt_iter = full_events.begin();
3566// for(; evt_iter!=full_events.end(); evt_iter++){
3567// ObjList *objs = *evt_iter;
3568// objs->run_number = run_number;
3569// }
3570
3571 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
3572}
3573
3574//----------------
3575// ParseBuiltTriggerBank
3576//----------------
3577void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
3578{
3579 if(!PARSE_TRIGGER) return;
3580
3581 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
3582
3583 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
3584 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
3585 evioDOMNodeP physics_event_bank = trigbank->getParent();
3586 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
3587
3588 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
3589
3590 // Some values to fill in while parsing the banks that will be used later to create objects
3591 vector<uint64_t> avg_timestamps;
3592 uint32_t run_number = 0;
3593 uint32_t run_type = 0;
3594 uint64_t first_event_num = 1;
3595 vector<uint16_t> event_types;
3596 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
3597 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
3598
3599 // Loop over children of built trigger bank
3600 evioDOMNodeListP bankList = trigbank->getChildren();
3601 evioDOMNodeList::iterator iter = bankList->begin();
3602 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
3603
3604 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
3605
3606 evioDOMNodeP bankPtr = *iter;
3607
3608 // The "Physics Event's Built Trigger Bank" is a bank of segments that
3609 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
3610 // The uint64_t contains the first event number, average timestamps, and
3611 // run number & types. The uint16_t contains the event type(s). The
3612 // uint32_t contains the optional ROC specific meta data starting with
3613 // the specific timestamp for each event. All of these have some options
3614 // on exactly what info is contained in the bank. The first check here is
3615 // on the data type the bank contains. At most, one of the following pointers
3616 // should be non-zero.
3617 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
3618 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
3619 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
3620
3621 // unit64_t = common data (1st part)
3622 if(vec64){
3623
3624 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
3625
3626 // In addition to the first event number (1st word) there are three
3627 // additional pieces of information that may be present:
3628 // t = average timestamp
3629 // r = run number and type
3630 // d = run specific data
3631 //
3632 // The last one ("d") comes in the form of multiple uint32_t banks
3633 // so is not included in vec64. The other two have their presence
3634 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
3635 // also deduce this from the bank length.)
3636
3637 if(vec64->size() == 0) continue; // need debug message here!
3638
3639 first_event_num = (*vec64)[0];
3640
3641 // Hi and lo 32bit words in 64bit numbers seem to be
3642 // switched for events read from ET, but not read from
3643 // file. Not sure if this is in the swapping routine
3644 if(source_type==kETSource) first_event_num = (first_event_num>>32) | (first_event_num<<32);
3645
3646 uint32_t Ntimestamps = vec64->size()-1;
3647 if(Ntimestamps==0) continue; // no more words of interest
3648 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
3649 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
3650
3651 // run number and run type
3652 if(trigbank->tag & 0x02){
3653 run_number = (*vec64)[vec64->size()-1] >> 32;
3654 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
3655 }
3656 }
3657
3658 // uint16_t = common data (2nd part)
3659 if(vec16){
3660
3661 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
3662
3663 for(uint32_t i=0; i<Mevents; i++){
3664 if(i>=vec16->size()) break;
3665 event_types.push_back((*vec16)[i]);
3666 }
3667 }
3668
3669 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
3670 if(vec32){
3671
3672 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
3673
3674 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
3675 uint32_t rocid = (uint32_t)bankPtr->tag;
3676 uint32_t Nwords_per_event = vec32->size()/Mevents;
3677 if(vec32->size() != Mevents*Nwords_per_event){
3678 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3678<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
3679 exit(-1);
3680 }
3681
3682 uint32_t *iptr = &(*vec32)[0];
3683 for(uint32_t ievent=0; ievent<Mevents; ievent++){
3684
3685 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
3686 codarocinfo->rocid = rocid;
3687
3688 uint64_t ts_low = *iptr++;
3689 uint64_t ts_high = *iptr++;
3690 codarocinfo->timestamp = (ts_high<<32) + ts_low;
3691 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
3692
3693 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
3694 rocinfos[ievent].push_back(codarocinfo);
3695 }
3696 }
3697 }
3698
3699 // Check that we have agreement on the number of events this data represents
3700 bool Nevent_mismatch = false;
3701 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
3702 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
3703 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
3704 if(Nevent_mismatch){
3705 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3705<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
3706 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3706<<" "
<<" Mevents="<<Mevents<<endl;
3707 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3707<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
3708 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3708<<" "
<<" event_types.size()="<<event_types.size()<<endl;
3709 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3709<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3710 exit(-1);
3711 }
3712
3713 // Copy all objects into events
3714 for(uint32_t i=0; i<Mevents; i++){
3715 while(events.size()<=i){
3716 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3717 events.push_back(new ObjList);
3718 }
3719 ObjList *objs = events.back();
3720
3721 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3722 codaeventinfo->run_number = run_number;
3723 codaeventinfo->run_type = run_type;
3724 codaeventinfo->event_number = first_event_num + i;
3725 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3726 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3727 objs->misc_objs.push_back(codaeventinfo);
3728 objs->event_number = codaeventinfo->event_number;
3729
3730 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3731 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3732 }
3733
3734 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3735 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3736}
3737
3738//----------------
3739// ParseModuleConfiguration
3740//----------------
3741void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3742{
3743 if(!PARSE_CONFIG){ iptr = iend; return; }
3744
3745 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3746
3747 /// Parse a bank of module configuration data. These are configuration values
3748 /// programmed into the module at the beginning of the run that may be needed
3749 /// in the offline. For example, the number of samples to sum in a FADC pulse
3750 /// integral.
3751 ///
3752 /// The bank has one or more sections, each describing parameters applicable
3753 /// to a number of modules as indicated by a 24bit slot mask.
3754 ///
3755 /// This bank should appear only once per DAQ event which, if in multi-event
3756 /// block mode, may have multiple L1 events. The parameters here will apply
3757 /// to all L1 events in the block. This method will put the config objects
3758 /// in the first event of "events", creating it if needed. The config objects
3759 /// are duplicated for all other events in the block later, after all event
3760 /// parsing is finished and the total number of events is known.
3761 /// (See the end of ParseEvents() .)
3762
3763 while(iptr < iend){
3764 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3765 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3766 iptr++;
3767
3768 Df250Config *f250config = NULL__null;
3769 Df125Config *f125config = NULL__null;
3770 DF1TDCConfig *f1tdcconfig = NULL__null;
3771 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3772
3773 // Loop over all parameters in this section
3774 for(uint32_t i=0; i< Nvals; i++){
3775 if( iptr >= iend){
3776 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3776<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3777 exit(-1);
3778 }
3779
3780 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3781 uint16_t val = (*iptr) & 0xFFFF;
3782
3783 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3784
3785 // Create config object of correct type if needed and copy
3786 // parameter value into it.
3787 switch(ptype>>8){
3788
3789 // f250
3790 case 0x05:
3791 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3792 switch(ptype){
3793 case kPARAM250_NSA : f250config->NSA = val; break;
3794 case kPARAM250_NSB : f250config->NSB = val; break;
3795 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3796 case kPARAM250_NPED : f250config->NPED = val; break;
3797 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3797<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3798 }
3799 break;
3800
3801 // f125
3802 case 0x0F:
3803 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3804 switch(ptype){
3805 case kPARAM125_NSA : f125config->NSA = val; break;
3806 case kPARAM125_NSB : f125config->NSB = val; break;
3807 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3808 case kPARAM125_NPED : f125config->NPED = val; break;
3809 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3810 case kPARAM125_PL : f125config->PL = val; break;
3811 case kPARAM125_NW : f125config->NW = val; break;
3812 case kPARAM125_NPK : f125config->NPK = val; break;
3813 case kPARAM125_P1 : f125config->P1 = val; break;
3814 case kPARAM125_P2 : f125config->P2 = val; break;
3815 case kPARAM125_PG : f125config->PG = val; break;
3816 case kPARAM125_IE : f125config->IE = val; break;
3817 case kPARAM125_H : f125config->H = val; break;
3818 case kPARAM125_TH : f125config->TH = val; break;
3819 case kPARAM125_TL : f125config->TL = val; break;
3820 case kPARAM125_IBIT : f125config->IBIT = val; break;
3821 case kPARAM125_ABIT : f125config->ABIT = val; break;
3822 case kPARAM125_PBIT : f125config->PBIT = val; break;
3823 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3823<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3824 }
3825 break;
3826
3827 // F1TDC
3828 case 0x06:
3829 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3830 switch(ptype){
3831 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3832 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3833 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3834 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3835 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3836 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3837 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3837<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3838 }
3839 break;
3840
3841 // caen1290
3842 case 0x10:
3843 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3844 switch(ptype){
3845 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3846 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = 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 default:
3852 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3852<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3853 exit(-1);
3854 }
3855
3856#if 0
3857 // Create config object of correct type if needed. (Only one type
3858 // should be created per section!)
3859 switch(ptype>>8){
3860 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3861 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3862 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3863 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3864 default:
3865 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3865<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3866 exit(-1);
3867 }
3868
3869 // Copy parameter into config. object
3870 switch(ptype){
3871 case kPARAM250_NSA : f250config->NSA = val; break;
3872 case kPARAM250_NSB : f250config->NSB = val; break;
3873 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3874 case kPARAM250_NPED : f250config->NPED = val; break;
3875
3876 case kPARAM125_NSA : f125config->NSA = val; break;
3877 case kPARAM125_NSB : f125config->NSB = val; break;
3878 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3879 case kPARAM125_NPED : f125config->NPED = val; break;
3880 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3881 case kPARAM125_PL : f125config->PL = val; break;
3882 case kPARAM125_NW : f125config->NW = val; break;
3883 case kPARAM125_NPK : f125config->NPK = val; break;
3884 case kPARAM125_P1 : f125config->P1 = val; break;
3885 case kPARAM125_P2 : f125config->P2 = val; break;
3886 case kPARAM125_PG : f125config->PG = val; break;
3887 case kPARAM125_IE : f125config->IE = val; break;
3888 case kPARAM125_H : f125config->H = val; break;
3889 case kPARAM125_TH : f125config->TH = val; break;
3890 case kPARAM125_TL : f125config->TL = val; break;
3891 case kPARAM125_IBIT : f125config->IBIT = val; break;
3892 case kPARAM125_ABIT : f125config->ABIT = val; break;
3893 case kPARAM125_PBIT : f125config->PBIT = val; break;
3894
3895 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3896 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3897 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3898 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3899 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3900 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3901
3902 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3903 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3904
3905 default:
3906 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3906<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3907 }
3908#endif
3909
3910 iptr++;
3911 }
3912
3913 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3914 // so there is at least one DDAQConfig object we need to store. Get pointer to
3915 // first event's ObjList, creating it if needed.
3916 if(events.empty()) events.push_back(new ObjList());
3917 ObjList *objs = *(events.begin());
3918
3919 if(f250config ) objs->config_objs.push_back(f250config );
3920 if(f125config ) objs->config_objs.push_back(f125config );
3921 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3922 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3923 }
3924
3925 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3926}
3927
3928//----------------
3929// ParseEventTag
3930//----------------
3931void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3932{
3933 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3934
3935 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3936
3937 // Make sure there is one event in the event container
3938 // and get pointer to it.
3939 if(events.empty()) events.push_back(new ObjList());
3940 ObjList *objs = *(events.begin());
3941
3942
3943 DEventTag *etag = new DEventTag;
3944
3945 // event_status
3946 uint64_t lo = *iptr++;
3947 uint64_t hi = *iptr++;
3948 etag->event_status = (hi<<32) + lo;
3949
3950 // L3_status
3951 lo = *iptr++;
3952 hi = *iptr++;
3953 etag->L3_status = (hi<<32) + lo;
3954
3955 // L3_decision
3956 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3957
3958 // L3_algorithm
3959 etag->L3_algorithm = *iptr++;
3960
3961 objs->misc_objs.push_back(etag);
3962
3963
3964 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3965}
3966
3967//----------------
3968// ParseJLabModuleData
3969//----------------
3970void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3971{
3972 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3973
3974 /// Parse a bank of data coming from one or more JLab modules.
3975 /// The data are assumed to follow the standard JLab format for
3976 /// block headers. If multiple modules are read out in a single
3977 /// chain block transfer, then the data will all be placed in
3978 /// a single EVIO bank and this will loop over the modules.
3979 while(iptr < iend){
3980
3981 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3982
3983 // This was observed in some CDC data. Not sure where it came from ...
3984 if(*iptr == 0xF800FAFA){
3985 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3986 iptr++;
3987 continue;
3988 }
3989
3990 // Get module type from next word (bits 18-21)
3991 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3992
3993 // The enum defined in DModuleType.h MUST be kept in alignment
3994 // with the DAQ group's definitions for modules types!
3995 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3996 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3997
3998 if(modtype_translate.find(type) != modtype_translate.end()){
3999 type = modtype_translate[type];
4000 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
4001 }
4002
4003 // Parse buffer depending on module type
4004 // (Note that each of the ParseXXX routines called below will
4005 // update the "iptr" variable to point to the next word
4006 // after the block it parsed.)
4007 list<ObjList*> tmp_events;
4008 const uint32_t *istart=iptr; // just for UNKNOWN case below
4009 bool module_parsed = true;
4010 switch(type){
4011 case DModuleType::FADC250:
4012 Parsef250Bank(rocid, iptr, iend, tmp_events);
4013 break;
4014
4015 case DModuleType::FADC125:
4016 Parsef125Bank(rocid, iptr, iend, tmp_events);
4017 break;
4018
4019 case DModuleType::F1TDC32:
4020 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
4021 break;
4022
4023 case DModuleType::F1TDC48:
4024 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
4025 break;
4026
4027 case DModuleType::JLAB_TS:
4028 //ParseTSBank(rocid, iptr, iend, tmp_events); // This is not used
4029 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4029<<" "
<< "What the ? ! This data type isn't supposed to be here!!" << endl;
4030 break;
4031
4032 case DModuleType::TID:
4033 ParseTIBank(rocid, iptr, iend, tmp_events);
4034 break;
4035
4036 case DModuleType::UNKNOWN:
4037 default:
4038 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
4039
4040 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4041 iptr++; // advance past JLab block trailer
4042 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4043 module_parsed = false;
4044 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
4045 break;
4046 }
4047
4048 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
4049
4050 if(module_parsed){
4051 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
4052 MergeObjLists(events, tmp_events);
4053 }
4054 }
4055
4056 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
4057}
4058
4059//----------------
4060// Parsef250Bank
4061//----------------
4062void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4063{
4064 /// Parse data from a single FADC250 module.
4065
4066 if(!PARSE_F250){ iptr = iend; return; }
4067
4068 // This will get updated to point to a newly allocated object when an
4069 // event header is encountered. The existing value (if non-NULL) is
4070 // added to the events queue first though so all events are kept.
4071 ObjList *objs = NULL__null;
4072
4073 // From the Block Header
4074 uint32_t slot=0;
4075 //uint32_t Nblock_events;
4076 //uint32_t iblock;
4077
4078 // From the Block Trailer
4079 //uint32_t slot_trailer;
4080 //uint32_t Nwords_in_block;
4081
4082 // From Event header
4083 //uint32_t slot_event_header;
4084 uint32_t itrigger = -1;
4085 uint32_t last_itrigger = -2;
4086
4087 // Loop over data words
4088 for(; iptr<iend; iptr++){
4089
4090 // Skip all non-data-type-defining words at this
4091 // level. When we do encounter one, the appropriate
4092 // case block below should handle parsing all of
4093 // the data continuation words and advance the iptr.
4094 if(((*iptr>>31) & 0x1) == 0)continue;
4095
4096 // Variables used inside of switch, but cannot be declared inside
4097 uint64_t t = 0L;
4098 uint32_t channel = 0;
4099 uint32_t sum = 0;
4100 uint32_t pulse_number = 0;
4101 uint32_t quality_factor = 0;
4102 uint32_t pulse_time = 0;
4103 uint32_t pedestal = 0;
4104 uint32_t pulse_peak = 0;
4105 uint32_t nsamples_integral = 0;
4106 uint32_t nsamples_pedestal = 0;
4107 bool overflow = false;
4108
4109 bool found_block_trailer = false;
4110 uint32_t data_type = (*iptr>>27) & 0x0F;
4111 switch(data_type){
4112 case 0: // Block Header
4113 slot = (*iptr>>22) & 0x1F;
4114 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4115 //iblock= (*iptr>>8) & 0x03FF;
4116 //Nblock_events= (*iptr>>0) & 0xFF;
4117 break;
4118 case 1: // Block Trailer
4119 //slot_trailer = (*iptr>>22) & 0x1F;
4120 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
4121 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4122 found_block_trailer = true;
4123 break;
4124 case 2: // Event Header
4125 //slot_event_header = (*iptr>>22) & 0x1F;
4126 itrigger = (*iptr>>0) & 0x3FFFFF;
4127 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;
4128 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
4129 if(ENABLE_DISENTANGLING){
4130 if(objs){
4131 events.push_back(objs);
4132 objs = NULL__null;
4133 }
4134 }
4135 if(!objs) objs = new ObjList;
4136 last_itrigger = itrigger;
4137 }
4138 break;
4139 case 3: // Trigger Time
4140 t = ((*iptr)&0xFFFFFF)<<0;
4141 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4142 iptr++;
4143 if(((*iptr>>31) & 0x1) == 0){
4144 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4145 if(VERBOSE>7) evioout << " Trigger time high word="<<(((*iptr)&0xFFFFFF))<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4146 }else{
4147 iptr--;
4148 }
4149 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
4150 break;
4151 case 4: // Window Raw Data
4152 // iptr passed by reference and so will be updated automatically
4153 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4154 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
4155 break;
4156 case 5: // Window Sum
4157 channel = (*iptr>>23) & 0x0F;
4158 sum = (*iptr>>0) & 0x3FFFFF;
4159 overflow = (*iptr>>22) & 0x1;
4160 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4161 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
4162 break;
4163 case 6: // Pulse Raw Data
4164 // iptr passed by reference and so will be updated automatically
4165 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4166 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
4167 break;
4168 case 7: // Pulse Integral
4169 channel = (*iptr>>23) & 0x0F;
4170 pulse_number = (*iptr>>21) & 0x03;
4171 quality_factor = (*iptr>>19) & 0x03;
4172 sum = (*iptr>>0) & 0x7FFFF;
4173 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4174 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4175 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
4176 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4177 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
4178 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
4179 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
4180 }
4181 break;
4182 case 8: // Pulse Time
4183 channel = (*iptr>>23) & 0x0F;
4184 pulse_number = (*iptr>>21) & 0x03;
4185 quality_factor = (*iptr>>19) & 0x03;
4186 pulse_time = (*iptr>>0) & 0x7FFFF;
4187 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4188 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) && (F250_PT_EMULATION_MODE!=kEmulationAlways)) {
4189 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
4190 }
4191 break;
4192 case 9: // Streaming Raw Data
4193 // This is marked "reserved for future implementation" in the current manual (v2).
4194 // As such, we don't try handling it here just yet.
4195 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4196 break;
4197 case 10: // Pulse Pedestal
4198 channel = (*iptr>>23) & 0x0F;
4199 pulse_number = (*iptr>>21) & 0x03;
4200 pedestal = (*iptr>>12) & 0x1FF;
4201 pulse_peak = (*iptr>>0) & 0xFFF;
4202 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4203 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) && (F250_PP_EMULATION_MODE!=kEmulationAlways)) {
4204 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
4205 }
4206 break;
4207 case 13: // Event Trailer
4208 // This is marked "suppressed for normal readout – debug mode only" in the
4209 // current manual (v2). It does not contain any data so the most we could do here
4210 // is return early. I'm hesitant to do that though since it would mean
4211 // different behavior for debug mode data as regular data.
4212 case 14: // Data not valid (empty module)
4213 case 15: // Filler (non-data) word
4214 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<" ("<<hex<<*iptr<<dec<<")"<<endl;
4215 break;
4216 }
4217
4218 // Once we find a block trailer, assume that is it for this module.
4219 if(found_block_trailer){
4220 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4221 break;
4222 }
4223 }
4224
4225 // Chop off filler words
4226 for(; iptr<iend; iptr++){
4227 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4228 }
4229
4230 // Add last event in block to list
4231 if(objs)events.push_back(objs);
4232
4233 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4234 // objects to each other so it is easier to get to these downstream without having to
4235 // make nested loops. This is the most efficient place to do it since the ObjList objects
4236 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4237 // worth.)
4238 list<ObjList*>::iterator iter = events.begin();
4239 for(; iter!=events.end(); iter++){
4240
4241 // Sort list of objects into type-specific lists
4242 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4243 vector<Df250TriggerTime*> vtrigt;
4244 vector<Df250WindowRawData*> vwrd;
4245 vector<Df250WindowSum*> vws;
4246 vector<Df250PulseRawData*> vprd;
4247 vector<Df250PulseIntegral*> vpi;
4248 vector<Df250PulseTime*> vpt;
4249 vector<Df250PulsePedestal*> vpp;
4250 for(unsigned int i=0; i<hit_objs.size(); i++){
4251 AddIfAppropriate(hit_objs[i], vtrigt);
4252 AddIfAppropriate(hit_objs[i], vwrd);
4253 AddIfAppropriate(hit_objs[i], vws);
4254 AddIfAppropriate(hit_objs[i], vprd);
4255 AddIfAppropriate(hit_objs[i], vpi);
4256 AddIfAppropriate(hit_objs[i], vpt);
4257 AddIfAppropriate(hit_objs[i], vpp);
4258 }
4259
4260 // Connect Df250PulseIntegral, Df250PulseTime, and
4261 // Df250PulsePedestal with Df250PulseRawData
4262 // (n.b. the associations between pi, pt, and pp are
4263 // done in GetObjects where emulated objects are
4264 // also available.)
4265 LinkAssociationsWithPulseNumber(vprd, vpi);
4266 LinkAssociationsWithPulseNumber(vprd, vpt);
4267 LinkAssociationsWithPulseNumber(vprd, vpp);
4268
4269 // Connect Df250WindowSum and Df250WindowRawData
4270 LinkAssociations(vwrd, vws);
4271
4272 // Connect Df250TriggerTime to everything
4273 LinkAssociationsModuleOnly(vtrigt, vwrd);
4274 LinkAssociationsModuleOnly(vtrigt, vws);
4275 LinkAssociationsModuleOnly(vtrigt, vprd);
4276 LinkAssociationsModuleOnly(vtrigt, vpi);
4277 LinkAssociationsModuleOnly(vtrigt, vpt);
4278 LinkAssociationsModuleOnly(vtrigt, vpp);
4279 }
4280}
4281
4282//----------------
4283// MakeDf250WindowRawData
4284//----------------
4285void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4286{
4287 uint32_t channel = (*iptr>>23) & 0x0F;
4288 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4289
4290 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
4291
4292 for(uint32_t isample=0; isample<window_width; isample +=2){
4293
4294 // Advance to next word
4295 iptr++;
4296
4297 // Make sure this is a data continuation word, if not, stop here
4298 if(((*iptr>>31) & 0x1) != 0x0){
4299 iptr--; // calling method expects us to point to last word in block
4300 break;
4301 }
4302
4303 bool invalid_1 = (*iptr>>29) & 0x1;
4304 bool invalid_2 = (*iptr>>13) & 0x1;
4305 uint16_t sample_1 = 0;
4306 uint16_t sample_2 = 0;
4307 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4308 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4309
4310 // Sample 1
4311 wrd->samples.push_back(sample_1);
4312 wrd->invalid_samples |= invalid_1;
4313 wrd->overflow |= (sample_1>>12) & 0x1;
4314
4315 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4316
4317 // Sample 2
4318 wrd->samples.push_back(sample_2);
4319 wrd->invalid_samples |= invalid_2;
4320 wrd->overflow |= (sample_2>>12) & 0x1;
4321 }
4322
4323 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4324 // This will happen if a Window Raw Data block is encountered before an event header.
4325 // For these cases, we still want to try parsing the data so that the iptr is updated
4326 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4327 // the list. Otherwise, delete it now.
4328 if(objs){
4329 objs->hit_objs.push_back(wrd);
4330 }else{
4331 delete wrd;
4332 }
4333}
4334
4335//----------------
4336// MakeDf250PulseRawData
4337//----------------
4338void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4339{
4340 const uint32_t *istart = iptr;
4341 uint32_t channel = (*iptr>>23) & 0x0F;
4342 uint32_t pulse_number = (*iptr>>21) & 0x0003;
4343 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4344
4345 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
4346
4347 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4348
4349 // This loop needs to break when it hits a non-continuation word
4350 for(uint32_t isample=0; isample<1000; isample +=2){
4351
4352 // Advance to next word
4353 iptr++;
4354
4355 // Make sure this is a data continuation word, if not, stop here
4356 if(((*iptr>>31) & 0x1) != 0x0)break;
4357
4358 bool invalid_1 = (*iptr>>29) & 0x1;
4359 bool invalid_2 = (*iptr>>13) & 0x1;
4360 uint16_t sample_1 = 0;
4361 uint16_t sample_2 = 0;
4362 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4363 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4364
4365 // Sample 1
4366 prd->samples.push_back(sample_1);
4367 prd->invalid_samples |= invalid_1;
4368 prd->overflow |= (sample_1>>12) & 0x1;
4369
4370 bool last_word = (iptr[1]>>31) & 0x1;
4371 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4372
4373 // Sample 2
4374 prd->samples.push_back(sample_2);
4375 prd->invalid_samples |= invalid_2;
4376 prd->overflow |= (sample_2>>12) & 0x1;
4377 }
4378
4379 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
4380
4381 // When should get here because the loop above stopped when it found
4382 // a data defining word (bit 31=1). The method calling this one will
4383 // assume iptr is pointing to the last word of this block and it will
4384 // advance to the first word of the next block. We need to back up one
4385 // word so that it is pointing to the last word of this block.
4386 iptr--;
4387
4388 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4389 // This will happen if a Window Raw Data block is encountered before an event header.
4390 // For these cases, we still want to try parsing the data so that the iptr is updated
4391 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4392 // the list. Otherwise, delete it now.
4393 if(objs){
4394 objs->hit_objs.push_back(prd);
4395 }else{
4396 delete prd;
4397 }
4398}
4399
4400//----------------
4401// Parsef125Bank
4402//----------------
4403void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4404{
4405 /// Parse data from a single FADC125 module.
4406 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
4407 /// data formats follow what is in the file:
4408 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
4409
4410 if(!PARSE_F125){ iptr = iend; return; }
4411
4412 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
4413
4414 // This will get updated to point to a newly allocated object when an
4415 // event header is encountered. The existing value (if non-NULL) is
4416 // added to the events queue first though so all events are kept.
4417 ObjList *objs = NULL__null;
4418
4419 // From the Block Header
4420 uint32_t slot=0;
4421 //uint32_t Nblock_events;
4422 //uint32_t iblock;
4423
4424 // From the Block Trailer
4425 //uint32_t slot_trailer;
4426 //uint32_t Nwords_in_block;
4427
4428 // From Event header
4429 //uint32_t slot_event_header;
4430 uint32_t itrigger = -1;
4431 uint32_t last_itrigger = -2;
4432 uint32_t last_pulse_time_channel=0;
4433 uint32_t last_slot = -1;
4434 uint32_t last_channel = -1;
4435
4436 // Loop over data words
4437 for(; iptr<iend; iptr++){
4438
4439 // Skip all non-data-type-defining words at this
4440 // level. When we do encounter one, the appropriate
4441 // case block below should handle parsing all of
4442 // the data continuation words and advance the iptr.
4443 if(((*iptr>>31) & 0x1) == 0)continue;
4444
4445 // Variables used inside of switch, but cannot be declared inside
4446 uint64_t t = 0L;
4447 uint32_t channel = 0;
4448 uint32_t sum = 0;
4449 uint32_t pulse_number = 0;
4450 uint32_t pulse_time = 0;
4451 uint32_t quality_factor = 0;
4452 uint32_t overflow_count = 0;
4453 uint32_t pedestal = 0;
4454 uint32_t pulse_peak = 0;
4455 uint32_t peak_time = 0;
4456 uint32_t nsamples_integral = 0;
4457 uint32_t nsamples_pedestal = 0;
4458 uint32_t word1=0;
4459 uint32_t word2=0;
4460
4461 bool found_block_trailer = false;
4462 uint32_t data_type = (*iptr>>27) & 0x0F;
4463 switch(data_type){
4464 case 0: // Block Header
4465 slot = (*iptr>>22) & 0x1F;
4466 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
4467 //iblock= (*iptr>>8) & 0x03FF;
4468 //Nblock_events= (*iptr>>0) & 0xFF;
4469 break;
4470 case 1: // Block Trailer
4471 //slot_trailer = (*iptr>>22) & 0x1F;
4472 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
4473 found_block_trailer = true;
4474 break;
4475 case 2: // Event Header
4476 //slot_event_header = (*iptr>>22) & 0x1F;
4477 itrigger = (*iptr>>0) & 0x3FFFFFF;
4478 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
4479 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
4480 if(ENABLE_DISENTANGLING){
4481 if(objs){
4482 events.push_back(objs);
4483 objs = NULL__null;
4484 }
4485 }
4486 if(!objs) objs = new ObjList;
4487 last_itrigger = itrigger;
4488 }
4489 break;
4490 case 3: // Trigger Time
4491 t = ((*iptr)&0xFFFFFF)<<0;
4492 iptr++;
4493 if(((*iptr>>31) & 0x1) == 0){
4494 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4495 }else{
4496 iptr--;
4497 }
4498 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
4499 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
4500 break;
4501 case 4: // Window Raw Data
4502 // iptr passed by reference and so will be updated automatically
4503 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
4504 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
4505 break;
4506
4507 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
4508
4509 // Word 1:
4510 word1 = *iptr;
4511 channel = (*iptr>>20) & 0x7F;
4512 pulse_number = (*iptr>>15) & 0x1F;
4513 pulse_time = (*iptr>>4 ) & 0x7FF;
4514 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4515 overflow_count = (*iptr>>0 ) & 0x7;
4516 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
4517 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4518
4519 // Word 2:
4520 ++iptr;
4521 if(iptr>=iend){
4522 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
4523 continue;
4524 }
4525 if( ((*iptr>>31) & 0x1) != 0 ){
4526 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
4527 continue;
4528 }
4529 word2 = *iptr;
4530 pedestal = (*iptr>>23) & 0xFF;
4531 sum = (*iptr>>9 ) & 0x3FFF;
4532 pulse_peak = (*iptr>>0 ) & 0x1FF;
4533 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
4534 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
4535
4536 // Create hit objects
4537 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4538 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4539
4540 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4541 // n.b. This is were we might apply a check on whether we are
4542 // only producing emulated objects. If so, then we shouldn't
4543 // create the Df125CDCPulse. At this point in time though,
4544 // there are 3 config. parameters that control this because
4545 // the original firmware produced 3 separate data types as
4546 // opposed to the new firmware that puts the same infomation
4547 // into a single data type. The emulation framework is also
4548 // being revamped.
4549 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
4550 , pulse_number // NPK
4551 , pulse_time // le_time
4552 , quality_factor // time_quality_bit
4553 , overflow_count // overflow_count
4554 , pedestal // pedestal
4555 , sum // integral
4556 , pulse_peak // first_max_amp
4557 , word1 // word1
4558 , word2 // word2
4559 , nsamples_pedestal // nsamples_pedestal
4560 , nsamples_integral // nsamples_integral
4561 , false) // emulated
4562 );
4563 }
4564
4565 // n.b. We don't record last_slot, last_channel, etc... here since those
4566 // are only used by data types corresponding to older firmware that did
4567 // not write out data type 5.
4568 break;
4569
4570 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
4571
4572 // Word 1:
4573 word1 = *iptr;
4574 channel = (*iptr>>20) & 0x7F;
4575 pulse_number = (*iptr>>15) & 0x1F;
4576 pulse_time = (*iptr>>4 ) & 0x7FF;
4577 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4578 overflow_count = (*iptr>>0 ) & 0x7;
4579 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
4580 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4581
4582 // Word 2:
4583 ++iptr;
4584 if(iptr>=iend){
4585 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4586 continue;
4587 }
4588 if( ((*iptr>>31) & 0x1) != 0 ){
4589 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4590 continue;
4591 }
4592 word2 = *iptr;
4593 pulse_peak = 0;
4594 sum = (*iptr>>19) & 0xFFF;
4595 peak_time = (*iptr>>11) & 0xFF;
4596 pedestal = (*iptr>>0 ) & 0x7FF;
4597 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
4598 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4599
4600 // Create hit objects
4601 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4602 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4603
4604 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4605 // n.b. This is were we might apply a check on whether we are
4606 // only producing emulated objects. If so, then we shouldn't
4607 // create the Df125FDCPulse. At this point in time though,
4608 // there are 3 config. parameters that control this because
4609 // the original firmware produced 3 separate data types as
4610 // opposed to the new firmware that puts the same infomation
4611 // into a single data type. The emulation framework is also
4612 // being revamped.
4613 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4614 , pulse_number // NPK
4615 , pulse_time // le_time
4616 , quality_factor // time_quality_bit
4617 , overflow_count // overflow_count
4618 , pedestal // pedestal
4619 , sum // integral
4620 , pulse_peak // peak_amp
4621 , peak_time // peak_time
4622 , word1 // word1
4623 , word2 // word2
4624 , nsamples_pedestal // nsamples_pedestal
4625 , nsamples_integral // nsamples_integral
4626 , false) // emulated
4627 );
4628 }
4629
4630 // n.b. We don't record last_slot, last_channel, etc... here since those
4631 // are only used by data types corresponding to older firmware that did
4632 // not write out data type 6.
4633 break;
4634
4635 case 7: // Pulse Integral
4636 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
4637 channel = (*iptr>>20) & 0x7F;
4638 sum = (*iptr>>0) & 0xFFFFF;
4639 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4640 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4641 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
4642 if (last_slot == slot && last_channel == channel) pulse_number = 1;
4643 last_slot = slot;
4644 last_channel = channel;
4645 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4646 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
4647 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
4648 }
4649 break;
4650 case 8: // Pulse Time
4651 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
4652 channel = (*iptr>>20) & 0x7F;
4653 pulse_number = (*iptr>>18) & 0x03;
4654 pulse_time = (*iptr>>0) & 0xFFFF;
4655 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) && (F125_PT_EMULATION_MODE!=kEmulationAlways) ) {
4656 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
4657 }
4658 last_pulse_time_channel = channel;
4659 break;
4660
4661 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
4662
4663 // Word 1:
4664 word1 = *iptr;
4665 channel = (*iptr>>20) & 0x7F;
4666 pulse_number = (*iptr>>15) & 0x1F;
4667 pulse_time = (*iptr>>4 ) & 0x7FF;
4668 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4669 overflow_count = (*iptr>>0 ) & 0x7;
4670 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
4671 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4672
4673 // Word 2:
4674 ++iptr;
4675 if(iptr>=iend){
4676 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4677 continue;
4678 }
4679 if( ((*iptr>>31) & 0x1) != 0 ){
4680 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4681 continue;
4682 }
4683 word2 = *iptr;
4684 pulse_peak = (*iptr>>19) & 0xFFF;
4685 sum = 0;
4686 peak_time = (*iptr>>11) & 0xFF;
4687 pedestal = (*iptr>>0 ) & 0x7FF;
4688 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
4689 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4690
4691 // Create hit objects
4692 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4693 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4694
4695 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4696 // n.b. This is were we might apply a check on whether we are
4697 // only producing emulated objects. If so, then we shouldn't
4698 // create the Df125FDCPulse. At this point in time though,
4699 // there are 3 config. parameters that control this because
4700 // the original firmware produced 3 separate data types as
4701 // opposed to the new firmware that puts the same infomation
4702 // into a single data type. The emulation framework is also
4703 // being revamped.
4704 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4705 , pulse_number // NPK
4706 , pulse_time // le_time
4707 , quality_factor // time_quality_bit
4708 , overflow_count // overflow_count
4709 , pedestal // pedestal
4710 , sum // integral
4711 , pulse_peak // peak_amp
4712 , peak_time // peak_time
4713 , word1 // word1
4714 , word2 // word2
4715 , nsamples_pedestal // nsamples_pedestal
4716 , nsamples_integral // nsamples_integral
4717 , false) // emulated
4718 );
4719 }
4720
4721 // n.b. We don't record last_slot, last_channel, etc... here since those
4722 // are only used by data types corresponding to older firmware that did
4723 // not write out data type 6.
4724 break;
4725
4726 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4727 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4728 //channel = (*iptr>>20) & 0x7F;
4729 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")
4730 pulse_number = (*iptr>>21) & 0x03;
4731 pedestal = (*iptr>>12) & 0x1FF;
4732 pulse_peak = (*iptr>>0) & 0xFFF;
4733 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4734 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) && (F125_PP_EMULATION_MODE!=kEmulationAlways) ) {
4735 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4736 }
4737 break;
4738
4739 case 13: // Event Trailer
4740 case 14: // Data not valid (empty module)
4741 case 15: // Filler (non-data) word
4742 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4743 break;
4744 }
4745
4746 // Once we find a block trailer, assume that is it for this module.
4747 if(found_block_trailer){
4748 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4749 break;
4750 }
4751 }
4752
4753 // Chop off filler words
4754 for(; iptr<iend; iptr++){
4755 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4756 }
4757
4758 // Add last event in block to list
4759 if(objs)events.push_back(objs);
4760
4761 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4762 // objects to each other so it is easier to get to these downstream without having to
4763 // make nested loops. This is the most efficient place to do it since the ObjList objects
4764 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4765 // worth.)
4766 list<ObjList*>::iterator iter = events.begin();
4767 for(; iter!=events.end(); iter++){
4768
4769 // Sort list of objects into type-specific lists
4770 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4771 vector<Df125TriggerTime*> vtrigt;
4772 vector<Df125WindowRawData*> vwrd;
4773 vector<Df125PulseRawData*> vprd;
4774 vector<Df125PulseIntegral*> vpi;
4775 vector<Df125PulseTime*> vpt;
4776 vector<Df125PulsePedestal*> vpp;
4777 for(unsigned int i=0; i<hit_objs.size(); i++){
4778 AddIfAppropriate(hit_objs[i], vtrigt);
4779 AddIfAppropriate(hit_objs[i], vwrd);
4780 AddIfAppropriate(hit_objs[i], vprd);
4781 AddIfAppropriate(hit_objs[i], vpi);
4782 AddIfAppropriate(hit_objs[i], vpt);
4783 AddIfAppropriate(hit_objs[i], vpp);
4784 }
4785
4786 // Connect Df125PulseIntegral with Df125PulseTime
4787 LinkAssociationsWithPulseNumber(vprd, vpi);
4788 LinkAssociationsWithPulseNumber(vprd, vpt);
4789 LinkAssociationsWithPulseNumber(vprd, vpp);
4790 LinkAssociationsWithPulseNumber(vpi, vpt);
4791 LinkAssociationsWithPulseNumber(vpi, vpp);
4792 LinkAssociationsWithPulseNumber(vpt, vpp);
4793
4794 // Connect Df125TriggerTime to everything
4795 LinkAssociationsModuleOnly(vtrigt, vwrd);
4796 LinkAssociationsModuleOnly(vtrigt, vprd);
4797 LinkAssociationsModuleOnly(vtrigt, vpi);
4798 LinkAssociationsModuleOnly(vtrigt, vpt);
4799 LinkAssociationsModuleOnly(vtrigt, vpp);
4800 }
4801
4802 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4803}
4804
4805//----------------
4806// MakeDf125WindowRawData
4807//----------------
4808void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4809{
4810 uint32_t channel = (*iptr>>20) & 0x7F;
4811 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4812
4813 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4814
4815 for(uint32_t isample=0; isample<window_width; isample +=2){
4816
4817 // Advance to next word
4818 iptr++;
4819
4820 // Make sure this is a data continuation word, if not, stop here
4821 if(((*iptr>>31) & 0x1) != 0x0)break;
4822
4823 bool invalid_1 = (*iptr>>29) & 0x1;
4824 bool invalid_2 = (*iptr>>13) & 0x1;
4825 uint16_t sample_1 = 0;
4826 uint16_t sample_2 = 0;
4827 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4828 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4829
4830 // Sample 1
4831 wrd->samples.push_back(sample_1);
4832 wrd->invalid_samples |= invalid_1;
4833 wrd->overflow |= (sample_1>>12) & 0x1;
4834
4835 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4836
4837 // Sample 2
4838 wrd->samples.push_back(sample_2);
4839 wrd->invalid_samples |= invalid_2;
4840 wrd->overflow |= (sample_2>>12) & 0x1;
4841 }
4842
4843 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4844
4845 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4846 // This will happen if a Window Raw Data block is encountered before an event header.
4847 // For these cases, we still want to try parsing the data so that the iptr is updated
4848 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4849 // the list. Otherwise, delete it now.
4850 if(objs){
4851 objs->hit_objs.push_back(wrd);
4852 }else{
4853 delete wrd;
4854 }
4855}
4856
4857//----------------
4858// MakeDf125PulseRawData
4859//----------------
4860void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4861{
4862 uint32_t channel = (*iptr>>23) & 0x0F;
4863 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4864 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4865
4866 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4867
4868 // This loop needs to break when it hits a non-continuation word
4869 for(uint32_t isample=0; isample<1000; isample +=2){
4870
4871 // Advance to next word
4872 iptr++;
4873
4874 // Make sure this is a data continuation word, if not, stop here
4875 if(((*iptr>>31) & 0x1) != 0x0)break;
4876
4877 bool invalid_1 = (*iptr>>29) & 0x1;
4878 bool invalid_2 = (*iptr>>13) & 0x1;
4879 uint16_t sample_1 = 0;
4880 uint16_t sample_2 = 0;
4881 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4882 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4883
4884 // Sample 1
4885 prd->samples.push_back(sample_1);
4886 prd->invalid_samples |= invalid_1;
4887 prd->overflow |= (sample_1>>12) & 0x1;
4888
4889 bool last_word = (iptr[1]>>31) & 0x1;
4890 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4891
4892 // Sample 2
4893 prd->samples.push_back(sample_2);
4894 prd->invalid_samples |= invalid_2;
4895 prd->overflow |= (sample_2>>12) & 0x1;
4896 }
4897
4898
4899 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4900 // This will happen if a Window Raw Data block is encountered before an event header.
4901 // For these cases, we still want to try parsing the data so that the iptr is updated
4902 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4903 // the list. Otherwise, delete it now.
4904 if(objs){
4905 objs->hit_objs.push_back(prd);
4906 }else{
4907 delete prd;
4908 }
4909}
4910
4911//----------------
4912// ParseF1TDCBank
4913//----------------
4914void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4915{
4916 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4917 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4918 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4919
4920 if(!PARSE_F1TDC){ iptr = iend; return; }
4921
4922 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4923
4924 const uint32_t *istart = iptr;
4925
4926 // Some early data had a marker word at just before the actual F1 data
4927 if(*iptr == 0xf1daffff) iptr++;
4928
4929 // Block header word
4930 // Double check that block header is set
4931 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4932 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4933 }
4934
4935 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4936 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4937 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4938 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4939 if(VERBOSE>5) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4940
4941 // Advance to next word
4942 iptr++;
4943
4944 // Loop over events
4945 ObjList *objs = NULL__null;
4946 while(iptr<iend){
4947
4948 // Event header
4949 // Double check that event header is set
4950 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4951 if(VERBOSE>10){
4952 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4952<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4953 DumpBinary(istart, iend, 0, iptr);
4954 }
4955 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4956 }
4957
4958 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4959 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4960 if(VERBOSE>5) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4961
4962 // Make sure slot number from event header matches block header
4963 if(slot_event_header != slot_block_header){
4964 char str[256];
4965 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4966 throw JException(str);
4967 }
4968
4969 // Advance to timestamp word
4970 iptr++;
4971 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4972
4973 // The most recent documentation says that the first time stamp
4974 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4975 // the second word is optional.
4976 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4977 if(VERBOSE>6) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4978 iptr++;
4979 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4980 if(((*iptr>>31) & 0x1) == 0){
4981 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4982 if(VERBOSE>6) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4983 }else{
4984 iptr--; // second time word not present, back up pointer
4985 }
4986
4987 // Create a new object list (i.e. new event)
4988 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4989 events.push_back(objs);
4990 objs = NULL__null;
4991 }
4992 if(!objs) objs = new ObjList;
4993
4994 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4995
4996 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4997 iptr++;
4998
4999 // Loop over F1 data words
5000 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
5001 while( iptr<iend && ((*iptr)>>31)==0x1 ){
5002
5003 bool done = false;
5004
5005 uint32_t chip, chan_on_chip, time;
5006 uint32_t channel;
5007 DF1TDCHit *hit=NULL__null;
5008 switch( (*iptr) & 0xF8000000 ){
5009 case 0xC0000000: // F1 Header
5010 chip_f1header = ((*iptr)>> 3) & 0x07;
5011 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
5012 itrigger_f1header = ((*iptr)>>16) & 0x3F;
5013 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
5014 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
5015 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
5016 break;
5017 case 0xB8000000: // F1 Data
5018 chip = (*iptr>>19) & 0x07;
5019 chan_on_chip = (*iptr>>16) & 0x07;
5020 time = (*iptr>> 0) & 0xFFFF;
5021 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
5022 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
5023 channel = F1TDC_channel(chip, chan_on_chip, modtype);
5024 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
5025 if(objs)objs->hit_objs.push_back(hit);
5026 break;
5027 case 0xF8000000: // Filler word
5028 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
5029 break;
5030 case 0x80000000: // JLab block header (handled in outer loop)
5031 case 0x88000000: // JLab block trailer (handled in outer loop)
5032 case 0x90000000: // JLab event header (handled in outer loop)
5033 case 0x98000000: // Trigger time (handled in outer loop)
5034 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
5035 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
5036 done = true;
5037 break;
5038 default:
5039 cerr<<endl;
5040 cout.flush(); cerr.flush();
5041 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5041<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
5042 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
5043 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5043<<" "
<<"0x"<<hex<<*iiptr<<dec;
5044 if(iiptr == iptr)cerr<<" <----";
5045 switch( (*iiptr) & 0xF8000000 ){
5046 case 0x80000000: cerr << " F1 Block Header"; break;
5047 case 0x90000000: cerr << " F1 Event Header"; break;
5048 case 0x98000000: cerr << " F1 Trigger time"; break;
5049 case 0xC0000000: cerr << " F1 Header"; break;
5050 case 0xB8000000: cerr << " F1 Data"; break;
5051 case 0x88000000: cerr << " F1 Block Trailer"; break;
5052 case 0xF8000000: cerr << " Filler word"; break;
5053 case 0xF0000000: cerr << " <module has no valid data>"; break;
5054 default: break;
5055 }
5056 cerr<<endl;
5057 if(iiptr > (iptr+4)) break;
5058 }
5059
5060 throw JException("Unexpected word type in F1TDC block!");
5061 }
5062
5063 if(done)break;
5064
5065 // Advance to next data word
5066 iptr++;
5067
5068 } // end loop over data words in this event
5069
5070 // If the current word is a JLab block trailer, then we are done
5071 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
5072
5073 } // end loop over events
5074
5075 // Add hits for last event to list of events.
5076 if(objs)events.push_back(objs);
5077
5078 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
5079 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
5080 }
5081
5082 // Advance past JLab block trailer
5083 iptr++;
5084
5085 // Skip filler words
5086 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
5087
5088 // Double check that we found all of the events we were supposed to
5089 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
5090 if(events.size() != Nevents_block_header){
5091 stringstream ss;
5092 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
5093 DumpBinary(istart, iend, 128);
5094 throw JException(ss.str());
5095 }
5096
5097 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
5098
5099}
5100
5101//----------------
5102// F1TDC_channel
5103//----------------
5104uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
5105{
5106 /// Convert a F1TDC chip number and channel on the chip to the
5107 /// front panel channel number. This is based on "Input Channel Mapping"
5108 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
5109
5110 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
5111 switch(modtype){
5112 case DModuleType::F1TDC32:
5113 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
5114 case DModuleType::F1TDC48:
5115 return (chip <<3) | chan_on_chip;
5116 default:
5117 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5117<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
5118 throw JException("F1TDC_channel called for non-F1TDC module type");
5119 }
5120 return 1000000; // (should never get here)
5121}
5122
5123//----------------
5124// ParseTSBank
5125//----------------
5126void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
5127{
5128 /// Parse data written to the TS roc data during sync events.
5129 /// This is written by the ts_scalers routine in the conf_utils.c
5130 /// file and called from ts_list.c
5131
5132 uint32_t Nwords = ((uint64_t)iend - (uint64_t)iptr)/sizeof(uint32_t);
5133 uint32_t Nwords_expected = (6+32+16+32+16);
5134 if(Nwords != Nwords_expected){
5135 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5135<<" "
<< "TS bank size does not match expected!!" << endl;
5136 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5136<<" "
<< "Found " << Nwords << " words. Expected " << Nwords_expected << endl;
5137
5138 }else{
5139 DTSscalers *s = new DTSscalers;
5140 s->nsync_event = *iptr++;
5141 s->int_count = *iptr++;
5142 s->live_time = *iptr++;
5143 s->busy_time = *iptr++;
5144 s->inst_livetime = *iptr++;
5145 s->time = *iptr++;
5146 for(uint32_t i=0; i<32; i++) s->gtp_scalers[i] = *iptr++;
5147 for(uint32_t i=0; i<16; i++) s->fp_scalers[i] = *iptr++;
5148 for(uint32_t i=0; i<32; i++) s->gtp_rate[i] = *iptr++;
5149 for(uint32_t i=0; i<16; i++) s->fp_rate[i] = *iptr++;
5150
5151 if(events.empty()) events.push_back(new ObjList);
5152 ObjList *objs = *(events.begin());
5153 objs->misc_objs.push_back(s);
5154 }
5155
5156 iptr = iend;
5157}
5158
5159//----------------
5160// ParseTIBank
5161//----------------
5162void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
5163{
5164 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
5165 iptr++; // advance past JLab block trailer
5166 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
5167 //iptr = iend;
5168}
5169
5170//----------------
5171// ParseCAEN1190
5172//----------------
5173void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
5174{
5175 /// Parse data from a CAEN 1190 or 1290 module
5176 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
5177
5178 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
5179
5180 uint32_t slot = 0;
5181 uint32_t event_count = 0;
5182 uint32_t word_count = 0;
5183 uint32_t trigger_time_tag = 0;
5184 uint32_t tdc_num = 0;
5185 uint32_t event_id = 0;
5186 uint32_t bunch_id = 0;
5187
5188 // We need to accomodate multi-event blocks where
5189 // events are entangled (i.e. hits from event 1
5190 // are mixed inbetween those of event 2,3,4,
5191 // etc... With CAEN modules, we only know which
5192 // event a hit came from by looking at the event_id
5193 // in the TDC header. This value is only 12 bits
5194 // and could roll over within an event block. This
5195 // means we need to keep track of the order we
5196 // encounter them in so it is maintained in the
5197 // "events" container. The event_id order is kept
5198 // in the "event_id_order" vector.
5199 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
5200 vector<uint32_t> event_id_order;
5201
5202 while(iptr<iend){
5203
5204 // This word appears to be appended to the data.
5205 // Probably in the ROL. Ignore it if found.
5206 if(*iptr == 0xd00dd00d) {
5207 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
5208 iptr++;
5209 continue;
5210 }
5211
5212 uint32_t type = (*iptr) >> 27;
5213 uint32_t edge = 0; // 1=trailing, 0=leading
5214 uint32_t channel = 0;
5215 uint32_t tdc = 0;
5216 uint32_t error_flags = 0;
5217 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
5218 map<uint32_t, ObjList*>::iterator iter;
5219 switch(type){
5220 case 0b01000: // Global Header
5221 slot = (*iptr) & 0x1f;
5222 event_count = ((*iptr)>>5) & 0xffffff;
5223 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
5224 break;
5225 case 0b10000: // Global Trailer
5226 slot = (*iptr) & 0x1f;
5227 word_count = ((*iptr)>>5) & 0x7ffff;
5228 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
5229 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
5230 break;
5231 case 0b10001: // Global Trigger Time Tag
5232 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
5233 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
5234 break;
5235 case 0b00001: // TDC Header
5236 tdc_num = ((*iptr)>>24) & 0x03;
5237 event_id = ((*iptr)>>12) & 0x0fff;
5238 bunch_id = (*iptr) & 0x0fff;
5239 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
5240 event_id_order.push_back(event_id);
5241 }
5242 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
5243 break;
5244 case 0b00000: // TDC Measurement
5245 edge = ((*iptr)>>26) & 0x01;
5246 channel = ((*iptr)>>21) & 0x1f;
5247 tdc = ((*iptr)>>0) & 0x1fffff;
5248 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
5249
5250 // Create DCAEN1290TDCHit object
5251 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
5252 hits_by_event_id[event_id].push_back(caen1290tdchit);
5253 break;
5254 case 0b00100: // TDC Error
5255 error_flags = (*iptr) & 0x7fff;
5256 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
5257 break;
5258 case 0b00011: // TDC Trailer
5259 tdc_num = ((*iptr)>>24) & 0x03;
5260 event_id = ((*iptr)>>12) & 0x0fff;
5261 word_count = ((*iptr)>>0) & 0x0fff;
5262 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
5263 tdc_num = event_id = bunch_id = 0;
5264 break;
5265 case 0b11000: // Filler Word
5266 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
5267 break;
5268 default:
5269 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
5270 }
5271
5272 iptr++;
5273 }
5274
5275 // If disentagling is disabled, then lump all hits into single event
5276 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
5277 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
5278 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
5279 for(uint32_t i=1; i<event_id_order.size(); i++){
5280 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
5281 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
5282 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
5283 }
5284 }
5285
5286 // Add hits for each event to the events container, creating ObjList's as needed
5287 for(uint32_t i=0; i<event_id_order.size(); i++){
5288
5289 // Make sure there are enough event containers to hold this event
5290 while(events.size() <= i) events.push_back(new ObjList);
5291 list<ObjList*>::iterator it = events.begin();
5292 advance(it, i);
5293 ObjList *objs = *it;
5294
5295 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
5296 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
5297
5298 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
5299 }
5300
5301}
5302
5303//----------------
5304// ParseBORevent
5305//----------------
5306void JEventSource_EVIO::ParseBORevent(evioDOMNodeP bankPtr)
5307{
5308 if(!PARSE_BOR) return;
5309
5310 // This really shouldn't be needed
5311 pthread_rwlock_wrlock(&BOR_lock);
5312
5313 // Delete any existing BOR config objects. BOR events should
5314 // be flagged as sequential (or barrier) events so all threads
5315 // that were using these should be done with them now.
5316 for(uint32_t i=0; i<BORobjs.size(); i++) delete BORobjs[i];
5317 BORobjs.clear();
5318
5319 evioDOMNodeListP bankList = bankPtr->getChildren();
5320 evioDOMNodeList::iterator iter = bankList->begin();
5321 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in BOR event" << endl;
5322 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
5323 evioDOMNodeP childBank = *iter;
5324
5325 if(childBank->tag==0x71){
5326// uint32_t rocid = childBank->num;
5327 evioDOMNodeListP bankList = childBank->getChildren();
5328 evioDOMNodeList::iterator iter = bankList->begin();
5329 for(; iter!=bankList->end(); iter++){
5330 evioDOMNodeP dataBank = *iter;
5331// uint32_t slot = dataBank->tag>>5;
5332 uint32_t modType = dataBank->tag&0x1f;
5333
5334 const vector<uint32_t> *vec = dataBank->getVector<uint32_t>();
5335
5336 const uint32_t *src = &(*vec)[0];
5337 uint32_t *dest = NULL__null;
5338 uint32_t sizeof_dest = 0;
5339
5340 Df250BORConfig *f250conf = NULL__null;
5341 Df125BORConfig *f125conf = NULL__null;
5342 DF1TDCBORConfig *F1TDCconf = NULL__null;
5343 DCAEN1290TDCBORConfig *caen1190conf = NULL__null;
5344
5345 switch(modType){
5346 case DModuleType::FADC250: // f250
5347 f250conf = new Df250BORConfig;
5348 dest = (uint32_t*)&f250conf->rocid;
5349 sizeof_dest = sizeof(f250config);
5350 break;
5351 case DModuleType::FADC125: // f125
5352 f125conf = new Df125BORConfig;
5353 dest = (uint32_t*)&f125conf->rocid;
5354 sizeof_dest = sizeof(f125config);
5355 break;
5356
5357 case DModuleType::F1TDC32: // F1TDCv2
5358 case DModuleType::F1TDC48: // F1TDCv3
5359 F1TDCconf = new DF1TDCBORConfig;
5360 dest = (uint32_t*)&F1TDCconf->rocid;
5361 sizeof_dest = sizeof(F1TDCconfig);
5362 break;
5363
5364 case DModuleType::CAEN1190: // CAEN 1190 TDC
5365 case DModuleType::CAEN1290: // CAEN 1290 TDC
5366 caen1190conf = new DCAEN1290TDCBORConfig;
5367 dest = (uint32_t*)&caen1190conf->rocid;
5368 sizeof_dest = sizeof(caen1190config);
5369 break;
5370 }
5371
5372 // Check that the bank size and data structure size match.
5373 // If they do, then copy the data and add the object to
5374 // the event. If not, then delete the object and print
5375 // a warning message.
5376 if( vec->size() == (sizeof_dest/sizeof(uint32_t)) ){
5377
5378 // Copy bank data, assuming format is the same
5379 for(uint32_t i=0; i<vec->size(); i++) *dest++ = *src++;
5380
5381 // Store object for use in this and subsequent events
5382 if(f250conf) BORobjs.push_back(f250conf);
5383 if(f125conf) BORobjs.push_back(f125conf);
5384 if(F1TDCconf) BORobjs.push_back(F1TDCconf);
5385 if(caen1190conf) BORobjs.push_back(caen1190conf);
5386
5387 }else if(sizeof_dest>0){
5388 if(f250conf) delete f250conf;
5389 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5389<<" "
<< "BOR bank size does not match structure! " << vec->size() <<" != " << (sizeof_dest/sizeof(uint32_t)) << endl;
5390 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5390<<" "
<< "sizeof(f250config)="<<sizeof(f250config)<<endl;
5391 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5391<<" "
<< "sizeof(f125config)="<<sizeof(f125config)<<endl;
5392 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5392<<" "
<< "sizeof(F1TDCconfig)="<<sizeof(F1TDCconfig)<<endl;
5393 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<5393<<" "
<< "sizeof(caen1190config)="<<sizeof(caen1190config)<<endl;
5394 }
5395 }
5396 }
5397 }
5398
5399 pthread_rwlock_unlock(&BOR_lock);
5400
5401}
5402
5403
5404//----------------
5405// ParseTSSyncevent
5406//----------------
5407void JEventSource_EVIO::ParseTSSync(evioDOMNodeP bankPtr, list<ObjList*> &events)
5408{
5409
5410 DL1Info *trig_info = new DL1Info;
5411
5412 // cout << " INSIDE ParseTSSync " << endl;
5413
5414 if((bankPtr->tag & 0xFFFF) == 0xEE02){
5415 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
5416
5417 trig_info->nsync = (*vec)[0];
5418 trig_info->trig_number = (*vec)[1];
5419 trig_info->live_time = (*vec)[2];
5420 trig_info->busy_time = (*vec)[3];
5421 trig_info->live_inst = (*vec)[4];
5422 trig_info->unix_time = (*vec)[5];
5423
5424
5425
5426 // GTP scalers
5427 for(uint32_t ii = 6; ii < 38; ii++){
5428 trig_info->gtp_sc.push_back((*vec)[ii]);
5429 }
5430
5431 // FP scalers
5432 for(uint32_t ii = 38; ii < 54; ii++){
5433 trig_info->fp_sc.push_back((*vec)[ii]);
5434 }
5435
5436 // GTP rate
5437 for(uint32_t ii = 54; ii < 86; ii++){
5438 trig_info->gtp_rate.push_back((*vec)[ii]);
5439 }
5440
5441 // FP rate
5442 for(uint32_t ii = 86; ii < 102; ii++){
5443 trig_info->fp_rate.push_back((*vec)[ii]);
5444 }
5445 }
5446
5447
5448 if(events.empty()){
5449 events.push_back(new ObjList());
5450 // cout << " TSSync: Empty event " << endl;
5451 }
5452
5453 ObjList *objs = *(events.begin());
5454
5455 objs->misc_objs.push_back(trig_info);
5456
5457
5458}
5459
5460
5461//----------------
5462// ParseEPICSevent
5463//----------------
5464void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
5465{
5466 if(!PARSE_EPICS) return;
5467
5468 time_t timestamp=0;
5469
5470 ObjList *objs = NULL__null;
5471
5472 evioDOMNodeListP bankList = bankPtr->getChildren();
5473 evioDOMNodeList::iterator iter = bankList->begin();
5474 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
5475 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
5476 evioDOMNodeP childBank = *iter;
5477
5478 if(childBank->tag == 97){
5479 // timestamp bank
5480 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
5481 if(vec) {
5482 timestamp = (time_t)(*vec)[0];
5483 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
5484 }
5485 }else if(childBank->tag==98){
5486 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
5487 if(vec){
5488 string nameval = (const char*)&((*vec)[0]);
5489 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
5490 if(VERBOSE>7) evioout << " " << nameval << endl;
5491
5492 if(!objs){
5493 if(events.empty()) events.push_back(new ObjList);
5494 objs = *(events.begin());
5495 }
5496 objs->misc_objs.push_back(epicsval);
5497 }
5498 }
5499 }
5500}
5501
5502//----------------
5503// DumpBinary
5504//----------------
5505void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
5506{
5507 /// This is used for debugging. It will print to the screen the words
5508 /// starting at the address given by iptr and ending just before iend
5509 /// or for MaxWords words, whichever comes first. If iend is NULL,
5510 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
5511 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
5512 /// only the word at iptr is printed.
5513
5514 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
5515
5516 if(iend==NULL__null && MaxWords==0) MaxWords=1;
5517 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
5518
5519 uint32_t Nwords=0;
5520 while(iptr!=iend && Nwords<MaxWords){
5521
5522 // line1 is hex and line2 is decimal
5523 stringstream line1, line2;
5524
5525 // print words in columns 8 words wide. First part is
5526 // reserved for word number
5527 uint32_t Ncols = 8;
5528 line1 << setw(5) << Nwords;
5529 line2 << string(5, ' ');
5530
5531 // Loop over columns
5532 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
5533
5534 if(iptr == iend) break;
5535 if(Nwords>=MaxWords) break;
5536
5537 stringstream iptr_hex;
5538 iptr_hex << hex << "0x" << *iptr;
5539
5540 string mark = (iptr==imark ? "*":" ");
5541
5542 line1 << setw(12) << iptr_hex.str() << mark;
5543 line2 << setw(12) << *iptr << mark;
5544 }
5545
5546 cout << line1.str() << endl;
5547 cout << line2.str() << endl;
5548 cout << endl;
5549 }
5550}
5551
5552#endif // HAVE_EVIO
5553
5554#if 0
5555//----------------
5556// GuessModuleType
5557//----------------
5558MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
5559{
5560 /// Try parsing through the information in the given data buffer
5561 /// to determine which type of module produced the data.
5562
5563 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
5564 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
5565 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
5566 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
5567 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
5568
5569
5570 // Couldn't figure it out...
5571 return DModuleType::UNKNOWN;
5572}
5573
5574//----------------
5575// IsFADC250
5576//----------------
5577bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
5578{
5579 //---- Check for f250
5580 // This will check if the first word appears to be a block header.
5581 // If so, it loops over all words looking for a block trailer.
5582 // If the slot number in the block trailer matches that in the
5583 // block header AND the number of words in the block matches that
5584 // specified in the block trailer, then it is assumed to be a f250.
5585 if(((*istart>>31) & 0x1) == 1){
5586 uint32_t data_type = (*istart>>27) & 0x0F;
5587 if(data_type == 0){ // Block Header
5588 uint32_t slot_header = (*istart>>22) & 0x1F;
5589 uint32_t Nwords = 1;
5590 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
5591 if(((*iptr>>31) & 0x1) == 1){
5592 uint32_t data_type = (*iptr>>27) & 0x0F;
5593 if(data_type == 1){ // Block Trailer
5594 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
5595 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
5596
5597 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
5598 return true;
5599 }else{
5600 return false;
5601 }
5602 }
5603 }
5604 }
5605 }
5606 }
5607
5608 // either first word was not a block header or no block trailer was found
5609 return false;
5610}
5611
5612//----------------
5613// IsF1TDC
5614//----------------
5615bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
5616{
5617 //---- Check for F1TDC
5618 // This will check for consistency in the slot numbers for all words
5619 // in the buffer. The slot number of data words are checked against
5620 // the slot number of the most recently encountered header word.
5621 uint32_t slot_header = 1000;
5622 uint32_t slot_trailer = 1000;
5623
5624 const uint32_t *iptr=istart;
5625
5626 // skip first word which appears to be ROL marker for F1TDC data
5627 if(*istart == 0xf1daffff)iptr++
5628
5629 // There is no distinction between header and trailer
5630 // words other than the order that they appear. We keep
5631 // track by flipping this value
5632 bool looking_for_header = true;
5633
5634 // Keep track of the number of valid blocks of F1TDC data we find
5635 // (i.e. ones where the header and trailer words were found
5636 int Nvalid = 0;
5637
5638 for(; iptr<iend; iptr++){
5639
5640 // ROL end of data marker (only in test setup data)
5641 if(*iptr == 0xda0000ff)break;
5642
5643 uint32_t slot = (*iptr>>27) & 0x1F;
5644
5645 // if slot is 0 or 30, we are supposed to ignore the data.
5646 if(slot == 30 || slot ==0)continue;
5647
5648 if(((*iptr>>23) & 0x1) == 0){
5649 // header/trailer word
5650 if(looking_for_header){
5651 slot_header = slot;
5652 looking_for_header = false;
5653 }else{
5654 slot_trailer = slot;
5655 if(slot_trailer != slot_header)return false;
5656 looking_for_header = true;
5657 Nvalid++;
5658 }
5659 }else{
5660 // data word
5661
5662 // if we encounter a data word when we are expecting
5663 // a header word, then the current word is not from
5664 // an F1TDC. However, if we did find at least one valid
5665 // block at the begining, of the buffer, claim the buffer
5666 // points to F1TDC data. We check for as many valid F1TDC
5667 // blocks as possible to help ensure that is what the data
5668 // is.
5669 if(looking_for_header)return Nvalid>0;
5670
5671 // If the slot number does not match, then this is
5672 // not valid F1TDC data
5673 if(slot != slot_header)return false;
5674 }
5675 }
5676
5677 return Nvalid>0;
5678}
5679
5680//----------------
5681// DumpModuleMap
5682//----------------
5683void JEventSource_EVIO::DumpModuleMap(void)
5684{
5685 // Open output file
5686 string fname = "module_map.txt";
5687 ofstream ofs(fname.c_str());
5688 if(!ofs.is_open()){
5689 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
5690 return;
5691 }
5692
5693 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
5694
5695 // Write header
5696 time_t now = time(NULL__null);
5697 ofs<<"# Autogenerated module map"<<endl;
5698 ofs<<"# Created: "<<ctime(&now);
5699 ofs<<"#"<<endl;
5700
5701 // Write known module types in header
5702 vector<DModuleType> modules;
5703 DModuleType::GetModuleList(modules);
5704 ofs<<"# Known module types:"<<endl;
5705 ofs<<"# ----------------------"<<endl;
5706 for(unsigned int i=0; i<modules.size(); i++){
5707 string name = modules[i].GetName();
5708 string space(12-name.size(), ' ');
5709 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5710 }
5711 ofs<<"#"<<endl;
5712 ofs<<"#"<<endl;
5713
5714 // Write module map
5715 ofs<<"# Format is:"<<endl;
5716 ofs<<"# tag num type"<<endl;
5717 ofs<<"#"<<endl;
5718
5719 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5720 for(; iter!=module_type.end(); iter++){
5721
5722 tagNum tag_num = iter->first;
5723 MODULE_TYPE type = iter->second;
5724 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5725 }
5726 ofs<<endl;
5727
5728 // Close output file
5729 ofs.close();
5730}
5731#endif