/* 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 "src/map/MapCppGlobalPID/MapCppGlobalPID.hh" #include "Interface/Squeak.hh" #include "src/common_cpp/DataStructure/Data.hh" #include "src/common_cpp/Converter/DataConverters/JsonCppSpillConverter.hh" #include "src/common_cpp/Converter/DataConverters/CppJsonSpillConverter.hh" namespace MAUS { MapCppGlobalPID::MapCppGlobalPID() { _classname = "MapCppGlobalPID"; } bool MapCppGlobalPID::birth(std::string argJsonConfigDocument) { // Check if the JSON document can be parsed, else return error only. bool parsingSuccessful = _reader.parse(argJsonConfigDocument, _configJSON); if (!parsingSuccessful) { _configCheck = false; return false; } char* pMAUS_ROOT_DIR = getenv("MAUS_ROOT_DIR"); if (!pMAUS_ROOT_DIR) { Squeak::mout(Squeak::error) << "Could not find the $MAUS_ROOT_DIR env variable." << std::endl; Squeak::mout(Squeak::error) << "Did you try running: source env.sh ?" << std::endl; return false; } _configCheck = true; _hypotheses.clear(); _pid_vars.clear(); PDF_file = _configJSON["PID_PDFs_file"].asString(); _histFile = new TFile(PDF_file.c_str(), "READ"); // vector of hypotheses // TODO(Pidcott) find a more elegant way of accessing hypotheses _hypotheses.push_back("200MeV_mu_plus"); _hypotheses.push_back("200MeV_e_plus"); _hypotheses.push_back("200MeV_pi_plus"); for (unsigned int i =0; i < _hypotheses.size(); ++i) { // vector of pid vars _pid_vars.push_back(new MAUS::recon::global::PIDVarA(_histFile, _hypotheses[i])); _pid_vars.push_back(new MAUS::recon::global::PIDVarB(_histFile, _hypotheses[i])); // etc. } return true; } bool MapCppGlobalPID::death() { return true; } std::string MapCppGlobalPID::process(std::string document) const { Json::FastWriter writer; Json::Value root; if (document.empty()) { Json::Value errors; std::stringstream ss; ss << _classname << " says: Empty document passed to process"; errors["bad_json_document"] = ss.str(); root["errors"] = errors; return writer.write(root); } if (!_configCheck) { Json::Value errors; std::stringstream ss; ss << _classname << " says: process was not passed a valid configuration"; errors["bad_json_document"] = ss.str(); root["errors"] = errors; return writer.write(root); } // Prepare converters, spill and json objects JsonCppSpillConverter json2cppconverter; CppJsonSpillConverter cpp2jsonconverter; Json::Value *data_json = NULL; MAUS::Data *data_cpp = NULL; // Read string and convert to a Json object try { Json::Value imported_json = JsonWrapper::StringToJson(document); data_json = new Json::Value(imported_json); } catch (Exception& exception) { MAUS::CppErrorHandler::getInstance()-> HandleExceptionNoJson(exception, _classname); Squeak::mout(Squeak::error) << "String to Json conversion failed," << "MapCppGlobalPID::process" << std::endl; Json::Value errors; std::stringstream ss; ss << _classname << " says: Bad json document"; errors["bad_json_document"] = ss.str(); root["errors"] = errors; delete data_json; return writer.write(root); } catch (std::exception& exc) { MAUS::CppErrorHandler::getInstance()->HandleStdExcNoJson(exc, _classname); Squeak::mout(Squeak::error) << "String to Json conversion failed," << "MapCppGlobalPID::process" << std::endl; Json::Value errors; std::stringstream ss; ss << _classname << " says: Bad json document"; errors["bad_json_document"] = ss.str(); root["errors"] = errors; delete data_json; return writer.write(root); } if (!data_json || data_json->isNull()) { if (data_json) delete data_json; return std::string("{\"errors\":{\"bad_json_document\":")+ std::string("\"Failed to parse input document\"}}"); } if (data_json->empty()) { delete data_json; return std::string("{\"errors\":{\"bad_json_document\":")+ std::string("\"Failed to parse input document\"}}"); } std::string maus_event = JsonWrapper::GetProperty( *data_json, "maus_event_type", JsonWrapper::stringValue).asString(); if ( maus_event.compare("Spill") != 0 ) { Squeak::mout(Squeak::error) << "Line of json document did not contain " << "a Spill" << std::endl; delete data_json; return document; } std::string daq_event = JsonWrapper::GetProperty( *data_json, "daq_event_type", JsonWrapper::stringValue).asString(); if ( daq_event.compare("physics_event") != 0 ) { Squeak::mout(Squeak::error) << "daq_event_type did not return a " << "physics event" << std::endl; delete data_json; return document; } // Convert Json into MAUS::Spill object. In future, this will all // be done for me, and process will take/return whichever object we // prefer. try { data_cpp = json2cppconverter(data_json); delete data_json; } catch (...) { Squeak::mout(Squeak::error) << "Missing required branch daq_event_type" << " converting json->cpp, MapCppGlobalPID" << std::endl; } if (!data_cpp) { return std::string("{\"errors\":{\"failed_json_cpp_conversion\":")+ std::string("\"Failed to convert Json to Cpp Spill object\"}}"); } const MAUS::Spill* _spill = data_cpp->GetSpill(); if ( _spill->GetReconEvents() ) { for ( unsigned int event_i = 0; event_i < _spill->GetReconEvents()->size(); ++event_i ) { MAUS::GlobalEvent* global_event = _spill->GetReconEvents()->at(event_i)->GetGlobalEvent(); std::vector *GlobalTrackArray = global_event->get_tracks(); for (unsigned int track_i = 0; track_i < GlobalTrackArray->size(); ++track_i) { MAUS::DataStructure::Global::Track* track = GlobalTrackArray->at(track_i); if (track->get_mapper_name() != "MapCppGlobalTrackMatching") continue; // doubles to hold cumulative log likelihoods for each hypothesis double logL_200MeV_mu_plus = 0; double logL_200MeV_e_plus = 0; double logL_200MeV_pi_plus = 0; for (size_t pid_var_count = 0; pid_var_count < _pid_vars.size(); ++pid_var_count) { std::string hyp = _pid_vars[pid_var_count]->Get_hyp(); if (hyp == "200MeV_mu_plus") { if (_pid_vars[pid_var_count]->logL(track) == 1) { continue; } else { logL_200MeV_mu_plus += _pid_vars[pid_var_count]->logL(track); } } else if (hyp == "200MeV_e_plus") { if (_pid_vars[pid_var_count]->logL(track) == 1) { continue; } else { logL_200MeV_e_plus += _pid_vars[pid_var_count]->logL(track); } } else if (hyp == "200MeV_pi_plus") { if (_pid_vars[pid_var_count]->logL(track) == 1) { continue; } else { logL_200MeV_pi_plus += _pid_vars[pid_var_count]->logL(track); } } else { Squeak::mout(Squeak::error) << "Unrecognised particle hypothesis," << " MapCppGlobalPID::process" << std::endl; } } if ((logL_200MeV_mu_plus - logL_200MeV_e_plus > 0.5) && (logL_200MeV_mu_plus - logL_200MeV_pi_plus > 0.5)) { track->set_pid(MAUS::DataStructure::Global::kMuPlus); } else if ((logL_200MeV_e_plus - logL_200MeV_mu_plus > 0.5) && (logL_200MeV_e_plus - logL_200MeV_pi_plus > 0.5)) { track->set_pid(MAUS::DataStructure::Global::kEPlus); } else if ((logL_200MeV_pi_plus - logL_200MeV_mu_plus > 0.5) && (logL_200MeV_pi_plus - logL_200MeV_e_plus > 0.5)) { track->set_pid(MAUS::DataStructure::Global::kPiPlus); } else { Squeak::mout(Squeak::error) << "PID for track could not be" << " determined." << std::endl; continue; } } } } data_json = cpp2jsonconverter(data_cpp); if (!data_json) { delete data_cpp; return std::string("{\"errors\":{\"failed_cpp_json_conversion\":")+ std::string("\"Failed to convert Cpp to Json Spill object\"}}"); } std::string output_document = JsonWrapper::JsonToString(*data_json); delete data_json; delete data_cpp; return output_document; } } // ~MAUS