Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 4659, column 11
Description:Value stored to 'last_event_id' during its initialization is never read

Annotated Source Code

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