Bug Summary

File:libraries/DAQ/JEventSource_EVIO.cc
Location:line 3230, column 66
Description:Access to field 'NPK' results in a dereference of a null pointer (loaded from variable 'f125config')

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