Bug Summary

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

Annotated Source Code

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