8 #define PPP_TO_UAMPH 1.738E-6
19 m_current_frame(-1), m_current_period(-1), m_period(
"period_number", crpt->start_time),m_vetoing(
"is_vetoing",crpt->start_time),
20 m_crpt(crpt), m_file(file), m_discarded_events(0),m_monitor_events_not_saved(0),m_good_frames(0),m_raw_frames(0),m_is_vetoing(-1),
21 m_mempool(4 *
EventStore::maxNumCallbackEvents()),m_entry_name(
"raw_data_1"),
22 m_good_uamph_sum(0), m_raw_uamph_sum(0), m_good_events_sum(0),m_raw_events_sum(0),m_worker(m_queue),
23 m_last_frame_time(0),m_worker_thread(
"NeXusWorker"),m_refeventdetcard(-1)
28 while( !
m_queue.hasIdleThreads() )
30 Poco::Thread::sleep(100);
32 BOOST_FOREACH(
int id, ev_source_ids)
39 det_name_t::left_const_iterator it;
40 for(
int i=0, j=0; i <nspec; ++i)
50 it =
m_det_name.left.insert(det_name_t::left_value_type(det_name, j++)).first;
54 if ( Poco::Util::Application::instance().config().getBool(
"isisicp.snseventfile",
false) )
64 int refeventdetcard = Poco::Util::Application::instance().config().getInt(
"isisicp.refeventdetcard", -1);
65 if ( (refeventdetcard == -1) || (std::find(ev_source_ids.begin(), ev_source_ids.end(), refeventdetcard) != ev_source_ids.end()) )
67 return refeventdetcard;
69 if ( ev_source_ids.size() == 0 )
71 LOGSTR_INFORMATION(
"No event sources, assuming histogram mode and setting refeventdetcard=-1");
74 static const int INVALID_CARD = std::numeric_limits<int>::max();
75 int crate0_low = INVALID_CARD, crate1_low = INVALID_CARD;
76 BOOST_FOREACH(
int id, ev_source_ids)
78 if ( (
id / 100 == 0) && (
id < crate0_low) )
82 if ( (
id / 100 == 1) && (
id < crate1_low) )
87 if (crate1_low != INVALID_CARD)
89 LOGSTR_WARNING(
"Using card number " << crate1_low <<
" as reference detecor card as " << refeventdetcard <<
" not present");
90 refeventdetcard = crate1_low;
92 else if (crate0_low != INVALID_CARD)
94 LOGSTR_WARNING(
"Using card number " << crate0_low <<
" as reference detecor card as " << refeventdetcard <<
" not present");
95 refeventdetcard = crate0_low;
99 LOGSTR_ERROR(
"Reference event detector card number " << refeventdetcard <<
" not present and cannot find alternative");
100 refeventdetcard = -1;
102 return refeventdetcard;
107 static bool random_shift = Poco::Util::Application::instance().config().getBool(
"isisicp.randomeventbinshift",
true);
120 LOGSTR_ERROR(
"Events with no frames to write - something is very wrong. Last time we saw this was on WISH when the first crate generated events/frames but the second one didn't");
127 int i, j, frame_no, nevents, n_no_events;
128 std::vector<uint64_t> event_index(nframes);
129 std::vector<int> event_frame_number(nframes);
130 std::vector<double> event_frame_time(nframes);
131 std::vector<int> frame_events(nframes, 0);
140 for(i = 0; i < nframes; ++i)
143 event_frame_time[i] =
static_cast<double>(
m_frame_time[i]);
145 std::map<int,int>::const_iterator v = this_det.find(frame_no);
146 if ( v != this_det.end() )
155 if ( i < (nframes - 1) )
157 event_index[i+1] = event_index[i] + nevents;
159 frame_events[i] += nevents;
164 memset(&tof_link, 0,
sizeof(NXlink));
186 if (strlen(tof_link.targetPath) > 0)
198 std::vector<NXlink> links(7);
212 if (strlen(tof_link.targetPath) > 0)
226 for(i = 0; i < nframes; ++i)
280 for(det_file_t::const_iterator det_pos =
m_det_file.begin(); det_pos !=
m_det_file.end(); ++det_pos)
295 for(det_file_t::const_iterator det_pos =
m_det_file.begin(); det_pos !=
m_det_file.end(); ++det_pos)
308 Poco::Thread::sleep(100);
311 Poco::Thread::sleep(100);
314 Poco::Thread::sleep(100);
317 if (
m_queue.hasIdleThreads() )
320 while(
m_queue.hasIdleThreads() )
323 Poco::Thread::sleep(100);
334 det_name = Poco::format(
"monitor_%d", mon_num);
359 m_file->
makeNewGroup(Poco::format(
"time_channels_%d", tr).c_str(),
"IXtime_channels");
373 const std::string& name = it->left;
374 if (name.substr(0, 8) ==
"monitor_")
392 static const uint32_t SIX_MONTHS_IN_SECS = 6 * 28 * 24 * 60 * 60;
393 int i, ndiscarded = 0, device_id, device_index, nignored = 0;
394 union { uint64_t u64;
double d; uint32_t u32;
float f;
unsigned char b[8]; } data_value;
395 float offset_time = -1.0;
397 std::ostringstream msgpfx_oss;
398 msgpfx_oss <<
"(Time: " << offset_time <<
", Frame: " << head->
frame_number <<
") ";
399 const std::string& msgpfx = msgpfx_oss.str();
403 ignore_value =
false;
410 if ( (det_ev[i].spectrum >> 8) != 0 )
412 LOGSTR_ERROR(msgpfx <<
"Expected device id packet, but found header: " << (det_ev[i].spectrum >> 8) <<
" value: " << (det_ev[i].spectrum & 0xff));
415 device_id = det_ev[i].
spectrum & 0xff;
424 if (device_index == -1)
426 LOGSTR_ERROR(msgpfx <<
"Invalid device id (not specified in XML file) " << device_id);
438 LOGSTR_ERROR(msgpfx <<
"Invalid data type " << data_dae.
data_type <<
" for device id " << device_id);
444 if ( (det_ev[i+j].spectrum >> 8) != j )
446 LOGSTR_WARNING(msgpfx <<
"invalid data byte " << j <<
" for device id " << device_id
447 <<
" header: " << (det_ev[i+j].spectrum >> 8) <<
" value: " << (det_ev[i+j].spectrum & 0xff) );
450 data_value.b[j-1] = det_ev[i+j].
spectrum & 0xff;
453 if (offset_time < 0.0 || offset_time > SIX_MONTHS_IN_SECS)
481 LOGSTR_ERROR(msgpfx <<
"SE Data count used mismatch " << i <<
" != " << n);
485 LOGSTR_WARNING(
"Ignored " << nignored <<
" SE data to dae values");
496 throw std::exception(
"NeXusEventCallback::allEventCallback");
506 int spec, dae_tr = -1, dae_tr0 = -1;
507 for(
int i=0; i<n; ++i)
520 if (dae_tr == -1 && dae_tr0 != -1)
534 m_logstr->warning() <<
"Ignoring " << n <<
" events from frame "<< head->
frame_number <<
" event source " << event_source_id <<
" as all spectra are invalid";
542 float_map_t::iterator event_time_it;
543 int_map_t::iterator event_id_it;
544 int mon_num, det_id, current_det_id = -1, nmonskippedevents = 0, ndiscarded = 0;
545 for(
int i=0; i<n; ++i)
565 if (current_det_id != det_id)
567 const std::string& det_name =
m_det_name.right.at(det_id);
568 if ( (event_time_it = event_time_offset.find(det_name)) == event_time_offset.end() )
570 event_time_offset[det_name];
571 event_time_it = event_time_offset.find(det_name);
573 if (event_time_it->second.capacity() < n)
575 event_time_it->second.reserve(n);
577 if ( (event_id_it = event_id.find(det_name)) == event_id.end() )
580 event_id_it = event_id.find(det_name);
582 if (event_id_it->second.capacity() < n)
584 event_id_it->second.reserve(n);
586 current_det_id = det_id;
588 event_time_it->second.push_back(
getTimeOffset(det_ev, event_source_id, dae_tr, i));
590 event_id_it->second.push_back(spec);
593 writeEvents(head, event_source_id, n - nmonskippedevents , event_id, event_time_offset);
594 for(int_map_t::iterator it = event_id.begin(); it != event_id.end(); ++it)
596 it->second.resize(0);
599 for(float_map_t::iterator it = event_time_offset.begin(); it != event_time_offset.end(); ++it)
601 it->second.resize(0);
610 static bool warneventpppmismatch = Poco::Util::Application::instance().config().getBool(
"isisicp.warneventpppmismatch",
false);
611 static const uint32_t MAX_ISIS_PPP =
static_cast<uint32_t
>( 0.5 + (300.0 * 3600.0) / (
PPP_TO_UAMPH * 50.0) );
612 static const uint32_t SIX_MONTHS_IN_SECS = 6 * 28 * 24 * 60 * 60;
613 uint32_t the_protons = head->
protons;
622 if ( head->
protons != ref_protons )
629 if (this_time != ref_time)
631 LOGSTR_WARNING(
"absolute time mismatch " << this_time <<
" != " << ref_time);
643 float previous_offset_time = 0.0;
644 uint32_t previous_protons = 0;
653 if (the_protons > MAX_ISIS_PPP)
658 float offset_time = -1.0;
660 if (offset_time < 0.0 || offset_time > SIX_MONTHS_IN_SECS)
704 card_frame_t::iterator it;
705 time_t ref_time = time(NULL);
711 it->second.first = frame;
712 it->second.second = ref_time;
721 it->second.first = frame;
722 it->second.second = ref_time;
727 LOGSTR_WARNING(
"Data from invalid source id " << event_source_id <<
" in frame " << frame);
735 card_frame_t::const_iterator it =
m_card_frame.find(event_source_id);
745 LOGSTR_WARNING(
"Data from invalid source id " << event_source_id);
753 card_frame_t::iterator it =
m_card_frame.find(event_source_id);
763 LOGSTR_WARNING(
"Data from invalid source id " << event_source_id);
769 static const int INITIAL_VAL = std::numeric_limits<int>::max();
770 int current_frame = INITIAL_VAL;
775 current_frame = std::min(current_frame, it->second.first);
778 if (current_frame == INITIAL_VAL)
782 return current_frame;
789 static bool single_nexus_writer_thread = Poco::Util::Application::instance().config().getBool(
"isisicp.singlenexuswriterthread",
true);
801 LOGSTR_WARNING(
"Writing data arriving too late: passed frame " << head->
frame_number <<
" when current is " << current_frame <<
" for source " << event_source_id);
803 if (single_nexus_writer_thread)
806 NeXusWorkerData d(
this, ev, head, event_source_id, nev, event_id, event_time_offset);
812 writeEventsImpl(head, event_source_id, nev, event_id, event_time_offset);
821 std::string current_group;
822 det_file_t::iterator det_pos;
823 uint64_t *group_total_events = NULL;
824 int *group_frame_events = NULL;
825 int64_t dims_array[1], slab_start[1], dest_start[1];
826 const float_map_t::mapped_type* event_times = NULL;
827 for(int_map_t::const_iterator it = event_id.begin(); it != event_id.end(); ++it)
829 if (it->second.size() == 0)
833 if (current_group != it->first)
835 current_group = it->first;
839 std::vector<IXNeXusFile*> det_tmp(2, NULL);
847 det_tmp[0]->openData(
"event_id");
848 det_tmp[1]->openData(
"event_time_offset");
854 event_times = &(event_time_offset.at(current_group));
856 std::vector<IXNeXusFile*>& det_nx_v = det_pos->second;
857 (*group_frame_events) += it->second.size();
859 dims_array[0] = it->second.size();
861 dest_start[0] = *group_total_events;
862 det_nx_v[0]->addSlab(it->second.data(), dims_array, 1, slab_start, dims_array, dest_start);
863 det_nx_v[1]->addSlab(event_times->data(), dims_array, 1, slab_start, dims_array, dest_start);
864 (*group_total_events) += it->second.size();
883 bool is_monitor = (name.find(
"monitor") != std::string::npos);
886 nx->
openGroup(name.c_str(),
"NXmonitor");
890 nx->
openGroup(
"instrument",
"NXinstrument");
891 nx->
openGroup(name.c_str(),
"NXdetector");
895 if (create_zero_size_if_missing)
898 nx->
makeData(
"event_id", NX_UINT32, dims_array, 1);
899 nx->
makeData(
"event_time_offset", NX_FLOAT32, dims_array, 1);
903 dims_array[0] = NX_UNLIMITED;
904 nx->
makeDataChunked(
"event_id", NX_UINT32, dims_array, chunks_array, 1);
905 nx->
makeDataChunked(
"event_time_offset", NX_FLOAT32, dims_array, chunks_array, 1);
915 if (name.size() == 0)
919 bool is_monitor = (name.find(
"monitor") != std::string::npos);
int openGroup(const char *group_name, const char *group_class)
void allEventCallback(const DAEEventHeader *head, const DetectorEvent32 *det_ev, int n, int event_source_id, const int *mapping)
void noFrameCallbackNull(bool end_present, NoFrameCallbackMode mode, int event_source_id)
int data_type
0=unknown, 1=int, 2=float
const char * ISOtime(time_t time)
int getSpectrum(const DetectorEvent32 *det_ev, int event_source_id, int i)
returns -1 if spectrum out of range
int getNumSpectra(bool include_spectrum_zero=false) const
void openDataGroup(IXNeXusFile *nx, const std::string &name, bool create_zero_size_if_missing=false)
Poco::MemoryPool m_mempool
static const int m_nexus_chunk_length
number of items in NeXus event list data chunk
void createEmptyFileStructure()
float rtcb[ISISCRPT_MAX_NTRG][ISISCRPT_MAX_TIMECHANB]
std::vector< float > m_frame_time
monitor events we did not save to file, instead just saving histograms
uint64_t m_raw_events_sum
int clone(const IXNeXusFile &orig)
int makeNewGroup(const char *name, const char *nxclass, bool open_group=true)
int m_is_vetoing
last period number seen, used for change period log
float_map_t m_se_float_values
int makeData(const char *data_name, int nxtype, const int *dims_array, int ndims)
int currentWriteFrame() const
void makeDetName(int spec, std::string &det_name)
bool saveMonitorEvents(int monitor_number) const
std::set< std::string > m_event_det
std::vector< float > m_frame_proton_charge
int m_good_frames
1 yes, 0 no (-1 means unknown, but just used for initialisation)
int addLog(const char *nxname, const char *filename, const char *log_name, const char *log_units, time_t ref_time)
void addValue(float time, T value)
static const int INVALID_FRAME_MARKER
static Poco::Mutex m_event_write_mutex
void updateCurrentWriteFrame(int frame, int event_source_id)
Poco::NotificationQueue m_queue
void allFrameCallback(const DAEEventHeader *head, int event_source_id)
this will get called for each frame for EACH event source
const char * detector_format
int makeDataChunked(const char *data_name, int nxtype, const int *dims_array, const int *chunk_array, int ndims)
#define LOGSTR_WARNING(__arg)
static Poco::Mutex m_frame_callback_mutex
int m_current_period
frame number we are currently processing
void processDataDae(const DAEEventHeader *head, const DetectorEvent32 *det_ev, int n, int event_source_id)
int spectrumDAETR(int spec) const
data_dae_t data_dae[ISISCRPT_MAX_DATADAE]
std::vector< int > m_frame_period
int writeAttribute(const std::string &data_name, const std::string &attr_name, const std::string &value)
SimpleStore< int_map_t > m_int_map_store
int spectrumToMonitorNumber(int spec) const
return monitor number, or 0 if not monitor
#define LOGSTR_INFORMATION(__arg)
int tcb[ISISCRPT_MAX_NTRG][ISISCRPT_MAX_TIMECHANB]
const ISISCRPT_STRUCT * m_crpt
#define LOGSTR_ERROR(__arg)
std::map< std::string, std::vector< int > > int_map_t
void setOffset(time_t offset)
static void DAETimeToOffset(const DAEEventHeader::DAETime &daetime, time_t base, T &offset)
void writeEventsImpl(const DAEEventHeader *head, int event_source_id, int nev, const int_map_t &event_id, const float_map_t &event_time_offset)
static Poco::Condition m_event_write_cond
int spectrumGroup(int spec) const
static float getTimeOffset(const ISISCRPT_STRUCT *crpt, const DetectorEvent32 *det_ev, int event_source_id, int tr, int i)
std::map< std::string, int > m_det_tr
const char * detector_base
int getLink(const char *name, const char *nxclass, NXlink &link)
frame_events_write_t m_frame_events_write
std::vector< int > m_good_frame
void write(IXNeXusFile *file, const std::string &name)
Poco::LogStream * m_logstr
void writeEvents(const DAEEventHeader *head, int event_source_id, int nev, const int_map_t &event_id, const float_map_t &event_time_offset)
bool isEventSpectrum(int spec) const
boost::array< int, ISISCRPT_MAX_NTRG > ntc
number of time channels per CRPT time regime
SimpleStore< float_map_t > m_float_map_store
U sum_map_values(const std::map< T, U > &m)
void setLoggerName(const std::string &logger_name)
int writeData(const char *data_name, const std::vector< T > &value)
std::vector< int > m_frame_number
std::map< int, uint32_t > m_frame_events_raw
uint_map_t m_se_uint_values
uint64_t m_good_events_sum
int makeLink(const char *name, const char *nxclass, NXlink &link)
NXlogWriter< int > m_vetoing
NXlogWriter< int > m_period
int getRefEventDetCard(const std::vector< int > &ev_source_ids)
void noFrameCallbackEnd(bool end_present, NoFrameCallbackMode mode, int event_source_id)
std::vector< int > m_det_id
NeXusEventCallback(const ISISCRPT_STRUCT *crpt, IXNeXusFile *file, const std::vector< int > &ev_source_ids)
LONGLONG m_monitor_events_not_saved
events discarded as outside tcb time window
std::map< std::string, uint64_t > m_events_write_total
card_frame_t m_card_frame
uint64_t m_good_uamph_sum
Poco::Thread m_worker_thread
void closeDataGroup(IXNeXusFile *nx, const std::string &name)
if name is null string, do nothing
std::map< std::string, std::vector< float > > float_map_t