Bug Summary

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