wavecatcher-analysis
Loading...
Searching...
No Matches
ReadSampic.cc
Go to the documentation of this file.
1#include "ReadSampic.h"
2
23void ReadSampic::ReadFile(string path, bool change_polarity, int change_sign_from_to_ch_num, string out_file_name, bool debug, long long max_nfs_to_read) {
24 if (max_nfs_to_read <= 0) max_nfs_to_read = static_cast<long long>(1e9); // default 1B waveforms
25 rundata.reserve(1'000'000); // reserve space for 1M waveforms
26 hitInfo.reserve(1'000'000);
27 eventsBuilt = false; // reset flag
28 if (path.back() != '/') path += '/';
30
31 // save results to root file
32 if (out_file_name.empty()) out_file_name = "out.root";
33 printf("+++ saving analysis results in '%s' ...\n\n", out_file_name.c_str());
34 root_out = TFile::Open(out_file_name.c_str(), "recreate");
35
36 // invert channels
38
39 // create list of binary files in folder
41 inFileList << Helpers::ListFiles(path.c_str(), ".bin");
42 if (debug) cout << inFileList.str() << endl;
43
44 string fileName;
45 int file_counter = 0, wfcounter = 0;
46 string data_settings("=== DATA STRUCTURE INFO === REDUCED DATA TYPE: YES === WITHOUT WAVEFORM: NO === TDC-LIKE FILES: NO === COMPACT BINARY DATA: YES === DATA_IN_FILE_TYPE: 1 ===");
47
48 while (inFileList >> fileName) {
49 // read only fraction/batch of the .bin files for testing or to reduce memory usage
52
55 if (!input_file.is_open()) {
56 printf("*** failed to open '%s'\n", fileName.c_str());
57 continue;
58 }
59
60 if (file_counter < 10 || file_counter % 10 == 0 || debug) printf("+++ reading '%s' ...\n", fileName.c_str());
61
62 string line;
63 int header_line = 0;
64 float sampling_frequency = 0;
65 const float ADC_factor = 0.1; // conversion to mV
66 int has_measurement = 1; // true: contains absolute time, baseline, amplitude
67 unordered_set<int> active_channels_set; // store channels in data
68 SP = 0.;
69 while (header_line < 7) {
71 if (debug) cout << line.c_str() << endl;
72 if (header_line == 0 && line.find("SOFTWARE VERSION: V3.5.34") == string::npos && line.find("SOFTWARE VERSION:") != string::npos) {
73 cout << "WARNING: Expected software version V3.5.34 but found:\n" << line.c_str() << endl;
74 }
75 if (header_line == 3) {
76 size_t pos = line.find("DATA_IN_FILE_TYPE:");
77 if (pos != string::npos) has_measurement = stoi(line.substr(pos + 18));
78 if (line.substr(0, line.length() - 5) != data_settings.substr(0, data_settings.length() - 5)) {
79 cout << "\nWARNING: Unexpected DATA STRUCTURE INFO line.\n Found " << line.c_str() << endl;
80 cout << "instead of " << data_settings.c_str() << endl;
81 }
82 if (has_measurement == 1) cout << "Using HitStructInfoForWaveformAndMeasurements_t." << endl;
83 else cout << "Using HitStructInfoForWaveformOnly_t." << endl;
84 }
85 if (line.find("SAMPLING FREQUENCY") != string::npos) {
86 size_t pos = line.find("SAMPLING FREQUENCY ");
87 size_t pos2 = line.find(" MS/s");
88 if (pos != string::npos) {
89 string freq_str = line.substr(pos + 19, pos2);
92 SP_inv = 1. / SP;
93 if (file_counter == 0) cout << "Sampling frequency: " << sampling_frequency << " MS/s" << endl;
94 }
95 }
97 }
98 if (SP == 0.) {
99 throw runtime_error("ERROR: File header could not be read.");
100 }
101
104 int previous_binNumber = -1;
105 HitStructInfoForWaveformAndMeasurements_t hitData;
106 HitStructInfoForWaveformOnly_t hitDataNoMeas;
108 while (has_measurement ?
109 input_file.read((char *)(&hitData), sizeof(hitData)) :
110 input_file.read((char *)(&hitDataNoMeas), sizeof(hitDataNoMeas))) {
111 //waveform loop
112
113 if (!has_measurement) {
115 currentHitInfo.Channel = static_cast<int>(hitDataNoMeas.Channel);
116 currentHitInfo.FirstSampleTimeStamp = hitDataNoMeas.FirstSampleTimeStamp;
117 binNumber = static_cast<int>(hitDataNoMeas.WaveformSize);
118 }
119 else {
120 currentHitInfo.HitNumber = hitData.HitNumber;
121 currentHitInfo.Channel = static_cast<int>(hitData.Channel);
122 currentHitInfo.FirstSampleTimeStamp = hitData.FirstSampleTimeStamp;
123 binNumber = static_cast<int>(hitData.WaveformSize);
124 }
125
126 if (debug && wfcounter < 10) {
127 cout << "hit number: " << currentHitInfo.HitNumber << endl;
128 cout << "channel: " << currentHitInfo.Channel << endl;
129 cout << "timestamp: " << currentHitInfo.FirstSampleTimeStamp << endl;
130 // other stuff that is not yet used
131 // cout << "RawToTValue: " << hitData.RawToTValue << endl;
132 // cout << "TOTValue: " << hitData.TOTValue << endl;
133 // if (has_measurement == 1) {
134 // cout << "Time: " << hitData.Time << endl;
135 // cout << "Baseline: " << hitData.Baseline << endl;
136 // cout << "Amplitude: " << hitData.Amplitude << endl;
137 // }
138 // cout << "FirstCellIndex: " << static_cast<int>(hitData.FirstCellIndex) << endl;
139 cout << "samples: " << binNumber << endl;
140 }
141
142 if (wfcounter == 0 && file_counter == 0) { // init
144 }
145
146 if (active_channels_set.insert(currentHitInfo.Channel).second) { // check if channel is new
147 active_channels.push_back(currentHitInfo.Channel);
148 }
149
151 waveform.resize(binNumber);
152 waveform_f.resize(binNumber);
154 }
155
156 size_t waveform_bytes = static_cast<size_t>(binNumber) * sizeof(short);
157 input_file.read((char *)waveform.data(), waveform_bytes);
158
159 float factor = ADC_factor;
160 if (polarity_map[currentHitInfo.Channel]) factor = -factor;
161
162 for (int i = 0; i < binNumber; i++) {
163 waveform_f[i] = static_cast<float>(waveform[i]) * factor;
165 }
166 rundata.push_back(waveform_f);
167
168 currentHitInfo.Max = *max_element(waveform_f.begin(), waveform_f.end());
169 currentHitInfo.Min = *min_element(waveform_f.begin(), waveform_f.end());
170 hitInfo.push_back(currentHitInfo);
171
172 wfcounter++;
174 cout << "Stopped reading waveforms after max_nfs_to_read=" << max_nfs_to_read << endl;
175 break;
176 }
177 }
178
179 input_file.close();
180 file_counter++;
181 }
182 nwf = wfcounter;
183 sort(active_channels.begin(), active_channels.end());
184 nchannels = static_cast<int>(active_channels.size());
185
186 printf("Finished reading %d files containing %d hits with %d channels.\n\n", file_counter, nwf, nchannels);
187}
188
189
194void ReadSampic::PlotWF(int wfNumber, float ymin, float ymax) {
195 gStyle->SetOptStat(0);
196 int channel = hitInfo[wfNumber].Channel;
197 TString name(Form("waveform_%05d", wfNumber));
198 TString title(Form("wf%d, ch%d;t [ns];U [mV]", wfNumber, channel));
199 auto intwinc = new TCanvas(name.Data(), name.Data(), 600, 400);
200 auto his = new TH1F(name.Data(), title.Data(), binNumber, 0, IndexToTime(binNumber - 1));
201 for (int i = 1; i <= binNumber; i++) his->SetBinContent(i, rundata[wfNumber][i - 1]);
202 his->Draw("HIST");
203 his->SetStats(0);
204 his->GetYaxis()->SetRange(ymin, ymax);
205 intwinc->Update();
206 root_out->WriteObject(intwinc, name.Data());
207}
208
209
228void ReadSampic::EventBuilder(double coincidence_time_window, vector<float> thresholds, vector<int> channels, unsigned int min_coincidences, bool shift_relative) {
229 cout << "---------Started EventBuilder()---------" << endl;
230
232 if (coincidence_time_window > 1000) {
233 cout << "Warning: coincidence_time_window=" << coincidence_time_window << " ns must be <=1 us. Will use 1 us." << endl;
235 }
236 // store for plotting (NOT USED AS OF NOW)
237 coincidence_time = coincidence_time_window;
238
239 // init
240 bool include_all_channels = false;
241 if (channels.empty()) {
244 }
246
247 min_coincidences = min(static_cast<unsigned int>(channels.size()), min_coincidences);
248
249 float default_threshold = 0.;
250 if (thresholds.size() == 1) default_threshold = thresholds[0];
251 thresholds.resize(channels.size(), default_threshold);
252
253 // reset events if called more than once
254 if (eventsBuilt) {
255 wf_nr_event_storage.clear();
256 ch_nr_event_storage.clear();
257 skip_event.clear();
258 eventnr_storage.clear();
259 }
260
261 cout << "Coincidence time: " << coincidence_time_window << " ns" << endl;
262 cout << "Minimum number of coincidences: " << min_coincidences << endl;
263
264 // check if waveforms above thresholds
265 int n_canditates = 0;
266
267 #pragma omp parallel for reduction(+:n_canditates)
268 for (int i=0; i<nwf; i++) {
269 if (eventsBuilt) {
270 hitInfo[i].IsEventCandidate = false;
271 hitInfo[i].IsEvent = false;
272 }
273
275 int i_ch = GetChannelIndex(hitInfo[i].Channel);
276 if (hitInfo[i].Max > thresholds[i_ch]) {
277 hitInfo[i].IsEventCandidate = true;
278 n_canditates++;
279 }
280 }
281 }
282 cout << "There are " << n_canditates << " event seed candidates out of " << nwf << " waveforms" << endl;
283
284 // check for coincidences
285 int event_counter = 0;
286 for (int i=0; i<nwf; i++) {
287 if (hitInfo[i].IsEventCandidate) {
288 unsigned int coincidence_counter = 1;
289 double coincidence_window_lo = hitInfo[i].FirstSampleTimeStamp - coincidence_time_window * .5;
290 double coincidence_window_hi = hitInfo[i].FirstSampleTimeStamp + coincidence_time_window * .5;
291
292 int k_lo = i;
293 while (--k_lo >= 0 && hitInfo[k_lo].FirstSampleTimeStamp > coincidence_window_lo) {
294 if (hitInfo[k_lo].IsEventCandidate && !hitInfo[k_lo].IsEvent) coincidence_counter++;
295 }
296 k_lo++;
297 int k_hi = i;
298 while (++k_hi < nwf && hitInfo[k_hi].FirstSampleTimeStamp < coincidence_window_hi) {
299 if (hitInfo[k_hi].IsEventCandidate) coincidence_counter++;
300 }
301 k_hi--;
302
304 wf_nr_event_storage.push_back(vector<int>());
305 ch_nr_event_storage.push_back(vector<int>());
306 event_time_stamps.push_back(hitInfo[i].FirstSampleTimeStamp);
307
308 for (int kk = k_lo; kk <= k_hi; kk++) {
309 if (shift_relative) { // BROKEN
310 int shift_bins = static_cast<int>(floor(event_time_stamps[event_counter] - hitInfo[kk].FirstSampleTimeStamp) * static_cast<double>(SP_inv));
311 cout << event_time_stamps[event_counter] - hitInfo[kk].FirstSampleTimeStamp << " shift: " << shift_bins << endl;
312 // auto his = (TH1F*)rundata->At(kk);
313 // Helpers::ShiftTH1(his, shift_bins);
314 }
315 hitInfo[kk].EventNumber = event_counter;
316 hitInfo[kk].IsEvent = true;
318 ch_nr_event_storage[event_counter].push_back(hitInfo[kk].Channel);
319 }
320 i = k_hi; // jump to last wf in event
322 skip_event.push_back(false);
324 }
325 }
326 }
328 eventsBuilt = true;
329 cout << "Finished EventBuilder() and found " << nevents << " events in data:" << endl;
330 cout << left << setw(8) << "Channel" << " | " << right << setw(10) << "Threshold" << " | " << right << setw(10) << "Events" << endl;
331 cout << string(37, '-') << endl;
332 for (int i = 0; i < nchannels; i++) {
333 float thrshld = 0;
334 auto it = find(channels.begin(), channels.end(), active_channels[i]);
335 if (it != channels.end()) thrshld = thresholds[it - channels.begin()];
336
337 cout << left << setw(8) << active_channels[i] << " | " <<
338 right << setw(10) << thrshld << " | " <<
339 right << setw(10) << Nevents_good(i) << endl;
340 }
341}
342
348TH1F* ReadSampic::Getwf(int channelnr, int eventnr, int color) {
349 checkData();
351 channelnr = min(channelnr, static_cast<int>(active_channels.size()));
352
353 int wfindex = -1;
357 break;
358 }
359 }
360
361 if (wfindex != -1) {
362 int channel = hitInfo[wfindex].Channel;
363 int event_nr = hitInfo[wfindex].EventNumber;
364 TString name(Form("ch%02d_%05d", channel, event_nr));
365 TString title(Form("ch%d, event %d;t [ns];U [mV]", channel, event_nr));
366 auto his = new TH1F(name.Data(), title.Data(), binNumber, 0, SP * static_cast<float>(binNumber));
367 his->SetLineColor(color);
368 his->SetMarkerColor(color);
369 for (int i = 1; i <= binNumber; i++) his->SetBinContent(i, rundata[wfindex][i - 1]);
370 return his;
371 }
372 else {
373 // return zeroes if there is no waveform
374 static TH1F defaultHis("default", "NO DATA; t [ns]; U [mV]", binNumber, 0, SP * static_cast<float>(binNumber));
375 return &defaultHis;
376 }
377}
378
379
384int ReadSampic::GetWaveformIndex(int eventnr, int channel_index) {
385 int wf_index = -1;
389 int index = static_cast<int>(distance(ch_nr_event_storage[eventnr].begin(), it));
391 }
392 return wf_index;
393}
394
395
399int ReadSampic::GetCurrentChannel(int waveform_index) {
400 return GetChannelIndex(hitInfo[waveform_index].Channel);
401}
402
406int ReadSampic::GetCurrentEvent(int waveform_index) {
407 return hitInfo[waveform_index].EventNumber;
408}
409
413bool ReadSampic::SkipEvent(int event_index, int channel_index) {
414 if (event_index >= static_cast<int>(skip_event.size()) || event_index < 0) { // wrong input
415 return true;
416 }
417 else if (channel_index == -1) { // default just like parent class ReadRun
418 return skip_event[event_index];
419 }
421 // if the channel index is passed as well, it will return false only if the channel exists in not skipped event
422 return false;
423 }
424 else {
425 return true;
426 }
427}
static void filterChannelUserInput(vector< int > &, const vector< int >)
Check if user input exists in data and remove channels that are not there.
Definition Helpers.cc:97
static bool Contains(const vector< T > &vec, const T &val)
Returns true if vector vec contains value val.
Definition Helpers.h:55
static string ListFiles(const char *, const char *)
Helper. Creates a list of .bin data files in data folder to be read in.
Definition Helpers.cc:7
int FirstBinFileToRead
Number first of .bin file to be read in.
Definition ReadRun.h:257
int nevents
Number of triggered events in data.
Definition ReadRun.h:282
float IndexToTime(int)
Convert the bin number of the waveform to the time of the left bin edge
Definition ReadRun.cc:2887
vector< bool > skip_event
Stores the event numbers which should be skipped in the analysis.
Definition ReadRun.h:332
vector< int > active_channels
Stores the numbers of the active channels.
Definition ReadRun.h:311
vector< vector< float > > rundata
Stores waveforms.
Definition ReadRun.h:132
vector< bool > PolarityMap(bool, int)
Channel map of polarity changes during reading. For parameters see ReadFile().
Definition ReadRun.cc:2846
int GetChannelIndex(int)
Match channel number (wavecatcher input channel) to channel index.
Definition ReadRun.cc:2788
TFile * root_out
Stores results of analysis.
Definition ReadRun.h:360
int nChannelsWC
Wavecatcher hardware max. number of channels (reduce/increase if not using the 64 channel crate)
Definition ReadRun.h:303
int start_read_at_channel
Do analysis only for limited range of channels to reduce memory usage.
Definition ReadRun.h:277
virtual int Nevents_good(int=0)
Number of good events that are not skipped.
Definition ReadRun.cc:1505
vector< vector< float > > amplValuessum
Collects sums of all waveforms for each channel.
Definition ReadRun.h:135
int nwf
Total number of waveforms read from data: number of active channels x number of events.
Definition ReadRun.h:286
int binNumber
Number of bins (usually 1024 samples per waveform).
Definition ReadRun.h:301
float SP_inv
1/SP
Definition ReadRun.h:295
string data_path
Path to data.
Definition ReadRun.h:248
int nchannels
Number of active channels in data.
Definition ReadRun.h:284
float SP
Sampling: ns per bin of data, sampling rate 3.2 GS/s -> 0.3125 ns.
Definition ReadRun.h:293
int LastBinFileToRead
Number of last .bin file to be read in.
Definition ReadRun.h:253
vector< unsigned int > eventnr_storage
Events will be stored here in the order they have been read.
Definition ReadRun.h:138
int GetCurrentEvent(int) override
Get the current event index for a certain waveform index.
vector< HitInfoReduced > hitInfo
Stores additional info about wf.
Definition ReadSampic.h:96
void PlotWF(int, float=0, float=0)
Plot any Waveform (can be called before EventBuilder to check data)
int GetWaveformIndex(int, int) override
Returns index of a certain event number (if data files are read in parallel threads)
void checkData(bool isBaselineCorrection=false) const override
Primitive check to see if data has been loaded.
Definition ReadSampic.h:43
void EventBuilder(double, vector< float >={}, vector< int > channels={}, unsigned int=1, bool=false)
Construct events based on coincident amplitude thresholds within a time window for different channels...
void ReadFile(string, bool=true, int=0, string="out.root", bool=false, long long=0) override
Routine to read files created by SAMPIC DAQ.
Definition ReadSampic.cc:23
TH1F * Getwf(int, int, int=1) override
Helper that returns the waveform histogram for a certain channel number and a certain event number.
vector< vector< int > > wf_nr_event_storage
Stores all waveform numbers assigned to events.
Definition ReadSampic.h:98
bool eventsBuilt
Check if the data is grouped in events (SAMPIC needs manual event building)
Definition ReadSampic.h:41
int GetCurrentChannel(int) override
Get the current channel index for a certain waveform index.
vector< double > event_time_stamps
Stores all event times.
Definition ReadSampic.h:102
bool SkipEvent(int, int=-1) override
Check if event has skipped flag. Will return true if event flag is false but channel does not exist i...
vector< vector< int > > ch_nr_event_storage
Stores all channel numbers assigned to events.
Definition ReadSampic.h:100
Stores additional information with the waveforms.
Definition ReadSampic.h:83