88
97
// For the Ckov, it's similar. Just change TOF to Ckov.
90
std::vector<Json::Value> all_ckov_digits;
91
all_ckov_digits.push_back(Json::Value());
100
// Get spill, break if there's no DAQ data
101
Spill *spill = data->GetSpill();
102
if (spill->GetMCEvents() == NULL)
105
MCEventPArray *mcEvts = spill->GetMCEvents();
106
int nPartEvents = spill->GetMCEventSize();
107
if (nPartEvents == 0)
110
ReconEventPArray *recEvts = spill->GetReconEvents();
112
// Resize the recon event to hold mc events
113
if (spill->GetReconEventSize() == 0) { // No recEvts yet
114
for (int iPe = 0; iPe < nPartEvents; iPe++) {
115
recEvts->push_back(new ReconEvent);
119
if (fDebug) std::cerr << "mc numevt = i" << mcEvts->size() << std::endl;
93
121
// loop over events
94
if (fDebug) printf("mc numevt = %i", mc.size());
95
for ( unsigned int i = 0; i < mc.size(); i++ ) {
96
Json::Value particle = mc[i];
97
double gentime = particle["primary"]["time"].asDouble();
98
if (fDebug) std::cout << "evt: " << i << " pcle= " << particle << std::endl;
100
// hits for this event
101
Json::Value _hits = particle["ckov_hits"];
102
// if _hits.size() = 0, the make_digits and fill_ckov_evt functions will
103
// return null. The Ckov recon expects something - either null or data, can't just skip
104
all_ckov_digits.clear();
106
// pick out tof hits, digitize and store
107
all_ckov_digits = make_ckov_digits(_hits, gentime, *document);
109
// Does Ckov need this pixel thing? Maybe not.
110
// std::string strig = findTriggerPixel(all_tof_digits);
112
// ------>NOW, go through the stations and fill Ckov events
113
// real data tof digits look like so:
114
// "digits":{"tof1":[ [evt0..{pmt0},{pmt1}..],[evt1..]],"tof0":[[evt0]..],tof2..}
115
// loop over ckov stations
116
Json::Value ckov_digitAB(Json::arrayValue);
117
ckov_digitAB.clear();
118
for (int snum = 0; snum < 2; ++snum) {
119
for (unsigned int kk = 0; kk < all_ckov_digits.size(); ++kk) {
120
// check that this digit belongs to the station we are trying to fill
121
if (all_ckov_digits[kk]["station"].asInt() != snum) continue;
122
ckov_digitAB.append(fill_ckov_evt(i, snum, all_ckov_digits, kk));
124
} // end loop over stations
125
root["recon_events"][i]["ckov_event"]["ckov_digits"] = ckov_digitAB;
122
for ( unsigned int i = 0; i < mcEvts->size(); i++ ) {
123
// Get Ckov hits for this event
124
CkovHitArray *hit_array = spill->GetAnMCEvent(i).GetCkovHits();
125
if (fDebug) printf("\nNumber of hits: %i\n", hit_array->size());
127
double gentime = spill->GetAnMCEvent(i).GetPrimary()->GetTime();
128
CkovEvent *evt = new CkovEvent();
129
(*recEvts)[i]->SetCkovEvent(evt);
131
// process only if there are hits
134
// pick out ckov hits, digitize and store
135
multi_ckov_dig all_ckov_dig = make_ckov_digits(hit_array, gentime);
137
CkovDigitArray* digit_array = evt->GetCkovDigitArrayPtr();
138
fill_ckov_evt(i, all_ckov_dig, digit_array);
140
} // end check-if-hits
126
141
} // end loop over events
129
144
//////////////////////////////////////////////////////////////////////
130
std::vector<Json::Value>
131
MapCppCkovMCDigitizer::make_ckov_digits(Json::Value hits, double gentime,
132
Json::Value& root) const {
133
std::vector<Json::Value> ckov_digits;
135
if (hits.size() == 0) return ckov_digits;
137
for (unsigned int j = 0; j < hits.size(); ++j) { // j-th hit
138
Json::Value hit = hits[j];
145
multi_ckov_dig MapCppCkovMCDigitizer::make_ckov_digits(CkovHitArray* hit_array,
146
double gentime) const {
148
multi_ckov_dig all_ckov_dig(0);
149
if (hit_array->size() == 0) return all_ckov_dig;
151
for (unsigned int j = 0; j < hit_array->size(); ++j) { // j-th hit
152
CkovHit hit = hit_array->at(j);
140
153
if (fDebug) std::cout << "=================== hit# " << j << std::endl;
142
// make sure we can get the station/slab info
143
if (!hit.isMember("channel_id"))
155
// make sure we can get the station number
156
if (!hit.GetChannelId())
144
157
throw(Exception(Exception::recoverable,
145
158
"No channel_id in hit",
146
159
"MapCppCkovMCDigitizer::make_ckov_digits"));
147
if (!hit.isMember("momentum"))
148
throw(Exception(Exception::recoverable,
149
"No momentum in hit",
150
"MapCppCkovMCDigitizer::make_ckov_digits"));
151
if (!hit.isMember("time"))
152
throw(Exception(Exception::recoverable,
154
"MapCppCkovMCDigitizer::make_ckov_digits"));
155
Json::Value channel_id = hit["channel_id"];
157
if (!hit.isMember("energy_deposited"))
158
throw(Exception(Exception::recoverable,
159
"No energy_deposited in hit",
160
"MapCppCkovMCDigitizer::make_ckov_digits"));
161
double edep = hit["energy_deposited"].asDouble();
161
double edep = hit.GetEnergyDeposited();
163
163
// Ckov hits in the CkovChannelIdProcessor of Json Parser registers a property
164
164
// "station_number" in channel_id
165
int stn = hit["channel_id"]["station_number"].asInt();
165
int stn = hit.GetChannelId()->GetStation();
167
167
// find the geo module corresponding to this hit
168
168
const MiceModule* hit_module = NULL;
234
236
<< " " << tdc2 << " " << tdc3 << std::endl;
237
Json::Value tmpDigit;
239
tmpDigit["channel_id"] = hit["channel_id"];
240
tmpDigit["momentum"] = hit["momentum"];
241
tmpDigit["time"] = hit["time"];
242
tmpDigit["position"]=hit["position"];
243
tmpDigit["isUsed"] = 0;
244
tmpDigit["npe"] = npe;
246
// set the key for this channel
247
tmpDigit["station"] = stn;
248
tmpDigit["npe0"] = npe0;
249
tmpDigit["leading_time0"] = tdc0;
250
tmpDigit["raw_time0"] = time0;
251
tmpDigit["npe1"] = npe1;
252
tmpDigit["leading_time1"] = tdc1;
253
tmpDigit["raw_time1"] = time1;
254
tmpDigit["npe2"] = npe2;
255
tmpDigit["leading_time2"] = tdc2;
256
tmpDigit["raw_time2"] = time2;
257
tmpDigit["npe3"] = npe3;
258
tmpDigit["leading_time3"] = tdc3;
259
tmpDigit["raw_time3"] = time3;
260
ckov_digits.push_back(tmpDigit);
261
} // for (unsigned int j = 0; j < hits.size(); ++j)
266
//////////////////////////////////////////////////////////////////////
267
Json::Value MapCppCkovMCDigitizer::check_sanity_mc(Json::Value& root) const {
268
// Check if the JSON document can be parsed, else return error only
269
// Check if the JSON document has a 'mc' branch, else return error
270
if (!root.isMember("mc_events")) {
271
throw MAUS::Exception(Exception::recoverable,
272
"Could not find an MC branch to simulate.",
273
"MapCppCkovMCDigitizer::check_sanity_mc");
276
Json::Value mc = root.get("mc_events", 0);
277
// Check if JSON document is of the right type, else return error
279
throw MAUS::Exception(Exception::recoverable,
280
"MC branch was not an array.",
281
"MapCppCkovMCDigitizer::check_sanity_mc");
286
//////////////////////////////////////////////////////////////////////
287
double MapCppCkovMCDigitizer::get_npe(Json::Value hit) const {
239
one_ckov_dig a_ckov_dig;
240
a_ckov_dig.fChannelId = hit.GetChannelId();
241
a_ckov_dig.fMom = hit.GetMomentum();
242
a_ckov_dig.fTime = hit.GetTime();
243
a_ckov_dig.fPos = hit.GetPosition();
244
a_ckov_dig.fIsUsed = 0;
245
a_ckov_dig.fNpe = npe;
247
// set the key for this channel
248
a_ckov_dig.fStation = stn;
249
a_ckov_dig.fNpe0 = npe0;
250
a_ckov_dig.fLeadingTime0 = tdc0;
251
a_ckov_dig.fRawTime0 = time0;
252
a_ckov_dig.fNpe1 = npe1;
253
a_ckov_dig.fLeadingTime1 = tdc1;
254
a_ckov_dig.fRawTime1 = time1;
255
a_ckov_dig.fNpe2 = npe2;
256
a_ckov_dig.fLeadingTime2 = tdc2;
257
a_ckov_dig.fRawTime2 = time2;
258
a_ckov_dig.fNpe3 = npe3;
259
a_ckov_dig.fLeadingTime3 = tdc3;
260
a_ckov_dig.fRawTime3 = time3;
261
all_ckov_dig.push_back(a_ckov_dig);
262
} // for (unsigned int j = 0; j < hit_array.size(); ++j)
266
//////////////////////////////////////////////////////////////////////
267
double MapCppCkovMCDigitizer::get_npe(CkovHit& hit) const {
289
269
double nphot = 0.;
290
270
double nptmp = 0.;
291
double muon_thrhold = 0.;
292
double charge_per_pe = 0.;
293
// scaling factor to data
294
double scaling = 0.935;
295
271
// mass of the hit particle;
296
double particle_mass = hit["mass"].asDouble();
272
double particle_mass = hit.GetMass();
297
273
// momentum of the hit particle;
298
double px = hit["momentum"]["x"].asDouble();
299
double py = hit["momentum"]["y"].asDouble();
300
double pz = hit["momentum"]["z"].asDouble();
274
double px = hit.GetMomentum().x();
275
double py = hit.GetMomentum().y();
276
double pz = hit.GetMomentum().z();
301
277
double p_tot = sqrt(px*px + py*py + pz*pz);
303
if (hit["channel_id"]["station_number"].asInt() == 0) {
304
muon_thrhold = 275.0;
305
charge_per_pe = 17.3;
306
} else if (hit["channel_id"]["station_number"].asInt() == 1) {
307
muon_thrhold = 210.0;
279
int hitStation = hit.GetChannelId()->GetStation();
280
int hitPid = hit.GetParticleId();
311
282
// momentum threshold, see Lucien's Python code.
312
double pp_threshold = muon_thrhold * particle_mass / 105.6;
283
double pp_threshold = muon_thrhold[hitStation] * particle_mass / 105.6;
314
285
// smearing constant
315
286
const double smear_const = 0.5;
406
377
//////////////////////////////////////////////////////////////////////
407
Json::Value MapCppCkovMCDigitizer::fill_ckov_evt(int evnum,
409
std::vector<Json::Value> all_ckov_digits,
412
Json::Value ckov_digits;
415
// return null if this evt had no ckov hits
416
if (all_ckov_digits.size() == 0) return ckov_digits;
426
// check if the digit has been used
427
if (all_ckov_digits[i]["isUsed"].asInt() == 0) {
431
npe = all_ckov_digits[i]["npe"].asDouble();
432
// 23 is the ADC factor.
433
int adc = static_cast<int>(npe * 23);
435
// NOTE: needs tweaking/verifying -- DR 3/15
436
// NOTE: if tof needs tweaking, Ckov also needs it. -- frankliuao 8/15
437
// Initialize digits for both stations:
438
digitA["position_min_0"] = 0;
439
digitA["position_min_1"] = 0;
440
digitA["position_min_2"] = 0;
441
digitA["position_min_3"] = 0;
442
digitA["pulse_0"] = 0;
443
digitA["pulse_1"] = 0;
444
digitA["pulse_2"] = 0;
445
digitA["pulse_3"] = 0;
446
digitA["coincidences"] = 0;
447
digitA["total_charge"] = 0;
448
digitA["arrival_time_0"] = 0;
449
digitA["arrival_time_1"] = 0;
450
digitA["arrival_time_2"] = 0;
451
digitA["arrival_time_3"] = 0;
452
digitA["part_event_number"] = 0;
453
digitA["number_of_pes"] = 0;
456
digitB["position_min_4"] = 0;
457
digitB["position_min_5"] = 0;
458
digitB["position_min_6"] = 0;
459
digitB["position_min_7"] = 0;
460
digitB["pulse_4"] = 0;
461
digitB["pulse_5"] = 0;
462
digitB["pulse_6"] = 0;
463
digitB["pulse_7"] = 0;
464
digitB["total_charge"] = 0;
465
digitB["coincidences"] = 0;
466
digitB["arrival_time_4"] = 0;
467
digitB["arrival_time_5"] = 0;
468
digitB["arrival_time_6"] = 0;
469
digitB["arrival_time_7"] = 0;
470
digitB["part_event_number"] = 0;
471
digitB["number_of_pes"] = 0;
475
digitA["arrival_time_0"] = all_ckov_digits[i]["leading_time0"];
476
digitA["arrival_time_1"] = all_ckov_digits[i]["leading_time1"];
477
digitA["arrival_time_2"] = all_ckov_digits[i]["leading_time2"];
478
digitA["arrival_time_3"] = all_ckov_digits[i]["leading_time3"];
479
digitA["total_charge"] = adc;
480
digitA["part_event_number"] = evnum;
481
digitA["number_of_pes"] = npe;
483
digitB["arrival_time_4"] = all_ckov_digits[i]["leading_time0"];
484
digitB["arrival_time_5"] = all_ckov_digits[i]["leading_time1"];
485
digitB["arrival_time_6"] = all_ckov_digits[i]["leading_time2"];
486
digitB["arrival_time_7"] = all_ckov_digits[i]["leading_time3"];
487
digitB["total_charge"] = adc;
488
digitB["part_event_number"] = evnum;
489
digitB["number_of_pes"] = npe;
492
all_ckov_digits[i]["isUsed"] = 1;
493
} // #if (all_ckov_digits[i]["isUsed"].asInt() == 0)
494
ckov_digits["A"] = digitA;
495
ckov_digits["B"] = digitB;
378
void MapCppCkovMCDigitizer::fill_ckov_evt(int evnum,
379
multi_ckov_dig& all_ckov_dig,
380
CkovDigitArray* digit_array) const {
381
// return null if this evt had no ckov hits, no need to go further;
382
if (all_ckov_dig.size() == 0) return;
384
/* If there are hits:
385
* For this given event number, there might be multiple hits;
386
* If the hits belong to 2 stations, they should be filled simultaneously to
387
* the digits, but in their respective structure;
388
* Otherwise, we need to integrate the digits together and get an average;
390
std::vector<double> npe_each_hit_a;
391
std::vector<double> npe_each_hit_b;
392
std::vector<double> arrival_time0_each_hit_a;
393
std::vector<double> arrival_time1_each_hit_a;
394
std::vector<double> arrival_time2_each_hit_a;
395
std::vector<double> arrival_time3_each_hit_a;
396
std::vector<double> arrival_time4_each_hit_b;
397
std::vector<double> arrival_time5_each_hit_b;
398
std::vector<double> arrival_time6_each_hit_b;
399
std::vector<double> arrival_time7_each_hit_b;
401
// Count how many hits each station has
402
int num_of_hits_a = 0;
403
int num_of_hits_b = 0;
405
for (int snum = 0; snum < 2; ++snum) {
406
for (unsigned int kk = 0; kk < all_ckov_dig.size(); ++kk) {
407
// check that this hit has not already been used/filled
408
if (all_ckov_dig[kk].fStation != snum) continue;
409
if (all_ckov_dig[kk].fIsUsed == 0) {
410
// 23 is the ADC factor.
411
// the factor - ckovNpeToAdc is set at birth, defined in header
412
// keeping for-now-hardcoded definitions in one place
416
arrival_time0_each_hit_a.push_back(all_ckov_dig[kk].fLeadingTime0);
417
arrival_time1_each_hit_a.push_back(all_ckov_dig[kk].fLeadingTime1);
418
arrival_time2_each_hit_a.push_back(all_ckov_dig[kk].fLeadingTime2);
419
arrival_time3_each_hit_a.push_back(all_ckov_dig[kk].fLeadingTime3);
420
npe_each_hit_a.push_back(all_ckov_dig[kk].fNpe);
423
arrival_time4_each_hit_b.push_back(all_ckov_dig[kk].fLeadingTime0);
424
arrival_time5_each_hit_b.push_back(all_ckov_dig[kk].fLeadingTime1);
425
arrival_time6_each_hit_b.push_back(all_ckov_dig[kk].fLeadingTime2);
426
arrival_time7_each_hit_b.push_back(all_ckov_dig[kk].fLeadingTime3);
427
npe_each_hit_b.push_back(all_ckov_dig[kk].fNpe);
430
all_ckov_dig[kk].fIsUsed = true;
431
} // end check if-digit-used
432
} // end loop over tmp digits
433
} // end loop over stations
435
// Now, if either num_of_hits_a(b) == 0, write the default values to the station:
436
// Can not be 0 at the same time. If there are no hits, it won't reach this far.
439
if (num_of_hits_a == 0) {
441
digitA.SetArrivalTime0(-999);
442
digitA.SetArrivalTime1(-999);
443
digitA.SetArrivalTime2(-999);
444
digitA.SetArrivalTime3(-999);
445
digitA.SetTotalCharge(-999);
446
digitA.SetPartEventNumber(evnum);
447
digitA.SetNumberOfPes(-999);
448
digitA.SetPositionMin0(-999);
449
digitA.SetPositionMin1(-999);
450
digitA.SetPositionMin2(-999);
451
digitA.SetPositionMin3(-999);
452
digitA.SetPulse0(-999);
453
digitA.SetPulse1(-999);
454
digitA.SetPulse2(-999);
455
digitA.SetPulse3(-999);
456
digitA.SetCoincidences(-999);
458
digitB.SetArrivalTime4(std::accumulate(arrival_time4_each_hit_b.begin(),
459
arrival_time4_each_hit_b.end(),
460
0.0) / arrival_time4_each_hit_b.size());
461
digitB.SetArrivalTime5(std::accumulate(arrival_time5_each_hit_b.begin(),
462
arrival_time5_each_hit_b.end(),
463
0.0) / arrival_time5_each_hit_b.size());
464
digitB.SetArrivalTime6(std::accumulate(arrival_time6_each_hit_b.begin(),
465
arrival_time6_each_hit_b.end(),
466
0.0) / arrival_time6_each_hit_b.size());
467
digitB.SetArrivalTime7(std::accumulate(arrival_time7_each_hit_b.begin(),
468
arrival_time7_each_hit_b.end(),
469
0.0) / arrival_time7_each_hit_b.size());
470
double total_npe = std::accumulate(npe_each_hit_b.begin(),
471
npe_each_hit_b.end(),
473
digitB.SetTotalCharge(static_cast<int> (total_npe * ckovNpeToAdc));
474
digitB.SetPartEventNumber(evnum);
475
digitB.SetNumberOfPes(total_npe);
476
digitB.SetPositionMin4(0);
477
digitB.SetPositionMin5(0);
478
digitB.SetPositionMin6(0);
479
digitB.SetPositionMin7(0);
484
digitB.SetCoincidences(0);
485
} else if (num_of_hits_b == 0) {
486
digitB.SetArrivalTime4(-999);
487
digitB.SetArrivalTime5(-999);
488
digitB.SetArrivalTime6(-999);
489
digitB.SetArrivalTime7(-999);
490
digitB.SetTotalCharge(-999);
491
digitB.SetPartEventNumber(evnum);
492
digitB.SetNumberOfPes(-999);
493
digitB.SetPositionMin4(-999);
494
digitB.SetPositionMin5(-999);
495
digitB.SetPositionMin6(-999);
496
digitB.SetPositionMin7(-999);
497
digitB.SetPulse4(-999);
498
digitB.SetPulse5(-999);
499
digitB.SetPulse6(-999);
500
digitB.SetPulse7(-999);
501
digitB.SetCoincidences(-999);
503
digitA.SetArrivalTime0(std::accumulate(arrival_time0_each_hit_a.begin(),
504
arrival_time0_each_hit_a.end(),
505
0.0) / arrival_time0_each_hit_a.size());
506
digitA.SetArrivalTime1(std::accumulate(arrival_time1_each_hit_a.begin(),
507
arrival_time1_each_hit_a.end(),
508
0.0) / arrival_time1_each_hit_a.size());
509
digitA.SetArrivalTime2(std::accumulate(arrival_time2_each_hit_a.begin(),
510
arrival_time2_each_hit_a.end(),
511
0.0) / arrival_time2_each_hit_a.size());
512
digitA.SetArrivalTime3(std::accumulate(arrival_time3_each_hit_a.begin(),
513
arrival_time3_each_hit_a.end(),
514
0.0) / arrival_time3_each_hit_a.size());
515
double total_npe = std::accumulate(npe_each_hit_a.begin(),
516
npe_each_hit_a.end(),
518
digitA.SetTotalCharge(static_cast<int> (total_npe * ckovNpeToAdc));
519
digitA.SetPartEventNumber(evnum);
520
digitA.SetNumberOfPes(total_npe);
521
digitA.SetPositionMin0(0);
522
digitA.SetPositionMin1(0);
523
digitA.SetPositionMin2(0);
524
digitA.SetPositionMin3(0);
529
digitA.SetCoincidences(0);
531
digitA.SetArrivalTime0(std::accumulate(arrival_time0_each_hit_a.begin(),
532
arrival_time0_each_hit_a.end(),
533
0.0) / arrival_time0_each_hit_a.size());
534
digitA.SetArrivalTime1(std::accumulate(arrival_time1_each_hit_a.begin(),
535
arrival_time1_each_hit_a.end(),
536
0.0) / arrival_time1_each_hit_a.size());
537
digitA.SetArrivalTime2(std::accumulate(arrival_time2_each_hit_a.begin(),
538
arrival_time2_each_hit_a.end(),
539
0.0) / arrival_time2_each_hit_a.size());
540
digitA.SetArrivalTime3(std::accumulate(arrival_time3_each_hit_a.begin(),
541
arrival_time3_each_hit_a.end(),
542
0.0) / arrival_time3_each_hit_a.size());
543
double total_npe = std::accumulate(npe_each_hit_a.begin(),
544
npe_each_hit_a.end(),
546
digitA.SetTotalCharge(static_cast<int> (total_npe * ckovNpeToAdc));
547
digitA.SetPartEventNumber(evnum);
548
digitA.SetNumberOfPes(total_npe);
549
digitA.SetPositionMin0(0);
550
digitA.SetPositionMin1(0);
551
digitA.SetPositionMin2(0);
552
digitA.SetPositionMin3(0);
557
digitA.SetCoincidences(0);
558
digitB.SetArrivalTime4(std::accumulate(arrival_time4_each_hit_b.begin(),
559
arrival_time4_each_hit_b.end(),
560
0.0) / arrival_time4_each_hit_b.size());
561
digitB.SetArrivalTime5(std::accumulate(arrival_time5_each_hit_b.begin(),
562
arrival_time5_each_hit_b.end(),
563
0.0) / arrival_time5_each_hit_b.size());
564
digitB.SetArrivalTime6(std::accumulate(arrival_time6_each_hit_b.begin(),
565
arrival_time6_each_hit_b.end(),
566
0.0) / arrival_time6_each_hit_b.size());
567
digitB.SetArrivalTime7(std::accumulate(arrival_time7_each_hit_b.begin(),
568
arrival_time7_each_hit_b.end(),
569
0.0) / arrival_time7_each_hit_b.size());
570
total_npe = std::accumulate(npe_each_hit_b.begin(),
571
npe_each_hit_b.end(),
573
digitB.SetTotalCharge(static_cast<int> (total_npe * ckovNpeToAdc));
574
digitB.SetPartEventNumber(evnum);
575
digitB.SetNumberOfPes(total_npe);
576
digitB.SetPositionMin4(0);
577
digitB.SetPositionMin5(0);
578
digitB.SetPositionMin6(0);
579
digitB.SetPositionMin7(0);
584
digitB.SetCoincidences(0);
587
// Now fill in the digits:
589
aDigit.SetCkovA(digitA);
590
aDigit.SetCkovB(digitB);
591
digit_array->push_back(aDigit);
498
593
//=====================================================================