/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
#include "Utils/CppErrorHandler.hh"
#include "Utils/JsonWrapper.hh"
#include "Utils/DAQChannelMap.hh"
#include "Utils/Exception.hh"
#include "Interface/dataCards.hh"
#include "API/PyWrapMapBase.hh"
#include "src/map/MapCppCkovDigits/MapCppCkovDigits.hh"
namespace MAUS {
PyMODINIT_FUNC init_MapCppCkovDigits(void) {
PyWrapMapBase::PyWrapMapBaseModInit
("MapCppCkovDigits", "", "", "", "");
}
MapCppCkovDigits::MapCppCkovDigits() : MapBase("MapCppCkovDigits") {
}
void MapCppCkovDigits::_birth(const std::string& argJsonConfigDocument) {
char* pMAUS_ROOT_DIR = getenv("MAUS_ROOT_DIR");
if (!pMAUS_ROOT_DIR) {
throw MAUS::Exceptions::Exception(Exceptions::recoverable,
"Could not find the $MAUS_ROOT_DIR environmental variable.",
"MapCppCkovDigits::_birth");
}
// Check if the JSON document can be parsed, else return error only
// JsonCpp setup
Json::Value configJSON;
Json::Value map_file_name;
Json::Value xEnable_V1731_Unpacking;
configJSON = JsonWrapper::StringToJson(argJsonConfigDocument);
xEnable_V1731_Unpacking = JsonWrapper::GetProperty(configJSON,
"Enable_V1731_Unpacking",
JsonWrapper::booleanValue);
if (!xEnable_V1731_Unpacking.asBool()) {
Squeak::mout(Squeak::warning)
<< "WARNING in MapCppCkovDigits::birth. The unpacking of the flashADC V1731 is disabled!!!"
<< " Are you sure you want this?"
<< std::endl;
}
_position_threshold = 40;
_pulse_area_threshold = 0;
_window_min = 19;
_window_max = 80;
_maxCoincidences = 4;
}
void MapCppCkovDigits::_death() {}
///////////////////////////////////////////////////////////
void MapCppCkovDigits::_process(MAUS::Data* data) const {
Spill *spill = data->GetSpill();
if (spill->GetDAQData() == NULL)
return;
/* return if not physics spill */
if (spill->GetDaqEventType() != "physics_event")
return;
CkovArray *ckov_data = spill->GetDAQData()->GetCkovArrayPtr();
int n_part_events = ckov_data->size();
int recPartEvents = spill->GetReconEventSize();
ReconEventPArray *recEvts = spill->GetReconEvents();
// Check if recon events, if not initialize
if (recPartEvents == 0) { // No recEvts yet
for (int iPe = 0; iPe < n_part_events; iPe++) {
recEvts->push_back(new ReconEvent);
}
}
/* loop over events, and get adc, calculate signal, set digits */
for (int xPE = 0; xPE < n_part_events; xPE++) {
CkovEvent *evt = new CkovEvent();
(*recEvts)[xPE]->SetCkovEvent(evt);
CkovDigitArray *ckov_digits = evt->GetCkovDigitArrayPtr();
/* return if no ckov daq data */
if (ckov_data->at(xPE) == NULL)
continue;
V1731Array ckov_adc_hits = (ckov_data->at(xPE))->GetV1731Array();
/* skip if no v1731 hits */
if (ckov_adc_hits.size() == 0)
continue;
CkovTmpDigs ckov_digs_tmp = getAdc(ckov_adc_hits);
this->setDigits(ckov_digs_tmp, ckov_digits);
}
}
///////////////////////////////////////////////////////////
CkovTmpDigs MapCppCkovDigits::getAdc(V1731Array &adcHits) const {
double _one_pe[8] = {23., 23., 23., 23., 23., 23., 23., 23.};
int ckovid, pindex;
CkovTmpDigs ckov_digs_tmp;
ckov_digs_tmp.resize(2);
for (int iPmt = 0; iPmt < adcHits.size(); iPmt++) {
pindex = iPmt % 4;
CkovAdcHits ckd;
if (iPmt < 4)
ckovid = 0;
else
ckovid = 1;
ckd.pulse[pindex] = (adcHits[iPmt]).GetPulseArea();
ckd.posmin[pindex] = (adcHits[iPmt]).GetPositionMin();
ckd.arTime[pindex] = (adcHits[iPmt]).GetArrivalTime();
if (ckd.pulse[pindex] >= _pulse_area_threshold &&
ckd.posmin[pindex] > _window_min && ckd.posmin[pindex] <= _window_max) {
ckd.totpulse[pindex] = ckd.pulse[pindex];
ckd.pes[pindex] = (static_cast(ckd.pulse[pindex])/_one_pe[iPmt]);
ckd.position[pindex] = ckd.posmin[pindex];
} else {
ckd.totpulse[pindex] = 0;
ckd.pes[pindex] = 0;
ckd.position[pindex] = 300;
}
if (iPmt == 3 || iPmt == 7) {
ckd.ckovindex = ckovid;
ckd.partnum = adcHits[iPmt].GetPartEventNumber();
getSignal(&ckd);
ckov_digs_tmp[ckovid] = ckd;
}
}
return ckov_digs_tmp;
}
///////////////////////////////////////////////////////////
void MapCppCkovDigits::getSignal(CkovAdcHits* ckdigs) const {
int nzeros = std::count(ckdigs->totpulse, ckdigs->totpulse + 4, 0);
ckdigs->ncoin = _maxCoincidences - nzeros;
int max_index = std::distance(ckdigs->totpulse,
std::max_element(ckdigs->totpulse, ckdigs->totpulse + 4));
int dist;
/* debug
for (int kk=0; kk<4; ++kk) {
std::cerr << "pulse: " << kk << " " << ckdigs->pulse[kk]
<< " totpulse: " << kk << " " << ckdigs->totpulse[kk]
<< "pos: " << kk << " " << ckdigs->position[kk
<< "pes: " << kk << " " << ckdigs->pes[kk]
<< std::endl;
}
*/
if (nzeros == 4) {
ckdigs->totcharge = 0;
ckdigs->totnpe = 0.0;
ckdigs->ncoin = 0;
} else if (nzeros == 3) {
ckdigs->totcharge = std::accumulate(ckdigs->totpulse, ckdigs->totpulse + 4, 0);
ckdigs->totnpe = std::accumulate(ckdigs->pes, ckdigs->pes + 4, 0.0);
} else if (nzeros < 3) {
for (int k = 0; k < 4; ++k) {
dist = abs(ckdigs->position[k] - ckdigs->position[max_index]);
if (dist > _position_threshold) {
ckdigs->totpulse[k] = 0;
ckdigs->pes[k] = 0;
}
}
ckdigs->totcharge = std::accumulate(ckdigs->totpulse, ckdigs->totpulse + 4, 0);
ckdigs->totnpe = std::accumulate(ckdigs->pes, ckdigs->pes + 4, 0.0);
}
}
///////////////////////////////////////////////////////////
void MapCppCkovDigits::setDigits(CkovTmpDigs &tmpDigs, CkovDigitArray* theDigits) const {
CkovDigit aDigit;
CkovA ckov_a;
CkovB ckov_b;
// this is a little silly, the parameters should be set in arrays
// rather than in noindexable string names
// datastructure changes will have to wait for another day, DR 6/30/15
// Set Ckov A
ckov_a.SetArrivalTime0(tmpDigs[0].arTime[0]);
ckov_a.SetArrivalTime1(tmpDigs[0].arTime[1]);
ckov_a.SetArrivalTime2(tmpDigs[0].arTime[2]);
ckov_a.SetArrivalTime3(tmpDigs[0].arTime[3]);
ckov_a.SetPositionMin0(tmpDigs[0].posmin[0]);
ckov_a.SetPositionMin1(tmpDigs[0].posmin[1]);
ckov_a.SetPositionMin2(tmpDigs[0].posmin[2]);
ckov_a.SetPositionMin3(tmpDigs[0].posmin[3]);
ckov_a.SetPulse0(tmpDigs[0].pulse[0]);
ckov_a.SetPulse1(tmpDigs[0].pulse[1]);
ckov_a.SetPulse2(tmpDigs[0].pulse[2]);
ckov_a.SetPulse3(tmpDigs[0].pulse[3]);
ckov_a.SetPulse0(tmpDigs[0].pulse[0]);
ckov_a.SetPulse1(tmpDigs[0].pulse[1]);
ckov_a.SetPulse2(tmpDigs[0].pulse[2]);
ckov_a.SetPulse3(tmpDigs[0].pulse[3]);
ckov_a.SetTotalCharge(tmpDigs[0].totcharge);
ckov_a.SetNumberOfPes(tmpDigs[0].totnpe);
ckov_a.SetCoincidences(tmpDigs[0].ncoin);
ckov_a.SetPartEventNumber(tmpDigs[0].partnum);
// Set Ckov B
ckov_b.SetArrivalTime4(tmpDigs[1].arTime[0]);
ckov_b.SetArrivalTime5(tmpDigs[1].arTime[1]);
ckov_b.SetArrivalTime6(tmpDigs[1].arTime[2]);
ckov_b.SetArrivalTime7(tmpDigs[1].arTime[3]);
ckov_b.SetPositionMin4(tmpDigs[1].posmin[0]);
ckov_b.SetPositionMin5(tmpDigs[1].posmin[1]);
ckov_b.SetPositionMin6(tmpDigs[1].posmin[2]);
ckov_b.SetPositionMin7(tmpDigs[1].posmin[3]);
ckov_b.SetPulse4(tmpDigs[1].pulse[0]);
ckov_b.SetPulse5(tmpDigs[1].pulse[1]);
ckov_b.SetPulse6(tmpDigs[1].pulse[2]);
ckov_b.SetPulse7(tmpDigs[1].pulse[3]);
ckov_b.SetTotalCharge(tmpDigs[1].totcharge);
ckov_b.SetNumberOfPes(tmpDigs[1].totnpe);
ckov_b.SetCoincidences(tmpDigs[1].ncoin);
ckov_b.SetPartEventNumber(tmpDigs[1].partnum);
aDigit.SetCkovA(ckov_a);
aDigit.SetCkovB(ckov_b);
theDigits->push_back(aDigit);
}
}