Bug Summary

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