Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 4690, 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 vector<JObject*> &vcdcp125 = hit_objs_by_type["Df125CDCPulse"];
1566 for(unsigned int i=0; i<vcdcp125.size(); i++){
1567
1568 Df125CDCPulse *cdcp = (Df125CDCPulse*)vcdcp125[i];
1569 const Df125Config*conf = NULL__null;
1570 cdcp->GetSingle(conf);
1571
1572 // If this CDCpulse is *not* emulated AND there is
1573 // a configuration object from the data stream associated,
1574 // then copy the number of samples for the integral from it.
1575 if(!cdcp->emulated){
1576 if(conf){
1577 cdcp->nsamples_integral = conf->NSA_NSB;
1578 }
1579 }
1580 }
1581 vector<JObject*> &vfdcp125 = hit_objs_by_type["Df125FDCPulse"];
1582 for(unsigned int i=0; i<vfdcp125.size(); i++){
1583
1584 Df125FDCPulse *fdcp = (Df125FDCPulse*)vfdcp125[i];
1585 const Df125Config*conf = NULL__null;
1586 fdcp->GetSingle(conf);
1587
1588 // If this FDCpulse is *not* emulated AND there is
1589 // a configuration object from the data stream associated,
1590 // then copy the number of samples for the integral from it.
1591 if(!fdcp->emulated){
1592 if(conf){
1593 fdcp->nsamples_integral = conf->NSA_NSB;
1594 }
1595 }
1596 }
1597
1598 // Loop over types of config objects, copying to appropriate factory
1599 map<string, vector<JObject*> >::iterator config_iter = config_objs_by_type.begin();
1600 for(; config_iter!=config_objs_by_type.end(); config_iter++){
1601 JFactory_base *fac = loop->GetFactory(config_iter->first, "", false); // false= don't allow default tag replacement
1602 if(fac) fac->CopyTo(config_iter->second);
1603 }
1604
1605 // Loop over types of hit objects, copying to appropriate factory
1606 map<string, vector<JObject*> >::iterator iter = hit_objs_by_type.begin();
1607 for(; iter!=hit_objs_by_type.end(); iter++){
1608 JFactory_base *fac = loop->GetFactory(iter->first, "", false); // false= don't allow default tag replacement
1609 fac->CopyTo(iter->second);
1610 }
1611
1612 // Loop over types of misc objects, copying to appropriate factory
1613 map<string, vector<JObject*> >::iterator misc_iter = misc_objs_by_type.begin();
1614 for(; misc_iter!=misc_objs_by_type.end(); misc_iter++){
1615 JFactory_base *fac = loop->GetFactory(misc_iter->first, "", false); // false= don't allow default tag replacement
1616 fac->CopyTo(misc_iter->second);
1617 }
1618 objs_ptr->own_objects = false;
1619
1620 // Returning OBJECT_NOT_AVAILABLE tells JANA that this source cannot
1621 // provide the type of object requested and it should try and generate
1622 // it via a factory algorithm. Returning NOERROR on the other hand
1623 // tells JANA that we can provide this type of object and any that
1624 // are present have already been copied into the appropriate factory.
1625 jerror_t err = OBJECT_NOT_AVAILABLE;
1626 if(strlen(factory->Tag()) == 0){ // We do not supply any tagged factory data here
1627 if(event_source_data_types.find(dataClassName) != event_source_data_types.end()) err = NOERROR;
1628 }
1629
1630 // If it turns out there are no objects of one of the types we supply
1631 // then the CopyTo method for that factory never gets called and subsequent
1632 // requests for that object type will end up calling this method again.
1633 // (For the case when this is done from the ApplyTranslationTable call
1634 // below, it results in an infinite loop!). To prevent this, we need to
1635 // mark all factories of the data types we supply as having had their
1636 // evnt method called.
1637 set<string>::iterator dtiter = event_source_data_types.begin();
1638 for(; dtiter!=event_source_data_types.end(); dtiter++){
1639 JFactory_base *fac = loop->GetFactory(*dtiter);
1640 if(fac) {
1641 // The DAQ_WRD2PI plugin wants to generate some objects from
1642 // the waveform data, overiding anything found in the file.
1643 // It this case, the factory's use_factory flag is set and
1644 // we should NOT mark the factory as having it's event method
1645 // called. Furthermore, we should delete any objects in the
1646 // factory.
1647 // Now, another complication is that the only way to check
1648 // the use_factory flag is to have a pointer to the JFactory
1649 // not the JFactory_base. This means we have to check the data
1650 // type of the factory and make the appropriate cast
1651 string dataClassName = fac->GetDataClassName();
1652 int checkSourceFirst = 1;
1653 if( dataClassName == "Df250Config") checkSourceFirst = ((JFactory<Df250Config >*)fac)->GetCheckSourceFirst();
1654 else if(dataClassName == "Df250PulseIntegral") checkSourceFirst = ((JFactory<Df250PulseIntegral >*)fac)->GetCheckSourceFirst();
1655 else if(dataClassName == "Df250StreamingRawData") checkSourceFirst = ((JFactory<Df250StreamingRawData>*)fac)->GetCheckSourceFirst();
1656 else if(dataClassName == "Df250WindowSum") checkSourceFirst = ((JFactory<Df250WindowSum >*)fac)->GetCheckSourceFirst();
1657 else if(dataClassName == "Df250PulseRawData") checkSourceFirst = ((JFactory<Df250PulseRawData >*)fac)->GetCheckSourceFirst();
1658 else if(dataClassName == "Df250TriggerTime") checkSourceFirst = ((JFactory<Df250TriggerTime >*)fac)->GetCheckSourceFirst();
1659 else if(dataClassName == "Df250PulseTime") checkSourceFirst = ((JFactory<Df250PulseTime >*)fac)->GetCheckSourceFirst();
1660 else if(dataClassName == "Df250PulsePedestal") checkSourceFirst = ((JFactory<Df250PulsePedestal >*)fac)->GetCheckSourceFirst();
1661 else if(dataClassName == "Df250WindowRawData") checkSourceFirst = ((JFactory<Df250WindowRawData >*)fac)->GetCheckSourceFirst();
1662 else if(dataClassName == "Df125Config") checkSourceFirst = ((JFactory<Df125Config >*)fac)->GetCheckSourceFirst();
1663 else if(dataClassName == "Df125PulseIntegral") checkSourceFirst = ((JFactory<Df125PulseIntegral >*)fac)->GetCheckSourceFirst();
1664 else if(dataClassName == "Df125TriggerTime") checkSourceFirst = ((JFactory<Df125TriggerTime >*)fac)->GetCheckSourceFirst();
1665 else if(dataClassName == "Df125PulseTime") checkSourceFirst = ((JFactory<Df125PulseTime >*)fac)->GetCheckSourceFirst();
1666 else if(dataClassName == "Df125PulsePedestal") checkSourceFirst = ((JFactory<Df125PulsePedestal >*)fac)->GetCheckSourceFirst();
1667 else if(dataClassName == "Df125WindowRawData") checkSourceFirst = ((JFactory<Df125WindowRawData >*)fac)->GetCheckSourceFirst();
1668 else if(dataClassName == "Df125CDCPulse") checkSourceFirst = ((JFactory<Df125CDCPulse >*)fac)->GetCheckSourceFirst();
1669 else if(dataClassName == "Df125FDCPulse") checkSourceFirst = ((JFactory<Df125FDCPulse >*)fac)->GetCheckSourceFirst();
1670 else if(dataClassName == "DF1TDCConfig") checkSourceFirst = ((JFactory<DF1TDCConfig >*)fac)->GetCheckSourceFirst();
1671 else if(dataClassName == "DF1TDCHit") checkSourceFirst = ((JFactory<DF1TDCHit >*)fac)->GetCheckSourceFirst();
1672 else if(dataClassName == "DF1TDCTriggerTime") checkSourceFirst = ((JFactory<DF1TDCTriggerTime >*)fac)->GetCheckSourceFirst();
1673 else if(dataClassName == "DCAEN1290TDCConfig") checkSourceFirst = ((JFactory<DCAEN1290TDCConfig >*)fac)->GetCheckSourceFirst();
1674 else if(dataClassName == "DCAEN1290TDCHit") checkSourceFirst = ((JFactory<DCAEN1290TDCHit >*)fac)->GetCheckSourceFirst();
1675 else if(dataClassName == "DCODAEventInfo") checkSourceFirst = ((JFactory<DCAEN1290TDCHit >*)fac)->GetCheckSourceFirst();
1676 else if(dataClassName == "DCODAROCInfo") checkSourceFirst = ((JFactory<DCAEN1290TDCHit >*)fac)->GetCheckSourceFirst();
1677
1678 if(checkSourceFirst) {
1679 fac->Set_evnt_called();
1680 }else{
1681 // Factory wants to generate these so delete any read
1682 // from source.
1683 fac->Reset();
1684 }
1685 }
1686 }
1687
1688 // If a translation table object is available, use it to create
1689 // detector hits from the low-level DAQ objects we just created.
1690 for(unsigned int i=0; i<translationTables.size(); i++){
1691 translationTables[i]->ApplyTranslationTable(loop);
1692 if(translationTables[i]->IsSuppliedType(dataClassName))
1693 if(strlen(factory->Tag()) == 0)err = NOERROR; // Don't allow tagged factories from Translation table
1694 }
1695
1696 if(VERBOSE>2) evioout << " Leaving GetObjects()" << endl;
1697
1698 return err;
1699}
1700
1701//----------------
1702// AddSourceObjectsToCallStack
1703//----------------
1704void JEventSource_EVIO::AddSourceObjectsToCallStack(JEventLoop *loop, string className)
1705{
1706 /// This is used to give information to JANA regarding the origin of objects
1707 /// that *should* come from the source. We add them in explicitly because
1708 /// the file may not have any, but factories may ask for them. We want those
1709 /// links to indicate that the "0" objects in the factory came from the source
1710 /// so that janadot draws these objects correctly.
1711
1712 JEventLoop::call_stack_t cs;
1713 cs.caller_name = "<ignore>"; // tells janadot this object wasn't actually requested by anybody
1714 cs.caller_tag = "";
1715 cs.callee_name = className;
1716 cs.callee_tag = "";
1717 cs.start_time = 0.0;
1718 cs.end_time = 0.0;
1719 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1720 loop->AddToCallStack(cs);
1721}
1722
1723//----------------
1724// AddEmulatedObjectsToCallStack
1725//----------------
1726void JEventSource_EVIO::AddEmulatedObjectsToCallStack(JEventLoop *loop, string caller, string callee)
1727{
1728 /// This is used to give information to JANA regarding the relationship and
1729 /// origin of some of these data objects. This is really just needed so that
1730 /// the janadot program can be used to produce the correct callgraph. Because
1731 /// of how this plugin works, JANA can't record the correct call stack (at
1732 /// least not easily!) Therefore, we have to give it a little help here.
1733
1734 JEventLoop::call_stack_t cs;
1735 cs.caller_name = caller;
1736 cs.callee_name = callee;
1737 cs.data_source = JEventLoop::DATA_FROM_SOURCE;
1738 loop->AddToCallStack(cs);
1739 cs.callee_name = cs.caller_name;
1740 cs.caller_name = "<ignore>";
1741 cs.data_source = JEventLoop::DATA_FROM_FACTORY;
1742 loop->AddToCallStack(cs);
1743}
1744
1745
1746//----------------
1747// EmulateDf250PulseIntegral
1748//----------------
1749void JEventSource_EVIO::EmulateDf250PulseIntegral(vector<JObject*> &wrd_objs, vector<JObject*> &pi_objs)
1750{
1751 if(VERBOSE>3) evioout << " Entering EmulateDf250PulseIntegral ..." <<endl;
1752
1753 // If emulation is being forced, then delete any existing objects.
1754 // We take extra care to check that we don't delete any existing
1755 // emulated objects. (I don't think there actually can be any at
1756 // this point, but this may protect against future upgrades to
1757 // the code.)
1758 if(F250_PI_EMULATION_MODE==kEmulationAlways){
1759 vector<JObject*> emulated_pi_objs;
1760 for(uint32_t j=0; j<pi_objs.size(); j++){
1761 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1762 if(pi->emulated){
1763 emulated_pi_objs.push_back(pi);
1764 }else{
1765 delete pi;
1766 }
1767 }
1768 pi_objs = emulated_pi_objs;
1769 }
1770
1771 uint32_t pulse_number = 0;
1772 uint32_t quality_factor = 0;
1773
1774 // Loop over all window raw data objects
1775 for(unsigned int i=0; i<wrd_objs.size(); i++){
1776 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
1777
1778 // If in auto mode then check if any pulse time objects already
1779 // exist for this channel and clear the emulate_pi flag if so.
1780 bool emulate_pi = true;
1781 if(F250_PI_EMULATION_MODE == kEmulationAuto){
1782 for(uint32_t j=0; j<pi_objs.size(); j++){
1783 Df250PulseIntegral *pi = (Df250PulseIntegral*)pi_objs[j];
1784 if(pi->rocid == f250WindowRawData->rocid){
1785 if(pi->slot == f250WindowRawData->slot){
1786 if(pi->channel == f250WindowRawData->channel){
1787 if(pi->emulated){
1788 jerr << "Emulating channel that already has emulated objects!" << endl;
1789 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1790 jerr << "PulseIntegral250: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
1791 jerr << "please report error to davidl@jlab.org" << endl;
1792 exit(-1);
1793 }
1794 emulate_pi = false;
1795 break;
1796 }
1797 }
1798 }
1799 }
1800 }
1801
1802 // If we're not emulating a pulse integral here then no need to proceed.
1803 if(!emulate_pi) continue;
1804
1805 // Get a vector of the samples for this channel
1806 const vector<uint16_t> &samplesvector = f250WindowRawData->samples;
1807 uint32_t nsamples=samplesvector.size();
1808 uint32_t signalsum = 0;
1809
1810 // variables to store the sample numbers
1811 uint32_t sn_min = 0, sn_max = 0;
1812 uint32_t min = samplesvector[sn_min];
1813 uint32_t max = samplesvector[sn_max];
1814
1815 // get max and min information to decide on which algorithm to use
1816 for (uint32_t c_samp=1; c_samp<nsamples; c_samp++) {
1817 if (samplesvector[c_samp] > max) {
1818 max = samplesvector[c_samp];
1819// sn_max = c_samp;
1820 }
1821 if (samplesvector[c_samp] < min) {
1822 min = samplesvector[c_samp];
1823// sn_min = c_samp;
1824 }
1825 }
1826 // if no signal, don't process further
1827 if (max-min < F250_EMULATION_MIN_SWING) {
1828 if(VERBOSE>4) evioout << " EmulateDf250PulseIntergral: object " << i << " max - min < "
1829 << F250_EMULATION_MIN_SWING <<endl;
1830 continue;
1831 }
1832 // if the min and max are reasonable compared to the threshold then use the requested threshold
1833 // otherwise adjust it to work better.
1834 uint32_t threshold = 0;
1835 if (min < F250_THRESHOLD-5 && max > F250_THRESHOLD+5) {
1836 threshold = F250_THRESHOLD;
1837 } else {
1838 threshold = (min + max)/2;
1839 quality_factor = 1;
1840 }
1841 // find the threshold crossing
1842 uint32_t first_sample_over_threshold = 0;
1843 for (uint32_t c_samp=0; c_samp<nsamples; c_samp++) {
1844 if(VERBOSE>5) evioout << c_samp << " " << samplesvector[c_samp] << " " << threshold <<endl;
1845 if (samplesvector[c_samp] > threshold) {
1846 first_sample_over_threshold = c_samp;
1847 if(VERBOSE>4) evioout << " EmulateDf250PulseIntegral: object " << i << " found value over "
1848 << threshold << " at samp " << c_samp << " with value " << samplesvector[c_samp] <<endl;
1849 break;
1850 }
1851 }
1852
1853 // calculate integral from relevant samples
1854 uint32_t start_sample = first_sample_over_threshold - F250_NSB;
1855 uint32_t end_sample = first_sample_over_threshold + F250_NSA; // first sample past where we should sum
1856 uint32_t nsamples_used = 0;
1857 if (F250_NSB > first_sample_over_threshold) start_sample=0;
1858 if (end_sample > nsamples) end_sample=nsamples;
1859 for (uint32_t c_samp=start_sample; c_samp<end_sample; c_samp++) {
1860 signalsum += samplesvector[c_samp];
1861 nsamples_used++;
1862 }
1863
1864 // Apply sparsification threshold
1865 if(signalsum < F250_SPARSIFICATION_THRESHOLD) continue;
1866
1867 // create new Df250PulseIntegral object
1868 Df250PulseIntegral *myDf250PulseIntegral = new Df250PulseIntegral;
1869 myDf250PulseIntegral->rocid =f250WindowRawData->rocid;
1870 myDf250PulseIntegral->slot = f250WindowRawData->slot;
1871 myDf250PulseIntegral->channel = f250WindowRawData->channel;
1872 myDf250PulseIntegral->itrigger = f250WindowRawData->itrigger;
1873 myDf250PulseIntegral->pulse_number = pulse_number;
1874 myDf250PulseIntegral->quality_factor = quality_factor;
1875 myDf250PulseIntegral->integral = signalsum;
1876 myDf250PulseIntegral->pedestal = 0;
1877 myDf250PulseIntegral->nsamples_integral = nsamples_used;
1878 myDf250PulseIntegral->nsamples_pedestal = 1;
1879 myDf250PulseIntegral->emulated = true;
1880
1881 // Add the Df250WindowRawData object as an associated object
1882 myDf250PulseIntegral->AddAssociatedObject(f250WindowRawData);
1883 pi_objs.push_back(myDf250PulseIntegral);
1884 }
1885
1886 if(VERBOSE>3) evioout << " Leaving EmulateDf250PulseIntegral" <<endl;
1887}
1888
1889//----------------
1890// EmulateDf125PulseIntegral
1891//----------------
1892void JEventSource_EVIO::EmulateDf125PulseIntegral(vector<JObject*> &wrd_objs, vector<JObject*> &pi_objs,
1893 vector<JObject*> &pt_objs,
1894 vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
1895{
1896 if(VERBOSE>3) evioout << " Entering EmulateDf125PulseIntegral ..." <<endl;
1897
1898 // If emulation is being forced, then delete any existing objects.
1899 // We take extra care to check that we don't delete any existing
1900 // emulated objects. (I don't think there actually can be any at
1901 // this point, but this may protect against future upgrades to
1902 // the code.)
1903 if(F125_PI_EMULATION_MODE==kEmulationAlways){
1904 vector<JObject*> emulated_pi_objs;
1905 for(uint32_t j=0; j<pi_objs.size(); j++){
1906 Df125PulseIntegral *pi = (Df125PulseIntegral*)pi_objs[j];
1907 if(pi->emulated){
1908 emulated_pi_objs.push_back(pi);
1909 }else{
1910 delete pi;
1911 }
1912 }
1913 pi_objs = emulated_pi_objs;
1914 }
1915
1916 uint32_t pulse_number = 0;
1917 uint32_t quality_factor = 0;
1918 // Loop over all window raw data objects
1919 for(unsigned int i=0; i<wrd_objs.size(); i++){
1920 const Df125WindowRawData *wrd = (Df125WindowRawData*)wrd_objs[i];
1921
1922 // If in auto mode then check if any pulse time objects already
1923 // exist for this channel and clear the emulate_pi flag if so.
1924 bool emulate_pi = true;
1925 if(F125_PI_EMULATION_MODE == kEmulationAuto){
1926 for(uint32_t j=0; j<pi_objs.size(); j++){
1927 Df125PulseIntegral *pi = (Df125PulseIntegral*)pi_objs[j];
1928 if(pi->rocid == wrd->rocid){
1929 if(pi->slot == wrd->slot){
1930 if(pi->channel == wrd->channel){
1931 if(pi->emulated){
1932 jerr << "Emulating channel that already has emulated objects!" << endl;
1933 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
1934 jerr << "PulseIntegral125: rocid="<<pi->rocid<<" slot="<<pi->slot<<" channel="<<pi->channel<<endl;
1935 jerr << "please report error to davidl@jlab.org" << endl;
1936 exit(-1);
1937 }
1938 emulate_pi = false;
1939 break;
1940 }
1941 }
1942 }
1943 }
1944
1945 //switch off PI emulation if CDC pulse time objects are found
1946 for(uint32_t j=0; j<cp_objs.size(); j++){
1947 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
1948 if(cp->rocid == wrd->rocid){
1949 if(cp->slot == wrd->slot){
1950 if(cp->channel == wrd->channel){
1951 emulate_pi = false;
1952 break;
1953 }
1954 }
1955 }
1956 }
1957
1958 //switch off PI emulation if FDC pulse time objects are found
1959 for(uint32_t j=0; j<fp_objs.size(); j++){
1960 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
1961 if(fp->rocid == wrd->rocid){
1962 if(fp->slot == wrd->slot){
1963 if(fp->channel == wrd->channel){
1964 emulate_pi = false;
1965 break;
1966 }
1967 }
1968 }
1969 }
1970 }
1971
1972 // If we're not emulating a pulse integral here then no need to proceed.
1973 if(!emulate_pi) continue;
1974
1975 // Find pulse time for this channel
1976 const Df125PulseTime *T = NULL__null;
1977 for (unsigned int k=0; k<pt_objs.size(); k++){
1978 const Df125PulseTime *t = (Df125PulseTime*)pt_objs[k];
1979 if( t->rocid == wrd->rocid ){
1980 if( t->slot == wrd->slot ) {
1981 if( t->channel == wrd->channel ){
1982 T = t;
1983 break;
1984 }
1985 }
1986 }
1987 }
1988
1989 // Choose value of NSA and NSB based on rocid (eechh!)
1990 uint32_t NSA = F125_NSA;
1991 uint32_t NSB = F125_NSB;
1992 if(wrd->rocid>=24 && wrd->rocid<=28){
1993 NSA = F125_NSA_CDC;
1994 NSB = F125_NSB_CDC;
1995 }
1996
1997 // Get a vector of the samples for this channel
1998 const vector<uint16_t> &samplesvector = wrd->samples;
1999 uint32_t nsamples=samplesvector.size();
2000 uint32_t signalsum = 0;
2001
2002 // loop over all samples to calculate integral
2003 uint32_t nsamples_used = 0;
2004
2005 uint32_t BinTC = T==NULL__null ? 0:(T->time >> 6);
2006 uint32_t StartSample = BinTC - NSB;
2007 if( NSB > BinTC) {
2008 StartSample = 0;
2009 }
2010 uint32_t EndSample = BinTC + NSA;
2011 if (EndSample>nsamples-1){
2012 EndSample = nsamples;
2013 }
2014 for (uint32_t c_samp=StartSample; c_samp<EndSample; c_samp++) {
2015 signalsum += samplesvector[c_samp];
2016 nsamples_used++;
2017 }
2018
2019 // Apply sparsification threshold
2020 if(signalsum < F125_SPARSIFICATION_THRESHOLD) continue;
2021
2022 // create new Df125PulseIntegral object
2023 Df125PulseIntegral *myDf125PulseIntegral = new Df125PulseIntegral;
2024 myDf125PulseIntegral->rocid =wrd->rocid;
2025 myDf125PulseIntegral->slot = wrd->slot;
2026 myDf125PulseIntegral->channel = wrd->channel;
2027 myDf125PulseIntegral->itrigger = wrd->itrigger;
2028 myDf125PulseIntegral->pulse_number = pulse_number;
2029 myDf125PulseIntegral->quality_factor = quality_factor;
2030 myDf125PulseIntegral->integral = signalsum;
2031 myDf125PulseIntegral->pedestal = 0; // This will be replaced by the one from Df125PulsePedestal in GetObjects
2032 myDf125PulseIntegral->nsamples_integral = nsamples_used;
2033 myDf125PulseIntegral->nsamples_pedestal = 1;
2034 myDf125PulseIntegral->emulated = true;
2035
2036 // Add the Df125WindowRawData object as an associated object
2037 myDf125PulseIntegral->AddAssociatedObject(wrd);
2038 pi_objs.push_back(myDf125PulseIntegral);
2039 }
2040
2041 if(VERBOSE>3) evioout << " Leaving EmulateDf125PulseIntegral" <<endl;
2042}
2043
2044//----------------
2045// EmulateDf250PulseTime
2046//----------------
2047void JEventSource_EVIO::EmulateDf250PulseTime(vector<JObject*> &wrd_objs, vector<JObject*> &pt_objs, vector<JObject*> &pp_objs)
2048{
2049 if(VERBOSE>3) evioout << " Entering EmulateDf250PulseTime ..." <<endl;
2050
2051 // If emulation is being forced, then delete any existing objects.
2052 // We take extra care to check that we don't delete any existing
2053 // emulated objects. (I don't think there actually can be any at
2054 // this point, but this may protect against future upgrades to
2055 // the code.)
2056 if(F250_PT_EMULATION_MODE==kEmulationAlways){
2057 vector<JObject*> emulated_pt_objs;
2058 for(uint32_t j=0; j<pt_objs.size(); j++){
2059 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
2060 if(pt->emulated){
2061 emulated_pt_objs.push_back(pt);
2062 }else{
2063 delete pt;
2064 }
2065 }
2066 pt_objs = emulated_pt_objs;
2067 }
2068 if(F250_PP_EMULATION_MODE==kEmulationAlways){
2069 vector<JObject*> emulated_pp_objs;
2070 for(uint32_t j=0; j<pp_objs.size(); j++){
2071 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
2072 if(pp->emulated){
2073 emulated_pp_objs.push_back(pp);
2074 }else{
2075 delete pp;
2076 }
2077 }
2078 pp_objs = emulated_pp_objs;
2079 }
2080
2081
2082 // Loop over all window raw data objects
2083 for(unsigned int i=0; i<wrd_objs.size(); i++){
2084 const Df250WindowRawData *f250WindowRawData = (Df250WindowRawData*)wrd_objs[i];
2085
2086 // If in auto mode then check if any pulse time objects already
2087 // exists for this channel and clear the emulate_pt flag if so.
2088 bool emulate_pt = true;
2089 if(F250_PT_EMULATION_MODE == kEmulationAuto){
2090 for(uint32_t j=0; j<pt_objs.size(); j++){
2091 Df250PulseTime *pt = (Df250PulseTime*)pt_objs[j];
2092 if(pt->rocid == f250WindowRawData->rocid){
2093 if(pt->slot == f250WindowRawData->slot){
2094 if(pt->channel == f250WindowRawData->channel){
2095 if(pt->emulated){
2096 jerr << "Emulating channel that already has emulated objects!" << endl;
2097 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2098 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
2099 jerr << "please report error to davidl@jlab.org" << endl;
2100 exit(-1);
2101 }
2102 emulate_pt = false;
2103 break;
2104 }
2105 }
2106 }
2107 }
2108 }
2109
2110 // Ditto for pulse pedestal objects
2111 bool emulate_pp = true;
2112 if(F250_PP_EMULATION_MODE == kEmulationAuto){
2113 for(uint32_t j=0; j<pp_objs.size(); j++){
2114 Df250PulsePedestal *pp = (Df250PulsePedestal*)pp_objs[j];
2115 if(pp->rocid == f250WindowRawData->rocid){
2116 if(pp->slot == f250WindowRawData->slot){
2117 if(pp->channel == f250WindowRawData->channel){
2118 if(pp->emulated){
2119 jerr << "Emulating channel that already has emulated objects!" << endl;
2120 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2121 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
2122 jerr << "please report error to davidl@jlab.org" << endl;
2123 exit(-1);
2124 }
2125 emulate_pp = false;
2126 break;
2127 }
2128 }
2129 }
2130 }
2131 }
2132
2133 // Skip to next wrd if nothing is to be emulated
2134 if( (!emulate_pt) && (!emulate_pp) ) continue;
2135
2136 // Get a vector of the samples for this channel
2137 const vector<uint16_t> &samplesvector = f250WindowRawData->samples;
2138 uint32_t nsamples=samplesvector.size();
2139
2140 // variables to store the sample numbers
2141 uint32_t sn_min = 0, sn_max = 0;
2142 uint32_t min = samplesvector[sn_min];
2143 uint32_t max = samplesvector[sn_max];
2144
2145 // get max and min information to decide on which algorithm to use
2146 for (uint32_t c_samp=1; c_samp<nsamples; c_samp++) {
2147 if (samplesvector[c_samp] > max) {
2148 max = samplesvector[c_samp];
2149// sn_max = c_samp;
2150 }
2151 if (samplesvector[c_samp] < min) {
2152 min = samplesvector[c_samp];
2153// sn_min = c_samp;
2154 }
2155 }
2156 // if no signal, don't process further
2157 if (max-min < F250_EMULATION_MIN_SWING) {
2158 if(VERBOSE>4) evioout << " EmulateDf250PulseIntergral: object " << i << " max - min < "
2159 << F250_EMULATION_MIN_SWING <<endl;
2160 continue;
2161 }
2162 // if the min and max are reasonable compared to the threshold then use the requested threshold
2163 // otherwise adjust it to work better
2164 uint32_t threshold = 0;
2165 if (min < F250_THRESHOLD-5 && max > F250_THRESHOLD+5) {
2166 threshold = F250_THRESHOLD;
2167 } else {
2168 threshold = (min + max)/2;
2169 }
2170 // find the threshold crossing
2171 int32_t first_sample_over_threshold = -1000;
2172 for (uint32_t c_samp=0; c_samp<nsamples; c_samp++) {
2173 if (samplesvector[c_samp] > threshold) {
2174 first_sample_over_threshold = c_samp;
2175 if(VERBOSE>4) evioout << " EmulateDf250PulseTime: object " << i << " found value over " << threshold << " at samp "
2176 << c_samp << " with value " << samplesvector[c_samp] <<endl;
2177 break;
2178 }
2179 }
2180 // Define the variables for the time extraction (named as in the f250 documentation)
2181 uint32_t VPEAK = 0, VMIN = 0, VMID = 0;
2182 uint32_t VN1=0, VN2=0;
2183 double time_fraction = -1000;
2184
2185 // loop over the first F250_NSPED samples to calculate pedestal
2186 uint32_t pedestalsum = 0;
2187 for (uint32_t c_samp=0; c_samp<F250_NSPED; c_samp++) {
2188 pedestalsum += samplesvector[c_samp];
2189 }
2190 uint32_t pedestalavg = ( F250_NSPED==0 ? 0:(pedestalsum/F250_NSPED) );
2191 VMIN = pedestalavg;
2192
2193 uint32_t time = 0;
2194 uint32_t mid_sample = 0;
2195 if (VMIN > threshold) { // firmware requires VMIN < F250_THRESHOLD
2196 time_fraction = 0;
2197 }
2198 if (first_sample_over_threshold == 0) {
2199 time_fraction = 1;
2200 }
2201 if (time_fraction < 0) {
2202 // Find maximum by looking for signal downturn
2203 for (uint32_t c_samp=first_sample_over_threshold; c_samp<nsamples; c_samp++) {
2204 if (samplesvector[c_samp] > VPEAK) {
2205 VPEAK = samplesvector[c_samp];
2206 } else {
2207 // we found the downturn
2208 break;
2209 }
2210 }
2211 VMID = (VPEAK + VMIN)/2;
2212
2213 // find the adjacent samples that straddle the VMID crossing
2214 for (uint32_t c_samp=0; c_samp<nsamples; c_samp++) {
2215 if (samplesvector[c_samp] > VMID) {
2216 if (c_samp==0) {
2217 // evioout << " EmulateDf250PulseTime: object " << i << " c_samp=" << c_samp
2218 // << " samplesvector[c_samp]=" << samplesvector[c_samp] << " VMID=" << VMID << endl;
2219 // evioout << " EmulateDf250PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2220 // << " mid_sample=" << mid_sample << " max_sample=" << max_sample
2221 // << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2222 // << " time=" << time << " sample_over=" << first_sample_over_threshold <<endl;
2223 } else {
2224 VN2 = samplesvector[c_samp];
2225 VN1 = samplesvector[c_samp-1];
2226 mid_sample = c_samp-1;
2227 break;
2228 }
2229 }
2230 }
2231 }
2232 time_fraction = mid_sample + ((double)(VMID-VN1))/((double)(VN2-VN1));
2233 time = time_fraction*64;
2234 if(VERBOSE>4) evioout << " EmulateDf250PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2235 << " mid_sample=" << mid_sample << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2236 << " time=" << time << " sample_over=" << first_sample_over_threshold << endl;
2237
2238 // create new Df250PulseTime object
2239 if(emulate_pt){
2240 Df250PulseTime *myDf250PulseTime = new Df250PulseTime;
2241 myDf250PulseTime->rocid =f250WindowRawData->rocid;
2242 myDf250PulseTime->slot = f250WindowRawData->slot;
2243 myDf250PulseTime->channel = f250WindowRawData->channel;
2244 myDf250PulseTime->itrigger = f250WindowRawData->itrigger;
2245 myDf250PulseTime->pulse_number = 0;
2246 myDf250PulseTime->quality_factor = 0;
2247 myDf250PulseTime->time = time;
2248 myDf250PulseTime->emulated = true;
2249 myDf250PulseTime->AddAssociatedObject(f250WindowRawData);
2250 pt_objs.push_back(myDf250PulseTime);
2251 }
2252
2253 // create new Df250PulsePedestal object
2254 if(emulate_pp){
2255 Df250PulsePedestal *myDf250PulsePedestal = new Df250PulsePedestal;
2256 myDf250PulsePedestal->rocid =f250WindowRawData->rocid;
2257 myDf250PulsePedestal->slot = f250WindowRawData->slot;
2258 myDf250PulsePedestal->channel = f250WindowRawData->channel;
2259 myDf250PulsePedestal->itrigger = f250WindowRawData->itrigger;
2260 myDf250PulsePedestal->pulse_number = 0;
2261 myDf250PulsePedestal->pedestal = pedestalavg; // Return the average pedestal. This is what the firmware will do.
2262 myDf250PulsePedestal->pulse_peak = VPEAK;
2263 myDf250PulsePedestal->emulated = true;
2264 myDf250PulsePedestal->AddAssociatedObject(f250WindowRawData);
2265 pp_objs.push_back(myDf250PulsePedestal);
2266 }
2267 }
2268
2269 // PulseTime and PulsePedestal objects are associated to one another in GetObjects
2270
2271 if(VERBOSE>3) evioout << " Leaving EmulateDf250PulseTime" <<endl;
2272}
2273
2274//----------------
2275// EmulateDf125PulseTime
2276//----------------
2277void JEventSource_EVIO::EmulateDf125PulseTime(vector<JObject*> &wrd_objs, vector<JObject*> &pt_objs, vector<JObject*> &pp_objs, vector<JObject*> &cp_objs, vector<JObject*> &fp_objs)
2278{
2279 /// Emulation of the f125 can be done in one of two ways. The first
2280 /// implements an upsampling technique developed by Naomi Jarvis at
2281 /// CMU. This was not implemented in the firmware for the 2014 commissioning
2282 /// run, but was implemented for later runs. The second algorithm is
2283 /// supposed to match the firmware algorithm used in the f125 during the
2284 /// 2014 commissioning run. This is a copy of the f250 algorithm. At the
2285 /// time I'm writing this, it does not appear to give identical, or even
2286 /// terribly close results to what the actual firmware reported. To select
2287 /// using this second algorithm (the "f250 algorithm") set the
2288 /// EVIO:F125_TIME_UPSAMPLE config. parameter to "0". To turn
2289 /// on emulation for data that actually has hits in the data stream from
2290 /// the firmware, set the EVIO:F125_PT_EMULATION_MODE config. parameter
2291 /// to 1.
2292 ///
2293 /// NOTE: The upsampling algorithm here currently converts the value reported
2294 /// into units of 1/64 of a sample to match the units of the firmware
2295 /// version used for 2014 commissioning data. When the upsampling algorithm
2296 /// is implemented in firmware, the units reported by the firmware will
2297 /// change to 1/10 of a sample! 2/9/2014 DL
2298 ///
2299 /// Changed the units to 1/10 sample to match the firmware 3 Nov 2015 NSJ.
2300
2301
2302 if(VERBOSE>3) evioout << " Entering EmulateDf125PulseTime ..." <<endl;
2303
2304 // If emulation is being forced, then delete any existing objects.
2305 // We take extra care to check that we don't delete any existing
2306 // emulated objects. (I don't think there actually can be any at
2307 // this point, but this may protect against future upgrades to
2308 // the code.)
2309 if(F125_PT_EMULATION_MODE==kEmulationAlways){
2310 vector<JObject*> emulated_pt_objs;
2311 for(uint32_t j=0; j<pt_objs.size(); j++){
2312 Df125PulseTime *pt = (Df125PulseTime*)pt_objs[j];
2313 if(pt->emulated){
2314 emulated_pt_objs.push_back(pt);
2315 }else{
2316 delete pt;
2317 }
2318 }
2319 pt_objs = emulated_pt_objs;
2320 }
2321 if(F125_PP_EMULATION_MODE==kEmulationAlways){
2322 vector<JObject*> emulated_pp_objs;
2323 for(uint32_t j=0; j<pp_objs.size(); j++){
2324 Df125PulsePedestal *pp = (Df125PulsePedestal*)pp_objs[j];
2325 if(pp->emulated){
2326 emulated_pp_objs.push_back(pp);
2327 }else{
2328 delete pp;
2329 }
2330 }
2331 pp_objs = emulated_pp_objs;
2332 }
2333
2334 uint32_t Nped_samples = 4; // number of samples to use for pedestal calculation (PED_SAMPLE)
2335 uint32_t Nsamples = 14; // Number of samples used to define leading edge (was NSAMPLES in Naomi's code)
2336
2337 // Loop over all window raw data objects
2338 for(unsigned int i=0; i<wrd_objs.size(); i++){
2339 const Df125WindowRawData *f125WindowRawData = (Df125WindowRawData*)wrd_objs[i];
2340
2341 // If in auto mode then check if any pulse time objects already
2342 // exists for this channel and clear the emulate_pt flag if so.
2343 bool emulate_pt = true;
2344 if(F125_PT_EMULATION_MODE == kEmulationAuto){
2345 for(uint32_t j=0; j<pt_objs.size(); j++){
2346 Df125PulseTime *pt = (Df125PulseTime*)pt_objs[j];
2347 if(pt->rocid == f125WindowRawData->rocid){
2348 if(pt->slot == f125WindowRawData->slot){
2349 if(pt->channel == f125WindowRawData->channel){
2350 if(pt->emulated){
2351 jerr << "Emulating channel that already has emulated objects!" << endl;
2352 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2353 jerr << "PulseTime: rocid="<<pt->rocid<<" slot="<<pt->slot<<" channel="<<pt->channel<<endl;
2354 jerr << "please report error to davidl@jlab.org" << endl;
2355 exit(-1);
2356 }
2357 emulate_pt = false;
2358 break;
2359 }
2360 }
2361 }
2362 }
2363
2364 //switch off PT auto-emulation if CDCPulse is found
2365 for(uint32_t j=0; j<cp_objs.size(); j++){
2366 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2367 if(cp->rocid == f125WindowRawData->rocid){
2368 if(cp->slot == f125WindowRawData->slot){
2369 if(cp->channel == f125WindowRawData->channel){
2370 emulate_pt = false;
2371 break;
2372 }
2373 }
2374 }
2375 }
2376
2377 //switch off PT auto-emulation if FDCPulse is found
2378 for(uint32_t j=0; j<fp_objs.size(); j++){
2379 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2380 if(fp->rocid == f125WindowRawData->rocid){
2381 if(fp->slot == f125WindowRawData->slot){
2382 if(fp->channel == f125WindowRawData->channel){
2383 emulate_pt = false;
2384 break;
2385 }
2386 }
2387 }
2388 }
2389 }
2390
2391 // Ditto for pulse pedestal objects
2392 bool emulate_pp = true;
2393 if(F125_PP_EMULATION_MODE == kEmulationAuto){
2394 for(uint32_t j=0; j<pp_objs.size(); j++){
2395 Df125PulsePedestal *pp = (Df125PulsePedestal*)pp_objs[j];
2396 if(pp->rocid == f125WindowRawData->rocid){
2397 if(pp->slot == f125WindowRawData->slot){
2398 if(pp->channel == f125WindowRawData->channel){
2399 if(pp->emulated){
2400 jerr << "Emulating channel that already has emulated objects!" << endl;
2401 jerr << "This likely means there is a bug in JEventSource_EVIO.cc" <<endl;
2402 jerr << "PulsePedestal: rocid="<<pp->rocid<<" slot="<<pp->slot<<" channel="<<pp->channel<<endl;
2403 jerr << "please report error to davidl@jlab.org" << endl;
2404 exit(-1);
2405 }
2406 emulate_pp = false;
2407 break;
2408 }
2409 }
2410 }
2411 }
2412
2413 //switch off PP auto-emulation if CDCPulse is found
2414 for(uint32_t j=0; j<cp_objs.size(); j++){
2415 Df125CDCPulse *cp = (Df125CDCPulse*)cp_objs[j];
2416 if(cp->rocid == f125WindowRawData->rocid){
2417 if(cp->slot == f125WindowRawData->slot){
2418 if(cp->channel == f125WindowRawData->channel){
2419 emulate_pp = false;
2420 break;
2421 }
2422 }
2423 }
2424 }
2425
2426 //switch off PP auto-emulation if FDCPulse is found
2427 for(uint32_t j=0; j<fp_objs.size(); j++){
2428 Df125FDCPulse *fp = (Df125FDCPulse*)fp_objs[j];
2429 if(fp->rocid == f125WindowRawData->rocid){
2430 if(fp->slot == f125WindowRawData->slot){
2431 if(fp->channel == f125WindowRawData->channel){
2432 emulate_pp = false;
2433 break;
2434 }
2435 }
2436 }
2437 }
2438
2439 }
2440
2441 int rocid = f125WindowRawData->rocid;
2442
2443 // Get a vector of the samples for this channel
2444 const vector<uint16_t> &samplesvector = f125WindowRawData->samples;
2445 uint32_t Nsamples_all = samplesvector.size(); // (was NADCBUFFER in Naomi's code)
2446 if(Nsamples_all < (Nped_samples+Nsamples)){
2447 static int Nwarn=0;
2448 if(Nwarn<10){
2449 char str[256];
2450 sprintf(str, "Too few samples in Df125WindowRawData for pulse time extraction! Nsamples_all=%d, (Nped_samples+Nsamples)=%d", Nsamples_all, (Nped_samples+Nsamples));
2451 jerr << str << endl;
2452 if(++Nwarn==10) jerr << "--- Last Warning! ---" <<endl;
2453 }
2454 return;
2455// throw JException(str);
2456 }
2457
2458 bool found_hit = false;
2459 uint32_t time = 0;
2460 uint32_t quality_factor = 0;
2461 uint32_t pedestalavg = 0;
2462 uint32_t pulse_peak = 0;
2463 uint32_t overflows = 0;
2464
2465 // loop over the first ped_samples samples to calculate pedestal
2466 int32_t pedestalsum = 0;
2467 for (uint32_t c_samp=0; c_samp<Nped_samples; c_samp++) {
2468 pedestalsum += samplesvector[c_samp];
2469 }
2470 pedestalavg = pedestalsum / Nped_samples;
2471
2472 if(F125_TIME_UPSAMPLE){
2473 fa125_algos_data_t fa125_algos_data;
2474 //fa125_algos(rocid, samplesvector, fa125_algos_data);
2475 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);
2476
2477 time = fa125_algos_data.time;
2478 quality_factor = fa125_algos_data.q_code;
2479 pedestalavg = fa125_algos_data.pedestal;
2480 pulse_peak = fa125_algos_data.maxamp;
2481 overflows = fa125_algos_data.overflows;
2482
2483 // The upsampling algorithm reports times in units of 1/10 of a
2484 // sample while the f250 algorithm reports it in units of 1/64
2485 // of a sample. Convert to units of 1/64 of a sample here to
2486 // make this consistent with the other algorithms.
2487 // time = (time*64)/10; //removed 4Nov2015 NSJ
2488
2489 // In Naomi's original code, she checked if maxamp was >0 to decide
2490 // whether to add the value to the tree. Note that this ignored the
2491 // "hitfound" variable in the cdc_algos2 code. We follow her example
2492 // here. DL
2493 found_hit = pulse_peak > 0;
2494
2495 }else{ // not F125_TIME_UPSAMPLE
2496
2497 //----------F250 algorithm ----------
2498 // variables to store the sample numbers
2499 uint32_t sn_min = 0, sn_max = 0;
2500 uint32_t min = samplesvector[sn_min];
2501 uint32_t max = samplesvector[sn_max];
2502
2503 // get max and min information to decide on which algorithm to use
2504 for (uint32_t c_samp=1; c_samp<Nsamples_all; c_samp++) {
2505 if (samplesvector[c_samp] > max) {
2506 max = samplesvector[c_samp];
2507// sn_max = c_samp;
2508 }
2509 if (samplesvector[c_samp] < min) {
2510 min = samplesvector[c_samp];
2511// sn_min = c_samp;
2512 }
2513 }
2514 // if no signal, don't process further
2515 if (max-min < F125_EMULATION_MIN_SWING) {
2516 if(VERBOSE>4) evioout << " EmulateDf125PulseTime: object " << i << " max - min < " << F250_EMULATION_MIN_SWING <<endl;
2517 continue;
2518 }
2519 // if the min and max are reasonable compared to the threshold then use the requested threshold
2520 // otherwise adjust it to work better
2521 uint32_t threshold = 0;
2522 if (min < F125_THRESHOLD-5 && max > F125_THRESHOLD+5) {
2523 threshold = F125_THRESHOLD;
2524 } else {
2525 threshold = (min + max)/2;
2526 }
2527 // find the threshold crossing
2528 int32_t first_sample_over_threshold = -1000;
2529 for (uint32_t c_samp=0; c_samp<Nsamples_all; c_samp++) {
2530 if (samplesvector[c_samp] > threshold) {
2531 first_sample_over_threshold = c_samp;
2532 if(VERBOSE>4) evioout << " EmulateDf125PulseTime: object " << i << " found value over " << threshold << " at samp "
2533 << c_samp << " with value " << samplesvector[c_samp] <<endl;
2534 break;
2535 }
2536 }
2537 // Define the variables for the time extraction (named as in the f250 documentation)
2538 uint32_t VPEAK = 0, VMIN = pedestalavg, VMID = 0;
2539 uint32_t VN1=0, VN2=0;
2540 double time_fraction = -1000;
2541
2542
2543 uint32_t mid_sample = 0;
2544 if (VMIN > threshold) { // firmware requires VMIN < F125_THRESHOLD
2545 time_fraction = 0;
2546 }
2547 if (first_sample_over_threshold == 0) {
2548 time_fraction = 1;
2549 }
2550 if (time_fraction < 0) {
2551 // Find maximum by looking for signal downturn
2552 for (uint32_t c_samp=first_sample_over_threshold; c_samp<Nsamples_all; c_samp++) {
2553 if (samplesvector[c_samp] > VPEAK) {
2554 pulse_peak = VPEAK = samplesvector[c_samp];
2555 } else {
2556 // we found the downturn
2557 break;
2558 }
2559 }
2560 VMID = (VPEAK + VMIN)/2;
2561
2562 // find the adjacent samples that straddle the VMID crossing
2563 for (uint32_t c_samp=0; c_samp<Nsamples_all; c_samp++) {
2564 if (samplesvector[c_samp] > VMID) {
2565 if (c_samp==0) {
2566 // evioout << " EmulateDf125PulseTime: object " << i << " c_samp=" << c_samp
2567 // << " samplesvector[c_samp]=" << samplesvector[c_samp] << " VMID=" << VMID << endl;
2568 // evioout << " EmulateDf125PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2569 // << " mid_sample=" << mid_sample << " max_sample=" << max_sample
2570 // << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2571 // << " time=" << time << " sample_over=" << first_sample_over_threshold <<endl;
2572 } else {
2573 VN2 = samplesvector[c_samp];
2574 VN1 = samplesvector[c_samp-1];
2575 mid_sample = c_samp-1;
2576 break;
2577 }
2578 }
2579 }
2580 }
2581 time_fraction = mid_sample + ((double)(VMID-VN1))/((double)(VN2-VN1));
2582 time = time_fraction*64;
2583 quality_factor = 1;
2584 found_hit = true;
2585 if(VERBOSE>4)
2586 evioout << " EmulateDf125PulseTime: object " << i << " VMIN=" << VMIN << " VPEAK=" << VPEAK << " VMID=" << VMID
2587 << " mid_sample=" << mid_sample << " VN1=" << VN1 << " VN2=" << VN2 << " time_fraction=" << time_fraction
2588 << " time=" << time << " sample_over=" << first_sample_over_threshold << endl;
2589
2590
2591 } // F125_TIME_UPSAMPLE
2592
2593 // At this point we know we have a hit and will be able to extract a time.
2594 // Go ahead and make the PulseTime object, filling in the "rough" time.
2595 // and corresponding quality factor. The time and quality factor
2596 // will be updated later when and if we can calculate a more accurate one.
2597
2598 if(found_hit){
2599
2600 // create new Df125PulseTime object
2601 if(emulate_pt){
2602 Df125PulseTime *myDf125PulseTime = new Df125PulseTime;
2603 myDf125PulseTime->rocid =f125WindowRawData->rocid;
2604 myDf125PulseTime->slot = f125WindowRawData->slot;
2605 myDf125PulseTime->channel = f125WindowRawData->channel;
2606 myDf125PulseTime->itrigger = f125WindowRawData->itrigger;
2607 myDf125PulseTime->pulse_number = 0;
2608 myDf125PulseTime->quality_factor = quality_factor;
2609 myDf125PulseTime->time = time;
2610 myDf125PulseTime->overflows = overflows;
2611 myDf125PulseTime->emulated = true;
2612 myDf125PulseTime->AddAssociatedObject(f125WindowRawData);
2613 pt_objs.push_back(myDf125PulseTime);
2614
2615 // The following is empirical from the first BCAL/CDC cosmic data
2616 //myDf125PulseTime->time -= 170.0;
2617 if(myDf125PulseTime->time > 10000){
2618 // If calculated time is <170.0, then the unsigned int is problematic. Flag this if it happens
2619 myDf125PulseTime->time = 0;
2620 myDf125PulseTime->quality_factor = 2;
2621 }
2622 }
2623
2624 // create new Df125PulsePedestal object
2625 if(emulate_pp){
2626 Df125PulsePedestal *myDf125PulsePedestal = new Df125PulsePedestal;
2627 myDf125PulsePedestal->rocid =f125WindowRawData->rocid;
2628 myDf125PulsePedestal->slot = f125WindowRawData->slot;
2629 myDf125PulsePedestal->channel = f125WindowRawData->channel;
2630 myDf125PulsePedestal->itrigger = f125WindowRawData->itrigger;
2631 myDf125PulsePedestal->pulse_number = 0;
2632 myDf125PulsePedestal->pedestal = pedestalavg;
2633 myDf125PulsePedestal->pulse_peak = pulse_peak;
2634 myDf125PulsePedestal->emulated = true;
2635 myDf125PulsePedestal->AddAssociatedObject(f125WindowRawData);
2636 pp_objs.push_back(myDf125PulsePedestal);
2637 }
2638 } // found_hit
2639 } // i loop over wrd_objs.size()
2640
2641 // Add PulseTime and PulsePedestal objects as associate objects of one another
2642 vector<Df125PulseTime*> ppt_objs;
2643 vector<Df125PulsePedestal*> ppp_objs;
2644 CopyContainerElementsWithCast(pt_objs, ppt_objs);
2645 CopyContainerElementsWithCast(pp_objs, ppp_objs);
2646 LinkAssociationsWithPulseNumber(ppt_objs, ppp_objs);
2647
2648 if(VERBOSE>3) evioout << " Leaving EmulateDf125PulseTime" <<endl;
2649}
2650
2651//----------------
2652// GetRunNumber
2653//----------------
2654int32_t JEventSource_EVIO::GetRunNumber(evioDOMTree *evt)
2655{
2656 // This is called during event parsing to get the
2657 // run number for the event.
2658 // Look through event to try and extract the run number.
2659 // We do this by looking for all uint64_t nodes. Then
2660 // check for a parent with one of the magic values for
2661 // the tag indicating it has run number information.
2662 if(USER_RUN_NUMBER>0) return USER_RUN_NUMBER;
2663 if(!evt) return last_run_number;
2664
2665 evioDOMNodeListP bankList = evt->getNodeList(typeIs<uint64_t>());
2666 evioDOMNodeList::iterator iter = bankList->begin();
2667 const uint64_t *run_number_and_type = NULL__null;
2668 for(; iter!=bankList->end(); iter++){
2669 evioDOMNodeP bankPtr = *iter;
2670 evioDOMNodeP physics_event_built_trigger_bank = bankPtr->getParent();
2671 if(physics_event_built_trigger_bank == NULL__null) continue;
2672 uint32_t tag = physics_event_built_trigger_bank->tag;
2673 const vector<uint64_t> *vec;
2674 switch(tag){
2675 case 0xFF22:
2676 case 0xFF23:
2677 case 0xFF26:
2678 case 0xFF27:
2679 vec = bankPtr->getVector<uint64_t>();
2680 if(!vec) continue;
2681 if(vec->size()<1) continue;
2682 run_number_and_type = &((*vec)[vec->size()-1]);
2683 break;
2684 }
2685 if(run_number_and_type != NULL__null) break;
2686 }
2687
2688 if(run_number_and_type != NULL__null) last_run_number = (*run_number_and_type)>>32;
2689
2690 return last_run_number;
2691}
2692
2693//----------------
2694// FindRunNumber
2695//----------------
2696int32_t JEventSource_EVIO::FindRunNumber(uint32_t *iptr)
2697{
2698 /// This is called from GetEvent() to quickly look for the run number
2699 /// at the time the event is read in so it can be passed into
2700 /// JEvent. It is what will be used for accessing the CCDB.
2701 /// from this event. If a bank containing the run number is found,
2702 /// use it to provide the run number. Otherwise, return whatever run
2703 /// number we were able to extract from the file name.
2704
2705 if(VERBOSE>1) evioout << " .. Searching for run number ..." <<endl;
2706 if(USER_RUN_NUMBER>0){
2707 if(VERBOSE>1) evioout << " returning user-supplied run number: " << USER_RUN_NUMBER << endl;
2708 return USER_RUN_NUMBER;
2709 }
2710
2711 // Assume first word is number of words in bank
2712 uint32_t *iend = &iptr[*iptr - 1];
2713 if(*iptr > 256) iend = &iptr[256];
2714 bool has_timestamps = false;
2715 while(iptr<iend){
2716 iptr++;
2717 switch((*iptr)>>16){
2718 case 0xFF10:
2719 case 0xFF11:
2720 case 0xFF20:
2721 case 0xFF21:
2722 case 0xFF24:
2723 case 0xFF25:
2724 case 0xFF30:
2725 // These Trigger Bank Tag values have no run number info in them
2726 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does not contain run number" <<endl;
2727 return filename_run_number;
2728 case 0xFF23:
2729 case 0xFF27:
2730 has_timestamps = true;
2731 case 0xFF22:
2732 case 0xFF26:
2733 if(VERBOSE>2) evioout << " ... Trigger bank tag (0x" << hex << ((*iptr)>>16) << dec << ") does contain run number" <<endl;
2734// Nrocs = (*iptr) & 0x0F;
2735 break;
2736 default:
2737 continue;
2738 }
2739 iptr++;
2740 if( ((*iptr)&0x00FF0000) != 0x000A0000) { iptr--; continue; }
2741 uint32_t M = iptr[-3] & 0x000000FF; // Number of events from Physics Event header
2742 if(VERBOSE>2) evioout << " ... Trigger bank " << (has_timestamps ? "does":"doesn't") << " have timestamps. Nevents in block M=" << M <<endl;
2743 iptr++;
2744 uint64_t *iptr64 = (uint64_t*)iptr;
2745
2746 uint64_t event_num = *iptr64;
2747 iptr64++;
2748 if(has_timestamps) iptr64 = &iptr64[M]; // advance past timestamps
2749 if(VERBOSE>3) evioout << " .... Event num: " << event_num <<endl;
2750
2751 // For some reason, we have to first put this into
2752 // 64bit number and then cast it.
2753 uint64_t run64 = (*iptr64)>>32;
2754 int32_t run = (int32_t)run64;
2755 if(VERBOSE>1) evioout << " .. Found run number: " << run <<endl;
2756
2757 return run;
2758 }
2759
2760 return filename_run_number;
2761}
2762
2763//----------------
2764// FindEventNumber
2765//----------------
2766uint64_t JEventSource_EVIO::FindEventNumber(uint32_t *iptr)
2767{
2768 /// This is called from GetEvent() to quickly look for the event number
2769 /// at the time the event is read in so it can be passed into JEvent.
2770 /// (See comments for FindRunNumber above.)
2771 if(*iptr < 6) return Nevents_read+1;
2772
2773 // Check header of Trigger bank
2774 uint32_t mask = 0xFF202000;
2775 if( (iptr[3]&mask) != mask ) return Nevents_read+1;
2776
2777 uint64_t loevent_num = iptr[5];
2778 uint64_t hievent_num = iptr[6];
2779 uint64_t event_num = loevent_num + (hievent_num<<32);
2780
2781 return event_num;
2782}
2783
2784//----------------
2785// FindEventType
2786//----------------
2787void JEventSource_EVIO::FindEventType(uint32_t *iptr, JEvent &event)
2788{
2789 /// This is called from GetEvent to quickly determine the type of
2790 /// event this is (Physics, EPICS, SYNC, BOR, ...)
2791 uint32_t head = iptr[1];
2792 if( (head & 0xff000f) == 0x600001){
2793 event.SetStatusBit(kSTATUS_EPICS_EVENT);
2794 }else if( (head & 0xffffff00) == 0xff501000){
2795 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2796 }else if( (head & 0xffffff00) == 0xff701000){
2797 event.SetStatusBit(kSTATUS_PHYSICS_EVENT);
2798 }else if( (head & 0xfff000ff) == 0xffd00000){
2799 event.SetStatusBit(kSTATUS_CONTROL_EVENT);
2800 if( (head>>16) == 0xffd0 ) event.SetStatusBit(kSTATUS_SYNC_EVENT);
2801 }else{
2802// DumpBinary(iptr, &iptr[16]);
2803 }
2804}
2805
2806//----------------
2807// MergeObjLists
2808//----------------
2809void JEventSource_EVIO::MergeObjLists(list<ObjList*> &events1, list<ObjList*> &events2)
2810{
2811 if(VERBOSE>5) evioout << " Entering MergeObjLists(). "
2812 << " &events1=" << hex << &events1 << dec << "(" << events1.size() << " events) "
2813 << " &events2=" << hex << &events2 << dec << "(" << events2.size() << " events) " << endl;
2814
2815 /// Merge the events referenced in events2 into the events1 list.
2816 ///
2817 /// This will append the object lists for each type of data object
2818 /// stored in events2 onto the appropriate list in events1. It does this
2819 /// event-by-event. The idea being that each entry in the queue represents a
2820 /// partial list of the objects for the event. The two queues are most likely
2821 /// filled from different EVIO banks orginiating from different ROCs.
2822 ///
2823 /// Before the merging is done, it is checked that both lists either have the
2824 /// same number of events, or one list is empty. One list is allowed to be
2825 /// empty since it is possible it was "filled" from a bank that contains no
2826 /// data at all which may not neccessarily be an error. If both queues have
2827 /// at least one event, but they do not contain an equal number of events,
2828 /// then an exception is thrown.
2829 ///
2830 /// The contents of event2 will be erased before returning. Ownership of all
2831 /// ObjList objects pointed to by event2 upon entry should be considered
2832 /// owned by event1 upon return.
2833
2834 // Allow a list of 1 event with only config objects in test below
2835 bool justconfig = false;
2836 if(events1.size()==1){
2837 ObjList *objs1 = events1.front();
2838 justconfig = objs1->hit_objs.size()==0 && objs1->misc_objs.size()==0 && objs1->config_objs.size()!=0;
2839 }else if(events2.size()==1){
2840 ObjList *objs2 = events2.front();
2841 justconfig = objs2->hit_objs.size()==0 && objs2->misc_objs.size()==0 && objs2->config_objs.size()!=0;
2842 }
2843
2844 // Check number of events and throw exception if appropriate
2845 unsigned int Nevents1 = events1.size();
2846 unsigned int Nevents2 = events2.size();
2847 if(Nevents1>0 && Nevents2>0 && !justconfig){
2848 if(Nevents1 != Nevents2){
2849 evioout << "Mismatch of number of events passed to MergeObjLists. Throwing exception." << endl;
2850 evioout << "Nevents1="<<Nevents1<<" Nevents2="<<Nevents2<<endl;
2851 throw JException("Number of events in JEventSource_EVIO::MergeObjLists do not match!");
2852 }
2853 }
2854
2855 // Handle cases when one or both lists are empty
2856 if(Nevents1==0 && Nevents2==0)return;
2857 if(Nevents1==0){
2858 events1 = events2;
2859 events2.clear(); // clear queue
2860 return;
2861 }
2862 if(Nevents2==0)return;
2863
2864 // If we get here it means both events1 and events2 have events
2865 list<ObjList*>::iterator iter = events1.begin();
2866 for(; iter!=events1.end(); iter++){
2867 if(events2.empty()) break; // in case one has just config objects in a single event
2868 ObjList *objs1 = *iter;
2869 ObjList *objs2 = events2.front();
2870 events2.pop_front();
2871
2872 objs1->hit_objs.insert(objs1->hit_objs.end(), objs2->hit_objs.begin(), objs2->hit_objs.end());
2873 objs1->config_objs.insert(objs1->config_objs.end(), objs2->config_objs.begin(), objs2->config_objs.end());
2874 objs1->misc_objs.insert(objs1->misc_objs.end(), objs2->misc_objs.begin(), objs2->misc_objs.end());
2875
2876 // Delete the objs2 container
2877 delete objs2;
2878 }
2879
2880 // Clear out any references to objects in event2 (this should be redundant)
2881 events2.clear(); // clear queue
2882
2883 if(VERBOSE>5) evioout << " Leaving MergeObjLists(). &events1=" << hex << &events1 << " &events2=" << &events2 << dec << endl;
2884}
2885
2886//----------------
2887// ParseEVIOEvent
2888//----------------
2889void JEventSource_EVIO::ParseEVIOEvent(evioDOMTree *evt, list<ObjList*> &full_events)
2890{
2891 if(VERBOSE>5) evioout << " Entering ParseEVIOEvent() with evt=" << hex << evt << dec << endl;
2892
2893 if(!evt)throw RESOURCE_UNAVAILABLE;
2894
2895 // Since each bank contains parts of many events, have them fill in
2896 // the "tmp_events" list and then merge those into the "full_events".
2897 // It is done this way so each bank can grow tmp_events to the appropriate
2898 // size to hold the number of events it discovers in the bank. A check
2899 // can then be made that this is consistent with the number of event
2900 // fragments found in the other banks.
2901 //list<ObjList*> full_events;
2902 list<ObjList*> tmp_events;
2903
2904 // The Physics Event bank is the outermost bank of the event and
2905 // it is a bank of banks. One of those banks is the
2906 // "Built Trigger Bank" which is a bank of segments. The others
2907 // are the "Data Bank" banks which in turn contain the
2908 // "Data Block Bank" banks which hold the actual data. For the
2909 // mc2coda generated data files (and presumably the real data)
2910 // these Data Block Banks are banks of ints. More specifically,
2911 // uint32_t.
2912 //
2913 // The "Physics Event's Built Trigger Bank" is a bank of segments.
2914 // This contains 3 segments, one each of type uint64, uint16, and
2915 // unit32. The first two are "common data" which contains information
2916 // common to all rocs. The last (uint32) has information specific to each
2917 // event and for each ROC.
2918 //
2919 // For now, we skip parseing the Built Trigger Bank and just
2920 // look for Data Block Banks. We do this by getting a list of
2921 // all uint32_t banks in the enitries DOM Tree (at all levels
2922 // of the heirachy) and checking the parent banks for depth
2923 // and additional info.
2924
2925 // Loop over list of all EVIO banks at all levels of the tree and parse
2926 // them, creating data objects and adding them to the overall list.
2927 evioDOMNodeListP bankList = evt->getNodeList();
2928 evioDOMNodeList::iterator iter = bankList->begin();
2929 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EVIO event" << endl;
2930 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
2931
2932 if(VERBOSE>7) evioout << " -------- bank " << ibank << "/" << bankList->size() << " --------" << endl;
2933
2934 // The data banks we want should have exactly two parents:
2935 // - Data Bank bank <-- parent
2936 // - Physics Event bank <-- grandparent
2937 evioDOMNodeP bankPtr = *iter;
2938 evioDOMNodeP data_bank = bankPtr->getParent();
2939 if( data_bank==NULL__null ) {
2940 if(VERBOSE>9) evioout << " bank has no parent. Checking if it's an EPICS event ... " << endl;
2941
2942 if(bankPtr->tag==96 && bankPtr->num==1){
2943 // This looks like an EPICS event. Hand it over to EPICS parser
2944 ParseEPICSevent(bankPtr, full_events);
2945 }else{
2946 if(VERBOSE>9) evioout << " Not an EPICS event bank. skipping ... " << endl;
2947 }
2948
2949 continue;
2950 }
2951 evioDOMNodeP physics_event_bank = data_bank->getParent();
2952 if( physics_event_bank==NULL__null ){
2953 if(VERBOSE>6) evioout << " bank has no grandparent. Checking if this is a trigger bank ... " << endl;
2954
2955 // Check if this is a CODA Reserved Bank Tag. If it is, then
2956 // this probably is part of the built trigger bank and not
2957 // the ROC data we're looking to parse here.
2958 if((bankPtr->tag & 0xFF00) == 0xFF00){
2959 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;
2960 ParseBuiltTriggerBank(bankPtr, tmp_events);
2961 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
2962 MergeObjLists(full_events, tmp_events);
2963
2964 // Check if this is a DEventTag bank
2965 }else if(bankPtr->tag == 0x0056){
2966 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
2967 if(vec){
2968 const uint32_t *iptr = &(*vec)[0];
2969 const uint32_t *iend = &(*vec)[vec->size()];
2970 ParseEventTag(iptr, iend, tmp_events);
2971 if(VERBOSE>5) evioout << " Merging DEventTag objects in ParseEVIOEvent" << endl;
2972 MergeObjLists(full_events, tmp_events);
2973 }
2974 }
2975
2976 continue; // if this wasn't a trigger bank, then it has the wrong lineage to be a data bank
2977 }
2978 if( physics_event_bank->getParent() != NULL__null ){
2979 if(VERBOSE>9) evioout << " bank DOES have great-grandparent. skipping ... " << endl;
2980 continue; // physics event bank should have no parent!
2981 }
2982 if(VERBOSE>9){
2983 evioout << " Physics Event Bank: tag=" << hex << physics_event_bank->tag << " num=" << (int)physics_event_bank->num << dec << endl;
2984 evioout << " Data Bank: tag=" << hex << data_bank->tag << " num=" << (int)data_bank->num << dec << endl;
2985 }
2986
2987 if(VERBOSE>9) evioout << " bank lineage check OK. Continuing with parsing ... " << endl;
2988
2989 // Check if this is a CODA Reserved Bank Tag.
2990 if((data_bank->tag & 0xFF00) == 0xFF00){
2991 if(VERBOSE>6) evioout << " Data Bank tag="<<hex<<data_bank->tag<<dec<<" is in reserved CODA range. This is probably not ROC data"<< endl;
2992 continue;
2993 }
2994
2995 // Check if this is a TS Bank.
2996 if((bankPtr->tag & 0xFF00) == 0xEE00){
2997 if(VERBOSE>6) evioout << " TS bank tag="<<hex<<data_bank->tag<<dec<<" (not currently handled so skip to next bank)"<< endl;
2998 continue;
2999 }
3000
3001 // Get data from bank in the form of a vector of uint32_t
3002 const vector<uint32_t> *vec = bankPtr->getVector<uint32_t>();
3003 if(!vec){
3004 if(VERBOSE>6) evioout << " bank is not uint32_t. Skipping..." << endl;
3005 continue;
3006 }
3007 const uint32_t *iptr = &(*vec)[0];
3008 const uint32_t *iend = &(*vec)[vec->size()];
3009 if(VERBOSE>6) evioout << " uint32_t bank has " << vec->size() << " words" << endl;
3010
3011 // Extract ROC id (crate number) from bank's parent
3012 uint32_t rocid = data_bank->tag & 0x0FFF;
3013
3014 // If there are rocid's specified that we wish to parse, make sure this one
3015 // is in the list. Otherwise, skip it.
3016 if(!ROCIDS_TO_PARSE.empty()){
3017 if(VERBOSE>4) evioout << " Skipping parsing of rocid="<<rocid<<" due to it being in ROCIDS_TO_PARSE set." << endl;
3018 if(ROCIDS_TO_PARSE.find(rocid) == ROCIDS_TO_PARSE.end()) continue;
3019 }
3020
3021 // The number of events in block is stored in lower 8 bits
3022 // of header word (aka the "num") of Data Bank. This should
3023 // be at least 1.
3024 uint32_t NumEvents = data_bank->num & 0xFF;
3025 if( NumEvents<1 ){
3026 if(VERBOSE>9) evioout << " bank has less than 1 event (Data Bank num or \"M\" = 0) skipping ... " << endl;
3027 continue;
3028 }
3029
3030 // At this point iptr and iend indicate the data that came
3031 // from the ROC itself (all CODA headers have been stripped
3032 // away). Here, we need to decide what type of data this
3033 // bank contains. All JLab modules have a common block
3034 // header format and so are handled in a common way. Other
3035 // modules (e.g. CAEN) will have to appear in their own
3036 // EVIO bank and should be identified by their own det_id
3037 // value in the Data Block Bank.
3038 //
3039 // Current, preliminary thinking includes writing the type
3040 // of data into the 12-bit detector id contained in the
3041 // Data Block Bank of the DAQ group's "Event Building EVIO
3042 // Scheme". (This is the lower 12 bits of the "tag"). We
3043 // use this to decide if it is JLab module data or somehting
3044 // else.
3045 uint32_t det_id = bankPtr->tag & 0x0FFF;
3046 // Call appropriate parsing method
3047 bool bank_parsed = true; // will be set to false if default case is entered
3048 switch(det_id){
3049 case 0:
3050 case 1:
3051 case 3:
3052 case 6: // flash 250 module, MMD 2014/2/4
3053 case 16: // flash 125 module (CDC), DL 2014/6/19
3054 case 26: // F1 TDC module (BCAL), MMD 2014-07-31
3055 ParseJLabModuleData(rocid, iptr, iend, tmp_events);
3056 break;
3057
3058 case 20:
3059 ParseCAEN1190(rocid, iptr, iend, tmp_events);
3060 break;
3061
3062 case 0x55:
3063 ParseModuleConfiguration(rocid, iptr, iend, tmp_events);
3064 break;
3065
3066 case 5:
3067 // Beni's original CDC ROL used for the stand-alone CDC DAQ
3068 // had the following for the TS readout list (used in the TI):
3069 // *dma_dabufp++ = 0xcebaf111;
3070 // *dma_dabufp++ = tsGetIntCount();
3071 // *dma_dabufp++ = 0xdead;
3072 // *dma_dabufp++ = 0xcebaf222;
3073 // We skip this here, but put in the case so that we avoid errors
3074 break;
3075
3076
3077 default:
3078 jerr<<"Unknown module type ("<<det_id<<") encountered for tag="<<bankPtr->tag<<" num="<< (int)bankPtr->num << endl;
3079 bank_parsed = false;
3080 if(VERBOSE>5){
3081 cerr << endl;
3082 cout << "----- First few words to help with debugging -----" << endl;
3083 cout.flush(); cerr.flush();
3084 int i=0;
3085 for(const uint32_t *iiptr = iptr; iiptr<iend; iiptr++, i++){
3086 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3086<<" "
<< "0x" << hex << *iiptr << dec << endl;
3087 if(i>=8) break;
3088 }
3089
3090 }
3091 }
3092
3093 // Merge this bank's partial events into the full events
3094 if(bank_parsed){
3095 if(VERBOSE>5) evioout << " Merging objects in ParseEVIOEvent" << endl;
3096 MergeObjLists(full_events, tmp_events);
3097 }
3098 }
3099
3100 // Set the run number for all events
3101 uint32_t run_number = GetRunNumber(evt);
3102 list<ObjList*>::iterator evt_iter = full_events.begin();
3103 for(; evt_iter!=full_events.end(); evt_iter++){
3104 ObjList *objs = *evt_iter;
3105 objs->run_number = run_number;
3106 }
3107
3108 if(VERBOSE>5) evioout << " Leaving ParseEVIOEvent()" << endl;
3109}
3110
3111//----------------
3112// ParseBuiltTriggerBank
3113//----------------
3114void JEventSource_EVIO::ParseBuiltTriggerBank(evioDOMNodeP trigbank, list<ObjList*> &events)
3115{
3116 if(!PARSE_TRIGGER) return;
3117
3118 if(VERBOSE>5) evioout << " Entering ParseBuiltTriggerBank()" << endl;
3119
3120 uint32_t Mevents = 1; // number of events in block (will be overwritten below)
3121 uint32_t Nrocs = (uint32_t)trigbank->num; // number of rocs providing data in this bank
3122 evioDOMNodeP physics_event_bank = trigbank->getParent();
3123 if(physics_event_bank) Mevents = (uint32_t)physics_event_bank->num;
3124
3125 if(VERBOSE>6) evioout << " Mevents=" << Mevents << " Nrocs=" << Nrocs << endl;
3126
3127 // Some values to fill in while parsing the banks that will be used later to create objects
3128 vector<uint64_t> avg_timestamps;
3129 uint32_t run_number = 0;
3130 uint32_t run_type = 0;
3131 uint64_t first_event_num = 1;
3132 vector<uint16_t> event_types;
3133 map<uint32_t, vector<DCODAROCInfo*> > rocinfos; // key=event (from 0 to Mevents-1)
3134 //vector<map<uint32_t, DCODAROCInfo*> > rocinfos; // key=rocid
3135
3136 // Loop over children of built trigger bank
3137 evioDOMNodeListP bankList = trigbank->getChildren();
3138 evioDOMNodeList::iterator iter = bankList->begin();
3139 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){
3140
3141 if(VERBOSE>7) evioout << " Looking for data in child banks ..." << endl;
3142
3143 evioDOMNodeP bankPtr = *iter;
3144
3145 // The "Physics Event's Built Trigger Bank" is a bank of segments that
3146 // may contain banks of 3 data types: uint64_t, uint32_t, and uint16_t
3147 // The uint64_t contains the first event number, average timestamps, and
3148 // run number & types. The uint16_t contains the event type(s). The
3149 // uint32_t contains the optional ROC specific meta data starting with
3150 // the specific timestamp for each event. All of these have some options
3151 // on exactly what info is contained in the bank. The first check here is
3152 // on the data type the bank contains. At most, one of the following pointers
3153 // should be non-zero.
3154 vector<uint64_t> *vec64 = bankPtr->getVector<uint64_t>();
3155 vector<uint32_t> *vec32 = bankPtr->getVector<uint32_t>();
3156 vector<uint16_t> *vec16 = bankPtr->getVector<uint16_t>();
3157
3158 // unit64_t = common data (1st part)
3159 if(vec64){
3160
3161 if(VERBOSE>9) evioout << " found uint64_t data" << endl;
3162
3163 // In addition to the first event number (1st word) there are three
3164 // additional pieces of information that may be present:
3165 // t = average timestamp
3166 // r = run number and type
3167 // d = run specific data
3168 //
3169 // The last one ("d") comes in the form of multiple uint32_t banks
3170 // so is not included in vec64. The other two have their presence
3171 // signaled by bit 0(=t) and bit 1(=r) in the trigbank tag. (We can
3172 // also deduce this from the bank length.)
3173
3174 if(vec64->size() == 0) continue; // need debug message here!
3175
3176 first_event_num = (*vec64)[0];
3177
3178 uint32_t Ntimestamps = vec64->size()-1;
3179 if(Ntimestamps==0) continue; // no more words of interest
3180 if(trigbank->tag & 0x2) Ntimestamps--; // subtract 1 for run number/type word if present
3181 for(uint32_t i=0; i<Ntimestamps; i++) avg_timestamps.push_back((*vec64)[i+1]);
3182
3183 // run number and run type
3184 if(trigbank->tag & 0x02){
3185 run_number = (*vec64)[vec64->size()-1] >> 32;
3186 run_type = (*vec64)[vec64->size()-1] & 0xFFFFFFFF;
3187 }
3188 }
3189
3190 // uint16_t = common data (2nd part)
3191 if(vec16){
3192
3193 if(VERBOSE>9) evioout << " found uint16_t data" << endl;
3194
3195 for(uint32_t i=0; i<Mevents; i++){
3196 if(i>=vec16->size()) break;
3197 event_types.push_back((*vec16)[i]);
3198 }
3199 }
3200
3201 // uint32_t = inidivdual ROC timestamps and misc. roc-specfic data
3202 if(vec32){
3203
3204 if(VERBOSE>9) evioout << " found uint32_t data" << endl;
3205
3206 // Get pointer to DCODAROCInfo object for this rocid/event, instantiating it if necessary
3207 uint32_t rocid = (uint32_t)bankPtr->tag;
3208 uint32_t Nwords_per_event = vec32->size()/Mevents;
3209 if(vec32->size() != Mevents*Nwords_per_event){
3210 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3210<<" "
<< "Number of ROC data words in Trigger Bank inconsistent with header" << endl;
3211 exit(-1);
3212 }
3213
3214 uint32_t *iptr = &(*vec32)[0];
3215 for(uint32_t ievent=0; ievent<Mevents; ievent++){
3216
3217 DCODAROCInfo *codarocinfo = new DCODAROCInfo;
3218 codarocinfo->rocid = rocid;
3219
3220 uint64_t ts_low = *iptr++;
3221 uint64_t ts_high = *iptr++;
3222 codarocinfo->timestamp = (ts_high<<32) + ts_low;
3223 for(uint32_t i=2; i<Nwords_per_event; i++) codarocinfo->misc.push_back(*iptr++);
3224
3225 if(VERBOSE>7) evioout << " Adding DCODAROCInfo for rocid="<<rocid<< " with timestamp " << codarocinfo->timestamp << endl;
3226 rocinfos[ievent].push_back(codarocinfo);
3227 }
3228 }
3229 }
3230
3231 // Check that we have agreement on the number of events this data represents
3232 bool Nevent_mismatch = false;
3233 if(!avg_timestamps.empty()) Nevent_mismatch |= (avg_timestamps.size() != Mevents);
3234 if(!event_types.empty() ) Nevent_mismatch |= (event_types.size() != Mevents);
3235 if(!rocinfos.empty() ) Nevent_mismatch |= (rocinfos.size() != Mevents);
3236 if(Nevent_mismatch){
3237 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3237<<" "
<<"Mismatch in number of events in Trigger Bank!"<<endl;
3238 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3238<<" "
<<" Mevents="<<Mevents<<endl;
3239 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3239<<" "
<<" avg_timestamps.size()="<<avg_timestamps.size()<<endl;
3240 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3240<<" "
<<" event_types.size()="<<event_types.size()<<endl;
3241 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3241<<" "
<<" rocinfos.size()="<<rocinfos.size()<<endl;
3242 exit(-1);
3243 }
3244
3245 // Copy all objects into events
3246 for(uint32_t i=0; i<Mevents; i++){
3247 while(events.size()<=i){
3248 if(!ENABLE_DISENTANGLING && !events.empty()) break;
3249 events.push_back(new ObjList);
3250 }
3251 ObjList *objs = events.back();
3252
3253 DCODAEventInfo *codaeventinfo = new DCODAEventInfo;
3254 codaeventinfo->run_number = run_number;
3255 codaeventinfo->run_type = run_type;
3256 codaeventinfo->event_number = first_event_num + i;
3257 codaeventinfo->event_type = event_types.empty() ? 0:event_types[i];
3258 codaeventinfo->avg_timestamp = avg_timestamps.empty() ? 0:avg_timestamps[i];
3259 objs->misc_objs.push_back(codaeventinfo);
3260 objs->event_number = codaeventinfo->event_number;
3261
3262 vector<DCODAROCInfo*> &codarocinfos = rocinfos[i];
3263 for(uint32_t i=0; i<codarocinfos.size(); i++) objs->misc_objs.push_back(codarocinfos[i]);
3264 }
3265
3266 if(VERBOSE>6) evioout << " Found "<<events.size()<<" events in Built Trigger Bank"<< endl;
3267 if(VERBOSE>5) evioout << " Leaving ParseBuiltTriggerBank()" << endl;
3268}
3269
3270//----------------
3271// ParseModuleConfiguration
3272//----------------
3273void JEventSource_EVIO::ParseModuleConfiguration(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3274{
3275 if(!PARSE_CONFIG){ iptr = iend; return; }
3276
3277 if(VERBOSE>5) evioout << " Entering ParseModuleConfiguration() (events.size()="<<events.size()<<")" << endl;
3278
3279 /// Parse a bank of module configuration data. These are configuration values
3280 /// programmed into the module at the beginning of the run that may be needed
3281 /// in the offline. For example, the number of samples to sum in a FADC pulse
3282 /// integral.
3283 ///
3284 /// The bank has one or more sections, each describing parameters applicable
3285 /// to a number of modules as indicated by a 24bit slot mask.
3286 ///
3287 /// This bank should appear only once per DAQ event which, if in multi-event
3288 /// block mode, may have multiple L1 events. The parameters here will apply
3289 /// to all L1 events in the block. This method will put the config objects
3290 /// in the first event of "events", creating it if needed. The config objects
3291 /// are duplicated for all other events in the block later, after all event
3292 /// parsing is finished and the total number of events is known.
3293
3294 while(iptr < iend){
3295 uint32_t slot_mask = (*iptr) & 0xFFFFFF;
3296 uint32_t Nvals = ((*iptr) >> 24) & 0xFF;
3297 iptr++;
3298
3299 Df250Config *f250config = NULL__null;
3300 Df125Config *f125config = NULL__null;
3301 DF1TDCConfig *f1tdcconfig = NULL__null;
3302 DCAEN1290TDCConfig *caen1290tdcconfig = NULL__null;
3303
3304 // Loop over all parameters in this section
3305 for(uint32_t i=0; i< Nvals; i++){
3306 if( iptr >= iend){
3307 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3307<<" "
<< "DAQ Configuration bank corrupt! slot_mask=0x" << hex << slot_mask << dec << " Nvals="<< Nvals << endl;
3308 exit(-1);
3309 }
3310
3311 daq_param_type ptype = (daq_param_type)((*iptr)>>16);
3312 uint16_t val = (*iptr) & 0xFFFF;
3313
3314 if(VERBOSE>6) evioout << " DAQ parameter of type: 0x" << hex << ptype << dec << " found with value: " << val << endl;
3315
3316 // Create config object of correct type if needed and copy
3317 // parameter value into it.
3318 switch(ptype>>8){
3319
3320 // f250
3321 case 0x05:
3322 if( !f250config ) f250config = new Df250Config(rocid, slot_mask);
3323 switch(ptype){
3324 case kPARAM250_NSA : f250config->NSA = val; break;
3325 case kPARAM250_NSB : f250config->NSB = val; break;
3326 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3327 case kPARAM250_NPED : f250config->NPED = val; break;
3328 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3328<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3329 }
3330 break;
3331
3332 // f125
3333 case 0x0F:
3334 if( !f125config ) f125config = new Df125Config(rocid, slot_mask);
3335 switch(ptype){
3336 case kPARAM125_NSA : f125config->NSA = val; break;
3337 case kPARAM125_NSB : f125config->NSB = val; break;
3338 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3339 case kPARAM125_NPED : f125config->NPED = val; break;
3340 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3341 case kPARAM125_PL : f125config->PL = val; break;
3342 case kPARAM125_NW : f125config->NW = val; break;
3343 case kPARAM125_NPK : f125config->NPK = val; break;
3344 case kPARAM125_P1 : f125config->P1 = val; break;
3345 case kPARAM125_P2 : f125config->P2 = val; break;
3346 case kPARAM125_PG : f125config->PG = val; break;
3347 case kPARAM125_IE : f125config->IE = val; break;
3348 case kPARAM125_H : f125config->H = val; break;
3349 case kPARAM125_TH : f125config->TH = val; break;
3350 case kPARAM125_TL : f125config->TL = val; break;
3351 case kPARAM125_IBIT : f125config->IBIT = val; break;
3352 case kPARAM125_ABIT : f125config->ABIT = val; break;
3353 case kPARAM125_PBIT : f125config->PBIT = val; break;
3354 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3354<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3355 }
3356 break;
3357
3358 // F1TDC
3359 case 0x06:
3360 if( !f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask);
3361 switch(ptype){
3362 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3363 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3364 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3365 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3366 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3367 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3368 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3368<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3369 }
3370 break;
3371
3372 // caen1290
3373 case 0x10:
3374 if( !caen1290tdcconfig ) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask);
3375 switch(ptype){
3376 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3377 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3378 default: _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3378<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3379 }
3380 break;
3381
3382 default:
3383 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3383<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3384 exit(-1);
3385 }
3386
3387#if 0
3388 // Create config object of correct type if needed. (Only one type
3389 // should be created per section!)
3390 switch(ptype>>8){
3391 case 0x05: if(!f250config ) f250config = new Df250Config(rocid, slot_mask); break;
3392 case 0x0F: if(!f125config ) f125config = new Df125Config(rocid, slot_mask); break;
3393 case 0x06: if(!f1tdcconfig ) f1tdcconfig = new DF1TDCConfig(rocid, slot_mask); break;
3394 case 0x10: if(!caen1290tdcconfig) caen1290tdcconfig = new DCAEN1290TDCConfig(rocid, slot_mask); break;
3395 default:
3396 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3396<<" "
<< "Unknown module type: 0x" << hex << (ptype>>8) << endl;
3397 exit(-1);
3398 }
3399
3400 // Copy parameter into config. object
3401 switch(ptype){
3402 case kPARAM250_NSA : f250config->NSA = val; break;
3403 case kPARAM250_NSB : f250config->NSB = val; break;
3404 case kPARAM250_NSA_NSB : f250config->NSA_NSB = val; break;
3405 case kPARAM250_NPED : f250config->NPED = val; break;
3406
3407 case kPARAM125_NSA : f125config->NSA = val; break;
3408 case kPARAM125_NSB : f125config->NSB = val; break;
3409 case kPARAM125_NSA_NSB : f125config->NSA_NSB = val; break;
3410 case kPARAM125_NPED : f125config->NPED = val; break;
3411 case kPARAM125_WINWIDTH : f125config->WINWIDTH = val; break;
3412 case kPARAM125_PL : f125config->PL = val; break;
3413 case kPARAM125_NW : f125config->NW = val; break;
3414 case kPARAM125_NPK : f125config->NPK = val; break;
3415 case kPARAM125_P1 : f125config->P1 = val; break;
3416 case kPARAM125_P2 : f125config->P2 = val; break;
3417 case kPARAM125_PG : f125config->PG = val; break;
3418 case kPARAM125_IE : f125config->IE = val; break;
3419 case kPARAM125_H : f125config->H = val; break;
3420 case kPARAM125_TH : f125config->TH = val; break;
3421 case kPARAM125_TL : f125config->TL = val; break;
3422 case kPARAM125_IBIT : f125config->IBIT = val; break;
3423 case kPARAM125_ABIT : f125config->ABIT = val; break;
3424 case kPARAM125_PBIT : f125config->PBIT = val; break;
3425
3426 case kPARAMF1_REFCNT : f1tdcconfig->REFCNT = val; break;
3427 case kPARAMF1_TRIGWIN : f1tdcconfig->TRIGWIN = val; break;
3428 case kPARAMF1_TRIGLAT : f1tdcconfig->TRIGLAT = val; break;
3429 case kPARAMF1_HSDIV : f1tdcconfig->HSDIV = val; break;
3430 case kPARAMF1_BINSIZE : f1tdcconfig->BINSIZE = val; break;
3431 case kPARAMF1_REFCLKDIV : f1tdcconfig->REFCLKDIV = val; break;
3432
3433 case kPARAMCAEN1290_WINWIDTH : caen1290tdcconfig->WINWIDTH = val; break;
3434 case kPARAMCAEN1290_WINOFFSET : caen1290tdcconfig->WINOFFSET = val; break;
3435
3436 default:
3437 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<3437<<" "
<< "UNKNOWN DAQ Config Parameter type: 0x" << hex << ptype << dec << endl;
3438 }
3439#endif
3440
3441 iptr++;
3442 }
3443
3444 // If we get here it means we didn't exit in the switch(ptype>>16) statement above
3445 // so there is at least one DDAQConfig object we need to store. Get pointer to
3446 // first event's ObjList, creating it if needed.
3447 if(events.empty()) events.push_back(new ObjList());
3448 ObjList *objs = *(events.begin());
3449
3450 if(f250config ) objs->config_objs.push_back(f250config );
3451 if(f125config ) objs->config_objs.push_back(f125config );
3452 if(f1tdcconfig ) objs->config_objs.push_back(f1tdcconfig );
3453 if(caen1290tdcconfig) objs->config_objs.push_back(caen1290tdcconfig);
3454 }
3455
3456 if(VERBOSE>5) evioout << " Leaving ParseModuleConfiguration()" << endl;
3457}
3458
3459//----------------
3460// ParseEventTag
3461//----------------
3462void JEventSource_EVIO::ParseEventTag(const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3463{
3464 if(!PARSE_EVENTTAG){ iptr = iend; return; }
3465
3466 if(VERBOSE>5) evioout << " Entering ParseEventTag() (events.size()="<<events.size()<<")" << endl;
3467
3468 // Make sure there is one event in the event container
3469 // and get pointer to it.
3470 if(events.empty()) events.push_back(new ObjList());
3471 ObjList *objs = *(events.begin());
3472
3473
3474 DEventTag *etag = new DEventTag;
3475
3476 // event_status
3477 uint64_t lo = *iptr++;
3478 uint64_t hi = *iptr++;
3479 etag->event_status = (hi<<32) + lo;
3480
3481 // L3_status
3482 lo = *iptr++;
3483 hi = *iptr++;
3484 etag->L3_status = (hi<<32) + lo;
3485
3486 // L3_decision
3487 etag->L3_decision = (DL3Trigger::L3_decision_t)*iptr++;
3488
3489 // L3_algorithm
3490 etag->L3_algorithm = *iptr++;
3491
3492 objs->misc_objs.push_back(etag);
3493
3494
3495 if(VERBOSE>5) evioout << " Leaving ParseEventTag()" << endl;
3496}
3497
3498//----------------
3499// ParseJLabModuleData
3500//----------------
3501void JEventSource_EVIO::ParseJLabModuleData(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3502{
3503 if(VERBOSE>5) evioout << " Entering ParseJLabModuleData()" << endl;
3504
3505 /// Parse a bank of data coming from one or more JLab modules.
3506 /// The data are assumed to follow the standard JLab format for
3507 /// block headers. If multiple modules are read out in a single
3508 /// chain block transfer, then the data will all be placed in
3509 /// a single EVIO bank and this will loop over the modules.
3510 while(iptr < iend){
3511
3512 if(VERBOSE>9) evioout << "Parsing word: " << hex << *iptr << dec << endl;
3513
3514 // This was observed in some CDC data. Not sure where it came from ...
3515 if(*iptr == 0xF800FAFA){
3516 if(VERBOSE>9) evioout << " 0xf800fafa is a known extra word. Skipping it ..." << endl;
3517 iptr++;
3518 continue;
3519 }
3520
3521 // Get module type from next word (bits 18-21)
3522 uint32_t mod_id = ((*iptr) >> 18) & 0x000F;
3523
3524 // The enum defined in DModuleType.h MUST be kept in alignment
3525 // with the DAQ group's definitions for modules types!
3526 MODULE_TYPE type = (MODULE_TYPE)mod_id;
3527 if(VERBOSE>5) evioout << " Encountered module type: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3528
3529 if(modtype_translate.find(type) != modtype_translate.end()){
3530 type = modtype_translate[type];
3531 if(VERBOSE>5) evioout << " switched module type to: " << type << " (=" << DModuleType::GetModule(type).GetName() << ")" << endl;
3532 }
3533
3534 // Parse buffer depending on module type
3535 // (Note that each of the ParseXXX routines called below will
3536 // update the "iptr" variable to point to the next word
3537 // after the block it parsed.)
3538 list<ObjList*> tmp_events;
3539 const uint32_t *istart=iptr; // just for UNKNOWN case below
3540 bool module_parsed = true;
3541 switch(type){
3542 case DModuleType::FADC250:
3543 Parsef250Bank(rocid, iptr, iend, tmp_events);
3544 break;
3545
3546 case DModuleType::FADC125:
3547 Parsef125Bank(rocid, iptr, iend, tmp_events);
3548 break;
3549
3550 case DModuleType::F1TDC32:
3551 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3552 break;
3553
3554 case DModuleType::F1TDC48:
3555 ParseF1TDCBank(rocid, iptr, iend, tmp_events);
3556 break;
3557
3558 case DModuleType::JLAB_TS:
3559 ParseTSBank(rocid, iptr, iend, tmp_events);
3560 break;
3561
3562 case DModuleType::TID:
3563 ParseTIBank(rocid, iptr, iend, tmp_events);
3564 break;
3565
3566 case DModuleType::UNKNOWN:
3567 default:
3568 jerr<<"Unknown module type ("<<mod_id<<") iptr=0x" << hex << iptr << dec << endl;
3569
3570 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
3571 iptr++; // advance past JLab block trailer
3572 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
3573 module_parsed = false;
3574 jerr<<"...skipping to 0x" << hex << iptr << dec << " (discarding " << (((uint64_t)iptr-(uint64_t)istart)/4) << " words)" << endl;
3575 break;
3576 }
3577
3578 if(VERBOSE>9) evioout << "Finished parsing (last word: " << hex << iptr[-1] << dec << ")" << endl;
3579
3580 if(module_parsed){
3581 if(VERBOSE>5) evioout << " Merging objects in ParseJLabModuleData" << endl;
3582 MergeObjLists(events, tmp_events);
3583 }
3584 }
3585
3586 if(VERBOSE>5) evioout << " Leaving ParseJLabModuleData()" << endl;
3587}
3588
3589//----------------
3590// Parsef250Bank
3591//----------------
3592void JEventSource_EVIO::Parsef250Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
3593{
3594 /// Parse data from a single FADC250 module.
3595
3596 if(!PARSE_F250){ iptr = iend; return; }
3597
3598 // This will get updated to point to a newly allocated object when an
3599 // event header is encountered. The existing value (if non-NULL) is
3600 // added to the events queue first though so all events are kept.
3601 ObjList *objs = NULL__null;
3602
3603 // From the Block Header
3604 uint32_t slot=0;
3605 //uint32_t Nblock_events;
3606 //uint32_t iblock;
3607
3608 // From the Block Trailer
3609 //uint32_t slot_trailer;
3610 //uint32_t Nwords_in_block;
3611
3612 // From Event header
3613 //uint32_t slot_event_header;
3614 uint32_t itrigger = -1;
3615 uint32_t last_itrigger = -2;
3616
3617 // Loop over data words
3618 for(; iptr<iend; iptr++){
3619
3620 // Skip all non-data-type-defining words at this
3621 // level. When we do encounter one, the appropriate
3622 // case block below should handle parsing all of
3623 // the data continuation words and advance the iptr.
3624 if(((*iptr>>31) & 0x1) == 0)continue;
3625
3626 // Variables used inside of switch, but cannot be declared inside
3627 uint64_t t = 0L;
3628 uint32_t channel = 0;
3629 uint32_t sum = 0;
3630 uint32_t pulse_number = 0;
3631 uint32_t quality_factor = 0;
3632 uint32_t pulse_time = 0;
3633 uint32_t pedestal = 0;
3634 uint32_t pulse_peak = 0;
3635 uint32_t nsamples_integral = 0;
3636 uint32_t nsamples_pedestal = 0;
3637 bool overflow = false;
3638
3639 bool found_block_trailer = false;
3640 uint32_t data_type = (*iptr>>27) & 0x0F;
3641 switch(data_type){
3642 case 0: // Block Header
3643 slot = (*iptr>>22) & 0x1F;
3644 if(VERBOSE>7) evioout << " FADC250 Block Header: slot="<<slot<<endl;
3645 //iblock= (*iptr>>8) & 0x03FF;
3646 //Nblock_events= (*iptr>>0) & 0xFF;
3647 break;
3648 case 1: // Block Trailer
3649 //slot_trailer = (*iptr>>22) & 0x1F;
3650 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
3651 if(VERBOSE>7) evioout << " FADC250 Block Trailer"<<endl;
3652 found_block_trailer = true;
3653 break;
3654 case 2: // Event Header
3655 //slot_event_header = (*iptr>>22) & 0x1F;
3656 itrigger = (*iptr>>0) & 0x3FFFFF;
3657 if(VERBOSE>7) evioout << " FADC250 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
3658 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
3659 if(ENABLE_DISENTANGLING){
3660 if(objs){
3661 events.push_back(objs);
3662 objs = NULL__null;
3663 }
3664 }
3665 if(!objs) objs = new ObjList;
3666 last_itrigger = itrigger;
3667 }
3668 break;
3669 case 3: // Trigger Time
3670 t = ((*iptr)&0xFFFFFF)<<0;
3671 if(VERBOSE>7) evioout << " FADC250 Trigger Time: t="<<t<<endl;
3672 iptr++;
3673 if(((*iptr>>31) & 0x1) == 0){
3674 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
3675 }else{
3676 iptr--;
3677 }
3678 if(objs) objs->hit_objs.push_back(new Df250TriggerTime(rocid, slot, itrigger, t));
3679 break;
3680 case 4: // Window Raw Data
3681 // iptr passed by reference and so will be updated automatically
3682 if(VERBOSE>7) evioout << " FADC250 Window Raw Data"<<endl;
3683 MakeDf250WindowRawData(objs, rocid, slot, itrigger, iptr);
3684 break;
3685 case 5: // Window Sum
3686 channel = (*iptr>>23) & 0x0F;
3687 sum = (*iptr>>0) & 0x3FFFFF;
3688 overflow = (*iptr>>22) & 0x1;
3689 if(VERBOSE>7) evioout << " FADC250 Window Sum"<<endl;
3690 if(objs) objs->hit_objs.push_back(new Df250WindowSum(rocid, slot, channel, itrigger, sum, overflow));
3691 break;
3692 case 6: // Pulse Raw Data
3693 // iptr passed by reference and so will be updated automatically
3694 if(VERBOSE>7) evioout << " FADC250 Pulse Raw Data"<<endl;
3695 MakeDf250PulseRawData(objs, rocid, slot, itrigger, iptr);
3696 break;
3697 case 7: // Pulse Integral
3698 channel = (*iptr>>23) & 0x0F;
3699 pulse_number = (*iptr>>21) & 0x03;
3700 quality_factor = (*iptr>>19) & 0x03;
3701 sum = (*iptr>>0) & 0x7FFFF;
3702 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
3703 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
3704 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
3705 if(VERBOSE>7) evioout << " FADC250 Pulse Integral: chan="<<channel<<" pulse_number="<<pulse_number<<" sum="<<sum<<endl;
3706 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) ) {
3707 objs->hit_objs.push_back(new Df250PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
3708 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
3709 }
3710 break;
3711 case 8: // Pulse Time
3712 channel = (*iptr>>23) & 0x0F;
3713 pulse_number = (*iptr>>21) & 0x03;
3714 quality_factor = (*iptr>>19) & 0x03;
3715 pulse_time = (*iptr>>0) & 0x7FFFF;
3716 if(VERBOSE>7) evioout << " FADC250 Pulse Time: chan="<<channel<<" pulse_number="<<pulse_number<<" pulse_time="<<pulse_time<<endl;
3717 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) && (F250_PT_EMULATION_MODE!=kEmulationAlways)) {
3718 objs->hit_objs.push_back(new Df250PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
3719 }
3720 break;
3721 case 9: // Streaming Raw Data
3722 // This is marked "reserved for future implementation" in the current manual (v2).
3723 // As such, we don't try handling it here just yet.
3724 if(VERBOSE>7) evioout << " FADC250 Streaming Raw Data (unsupported)"<<endl;
3725 break;
3726 case 10: // Pulse Pedestal
3727 channel = (*iptr>>23) & 0x0F;
3728 pulse_number = (*iptr>>21) & 0x03;
3729 pedestal = (*iptr>>12) & 0x1FF;
3730 pulse_peak = (*iptr>>0) & 0xFFF;
3731 if(VERBOSE>7) evioout << " FADC250 Pulse Pedestal chan="<<channel<<" pulse_number="<<pulse_number<<" pedestal="<<pedestal<<" pulse_peak="<<pulse_peak<<endl;
3732 if( (objs!=NULL__null) && (pulse_number<F250PULSE_NUMBER_FILTER) && (F250_PP_EMULATION_MODE!=kEmulationAlways)) {
3733 objs->hit_objs.push_back(new Df250PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak));
3734 }
3735 break;
3736 case 13: // Event Trailer
3737 // This is marked "suppressed for normal readout – debug mode only" in the
3738 // current manual (v2). It does not contain any data so the most we could do here
3739 // is return early. I'm hesitant to do that though since it would mean
3740 // different behavior for debug mode data as regular data.
3741 case 14: // Data not valid (empty module)
3742 case 15: // Filler (non-data) word
3743 if(VERBOSE>7) evioout << " FADC250 Event Trailer, Data not Valid, or Filler word ("<<data_type<<")"<<endl;
3744 break;
3745 }
3746
3747 // Once we find a block trailer, assume that is it for this module.
3748 if(found_block_trailer){
3749 iptr++; // iptr is still pointing to block trailer. Jump to next word.
3750 break;
3751 }
3752 }
3753
3754 // Chop off filler words
3755 for(; iptr<iend; iptr++){
3756 if(((*iptr)&0xf8000000) != 0xf8000000) break;
3757 }
3758
3759 // Add last event in block to list
3760 if(objs)events.push_back(objs);
3761
3762 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
3763 // objects to each other so it is easier to get to these downstream without having to
3764 // make nested loops. This is the most efficient place to do it since the ObjList objects
3765 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
3766 // worth.)
3767 list<ObjList*>::iterator iter = events.begin();
3768 for(; iter!=events.end(); iter++){
3769
3770 // Sort list of objects into type-specific lists
3771 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
3772 vector<Df250TriggerTime*> vtrigt;
3773 vector<Df250WindowRawData*> vwrd;
3774 vector<Df250WindowSum*> vws;
3775 vector<Df250PulseRawData*> vprd;
3776 vector<Df250PulseIntegral*> vpi;
3777 vector<Df250PulseTime*> vpt;
3778 vector<Df250PulsePedestal*> vpp;
3779 for(unsigned int i=0; i<hit_objs.size(); i++){
3780 AddIfAppropriate(hit_objs[i], vtrigt);
3781 AddIfAppropriate(hit_objs[i], vwrd);
3782 AddIfAppropriate(hit_objs[i], vws);
3783 AddIfAppropriate(hit_objs[i], vprd);
3784 AddIfAppropriate(hit_objs[i], vpi);
3785 AddIfAppropriate(hit_objs[i], vpt);
3786 AddIfAppropriate(hit_objs[i], vpp);
3787 }
3788
3789 // Connect Df250PulseIntegral, Df250PulseTime, and
3790 // Df250PulsePedestal with Df250PulseRawData
3791 // (n.b. the associations between pi, pt, and pp are
3792 // done in GetObjects where emulated objects are
3793 // also available.)
3794 LinkAssociationsWithPulseNumber(vprd, vpi);
3795 LinkAssociationsWithPulseNumber(vprd, vpt);
3796 LinkAssociationsWithPulseNumber(vprd, vpp);
3797
3798 // Connect Df250WindowSum and Df250WindowRawData
3799 LinkAssociations(vwrd, vws);
3800
3801 // Connect Df250TriggerTime to everything
3802 LinkAssociationsModuleOnly(vtrigt, vwrd);
3803 LinkAssociationsModuleOnly(vtrigt, vws);
3804 LinkAssociationsModuleOnly(vtrigt, vprd);
3805 LinkAssociationsModuleOnly(vtrigt, vpi);
3806 LinkAssociationsModuleOnly(vtrigt, vpt);
3807 LinkAssociationsModuleOnly(vtrigt, vpp);
3808 }
3809}
3810
3811//----------------
3812// MakeDf250WindowRawData
3813//----------------
3814void JEventSource_EVIO::MakeDf250WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3815{
3816 uint32_t channel = (*iptr>>23) & 0x0F;
3817 uint32_t window_width = (*iptr>>0) & 0x0FFF;
3818
3819 Df250WindowRawData *wrd = new Df250WindowRawData(rocid, slot, channel, itrigger);
3820
3821 for(uint32_t isample=0; isample<window_width; isample +=2){
3822
3823 // Advance to next word
3824 iptr++;
3825
3826 // Make sure this is a data continuation word, if not, stop here
3827 if(((*iptr>>31) & 0x1) != 0x0){
3828 iptr--; // calling method expects us to point to last word in block
3829 break;
3830 }
3831
3832 bool invalid_1 = (*iptr>>29) & 0x1;
3833 bool invalid_2 = (*iptr>>13) & 0x1;
3834 uint16_t sample_1 = 0;
3835 uint16_t sample_2 = 0;
3836 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3837 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3838
3839 // Sample 1
3840 wrd->samples.push_back(sample_1);
3841 wrd->invalid_samples |= invalid_1;
3842 wrd->overflow |= (sample_1>>12) & 0x1;
3843
3844 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
3845
3846 // Sample 2
3847 wrd->samples.push_back(sample_2);
3848 wrd->invalid_samples |= invalid_2;
3849 wrd->overflow |= (sample_2>>12) & 0x1;
3850 }
3851
3852 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3853 // This will happen if a Window Raw Data block is encountered before an event header.
3854 // For these cases, we still want to try parsing the data so that the iptr is updated
3855 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3856 // the list. Otherwise, delete it now.
3857 if(objs){
3858 objs->hit_objs.push_back(wrd);
3859 }else{
3860 delete wrd;
3861 }
3862}
3863
3864//----------------
3865// MakeDf250PulseRawData
3866//----------------
3867void JEventSource_EVIO::MakeDf250PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
3868{
3869 const uint32_t *istart = iptr;
3870 uint32_t channel = (*iptr>>23) & 0x0F;
3871 uint32_t pulse_number = (*iptr>>21) & 0x0003;
3872 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
3873
3874 if(VERBOSE>9) evioout << " DF250PulseRawData: iptr=0x" << hex << iptr << dec << " channel=" << channel << " pulse_number=" << pulse_number << " first_sample=" << first_sample_number << endl;
3875
3876 Df250PulseRawData *prd = new Df250PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
3877
3878 // This loop needs to break when it hits a non-continuation word
3879 for(uint32_t isample=0; isample<1000; isample +=2){
3880
3881 // Advance to next word
3882 iptr++;
3883
3884 // Make sure this is a data continuation word, if not, stop here
3885 if(((*iptr>>31) & 0x1) != 0x0)break;
3886
3887 bool invalid_1 = (*iptr>>29) & 0x1;
3888 bool invalid_2 = (*iptr>>13) & 0x1;
3889 uint16_t sample_1 = 0;
3890 uint16_t sample_2 = 0;
3891 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
3892 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
3893
3894 // Sample 1
3895 prd->samples.push_back(sample_1);
3896 prd->invalid_samples |= invalid_1;
3897 prd->overflow |= (sample_1>>12) & 0x1;
3898
3899 bool last_word = (iptr[1]>>31) & 0x1;
3900 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
3901
3902 // Sample 2
3903 prd->samples.push_back(sample_2);
3904 prd->invalid_samples |= invalid_2;
3905 prd->overflow |= (sample_2>>12) & 0x1;
3906 }
3907
3908 if(VERBOSE>9) evioout << " number of samples: " << prd->samples.size() << " words processed: " << iptr-istart << endl;
3909
3910 // When should get here because the loop above stopped when it found
3911 // a data defining word (bit 31=1). The method calling this one will
3912 // assume iptr is pointing to the last word of this block and it will
3913 // advance to the first word of the next block. We need to back up one
3914 // word so that it is pointing to the last word of this block.
3915 iptr--;
3916
3917 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
3918 // This will happen if a Window Raw Data block is encountered before an event header.
3919 // For these cases, we still want to try parsing the data so that the iptr is updated
3920 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
3921 // the list. Otherwise, delete it now.
3922 if(objs){
3923 objs->hit_objs.push_back(prd);
3924 }else{
3925 delete prd;
3926 }
3927}
3928
3929//----------------
3930// Parsef125Bank
3931//----------------
3932void JEventSource_EVIO::Parsef125Bank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
3933{
3934 /// Parse data from a single FADC125 module.
3935 /// This is currently written assuming that the Pulse Integral, Pulse Time, and Pulse Pedestal
3936 /// data formats follow what is in the file:
3937 /// https://halldweb1.jlab.org/wiki/index.php/File:FADC125_dataformat_250_modes.docx
3938
3939 if(!PARSE_F125){ iptr = iend; return; }
3940
3941 if(VERBOSE>6) evioout << " Entering Parsef125Bank for rocid=" << rocid << "..."<<endl;
3942
3943 // This will get updated to point to a newly allocated object when an
3944 // event header is encountered. The existing value (if non-NULL) is
3945 // added to the events queue first though so all events are kept.
3946 ObjList *objs = NULL__null;
3947
3948 // From the Block Header
3949 uint32_t slot=0;
3950 //uint32_t Nblock_events;
3951 //uint32_t iblock;
3952
3953 // From the Block Trailer
3954 //uint32_t slot_trailer;
3955 //uint32_t Nwords_in_block;
3956
3957 // From Event header
3958 //uint32_t slot_event_header;
3959 uint32_t itrigger = -1;
3960 uint32_t last_itrigger = -2;
3961 uint32_t last_pulse_time_channel=0;
3962 uint32_t last_slot = -1;
3963 uint32_t last_channel = -1;
3964
3965 // Loop over data words
3966 for(; iptr<iend; iptr++){
3967
3968 // Skip all non-data-type-defining words at this
3969 // level. When we do encounter one, the appropriate
3970 // case block below should handle parsing all of
3971 // the data continuation words and advance the iptr.
3972 if(((*iptr>>31) & 0x1) == 0)continue;
3973
3974 // Variables used inside of switch, but cannot be declared inside
3975 uint64_t t = 0L;
3976 uint32_t channel = 0;
3977 uint32_t sum = 0;
3978 uint32_t pulse_number = 0;
3979 uint32_t pulse_time = 0;
3980 uint32_t quality_factor = 0;
3981 uint32_t overflow_count = 0;
3982 uint32_t pedestal = 0;
3983 uint32_t pulse_peak = 0;
3984 uint32_t peak_time = 0;
3985 uint32_t nsamples_integral = 0;
3986 uint32_t nsamples_pedestal = 0;
3987 uint32_t word1=0;
3988 uint32_t word2=0;
3989
3990 bool found_block_trailer = false;
3991 uint32_t data_type = (*iptr>>27) & 0x0F;
3992 switch(data_type){
3993 case 0: // Block Header
3994 slot = (*iptr>>22) & 0x1F;
3995 if(VERBOSE>7) evioout << " FADC125 Block Header: slot="<<slot<<endl;
3996 //iblock= (*iptr>>8) & 0x03FF;
3997 //Nblock_events= (*iptr>>0) & 0xFF;
3998 break;
3999 case 1: // Block Trailer
4000 //slot_trailer = (*iptr>>22) & 0x1F;
4001 //Nwords_in_block = (*iptr>>0) & 0x3FFFFF;
4002 found_block_trailer = true;
4003 break;
4004 case 2: // Event Header
4005 //slot_event_header = (*iptr>>22) & 0x1F;
4006 itrigger = (*iptr>>0) & 0x3FFFFFF;
4007 if(VERBOSE>7) evioout << " FADC125 Event Header: itrigger="<<itrigger<<" (objs=0x"<<hex<<objs<<dec<<", last_itrigger="<<last_itrigger<<", rocid="<<rocid<<", slot="<<slot<<")" <<endl;
4008 if( (itrigger!=last_itrigger) || (objs==NULL__null) ){
4009 if(ENABLE_DISENTANGLING){
4010 if(objs){
4011 events.push_back(objs);
4012 objs = NULL__null;
4013 }
4014 }
4015 if(!objs) objs = new ObjList;
4016 last_itrigger = itrigger;
4017 }
4018 break;
4019 case 3: // Trigger Time
4020 t = ((*iptr)&0xFFFFFF)<<0;
4021 iptr++;
4022 if(((*iptr>>31) & 0x1) == 0){
4023 t += ((*iptr)&0xFFFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4024 }else{
4025 iptr--;
4026 }
4027 if(VERBOSE>7) evioout << " FADC125 Trigger Time (t="<<t<<")"<<endl;
4028 if(objs) objs->hit_objs.push_back(new Df125TriggerTime(rocid, slot, itrigger, t));
4029 break;
4030 case 4: // Window Raw Data
4031 // iptr passed by reference and so will be updated automatically
4032 if(VERBOSE>7) evioout << " FADC125 Window Raw Data"<<endl;
4033 MakeDf125WindowRawData(objs, rocid, slot, itrigger, iptr);
4034 break;
4035
4036 case 5: // CDC pulse data (new) (GlueX-doc-2274-v8)
4037
4038 // Word 1:
4039 word1 = *iptr;
4040 channel = (*iptr>>20) & 0x7F;
4041 pulse_number = (*iptr>>15) & 0x1F;
4042 pulse_time = (*iptr>>4 ) & 0x7FF;
4043 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4044 overflow_count = (*iptr>>0 ) & 0x7;
4045 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word1: " << hex << (*iptr) << dec << endl;
4046 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4047
4048 // Word 2:
4049 ++iptr;
4050 if(iptr>=iend){
4051 jerr << " Truncated f125 CDC hit (block ends before continuation word!)" << endl;
4052 continue;
4053 }
4054 if( ((*iptr>>31) & 0x1) != 0 ){
4055 jerr << " Truncated f125 CDC hit (missing continuation word!)" << endl;
4056 continue;
4057 }
4058 word2 = *iptr;
4059 pedestal = (*iptr>>23) & 0xFF;
4060 sum = (*iptr>>9 ) & 0x3FFF;
4061 pulse_peak = (*iptr>>0 ) & 0x1FF;
4062 if(VERBOSE>8) evioout << " FADC125 CDC Pulse Data word2: " << hex << (*iptr) << dec << endl;
4063 if(VERBOSE>7) evioout << " FADC125 CDC Pulse Data (pedestal="<<pedestal<<" sum="<<sum<<" peak="<<pulse_peak<<")"<<endl;
4064
4065 // Create hit objects
4066 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4067 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4068
4069 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4070 // n.b. This is were we might apply a check on whether we are
4071 // only producing emulated objects. If so, then we shouldn't
4072 // create the Df125CDCPulse. At this point in time though,
4073 // there are 3 config. parameters that control this because
4074 // the original firmware produced 3 separate data types as
4075 // opposed to the new firmware that puts the same infomation
4076 // into a single data type. The emulation framework is also
4077 // being revamped.
4078 objs->hit_objs.push_back( new Df125CDCPulse(rocid, slot, channel, itrigger
4079 , pulse_number // NPK
4080 , pulse_time // le_time
4081 , quality_factor // time_quality_bit
4082 , overflow_count // overflow_count
4083 , pedestal // pedestal
4084 , sum // integral
4085 , pulse_peak // first_max_amp
4086 , word1 // word1
4087 , word2 // word2
4088 , nsamples_pedestal // nsamples_pedestal
4089 , nsamples_integral // nsamples_integral
4090 , false) // emulated
4091 );
4092 }
4093
4094 // n.b. We don't record last_slot, last_channel, etc... here since those
4095 // are only used by data types corresponding to older firmware that did
4096 // not write out data type 5.
4097 break;
4098
4099 case 6: // FDC pulse data-integral (new) (GlueX-doc-2274-v8)
4100
4101 // Word 1:
4102 word1 = *iptr;
4103 channel = (*iptr>>20) & 0x7F;
4104 pulse_number = (*iptr>>15) & 0x1F;
4105 pulse_time = (*iptr>>4 ) & 0x7FF;
4106 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4107 overflow_count = (*iptr>>0 ) & 0x7;
4108 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word1: " << hex << (*iptr) << dec << endl;
4109 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4110
4111 // Word 2:
4112 ++iptr;
4113 if(iptr>=iend){
4114 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4115 continue;
4116 }
4117 if( ((*iptr>>31) & 0x1) != 0 ){
4118 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4119 continue;
4120 }
4121 word2 = *iptr;
4122 pulse_peak = 0;
4123 sum = (*iptr>>19) & 0xFFF;
4124 peak_time = (*iptr>>11) & 0xFF;
4125 pedestal = (*iptr>>0 ) & 0x7FF;
4126 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(integral) word2: " << hex << (*iptr) << dec << endl;
4127 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4128
4129 // Create hit objects
4130 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4131 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4132
4133 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4134 // n.b. This is were we might apply a check on whether we are
4135 // only producing emulated objects. If so, then we shouldn't
4136 // create the Df125FDCPulse. At this point in time though,
4137 // there are 3 config. parameters that control this because
4138 // the original firmware produced 3 separate data types as
4139 // opposed to the new firmware that puts the same infomation
4140 // into a single data type. The emulation framework is also
4141 // being revamped.
4142 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4143 , pulse_number // NPK
4144 , pulse_time // le_time
4145 , quality_factor // time_quality_bit
4146 , overflow_count // overflow_count
4147 , pedestal // pedestal
4148 , sum // integral
4149 , pulse_peak // peak_amp
4150 , peak_time // peak_time
4151 , word1 // word1
4152 , word2 // word2
4153 , nsamples_pedestal // nsamples_pedestal
4154 , nsamples_integral // nsamples_integral
4155 , false) // emulated
4156 );
4157 }
4158
4159 // n.b. We don't record last_slot, last_channel, etc... here since those
4160 // are only used by data types corresponding to older firmware that did
4161 // not write out data type 6.
4162 break;
4163
4164 case 7: // Pulse Integral
4165 if(VERBOSE>7) evioout << " FADC125 Pulse Integral"<<endl;
4166 channel = (*iptr>>20) & 0x7F;
4167 sum = (*iptr>>0) & 0xFFFFF;
4168 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4169 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4170 pedestal = 0; // This will be replaced by the one from Df250PulsePedestal in GetObjects
4171 if (last_slot == slot && last_channel == channel) pulse_number = 1;
4172 last_slot = slot;
4173 last_channel = channel;
4174 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4175 objs->hit_objs.push_back(new Df125PulseIntegral(rocid, slot, channel, itrigger, pulse_number,
4176 quality_factor, sum, pedestal, nsamples_integral, nsamples_pedestal));
4177 }
4178 break;
4179 case 8: // Pulse Time
4180 if(VERBOSE>7) evioout << " FADC125 Pulse Time"<<endl;
4181 channel = (*iptr>>20) & 0x7F;
4182 pulse_number = (*iptr>>18) & 0x03;
4183 pulse_time = (*iptr>>0) & 0xFFFF;
4184 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) && (F125_PT_EMULATION_MODE!=kEmulationAlways) ) {
4185 objs->hit_objs.push_back(new Df125PulseTime(rocid, slot, channel, itrigger, pulse_number, quality_factor, pulse_time));
4186 }
4187 last_pulse_time_channel = channel;
4188 break;
4189
4190 case 9: // FDC pulse data-peak (new) (GlueX-doc-2274-v8)
4191
4192 // Word 1:
4193 word1 = *iptr;
4194 channel = (*iptr>>20) & 0x7F;
4195 pulse_number = (*iptr>>15) & 0x1F;
4196 pulse_time = (*iptr>>4 ) & 0x7FF;
4197 quality_factor = (*iptr>>3 ) & 0x1; //time QF bit
4198 overflow_count = (*iptr>>0 ) & 0x7;
4199 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word1: " << hex << (*iptr) << dec << endl;
4200 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (chan="<<channel<<" pulse="<<pulse_number<<" time="<<pulse_time<<" QF="<<quality_factor<<" OC="<<overflow_count<<")"<<endl;
4201
4202 // Word 2:
4203 ++iptr;
4204 if(iptr>=iend){
4205 jerr << " Truncated f125 FDC hit (block ends before continuation word!)" << endl;
4206 continue;
4207 }
4208 if( ((*iptr>>31) & 0x1) != 0 ){
4209 jerr << " Truncated f125 FDC hit (missing continuation word!)" << endl;
4210 continue;
4211 }
4212 word2 = *iptr;
4213 pulse_peak = (*iptr>>19) & 0xFFF;
4214 sum = 0;
4215 peak_time = (*iptr>>11) & 0xFF;
4216 pedestal = (*iptr>>0 ) & 0x7FF;
4217 if(VERBOSE>8) evioout << " FADC125 FDC Pulse Data(peak) word2: " << hex << (*iptr) << dec << endl;
4218 if(VERBOSE>7) evioout << " FADC125 FDC Pulse Data (integral="<<sum<<" time="<<peak_time<<" pedestal="<<pedestal<<")"<<endl;
4219
4220 // Create hit objects
4221 nsamples_integral = 0; // must be overwritten later in GetObjects with value from Df125Config value
4222 nsamples_pedestal = 1; // The firmware pedestal divided by 2^PBIT where PBIT is a config. parameter
4223
4224 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) ) {
4225 // n.b. This is were we might apply a check on whether we are
4226 // only producing emulated objects. If so, then we shouldn't
4227 // create the Df125FDCPulse. At this point in time though,
4228 // there are 3 config. parameters that control this because
4229 // the original firmware produced 3 separate data types as
4230 // opposed to the new firmware that puts the same infomation
4231 // into a single data type. The emulation framework is also
4232 // being revamped.
4233 objs->hit_objs.push_back( new Df125FDCPulse(rocid, slot, channel, itrigger
4234 , pulse_number // NPK
4235 , pulse_time // le_time
4236 , quality_factor // time_quality_bit
4237 , overflow_count // overflow_count
4238 , pedestal // pedestal
4239 , sum // integral
4240 , pulse_peak // peak_amp
4241 , peak_time // peak_time
4242 , word1 // word1
4243 , word2 // word2
4244 , nsamples_pedestal // nsamples_pedestal
4245 , nsamples_integral // nsamples_integral
4246 , false) // emulated
4247 );
4248 }
4249
4250 // n.b. We don't record last_slot, last_channel, etc... here since those
4251 // are only used by data types corresponding to older firmware that did
4252 // not write out data type 6.
4253 break;
4254
4255 case 10: // Pulse Pedestal (consistent with Beni's hand-edited version of Cody's document)
4256 if(VERBOSE>7) evioout << " FADC125 Pulse Pedestal"<<endl;
4257 //channel = (*iptr>>20) & 0x7F;
4258 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")
4259 pulse_number = (*iptr>>21) & 0x03;
4260 pedestal = (*iptr>>12) & 0x1FF;
4261 pulse_peak = (*iptr>>0) & 0xFFF;
4262 nsamples_pedestal = 1; // The firmware returns an already divided pedestal
4263 if( (objs!=NULL__null) && (pulse_number<F125PULSE_NUMBER_FILTER) && (F125_PP_EMULATION_MODE!=kEmulationAlways) ) {
4264 objs->hit_objs.push_back(new Df125PulsePedestal(rocid, slot, channel, itrigger, pulse_number, pedestal, pulse_peak, nsamples_pedestal));
4265 }
4266 break;
4267
4268 case 13: // Event Trailer
4269 case 14: // Data not valid (empty module)
4270 case 15: // Filler (non-data) word
4271 if(VERBOSE>7) evioout << " FADC125 ignored data type: " << data_type <<endl;
4272 break;
4273 }
4274
4275 // Once we find a block trailer, assume that is it for this module.
4276 if(found_block_trailer){
4277 iptr++; // iptr is still pointing to block trailer. Jump to next word.
4278 break;
4279 }
4280 }
4281
4282 // Chop off filler words
4283 for(; iptr<iend; iptr++){
4284 if(((*iptr)&0xf8000000) != 0xf8000000) break;
4285 }
4286
4287 // Add last event in block to list
4288 if(objs)events.push_back(objs);
4289
4290 // Here, we make object associations to link PulseIntegral, PulseTime, PulseRawData, etc
4291 // objects to each other so it is easier to get to these downstream without having to
4292 // make nested loops. This is the most efficient place to do it since the ObjList objects
4293 // in "event" contain only the objects from this EVIO block (i.e. at most one crate's
4294 // worth.)
4295 list<ObjList*>::iterator iter = events.begin();
4296 for(; iter!=events.end(); iter++){
4297
4298 // Sort list of objects into type-specific lists
4299 vector<DDAQAddress*> &hit_objs = (*iter)->hit_objs;
4300 vector<Df125TriggerTime*> vtrigt;
4301 vector<Df125WindowRawData*> vwrd;
4302 vector<Df125PulseRawData*> vprd;
4303 vector<Df125PulseIntegral*> vpi;
4304 vector<Df125PulseTime*> vpt;
4305 vector<Df125PulsePedestal*> vpp;
4306 for(unsigned int i=0; i<hit_objs.size(); i++){
4307 AddIfAppropriate(hit_objs[i], vtrigt);
4308 AddIfAppropriate(hit_objs[i], vwrd);
4309 AddIfAppropriate(hit_objs[i], vprd);
4310 AddIfAppropriate(hit_objs[i], vpi);
4311 AddIfAppropriate(hit_objs[i], vpt);
4312 AddIfAppropriate(hit_objs[i], vpp);
4313 }
4314
4315 // Connect Df125PulseIntegral with Df125PulseTime
4316 LinkAssociationsWithPulseNumber(vprd, vpi);
4317 LinkAssociationsWithPulseNumber(vprd, vpt);
4318 LinkAssociationsWithPulseNumber(vprd, vpp);
4319 LinkAssociationsWithPulseNumber(vpi, vpt);
4320 LinkAssociationsWithPulseNumber(vpi, vpp);
4321 LinkAssociationsWithPulseNumber(vpt, vpp);
4322
4323 // Connect Df125TriggerTime to everything
4324 LinkAssociationsModuleOnly(vtrigt, vwrd);
4325 LinkAssociationsModuleOnly(vtrigt, vprd);
4326 LinkAssociationsModuleOnly(vtrigt, vpi);
4327 LinkAssociationsModuleOnly(vtrigt, vpt);
4328 LinkAssociationsModuleOnly(vtrigt, vpp);
4329 }
4330
4331 if(VERBOSE>6) evioout << " Leaving Parsef125Bank"<<endl;
4332}
4333
4334//----------------
4335// MakeDf125WindowRawData
4336//----------------
4337void JEventSource_EVIO::MakeDf125WindowRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4338{
4339 uint32_t channel = (*iptr>>20) & 0x7F;
4340 uint32_t window_width = (*iptr>>0) & 0x0FFF;
4341
4342 Df125WindowRawData *wrd = new Df125WindowRawData(rocid, slot, channel, itrigger);
4343
4344 for(uint32_t isample=0; isample<window_width; isample +=2){
4345
4346 // Advance to next word
4347 iptr++;
4348
4349 // Make sure this is a data continuation word, if not, stop here
4350 if(((*iptr>>31) & 0x1) != 0x0)break;
4351
4352 bool invalid_1 = (*iptr>>29) & 0x1;
4353 bool invalid_2 = (*iptr>>13) & 0x1;
4354 uint16_t sample_1 = 0;
4355 uint16_t sample_2 = 0;
4356 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4357 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4358
4359 // Sample 1
4360 wrd->samples.push_back(sample_1);
4361 wrd->invalid_samples |= invalid_1;
4362 wrd->overflow |= (sample_1>>12) & 0x1;
4363
4364 if((isample+2) == window_width && invalid_2)break; // skip last sample if flagged as invalid
4365
4366 // Sample 2
4367 wrd->samples.push_back(sample_2);
4368 wrd->invalid_samples |= invalid_2;
4369 wrd->overflow |= (sample_2>>12) & 0x1;
4370 }
4371
4372 if(VERBOSE>7) evioout << " FADC125 - " << wrd->samples.size() << " samples" << endl;
4373
4374 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4375 // This will happen if a Window Raw Data block is encountered before an event header.
4376 // For these cases, we still want to try parsing the data so that the iptr is updated
4377 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4378 // the list. Otherwise, delete it now.
4379 if(objs){
4380 objs->hit_objs.push_back(wrd);
4381 }else{
4382 delete wrd;
4383 }
4384}
4385
4386//----------------
4387// MakeDf125PulseRawData
4388//----------------
4389void JEventSource_EVIO::MakeDf125PulseRawData(ObjList *objs, uint32_t rocid, uint32_t slot, uint32_t itrigger, const uint32_t* &iptr)
4390{
4391 uint32_t channel = (*iptr>>23) & 0x0F;
4392 uint32_t pulse_number = (*iptr>>21) & 0x000F;
4393 uint32_t first_sample_number = (*iptr>>0) & 0x03FF;
4394
4395 Df125PulseRawData *prd = new Df125PulseRawData(rocid, slot, channel, itrigger, pulse_number, first_sample_number);
4396
4397 // This loop needs to break when it hits a non-continuation word
4398 for(uint32_t isample=0; isample<1000; isample +=2){
4399
4400 // Advance to next word
4401 iptr++;
4402
4403 // Make sure this is a data continuation word, if not, stop here
4404 if(((*iptr>>31) & 0x1) != 0x0)break;
4405
4406 bool invalid_1 = (*iptr>>29) & 0x1;
4407 bool invalid_2 = (*iptr>>13) & 0x1;
4408 uint16_t sample_1 = 0;
4409 uint16_t sample_2 = 0;
4410 if(!invalid_1)sample_1 = (*iptr>>16) & 0x1FFF;
4411 if(!invalid_2)sample_2 = (*iptr>>0) & 0x1FFF;
4412
4413 // Sample 1
4414 prd->samples.push_back(sample_1);
4415 prd->invalid_samples |= invalid_1;
4416 prd->overflow |= (sample_1>>12) & 0x1;
4417
4418 bool last_word = (iptr[1]>>31) & 0x1;
4419 if(last_word && invalid_2)break; // skip last sample if flagged as invalid
4420
4421 // Sample 2
4422 prd->samples.push_back(sample_2);
4423 prd->invalid_samples |= invalid_2;
4424 prd->overflow |= (sample_2>>12) & 0x1;
4425 }
4426
4427
4428 // Due to how the calling function works, the value of "objs" passed to us may be NULL.
4429 // This will happen if a Window Raw Data block is encountered before an event header.
4430 // For these cases, we still want to try parsing the data so that the iptr is updated
4431 // but don't have an event to assign it to. If "objs" is non-NULL, add this object to
4432 // the list. Otherwise, delete it now.
4433 if(objs){
4434 objs->hit_objs.push_back(prd);
4435 }else{
4436 delete prd;
4437 }
4438}
4439
4440//----------------
4441// ParseF1TDCBank
4442//----------------
4443void JEventSource_EVIO::ParseF1TDCBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4444{
4445 /// Parse data from a single F1TDCv2 (32 ch) or F1TDCv3 (48 ch) module.
4446 /// This code is based on the document F1TDC_V2_V3_4_29_14.pdf obtained from:
4447 /// https://coda.jlab.org/wiki/index.php/JLab_Module_Manuals
4448
4449 if(!PARSE_F1TDC){ iptr = iend; return; }
4450
4451 if(VERBOSE>6) evioout << " Entering ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4452
4453 const uint32_t *istart = iptr;
4454
4455 // Some early data had a marker word at just before the actual F1 data
4456 if(*iptr == 0xf1daffff) iptr++;
4457
4458 // Block header word
4459 // Double check that block header is set
4460 if( ((*iptr) & 0xF8000000) != 0x80000000 ){
4461 throw JException("F1TDC Block header corrupt! (high 5 bits not set to 0x80000000!)");
4462 }
4463
4464 uint32_t slot_block_header = (*iptr)>>22 & 0x001F;
4465 uint32_t block_num = (*iptr)>> 8 & 0x03FF;
4466 uint32_t Nevents_block_header = (*iptr)>> 0 & 0x00FF;
4467 int modtype = (*iptr)>>18 & 0x000F; // should match a DModuleType::type_id_t
4468 if(VERBOSE>2) evioout << " F1 Block Header: slot=" << slot_block_header << " block_num=" << block_num << " Nevents=" << Nevents_block_header << endl;
4469
4470 // Advance to next word
4471 iptr++;
4472
4473 // Loop over events
4474 ObjList *objs = NULL__null;
4475 while(iptr<iend){
4476
4477 // Event header
4478 // Double check that event header is set
4479 if( ((*iptr) & 0xF8000000) != 0x90000000 ){
4480 if(VERBOSE>10){
4481 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4481<<" "
<<"Corrupt F1TDC Event header! Data dump follows (\"*\" indicates bad header word):" <<endl;
4482 DumpBinary(istart, iend, 0, iptr);
4483 }
4484 throw JException("F1TDC Event header corrupt! (high 5 bits not set to 0x90000000!)");
4485 }
4486
4487 uint32_t slot_event_header = (*iptr)>>22 & 0x00000001F;
4488 uint32_t itrigger = (*iptr)>>0 & 0x0003FFFFF;
4489 if(VERBOSE>2) evioout << " F1 Event Header: slot=" << slot_block_header << " itrigger=" << itrigger << endl;
4490
4491 // Make sure slot number from event header matches block header
4492 if(slot_event_header != slot_block_header){
4493 char str[256];
4494 sprintf(str, "F1TDC slot from event header(%d) doesn't match block header(%d)", slot_event_header, slot_block_header);
4495 throw JException(str);
4496 }
4497
4498 // Advance to timestamp word
4499 iptr++;
4500 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before timestamp word!");
4501
4502 // The most recent documentation says that the first time stamp
4503 // word holds the low 24 bits and the second the high 16 bits. According to Dave A.,
4504 // the second word is optional.
4505 uint32_t trig_time = ((*iptr)&0xFFFFFF);
4506 if(VERBOSE>2) evioout << " F1 Trigger time: low 24 bits=" << trig_time << endl;
4507 iptr++;
4508 if(iptr>=iend) throw JException("F1TDC data corrupt! Block truncated before trailer word!");
4509 if(((*iptr>>31) & 0x1) == 0){
4510 trig_time += ((*iptr)&0xFFFF)<<24; // from word on the street: second trigger time word is optional!!??
4511 if(VERBOSE>2) evioout << " F1 Trigger time: high 16 bits=" << ((*iptr)&0xFFFF) << " total trig_time=" << trig_time << endl;
4512 }else{
4513 iptr--; // second time word not present, back up pointer
4514 }
4515
4516 // Create a new object list (i.e. new event)
4517 if(objs!=NULL__null && ENABLE_DISENTANGLING){
4518 events.push_back(objs);
4519 objs = NULL__null;
4520 }
4521 if(!objs) objs = new ObjList;
4522
4523 if(objs) objs->hit_objs.push_back(new DF1TDCTriggerTime(rocid, slot_block_header, itrigger, trig_time));
4524
4525 // Advance past last timestamp word to first data word (or rather, F1 chip header)
4526 iptr++;
4527
4528 // Loop over F1 data words
4529 uint32_t chip_f1header=0, chan_on_chip_f1header=0, itrigger_f1header=0, trig_time_f1header=0;
4530 while( iptr<iend && ((*iptr)>>31)==0x1 ){
4531
4532 bool done = false;
4533
4534 uint32_t chip, chan_on_chip, time;
4535 uint32_t channel;
4536 DF1TDCHit *hit=NULL__null;
4537 switch( (*iptr) & 0xF8000000 ){
4538 case 0xC0000000: // F1 Header
4539 chip_f1header = ((*iptr)>> 3) & 0x07;
4540 chan_on_chip_f1header = ((*iptr)>> 0) & 0x07; // this is always 7 in real data!
4541 itrigger_f1header = ((*iptr)>>16) & 0x3F;
4542 trig_time_f1header = ((*iptr)>> 7) & 0x1FF;
4543 if(VERBOSE>5) evioout << " Found F1 header: chip=" << chip_f1header << " chan=" << chan_on_chip_f1header << " itrig=" << itrigger_f1header << " trig_time=" << trig_time_f1header << endl;
4544 //if( itrigger_f1header != (itrigger & 0x3F)) throw JException("Trigger number in F1 header word does not match Event header word!");
4545 break;
4546 case 0xB8000000: // F1 Data
4547 chip = (*iptr>>19) & 0x07;
4548 chan_on_chip = (*iptr>>16) & 0x07;
4549 time = (*iptr>> 0) & 0xFFFF;
4550 if(VERBOSE>5) evioout << " Found F1 data : chip=" << chip << " chan=" << chan_on_chip << " time=" << time << " (header: chip=" << chip_f1header << ")" << endl;
4551 //if(chip!=chip_f1header) throw JException("F1 chip number in data does not match header!");
4552 channel = F1TDC_channel(chip, chan_on_chip, modtype);
4553 hit = new DF1TDCHit(rocid, slot_block_header, channel, itrigger, trig_time_f1header, time, *iptr, MODULE_TYPE(modtype));
4554 if(objs)objs->hit_objs.push_back(hit);
4555 break;
4556 case 0xF8000000: // Filler word
4557 if(VERBOSE>7) evioout << " Found F1 filler word" << endl;
4558 break;
4559 case 0x80000000: // JLab block header (handled in outer loop)
4560 case 0x88000000: // JLab block trailer (handled in outer loop)
4561 case 0x90000000: // JLab event header (handled in outer loop)
4562 case 0x98000000: // Trigger time (handled in outer loop)
4563 case 0xF0000000: // module has no valid data available for read out (how to handle this?)
4564 if(VERBOSE>5) evioout << " Found F1 break word: 0x" << hex << *iptr << dec << endl;
4565 done = true;
4566 break;
4567 default:
4568 cerr<<endl;
4569 cout.flush(); cerr.flush();
4570 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4570<<" "
<<"Unknown data word in F1TDC block. Dumping for debugging:" << endl;
4571 for(const uint32_t *iiptr = istart; iiptr<iend; iiptr++){
4572 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4572<<" "
<<"0x"<<hex<<*iiptr<<dec;
4573 if(iiptr == iptr)cerr<<" <----";
4574 switch( (*iiptr) & 0xF8000000 ){
4575 case 0x80000000: cerr << " F1 Block Header"; break;
4576 case 0x90000000: cerr << " F1 Event Header"; break;
4577 case 0x98000000: cerr << " F1 Trigger time"; break;
4578 case 0xC0000000: cerr << " F1 Header"; break;
4579 case 0xB8000000: cerr << " F1 Data"; break;
4580 case 0x88000000: cerr << " F1 Block Trailer"; break;
4581 case 0xF8000000: cerr << " Filler word"; break;
4582 case 0xF0000000: cerr << " <module has no valid data>"; break;
4583 default: break;
4584 }
4585 cerr<<endl;
4586 if(iiptr > (iptr+4)) break;
4587 }
4588
4589 throw JException("Unexpected word type in F1TDC block!");
4590 }
4591
4592 if(done)break;
4593
4594 // Advance to next data word
4595 iptr++;
4596
4597 } // end loop over data words in this event
4598
4599 // If the current word is a JLab block trailer, then we are done
4600 if( ((*iptr) & 0xF8000000) == 0x88000000) break;
4601
4602 } // end loop over events
4603
4604 // Add hits for last event to list of events.
4605 if(objs)events.push_back(objs);
4606
4607 if( ((*iptr) & 0xF8000000) != 0x88000000 ){
4608 throw JException("F1TDC Block Trailer corrupt! (high 5 bits not set to 0x88000000!)");
4609 }
4610
4611 // Advance past JLab block trailer
4612 iptr++;
4613
4614 // Skip filler words
4615 while(iptr<iend && (*iptr&0xF8000000)==0xF8000000)iptr++;
4616
4617 // Double check that we found all of the events we were supposed to
4618 if(!ENABLE_DISENTANGLING) Nevents_block_header=1;
4619 if(events.size() != Nevents_block_header){
4620 stringstream ss;
4621 ss << "F1TDC missing events in block! (found "<< events.size() <<" but should have found "<<Nevents_block_header<<")";
4622 DumpBinary(istart, iend, 128);
4623 throw JException(ss.str());
4624 }
4625
4626 if(VERBOSE>6) evioout << " Leaving ParseF1TDCBank (rocid=" << rocid << ")" << endl;
4627
4628}
4629
4630//----------------
4631// F1TDC_channel
4632//----------------
4633uint32_t JEventSource_EVIO::F1TDC_channel(uint32_t chip, uint32_t chan_on_chip, int modtype)
4634{
4635 /// Convert a F1TDC chip number and channel on the chip to the
4636 /// front panel channel number. This is based on "Input Channel Mapping"
4637 /// section at the very bottom of the document F1TDC_V2_V3_4_29_14.pdf
4638
4639 uint32_t channel_map[8] = {0, 0, 1, 1, 2, 2, 3, 3};
4640 switch(modtype){
4641 case DModuleType::F1TDC32:
4642 return (4 * chip) + channel_map[ chan_on_chip&0x7 ];
4643 case DModuleType::F1TDC48:
4644 return (chip <<3) | chan_on_chip;
4645 default:
4646 _DBG_std::cerr<<"libraries/DAQ/JEventSource_EVIO.cc"<<
":"<<4646<<" "
<< "Calling F1TDC_channel for module type: " << DModuleType::GetName((DModuleType::type_id_t)modtype) << endl;
4647 throw JException("F1TDC_channel called for non-F1TDC module type");
4648 }
4649 return 1000000; // (should never get here)
4650}
4651
4652//----------------
4653// ParseTSBank
4654//----------------
4655void JEventSource_EVIO::ParseTSBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4656{
4657 cout << "<><><><><> !! Parsing of JLab TS module requested !! <><><>" << endl;
4658 cout << "<><><><><> !! TS parsing not yet supported !! <><><>" << endl;
4659 iptr = iend;
4660}
4661
4662//----------------
4663// ParseTIBank
4664//----------------
4665void JEventSource_EVIO::ParseTIBank(int32_t rocid, const uint32_t* &iptr, const uint32_t* iend, list<ObjList*> &events)
4666{
4667 while(iptr<iend && ((*iptr) & 0xF8000000) != 0x88000000) iptr++; // Skip to JLab block trailer
4668 iptr++; // advance past JLab block trailer
4669 while(iptr<iend && *iptr == 0xF8000000) iptr++; // skip filler words after block trailer
4670 //iptr = iend;
4671}
4672
4673//----------------
4674// ParseCAEN1190
4675//----------------
4676void JEventSource_EVIO::ParseCAEN1190(int32_t rocid, const uint32_t* &iptr, const uint32_t *iend, list<ObjList*> &events)
4677{
4678 /// Parse data from a CAEN 1190 or 1290 module
4679 /// (See ppg. 72-74 of V1290_REV15.pdf manual)
4680
4681 if(!PARSE_CAEN1290TDC){ iptr = iend; return; }
4682
4683 uint32_t slot = 0;
4684 uint32_t event_count = 0;
4685 uint32_t word_count = 0;
4686 uint32_t trigger_time_tag = 0;
4687 uint32_t tdc_num = 0;
4688 uint32_t event_id = 0;
4689 uint32_t bunch_id = 0;
4690 uint32_t last_event_id = event_id - 1;
Value stored to 'last_event_id' during its initialization is never read
4691
4692 // We need to accomodate multi-event blocks where
4693 // events are entangled (i.e. hits from event 1
4694 // are mixed inbetween those of event 2,3,4,
4695 // etc... With CAEN modules, we only know which
4696 // event a hit came from by looking at the event_id
4697 // in the TDC header. This value is only 12 bits
4698 // and could roll over within an event block. This
4699 // means we need to keep track of the order we
4700 // encounter them in so it is maintained in the
4701 // "events" container. The event_id order is kept
4702 // in the "event_id_order" vector.
4703 map<uint32_t, vector<DCAEN1290TDCHit*> > hits_by_event_id;
4704 vector<uint32_t> event_id_order;
4705
4706 while(iptr<iend){
4707
4708 // This word appears to be appended to the data.
4709 // Probably in the ROL. Ignore it if found.
4710 if(*iptr == 0xd00dd00d) {
4711 if(VERBOSE>7) evioout << " CAEN skipping 0xd00dd00d word" << endl;
4712 iptr++;
4713 continue;
4714 }
4715
4716 uint32_t type = (*iptr) >> 27;
4717 uint32_t edge = 0; // 1=trailing, 0=leading
4718 uint32_t channel = 0;
4719 uint32_t tdc = 0;
4720 uint32_t error_flags = 0;
4721 DCAEN1290TDCHit *caen1290tdchit = NULL__null;
4722 map<uint32_t, ObjList*>::iterator iter;
4723 switch(type){
4724 case 0b01000: // Global Header
4725 slot = (*iptr) & 0x1f;
4726 event_count = ((*iptr)>>5) & 0xffffff;
4727 if(VERBOSE>7) evioout << " CAEN TDC Global Header (slot=" << slot << " , event count=" << event_count << ")" << endl;
4728 break;
4729 case 0b10000: // Global Trailer
4730 slot = (*iptr) & 0x1f;
4731 word_count = ((*iptr)>>5) & 0x7ffff;
4732 if(VERBOSE>7) evioout << " CAEN TDC Global Trailer (slot=" << slot << " , word count=" << word_count << ")" << endl;
4733 slot = event_count = word_count = trigger_time_tag = tdc_num = event_id = bunch_id = 0;
4734 break;
4735 case 0b10001: // Global Trigger Time Tag
4736 trigger_time_tag = ((*iptr)>>5) & 0x7ffffff;
4737 if(VERBOSE>7) evioout << " CAEN TDC Global Trigger Time Tag (tag=" << trigger_time_tag << ")" << endl;
4738 break;
4739 case 0b00001: // TDC Header
4740 tdc_num = ((*iptr)>>24) & 0x03;
4741 event_id = ((*iptr)>>12) & 0x0fff;
4742 bunch_id = (*iptr) & 0x0fff;
4743 if( find(event_id_order.begin(), event_id_order.end(), event_id) == event_id_order.end()){
4744 event_id_order.push_back(event_id);
4745 }
4746 //if(event_id != last_event_id) event_id_order.push_back(event_id);
4747 last_event_id = event_id;
4748 if(VERBOSE>7) evioout << " CAEN TDC TDC Header (tdc=" << tdc_num <<" , event id=" << event_id <<" , bunch id=" << bunch_id << ")" << endl;
4749 break;
4750 case 0b00000: // TDC Measurement
4751 edge = ((*iptr)>>26) & 0x01;
4752 channel = ((*iptr)>>21) & 0x1f;
4753 tdc = ((*iptr)>>0) & 0x1fffff;
4754 if(VERBOSE>7) evioout << " CAEN TDC TDC Measurement (" << (edge ? "trailing":"leading") << " , channel=" << channel << " , tdc=" << tdc << ")" << endl;
4755
4756 // Create DCAEN1290TDCHit object
4757 caen1290tdchit = new DCAEN1290TDCHit(rocid, slot, channel, 0, edge, tdc_num, event_id, bunch_id, tdc);
4758 hits_by_event_id[event_id].push_back(caen1290tdchit);
4759 break;
4760 case 0b00100: // TDC Error
4761 error_flags = (*iptr) & 0x7fff;
4762 if(VERBOSE>7) evioout << " CAEN TDC TDC Error (err flags=0x" << hex << error_flags << dec << ")" << endl;
4763 break;
4764 case 0b00011: // TDC Trailer
4765 tdc_num = ((*iptr)>>24) & 0x03;
4766 event_id = ((*iptr)>>12) & 0x0fff;
4767 word_count = ((*iptr)>>0) & 0x0fff;
4768 if(VERBOSE>7) evioout << " CAEN TDC TDC Trailer (tdc=" << tdc_num <<" , event id=" << event_id <<" , word count=" << word_count << ")" << endl;
4769 tdc_num = event_id = bunch_id = 0;
4770 break;
4771 case 0b11000: // Filler Word
4772 if(VERBOSE>7) evioout << " CAEN TDC Filler Word" << endl;
4773 break;
4774 default:
4775 evioout << "Unknown datatype: 0x" << hex << type << " full word: "<< *iptr << dec << endl;
4776 }
4777
4778 iptr++;
4779 }
4780
4781 // If disentagling is disabled, then lump all hits into single event
4782 if( (!ENABLE_DISENTANGLING) && (event_id_order.size()>1) ){
4783 if(VERBOSE>2) evioout << " Disentangling disabled. Merging all hits into single event" << endl;
4784 vector<DCAEN1290TDCHit*> &hits1 = hits_by_event_id[event_id_order[0]];
4785 for(uint32_t i=1; i<event_id_order.size(); i++){
4786 vector<DCAEN1290TDCHit*> &hits2 = hits_by_event_id[event_id_order[i]];
4787 hits1.insert(hits1.end(), hits2.begin(), hits2.end()); // copy hits into first event
4788 hits_by_event_id.erase(event_id_order[i]); // remove hits list for this event_id
4789 }
4790 }
4791
4792 // Add hits for each event to the events container, creating ObjList's as needed
4793 for(uint32_t i=0; i<event_id_order.size(); i++){
4794
4795 // Make sure there are enough event containers to hold this event
4796 while(events.size() <= i) events.push_back(new ObjList);
4797 list<ObjList*>::iterator it = events.begin();
4798 advance(it, i);
4799 ObjList *objs = *it;
4800
4801 vector<DCAEN1290TDCHit*> &hits = hits_by_event_id[event_id_order[i]];
4802 objs->hit_objs.insert(objs->hit_objs.end(), hits.begin(), hits.end());
4803
4804 if(VERBOSE>7) evioout << " Added " << hits.size() << " hits with event_id=" << event_id_order[i] << " to event " << i << endl;
4805 }
4806
4807}
4808
4809//----------------
4810// ParseEPICSevent
4811//----------------
4812void JEventSource_EVIO::ParseEPICSevent(evioDOMNodeP bankPtr, list<ObjList*> &events)
4813{
4814 if(!PARSE_EPICS) return;
4815
4816 time_t timestamp=0;
4817
4818 ObjList *objs = NULL__null;
4819
4820 evioDOMNodeListP bankList = bankPtr->getChildren();
4821 evioDOMNodeList::iterator iter = bankList->begin();
4822 if(VERBOSE>7) evioout << " Looping over " << bankList->size() << " banks in EPICS event" << endl;
4823 for(int ibank=1; iter!=bankList->end(); iter++, ibank++){ // ibank only used for debugging messages
4824 evioDOMNodeP childBank = *iter;
4825
4826 if(childBank->tag == 97){
4827 // timestamp bank
4828 const vector<uint32_t> *vec = childBank->getVector<uint32_t>();
4829 if(vec) {
4830 timestamp = (time_t)(*vec)[0];
4831 if(VERBOSE>7) evioout << " timestamp: " << ctime(&timestamp);
4832 }
4833 }else if(childBank->tag==98){
4834 const vector<uint8_t> *vec = childBank->getVector<uint8_t>();
4835 if(vec){
4836 string nameval = (const char*)&((*vec)[0]);
4837 DEPICSvalue *epicsval = new DEPICSvalue(timestamp, nameval);
4838 if(VERBOSE>7) evioout << " " << nameval << endl;
4839
4840 if(!objs){
4841 if(events.empty()) events.push_back(new ObjList);
4842 objs = *(events.begin());
4843 }
4844 objs->misc_objs.push_back(epicsval);
4845 }
4846 }
4847 }
4848}
4849
4850//----------------
4851// DumpBinary
4852//----------------
4853void JEventSource_EVIO::DumpBinary(const uint32_t *iptr, const uint32_t *iend, uint32_t MaxWords, const uint32_t *imark)
4854{
4855 /// This is used for debugging. It will print to the screen the words
4856 /// starting at the address given by iptr and ending just before iend
4857 /// or for MaxWords words, whichever comes first. If iend is NULL,
4858 /// then MaxWords will be printed. If MaxWords is zero then it is ignored
4859 /// and only iend is checked. If both iend==NULL and MaxWords==0, then
4860 /// only the word at iptr is printed.
4861
4862 cout << "Dumping binary: istart=" << hex << iptr << " iend=" << iend << " MaxWords=" << dec << MaxWords << endl;
4863
4864 if(iend==NULL__null && MaxWords==0) MaxWords=1;
4865 if(MaxWords==0) MaxWords = (uint32_t)0xffffffff;
4866
4867 uint32_t Nwords=0;
4868 while(iptr!=iend && Nwords<MaxWords){
4869
4870 // line1 is hex and line2 is decimal
4871 stringstream line1, line2;
4872
4873 // print words in columns 8 words wide. First part is
4874 // reserved for word number
4875 uint32_t Ncols = 8;
4876 line1 << setw(5) << Nwords;
4877 line2 << string(5, ' ');
4878
4879 // Loop over columns
4880 for(uint32_t i=0; i<Ncols; i++, iptr++, Nwords++){
4881
4882 if(iptr == iend) break;
4883 if(Nwords>=MaxWords) break;
4884
4885 stringstream iptr_hex;
4886 iptr_hex << hex << "0x" << *iptr;
4887
4888 string mark = (iptr==imark ? "*":" ");
4889
4890 line1 << setw(12) << iptr_hex.str() << mark;
4891 line2 << setw(12) << *iptr << mark;
4892 }
4893
4894 cout << line1.str() << endl;
4895 cout << line2.str() << endl;
4896 cout << endl;
4897 }
4898}
4899
4900#endif // HAVE_EVIO
4901
4902#if 0
4903//----------------
4904// GuessModuleType
4905//----------------
4906MODULE_TYPE JEventSource_EVIO::GuessModuleType(const uint32_t* istart, const uint32_t* iend, evioDOMNodeP bankPtr)
4907{
4908 /// Try parsing through the information in the given data buffer
4909 /// to determine which type of module produced the data.
4910
4911 if(IsFADC250(istart, iend)) return DModuleType::FADC250;
4912 if(IsF125ADC(istart, iend)) return DModuleType::F125ADC;
4913 if(IsF1TDC(istart, iend)) return DModuleType::F1TDC;
4914 if(IsTS(istart, iend)) return DModuleType::JLAB_TS;
4915 if(IsTI(istart, iend)) return DModuleType::JLAB_TID;
4916
4917
4918 // Couldn't figure it out...
4919 return DModuleType::UNKNOWN;
4920}
4921
4922//----------------
4923// IsFADC250
4924//----------------
4925bool JEventSource_EVIO::IsFADC250(const uint32_t *istart, const uint32_t *iend)
4926{
4927 //---- Check for f250
4928 // This will check if the first word appears to be a block header.
4929 // If so, it loops over all words looking for a block trailer.
4930 // If the slot number in the block trailer matches that in the
4931 // block header AND the number of words in the block matches that
4932 // specified in the block trailer, then it is assumed to be a f250.
4933 if(((*istart>>31) & 0x1) == 1){
4934 uint32_t data_type = (*istart>>27) & 0x0F;
4935 if(data_type == 0){ // Block Header
4936 uint32_t slot_header = (*istart>>22) & 0x1F;
4937 uint32_t Nwords = 1;
4938 for(const uint32_t *iptr=istart; iptr<iend; iptr++, Nwords++){
4939 if(((*iptr>>31) & 0x1) == 1){
4940 uint32_t data_type = (*iptr>>27) & 0x0F;
4941 if(data_type == 1){ // Block Trailer
4942 uint32_t slot_trailer = (*iptr>>22) & 0x1F;
4943 uint32_t Nwords_trailer = (*iptr>>0) & 0x3FFFFF;
4944
4945 if( slot_header == slot_trailer && Nwords == Nwords_trailer ){
4946 return true;
4947 }else{
4948 return false;
4949 }
4950 }
4951 }
4952 }
4953 }
4954 }
4955
4956 // either first word was not a block header or no block trailer was found
4957 return false;
4958}
4959
4960//----------------
4961// IsF1TDC
4962//----------------
4963bool JEventSource_EVIO::IsF1TDC(const uint32_t *istart, const uint32_t *iend)
4964{
4965 //---- Check for F1TDC
4966 // This will check for consistency in the slot numbers for all words
4967 // in the buffer. The slot number of data words are checked against
4968 // the slot number of the most recently encountered header word.
4969 uint32_t slot_header = 1000;
4970 uint32_t slot_trailer = 1000;
4971
4972 const uint32_t *iptr=istart;
4973
4974 // skip first word which appears to be ROL marker for F1TDC data
4975 if(*istart == 0xf1daffff)iptr++
4976
4977 // There is no distinction between header and trailer
4978 // words other than the order that they appear. We keep
4979 // track by flipping this value
4980 bool looking_for_header = true;
4981
4982 // Keep track of the number of valid blocks of F1TDC data we find
4983 // (i.e. ones where the header and trailer words were found
4984 int Nvalid = 0;
4985
4986 for(; iptr<iend; iptr++){
4987
4988 // ROL end of data marker (only in test setup data)
4989 if(*iptr == 0xda0000ff)break;
4990
4991 uint32_t slot = (*iptr>>27) & 0x1F;
4992
4993 // if slot is 0 or 30, we are supposed to ignore the data.
4994 if(slot == 30 || slot ==0)continue;
4995
4996 if(((*iptr>>23) & 0x1) == 0){
4997 // header/trailer word
4998 if(looking_for_header){
4999 slot_header = slot;
5000 looking_for_header = false;
5001 }else{
5002 slot_trailer = slot;
5003 if(slot_trailer != slot_header)return false;
5004 looking_for_header = true;
5005 Nvalid++;
5006 }
5007 }else{
5008 // data word
5009
5010 // if we encounter a data word when we are expecting
5011 // a header word, then the current word is not from
5012 // an F1TDC. However, if we did find at least one valid
5013 // block at the begining, of the buffer, claim the buffer
5014 // points to F1TDC data. We check for as many valid F1TDC
5015 // blocks as possible to help ensure that is what the data
5016 // is.
5017 if(looking_for_header)return Nvalid>0;
5018
5019 // If the slot number does not match, then this is
5020 // not valid F1TDC data
5021 if(slot != slot_header)return false;
5022 }
5023 }
5024
5025 return Nvalid>0;
5026}
5027
5028//----------------
5029// DumpModuleMap
5030//----------------
5031void JEventSource_EVIO::DumpModuleMap(void)
5032{
5033 // Open output file
5034 string fname = "module_map.txt";
5035 ofstream ofs(fname.c_str());
5036 if(!ofs.is_open()){
5037 jerr<<"Unable to open file \""<<fname<<"\" for writing!"<<endl;
5038 return;
5039 }
5040
5041 jout<<"Writing module map to file \""<<fname<<"\""<<endl;
5042
5043 // Write header
5044 time_t now = time(NULL__null);
5045 ofs<<"# Autogenerated module map"<<endl;
5046 ofs<<"# Created: "<<ctime(&now);
5047 ofs<<"#"<<endl;
5048
5049 // Write known module types in header
5050 vector<DModuleType> modules;
5051 DModuleType::GetModuleList(modules);
5052 ofs<<"# Known module types:"<<endl;
5053 ofs<<"# ----------------------"<<endl;
5054 for(unsigned int i=0; i<modules.size(); i++){
5055 string name = modules[i].GetName();
5056 string space(12-name.size(), ' ');
5057 ofs << "# " << name << space << " - " << modules[i].GetDescription() <<endl;
5058 }
5059 ofs<<"#"<<endl;
5060 ofs<<"#"<<endl;
5061
5062 // Write module map
5063 ofs<<"# Format is:"<<endl;
5064 ofs<<"# tag num type"<<endl;
5065 ofs<<"#"<<endl;
5066
5067 map<tagNum, MODULE_TYPE>::iterator iter = module_type.begin();
5068 for(; iter!=module_type.end(); iter++){
5069
5070 tagNum tag_num = iter->first;
5071 MODULE_TYPE type = iter->second;
5072 ofs<<tag_num.first<<" "<<(int)tag_num.second<<" "<<DModuleType::GetName(type)<<endl;
5073 }
5074 ofs<<endl;
5075
5076 // Close output file
5077 ofs.close();
5078}
5079#endif