Bug Summary

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