/* 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/common_cpp/Recon/SciFi/SciFiClusterRec.hh" namespace MAUS { SciFiClusterRec::SciFiClusterRec():_size_exception(0), _min_npe(0.) {} SciFiClusterRec::SciFiClusterRec(int cluster_exception, double min_npe, const SciFiTrackerMap& geometry_map): _size_exception(cluster_exception), _min_npe(min_npe), _geometry_map(geometry_map) {} SciFiClusterRec::~SciFiClusterRec() {} bool sort_by_npe(SciFiDigit *a, SciFiDigit *b ) { return ( a->get_npe() > b->get_npe() ); } void SciFiClusterRec::process(SciFiEvent &evt) const { // Create and fill the seeds vector. std::vector seeds; get_seeds(evt, seeds); // Get the number of clusters. If too large, abort reconstruction. int seeds_size = seeds.size(); if ( seeds_size > _size_exception ) { std::cout << "NUMBER OF SCIFI SEED DIGITS EXCEEDS CUTOFF LIMIT: " << "(" << seeds_size << "/" << _size_exception << ")" << "\n" << "Spill: " << seeds[0]->get_spill() << " Event: " << seeds[0]->get_event() << "\n"; std::cout << "To raise limit enter command line --SciFiClustExcept n\n"; ofstream logfile; std::string root_dir = std::getenv("MAUS_ROOT_DIR"); std::string path = root_dir + "/tmp/digit_exception.log"; logfile.open(path.c_str(), ios::app); logfile << "spill: " << seeds[0]->get_spill() << " digit: " << seeds[0]->get_event() << " total number of seed digits: " << seeds.size() << "\n"; logfile.close(); return; } // Sort seeds so that we use higher npe first. std::sort(seeds.begin(), seeds.end(), sort_by_npe); make_clusters(evt, seeds); } void SciFiClusterRec::get_seeds(SciFiEvent &evt, std::vector& seeds) const { size_t num_digits = evt.digits().size(); for ( size_t dig = 0; dig < num_digits; ++dig ) { if ( evt.digits()[dig]->get_npe() > _min_npe/2.0 ) seeds.push_back(evt.digits()[dig]); } } void SciFiClusterRec::make_clusters(SciFiEvent &evt, std::vector& seeds) const { size_t seeds_size = seeds.size(); for ( size_t i = 0; i < seeds_size; i++ ) { if (seeds[i]->get_npe() < _min_npe/2.0) std::cerr << "ERROR : DIGIT NPE = " << seeds[i]->get_npe() << "(" << _min_npe << ")" << std::endl; if ( !(seeds[i]->is_used()) ) { SciFiDigit* neigh = NULL; SciFiDigit* seed = seeds[i]; double pe = seed->get_npe(); // Look for a neighbour. for ( size_t j = i+1; j < seeds_size; ++j ) { if ( are_neighbours(seeds[i], seeds[j]) ) { neigh = seeds[j]; } } // If there is a neighbour, sum npe contribution. if ( neigh ) { pe += neigh->get_npe(); } // Save cluster if it's above npe cut. if ( pe > _min_npe ) { SciFiCluster* clust = new SciFiCluster(seed); if ( neigh ) { clust->add_digit(neigh); } process_cluster(clust); evt.add_cluster(clust); } } } // ends loop over seeds } void SciFiClusterRec::process_cluster(SciFiCluster *clust) const { int tracker = clust->get_tracker(); int station = clust->get_station(); int plane = clust->get_plane(); int id = 3*(station-1) + (plane+1); SciFiPlaneMap::const_iterator iterator = _geometry_map.find(tracker)->second.Planes.find(id); // iterator = _geometry_map.find(id); // Throw if the plane isn't found. // if ( iterator == _geometry_map.end() ) { if ( iterator == _geometry_map.find(tracker)->second.Planes.end() ) { throw(Exceptions::Exception(Exceptions::nonRecoverable, "Failed to find SciFi plane in _geometry_map.", "SciFiClusterRec::process_cluster")); } id = ( tracker == 0 ? -id : id ); clust->set_id(id); SciFiPlaneGeometry this_plane = (*iterator).second; ThreeVector plane_direction = this_plane.Direction; ThreeVector plane_position = this_plane.Position; double Pitch = this_plane.Pitch; double CentralFibre = this_plane.CentralFibre; // alpha is the distance to the central fibre. double alpha = CentralFibre - clust->get_channel(); double dist_mm = Pitch * (7.0 / 2.0) * alpha; ThreeVector perp = plane_direction.Orthogonal(); ThreeVector position = dist_mm * perp + plane_position; clust->set_direction(plane_direction); clust->set_position(position); clust->set_alpha(dist_mm); } bool SciFiClusterRec::are_neighbours(SciFiDigit *seed_i, SciFiDigit *seed_j) const { bool neigh = false; if ( !(seed_j->is_used()) && // seed is unused seed_j->get_spill() == seed_i->get_spill() && // same spill seed_j->get_event() == seed_i->get_event() && // same event seed_j->get_tracker() == seed_i->get_tracker() && // same tracker seed_j->get_station() == seed_i->get_station() && // same station seed_j->get_plane() == seed_i->get_plane() && // seeds belong to same plane abs(seed_j->get_channel() - seed_i->get_channel()) < 2.0 ) { // and are neighbours neigh = true; } return neigh; } } // ~namespace MAUS