Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 5152, column 52
Description:Dereference of null pointer

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