/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/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
#include
#include "Geant4/G4Material.hh"
#include "src/common_cpp/Utils/Exception.hh"
#include "src/common_cpp/Utils/Globals.hh"
#include "src/common_cpp/Simulation/GeometryNavigator.hh"
#include "src/common_cpp/Recon/Global/MaterialModelAxialLookup.hh"
namespace MAUS {
double MaterialModelAxialLookup::_z_tolerance = 1e-1;
std::vector > MaterialModelAxialLookup::_lookup;
MaterialModelAxialLookup::MaterialModelAxialLookup(double x, double y, double z) {
SetMaterial(x, y, z);
}
MaterialModelAxialLookup::MaterialModelAxialLookup(const MaterialModelAxialLookup& mat) {
*this = mat;
}
MaterialModelAxialLookup& MaterialModelAxialLookup::operator=(const MaterialModelAxialLookup& mat) {
if (&mat == this) {
return *this;
}
_material = mat._material;
_n_e = mat._n_e;
_I = mat._I;
_x_0 = mat._x_0;
_x_1 = mat._x_1;
_C = mat._C;
_a = mat._a;
_k = mat._k;
_rad_len_ratio = mat._rad_len_ratio;
_density = mat._density;
_z_over_a = mat._z_over_a;
return *this;
}
MaterialModelAxialLookup* MaterialModelAxialLookup::Clone() {
throw Exceptions::Exception(Exceptions::recoverable,
"Not implemented", "MaterialModelDynamic::Clone");
}
bool compare(std::pair a_pair, double z) {
return z > a_pair.first;
}
void MaterialModelAxialLookup::SetMaterial(double x, double y, double z) {
if (_lookup.size() == 0)
throw Exceptions::Exception(Exceptions::recoverable,
"Attempt to set material without building lookup table first",
"MaterialModelAxialLookup::Clone");
typedef std::vector >::iterator iter;
iter a_pair = std::lower_bound(_lookup.begin(), _lookup.end(), z, compare);
if (a_pair != _lookup.begin())
a_pair--;
MaterialModel::_material = a_pair->second;
if (!IsEnabledMaterial(_material->GetName())) { // URG... string comparison
MaterialModel::_material = NULL;
} else {
MaterialModel::SetMaterial(_material);
}
if (a_pair == _lookup.begin() or a_pair+1 == _lookup.end()) {
MaterialModel::SetThickness(1.);
} else {
double thickness = (a_pair+1)->first - (a_pair)->first;
MaterialModel::SetThickness(thickness);
}
}
void MaterialModelAxialLookup::BuildLookupTable(double z_start, double z_end) {
if (z_end <= z_start)
throw Exceptions::Exception(Exceptions::recoverable,
"z_start must be less than z_end",
"MaterialModelAxialLookup::BuildLookupTable");
_lookup = std::vector >();
GeometryNavigator* navigator = Globals::GetMCGeometryNavigator();
ThreeVector dir(0., 0., 1.);
G4Material* old_mat = NULL;
G4Material* new_mat = NULL;
double z = z_start;
while (z < z_end) {
navigator->SetPoint(ThreeVector(0., 0., z));
new_mat = navigator->GetMaterial();
if (new_mat != old_mat) {
std::pair new_pair(z, new_mat);
_lookup.push_back(new_pair);
}
old_mat = new_mat;
double delta_z = _z_tolerance;
z += delta_z;
}
}
void MaterialModelAxialLookup::PrintLookupTable(std::ostream& out) {
for (size_t i = 0; i < _lookup.size(); ++i) {
out << _lookup[i].first << " " << _lookup[i].second->GetName() << " "
<< IsEnabledMaterial(_lookup[i].second->GetName()) << std::endl;
}
}
void MaterialModelAxialLookup::GetBounds(double z_pos, double& lower_bound, double& upper_bound) {
typedef std::vector >::iterator iter;
iter a_pair = std::lower_bound(_lookup.begin(), _lookup.end(), z_pos, compare);
// std::cerr << "GetBounds at " << z_pos << " finds " << a_pair->first
// << " " << a_pair->second << std::endl;
if (a_pair == _lookup.begin()) {
lower_bound = std::numeric_limits::lowest();
upper_bound = a_pair->first;
} else if (a_pair == _lookup.end()) {
lower_bound = _lookup.back().first;
upper_bound = std::numeric_limits::max();
} else {
upper_bound = a_pair->first;
lower_bound = (--a_pair)->first;
}
}
} // namespace MAUS