/* 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
#include
#include "src/common_cpp/Utils/JsonWrapper.hh"
#include "src/common_cpp/Utils/CppErrorHandler.hh"
#include "Interface/Squeak.hh"
#include "Utils/Exception.hh"
#include "Interface/dataCards.hh"
#include "src/map/MapCppTOFSpacePoints/MapCppTOFSpacePoints.hh"
namespace MAUS {
bool MapCppTOFSpacePoints::birth(std::string argJsonConfigDocument) {
// Check if the JSON document can be parsed, else return error only
_classname = "MapCppTOFSpacePoints";
// JsonCpp setup
Json::Value configJSON;
try {
configJSON = JsonWrapper::StringToJson(argJsonConfigDocument);
// this will contain the configuration
// Load the calibration.
_map_init = true;
bool loaded = _map.InitializeFromCards(configJSON);
if (!loaded)
_map_init = false;
std::cout << "_map_init = " << _map_init << std::endl;
_makeSpacePointCut =
JsonWrapper::GetProperty(configJSON,
"TOF_makeSpacePointCut",
JsonWrapper::realValue).asDouble(); // nanoseconds
_findTriggerPixelCut =
JsonWrapper::GetProperty(configJSON,
"TOF_findTriggerPixelCut",
JsonWrapper::realValue).asDouble(); // nanoseconds
_triggerStation
= JsonWrapper::GetProperty(configJSON,
"TOF_trigger_station",
JsonWrapper::stringValue).asString();
// The first element of the vectro has to be the trigger station.
// This is mandatory!!!
_stationKeys.push_back(_triggerStation);
if (_triggerStation == "tof1") {
_stationKeys.push_back("tof0");
_stationKeys.push_back("tof2");
} else if (_triggerStation == "tof0") {
_stationKeys.push_back("tof1");
_stationKeys.push_back("tof2");
} else if (_triggerStation == "tof2") {
_stationKeys.push_back("tof0");
_stationKeys.push_back("tof1");
} else {
Squeak::mout(Squeak::error)
<< "Error in MapCppTOFSpacePoints::birth. TOF trigger station is wrong."
<< "It can be tof1 or tof0. The provided trigger station is : "
<< _triggerStation << std::endl;
return false;
}
return true;
} catch (Exception exc) {
MAUS::CppErrorHandler::getInstance()->HandleExceptionNoJson(exc, _classname);
} catch (std::exception exc) {
MAUS::CppErrorHandler::getInstance()->HandleStdExcNoJson(exc, _classname);
}
return false;
}
bool MapCppTOFSpacePoints::death() {return true;}
std::string MapCppTOFSpacePoints::process(std::string document) {
std::cout << "DEBUG MapCppTOFSpacePoints::process| Entry Checkpoint"
<< std::endl;
// JsonCpp setup
Json::FastWriter writer;
Json::Value root;
Json::Value xEventType;
// Check if the JSON document can be parsed, else return error only
try {root = JsonWrapper::StringToJson(document);}
catch (...) {
Json::Value errors;
std::stringstream ss;
ss << _classname << " says: Failed to parse input document";
errors["bad_json_document"] = ss.str();
root["errors"] = errors;
return writer.write(root);
}
if (!_map_init) {
Json::Value errors;
std::stringstream ss;
ss << _classname << " says: Failed to initialize calibration map";
errors["no_tofcalib"] = ss.str();
root["errors"] = errors;
return writer.write(root);
}
try {
xEventType = JsonWrapper::GetProperty(root,
"daq_event_type",
JsonWrapper::stringValue);
if (xEventType == "physics_event" || xEventType == "calibration_event") {
_triggerhit_pixels.clear();
Json::Value xRecEvent = JsonWrapper::GetProperty(root,
"recon_events",
JsonWrapper::arrayValue);
for (unsigned int n_event = 0; n_event < xRecEvent.size(); n_event++) {
Json::Value xTofEvent = JsonWrapper::GetItem
(xRecEvent, n_event, JsonWrapper::objectValue);
xTofEvent = JsonWrapper::GetProperty
(xTofEvent, "tof_event", JsonWrapper::objectValue);
if (xTofEvent.isMember("tof_slab_hits")) {
Json::Value xSlabHits = JsonWrapper::GetProperty
(xTofEvent, "tof_slab_hits", JsonWrapper::objectValue);
// NOTE: DR March15
// Cheating -- until I figure out how to handle trig-req-time in MC:
// I have to change the triggerpixelcut for MC in order for the
// calib corrections to be applied correctly.
// 2 options --
// a) change the cut in ConfigDefaults
// but this mess up data -- though I did run on real data
// with this modified cut and things (resol,time) look OK @ 1st
// glance
// b) use a different cut if it's MC
// this breaks the agreement that we'll treat real data/MC same
// way but for now it at least lets MC get reconstructed without
// clobbering real data
// For now I have chosen option a) with option b) commented out below
// need to be sure to change ConfigDefaults for switching between
// data<->mc
if (root.isMember("mc_events")) _findTriggerPixelCut = 50.0;
// Loop over each station starting from the trigger station.
for (unsigned int n_station = 0;
n_station < _stationKeys.size();
n_station++) {
std::string detector = _stationKeys[n_station];
if (xSlabHits.isMember(detector))
std::cout << "DEBUG MapCppTOFSpacePoints::process| "
<< "processing event " << n_event << " station "
<< n_station << std::endl;
root["recon_events"][n_event]["tof_event"]["tof_space_points"]
[detector] = processTOFStation(xSlabHits, detector, n_event);
}
// The slab hit document is now modified. The calibrated time
// measurements are added. Save the modifications.
root["recon_events"][n_event]["tof_event"]["tof_slab_hits"]
= xSlabHits;
}
}
}
} catch (Exception exc) {
root = MAUS::CppErrorHandler::getInstance()
->HandleException(root, exc, _classname);
} catch (std::exception exc) {
root = MAUS::CppErrorHandler::getInstance()
->HandleStdExc(root, exc, _classname);
}
// if (root.isMember("slab_hits")) std::cout << root["slab_hits"] << std::endl;
// if (root.isMember("space_points")) std::cout << root["space_points"] << std::endl;
return writer.write(root);
}
Json::Value MapCppTOFSpacePoints::processTOFStation(Json::Value &xSlabHits,
std::string detector,
unsigned int part_event) {
std::cout << "DEBUG MapCppTOFSpacePoints::processTOFStation| "
<< "Entry Checkpoint" << std::endl;
// Get the slab hits document for this TOF station.
Json::Value xDocPartEvent = JsonWrapper::GetProperty(xSlabHits,
detector,
JsonWrapper::anyValue);
Json::Value xDocPartEventSpacePoints(Json::arrayValue);
if (xDocPartEvent.isArray()) {
int n_slab_hits = xDocPartEvent.size();
std::cout << "DEBUG MapCppTOFSpacePoints::processTOFStation| "
<< "# Slab Hits: " << n_slab_hits << std::endl;
// Delete the information from the previous particle event.
_xPlane0Hits.resize(0);
_xPlane1Hits.resize(0);
// Loop over the slab hits and select the hits in
// plane0 (horizontal) and plane1 (vertical).
for (int SlHit = 0; SlHit < n_slab_hits; SlHit++) {
// Get the slab hit.
Json::Value xThisSlabHit = JsonWrapper::GetItem(xDocPartEvent,
SlHit,
JsonWrapper::objectValue);
int xPlane = JsonWrapper::GetProperty(xThisSlabHit,
"plane",
JsonWrapper::intValue).asInt();
std::cout << "DEBUG MapCppTOFSpacePoints::processTOFStation| "
<< "Slab Plane: " << xPlane << std::endl;
// According to the convention used in the cabling file the horizontal
// slabs are always in plane 0 and the vertical slabs are always in
// plane 1.
switch (xPlane) {
case 0 :
_xPlane0Hits.push_back(SlHit);
break;
case 1 :
_xPlane1Hits.push_back(SlHit);
break;
}
}
// If this is the trigger station find the pixel that is giving the trigger.
if (detector == _triggerStation) {
_triggerhit_pixels[part_event] = findTriggerPixel(xDocPartEvent);
std::cout << "DEBUG MapCppTOFSpacePoints::processTOFStation| "
<< "Trigger Pixel: " << _triggerhit_pixels[part_event]
<< std::endl;
}
// If we do not know the trigger pixel there is no way to reconstruct the
// time.
if (_triggerhit_pixels[part_event] != "unknown") {
// Create the space point. Add the calibrated value of the time to the
// slab hits.
xDocPartEventSpacePoints = makeSpacePoints(xDocPartEvent);
// The slab hit document is now modified. The calibrated time measurements
// are added. Save the modifications.
xSlabHits[detector] = xDocPartEvent;
}
}
return xDocPartEventSpacePoints;
}
std::string MapCppTOFSpacePoints::findTriggerPixel(Json::Value xDocPartEvent) {
// Loop over all possible combinations of slab hits in the trigger station.
for (unsigned int nX = 0; nX < _xPlane0Hits.size(); nX++) {
for (unsigned int nY = 0; nY < _xPlane1Hits.size(); nY++) {
// Get the two slab hits.
Json::Value xSlabHit_X = JsonWrapper::GetItem(xDocPartEvent,
_xPlane0Hits[nX],
JsonWrapper::objectValue);
Json::Value xSlabHit_Y = JsonWrapper::GetItem(xDocPartEvent,
_xPlane1Hits[nY],
JsonWrapper::objectValue);
int slabX = xSlabHit_X["slab"].asInt();
int slabY = xSlabHit_Y["slab"].asInt();
TOFPixelKey xTriggerPixelKey(1, slabX, slabY, _triggerStation);
// Apply the calibration corrections assuming that this pixel gives the
// trigger. If this assumption is correct the value of the time after the
// corrections has to be approximately 0.
double t_x, t_y;
if (calibrateSlabHit(xTriggerPixelKey, xSlabHit_X, t_x) &&
calibrateSlabHit(xTriggerPixelKey, xSlabHit_Y, t_y)) {
std::cout << "DEBUG MapCppTOFSpacePoints::findTriggerPixel| "
<< "t_x: " << t_x << "\tt_y: " << t_y
<< "\t_findTriggerPixelCut: " << _findTriggerPixelCut
<< std::endl;
if (fabs(t_x/2. + t_y/2.) < _findTriggerPixelCut) {
// The trigger pixel has been found.
// std::cout << xTriggerPixelKey << std::endl;
return xTriggerPixelKey.str();
}
}
}
}
return "unknown";
}
Json::Value MapCppTOFSpacePoints::makeSpacePoints(Json::Value &xDocPartEvent) {
Json::Value xDocSpacePoints(Json::arrayValue);
// Loop over all possible combinations of slab hits in the trigger station.
for (unsigned int nX = 0; nX < _xPlane0Hits.size(); nX++) {
for (unsigned int nY = 0; nY < _xPlane1Hits.size(); nY++) {
Json::Value xDocSpacePoint;
int xPartEvent = JsonWrapper::GetProperty(xDocPartEvent[_xPlane0Hits[0]],
"part_event_number",
JsonWrapper::intValue).asInt();
TOFPixelKey xTriggerPixelKey(_triggerhit_pixels[xPartEvent]);
double t_x, t_y;
if (calibrateSlabHit(xTriggerPixelKey,
xDocPartEvent[_xPlane0Hits[nX]],
t_x) &&
calibrateSlabHit(xTriggerPixelKey,
xDocPartEvent[_xPlane1Hits[nY]],
t_y)) {
// The first argument should be the hit in the horizontal slab and the
// second should be the hit in the vertical slab. This is mandatory!!!
Json::Value xDocSpacePoint
= fillSpacePoint(xDocPartEvent[_xPlane0Hits[nX]],
xDocPartEvent[_xPlane1Hits[nY]]);
double deltaT = xDocSpacePoint["dt"].asInt();
if (fabs(deltaT) < _makeSpacePointCut) {
xDocSpacePoints.append(xDocSpacePoint);
}
}
}
}
return xDocSpacePoints;
}
Json::Value MapCppTOFSpacePoints::fillSpacePoint(Json::Value &xDocSlabHit_X,
Json::Value &xDocSlabHit_Y) {
Json::Value xDocSpacePoint;
// First get the two channel keys and make the pixel key.
std::string keyStr_SlabX_digit0
= JsonWrapper::GetProperty(xDocSlabHit_X["pmt0"],
"tof_key",
JsonWrapper::stringValue).asString();
TOFChannelKey xKey_SlabX_digit0(keyStr_SlabX_digit0);
std::string keyStr_SlabY_digit0
= JsonWrapper::GetProperty(xDocSlabHit_Y["pmt0"],
"tof_key",
JsonWrapper::stringValue).asString();
TOFChannelKey xKey_SlabY_digit0(keyStr_SlabY_digit0);
// ATTENTION : according to the convention used in the cabling file the
// horizontal slabs are always in plane 0 and the vertical slabs are always in
// plane 1.
// The second argument in the constructor has to be the number of the
// horizontal slab, and the third argument has to be the vertical slab.
// This is mandatory!!!
TOFPixelKey xSPKey(xKey_SlabX_digit0.station(),
xKey_SlabX_digit0.slab(),
xKey_SlabY_digit0.slab(),
xKey_SlabY_digit0.detector());
// Get the corrected time from the two slab hits.
double time_SlabX
= JsonWrapper::GetProperty(xDocSlabHit_X,
"time",
JsonWrapper::realValue).asDouble();
double time_SlabY
= JsonWrapper::GetProperty(xDocSlabHit_Y,
"time",
JsonWrapper::realValue).asDouble();
// Get the charge and the charge product.
int charge_SlabX = JsonWrapper::GetProperty(xDocSlabHit_X,
"charge",
JsonWrapper::intValue).asInt();
int chargeProduct_SlabX
= JsonWrapper::GetProperty(xDocSlabHit_X,
"charge_product",
JsonWrapper::intValue).asInt();
int charge_SlabY = JsonWrapper::GetProperty(xDocSlabHit_Y,
"charge",
JsonWrapper::intValue).asInt();
int chargeProduct_SlabY
= JsonWrapper::GetProperty(xDocSlabHit_Y,
"charge_product",
JsonWrapper::intValue).asInt();
// Now calculate the time of the space point.
double time = (time_SlabX + time_SlabY)/2.;
double dt = time_SlabX - time_SlabY;
xDocSpacePoint["time"] = time;
xDocSpacePoint["dt"] = dt;
// Fill all other necessary information in the Space point.
xDocSpacePoint["part_event_number"] = xDocSlabHit_X["part_event_number"];
xDocSpacePoint["phys_event_number"] = xDocSlabHit_X["phys_event_number"];
xDocSpacePoint["slabX"] = xKey_SlabX_digit0.slab();
xDocSpacePoint["station"] = xKey_SlabX_digit0.station();
xDocSpacePoint["detector"] = xKey_SlabX_digit0.detector();
xDocSpacePoint["slabY"] = xKey_SlabY_digit0.slab();
xDocSpacePoint["pixel_key"] = xSPKey.str();
xDocSpacePoint["charge"] = charge_SlabX + charge_SlabY;
xDocSpacePoint["charge_product"] = chargeProduct_SlabX + chargeProduct_SlabY;
// std::cout << xSPKey << " t = " << time << " dt = " << dt << std::endl;
// std::cout << xDocSpacePoint << std::endl;
return xDocSpacePoint;
}
bool MapCppTOFSpacePoints::calibratePmtHit(TOFPixelKey xTriggerPixelKey,
Json::Value &xPmtHit,
double &time) {
int charge;
// Charge of the digit can be unset because of the Zero suppresion of the
// fADCs.
if (xPmtHit.isMember("charge")) {
charge= JsonWrapper::GetProperty(xPmtHit,
"charge",
JsonWrapper::intValue).asInt();
} else {
std::cout << "DEBUG MapCppTOFSpacePoints::calibratePmtHit: "
<< "!xPmtHit.isMember(\"charge\")" << std::endl;
return false;
}
std::string keyStr
= JsonWrapper::GetProperty(xPmtHit,
"tof_key",
JsonWrapper::stringValue).asString();
TOFChannelKey xChannelKey(keyStr);
double raw_time
= JsonWrapper::GetProperty(xPmtHit,
"raw_time",
JsonWrapper::realValue).asDouble();
// Get the calibration correction.
double dT = _map.dT(xChannelKey, xTriggerPixelKey, charge);
std::cout << "dt= " << dT << std::endl;
if (dT == TOFCalibrationMap::NOCALIB)
return false;
time = raw_time - dT;
xPmtHit["time"] = time;
std::cout << "calibratePmtHit " << xChannelKey << " " << xTriggerPixelKey
<< " t = " << raw_time << " - " << dT << " = " << time << std::endl;
return true;
}
bool MapCppTOFSpacePoints::calibrateSlabHit(TOFPixelKey xTriggerPixelKey,
Json::Value &xSlabHit,
double &time) {
double time_digit0, time_digit1;
// Calibrate the digit measurements.
if (calibratePmtHit(xTriggerPixelKey, xSlabHit["pmt0"], time_digit0) &&
calibratePmtHit(xTriggerPixelKey, xSlabHit["pmt1"], time_digit1)) {
time = (time_digit0 + time_digit1)/2.;
xSlabHit["time"] = time;
return true;
}
return false;
}
}