All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SpaceChargeICARUS.cxx
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 // SpaceChargeICARUS.cxx; brief implementation of class for storing/accessing space charge distortions for ICARUS
3 // Based largely on SpaceChargeSBND and SpaceChargeProtoDUNE
4 // rlazur@colostate.edu
5 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
6 // C++ language includes
7 #include <iostream>
8 #include <fstream>
9 #include <string>
10 #include <vector>
11 #include <math.h>
12 #include <stdio.h>
13 // LArSoft includes
15 
16 // Framework includes
17 #include "cetlib_except/exception.h"
18 
19 spacecharge::SpaceChargeICARUS::SpaceChargeICARUS(fhicl::ParameterSet const& pset)
20 {
21  Configure(pset);
22 }
23 
24 bool spacecharge::SpaceChargeICARUS::Configure(fhicl::ParameterSet const& pset)
25 {
26  fEnableSimSpatialSCE = pset.get<bool>("EnableSimSpatialSCE");
27  fEnableSimEfieldSCE = pset.get<bool>("EnableSimEfieldSCE");
28  //fEnableCorrSCE = pset.get<bool>("EnableCorrSCE");
29  fEnableCalSpatialSCE = pset.get<bool>("EnableCalSpatialSCE");
30  fEnableCalEfieldSCE = pset.get<bool>("EnableCalEfieldSCE");
31 
32  std::cout << "Configuring SpaceCharge..." << std::endl;
33 
34  if((fEnableSimSpatialSCE == true) || (fEnableSimEfieldSCE == true)){
35  fRepresentationType = pset.get<std::string>("RepresentationType");
36  fInputFilename = pset.get<std::string>("InputFilename");
37 
38  std::string fname;
39  cet::search_path sp("FW_SEARCH_PATH");
40  sp.find_file(fInputFilename, fname);
41 
42  std::unique_ptr<TFile> infile(new TFile(fname.c_str(), "READ"));
43  if(!infile->IsOpen()){
44  throw cet::exception("SpaceChargeICARUS") << "Could not find the space charge input file '" << fInputFilename << "'!\n";
45  }
46 
47  if(fRepresentationType == "Voxelized_TH3"){
48  std::cout << "begin loading voxelized TH3s..." << std::endl;
49 
50  //Load in histograms
51  TH3F* hTrueFwdX = (TH3F*) infile->Get("TrueFwd_Displacement_X");
52  TH3F* hTrueFwdY = (TH3F*) infile->Get("TrueFwd_Displacement_Y");
53  TH3F* hTrueFwdZ = (TH3F*) infile->Get("TrueFwd_Displacement_Z");
54  TH3F* hTrueBkwdX = (TH3F*) infile->Get("TrueBkwd_Displacement_X");
55  TH3F* hTrueBkwdY = (TH3F*) infile->Get("TrueBkwd_Displacement_Y");
56  TH3F* hTrueBkwdZ = (TH3F*) infile->Get("TrueBkwd_Displacement_Z");
57  TH3F* hTrueEFieldX = (TH3F*) infile->Get("True_ElecField_X");
58  TH3F* hTrueEFieldY = (TH3F*) infile->Get("True_ElecField_Y");
59  TH3F* hTrueEFieldZ = (TH3F*) infile->Get("True_ElecField_Z");
60 
61  //https://root.cern.ch/doc/master/classTH1.html#a0367fe04ae8709fd4b82795d0a5462c3
62  //Set hist directories so they can be referenced elsewhere
63  //This needs to be done because they were read in from ext file
64  //Note this is not a property of the TH3F, so does't survive copying
65  hTrueFwdX->SetDirectory(0);
66  hTrueFwdY->SetDirectory(0);
67  hTrueFwdZ->SetDirectory(0);
68  hTrueBkwdX->SetDirectory(0);
69  hTrueBkwdY->SetDirectory(0);
70  hTrueBkwdZ->SetDirectory(0);
71  hTrueEFieldX->SetDirectory(0);
72  hTrueEFieldY->SetDirectory(0);
73  hTrueEFieldZ->SetDirectory(0);
74 
75  //SCEhistograms can be accessed globally in this script
76  SCEhistograms = {hTrueFwdX, hTrueFwdY, hTrueFwdZ,
77  hTrueBkwdX, hTrueBkwdY, hTrueBkwdZ,
78  hTrueEFieldX, hTrueEFieldY, hTrueEFieldZ};
79 
80 
81  std::cout << "...finished loading TH3s" << std::endl;
82  }
83  infile->Close();
84  }
85  if(fEnableCorrSCE == true){
86  //keeping here (for now) for historic reasons
87  }
88  return true;
89 }
90 
92 {
93  if (ts == 0){return false;}
94  return true;
95 }
96 
97 // Whether or not to turn simulation of SCE on for spatial distortions
99 {
100  return fEnableSimSpatialSCE;
101 }
102 
103 // Whether or not to turn simulation of SCE on for E-field distortions
105 {
106  return fEnableSimEfieldSCE;
107 }
108 
109 // Return boolean indicating whether
111 {
112  return fEnableCalSpatialSCE;
113 }
114 
115 // Return boolean indicating whether or not to apply SCE corrections
117 {
118  return fEnableCalEfieldSCE;
119 }
120 
121 /////////////////////////////////////////////////////////////////////////////
122 // BELOW ARE THE WORKHORSE FUNCTIONS
123 ////////////////////////////////////////////////////////////////////////////
124 
125 // Primary working method of service that provides position offsets
127 {
128  std::vector<double> thePosOffsets;
129  double xx=point.X(), yy=point.Y(), zz=point.Z();
130  double cryo_corr=1., tpc_corr=1.;
131 
132  if(fRepresentationType == "Voxelized_TH3"){
133  //handle OOAV by projecting edge cases
134  //also only have map for positive cryostat (assume symmetry)
135  //need to invert coordinates for cryo0 (cryo_corr)
136 
137  //in larsim, this is how the offsets are used in DriftElectronstoPlane_module
138  // DriftDistance += -1.0 * thePosOffsets[0]
139  // thus need to apply correction to TPCs "left" of cryostat (tpc_corr)
140  // cathode spans x=210.14 and x=210.29 in pos cryostat
141  if(xx>0){
142  cryo_corr=1.0;
143  if(xx<210.14){
144  tpc_corr=-1.0;
145  }
146  }else{
147  cryo_corr=-1.0;
148  if(xx<-210.29){
149  tpc_corr=-1.0;
150  }
151  }
152  fixCoords(&xx, &yy, &zz); //bring into AV and x = abs(x)
153  double offset_x=0., offset_y=0., offset_z=0.;
154  offset_x = tpc_corr*cryo_corr*SCEhistograms.at(0)->Interpolate(xx,yy,zz);
155  offset_y = SCEhistograms.at(1)->Interpolate(xx,yy,zz);
156  offset_z = SCEhistograms.at(2)->Interpolate(xx,yy,zz);
157  thePosOffsets = {offset_x, offset_y, offset_z};
158  }else{
159  thePosOffsets.resize(3, 0.0);
160  }
161 
162  return { thePosOffsets[0], thePosOffsets[1], thePosOffsets[2] };
163 }
164 
165 // Returns the SCE correction at a specific point in the AV
167 {
168  std::vector<double> theCalPosOffsets;
169  //make copies of const vars to modify
170  double xx=point.X(), yy=point.Y(), zz=point.Z();
171  int tpcid = TPCid;
172 
173  if(fRepresentationType == "Voxelized_TH3"){
174  //handle OOAV by projecting edge cases
175  //also only have map for positive cryostat (assume symmetry)
176  //need to invert coordinates for cryo0
177  double corr=1.;
178  if(xx<0){
179  corr=-1.0;
180  }
181 
182  bool x_is_pos = xx > 0;
183 
184  fixCoords(&xx, &yy, &zz); //bring into AV and x = abs(x)
185  //handle the depositions that was reconstructed in the wrong TPC
186  //hard code in the cathode faces (got from dump_icarus_geometry.fcl)
187  //
188  //Gray Putnam: update this check to the split-wire Geometry
189  if (x_is_pos && (tpcid == 0 || tpcid == 1) && xx > 210.14 ) { xx = 210.14; }
190  if (x_is_pos && (tpcid == 2 || tpcid == 3) && xx < 210.29 ) { xx = 210.29; }
191 
192  if (!x_is_pos && (tpcid == 2 || tpcid == 3) && xx > 210.14 ) { xx = 210.14; }
193  if (!x_is_pos && (tpcid == 0 || tpcid == 1) && xx < 210.29 ) { xx = 210.29; }
194 
195  double offset_x=0., offset_y=0., offset_z=0.;
196  offset_x = corr*SCEhistograms.at(3)->Interpolate(xx,yy,zz);
197  offset_y = SCEhistograms.at(4)->Interpolate(xx,yy,zz);
198  offset_z = SCEhistograms.at(5)->Interpolate(xx,yy,zz);
199  theCalPosOffsets = {offset_x, offset_y, offset_z};
200  }else{
201  theCalPosOffsets.resize(3, 0.0);
202  }
203 
204  return { theCalPosOffsets[0], theCalPosOffsets[1], theCalPosOffsets[2] };
205 }
206 
208 {
209  return GetCalPosOffsets(point, TPCid.TPC);
210 }
211 
212 // Primary working method of service that provides E field offsets
214 {
215  //chiefly utilized by larsim, ISCalculationSeparate
216  //the magnitude of the Efield is most important
217  std::vector<double> theEfieldOffsets;
218  double xx=point.X(), yy=point.Y(), zz=point.Z();
219  double offset_x=0., offset_y=0., offset_z=0.;
220 
221  if(fRepresentationType == "Voxelized_TH3"){
222  //handle OOAV by projecting edge cases
223  //also only have map for positive cryostat (assume symmetry)
224  fixCoords(&xx, &yy, &zz);
225  offset_x = SCEhistograms.at(6)->Interpolate(xx, yy, zz);
226  offset_y = SCEhistograms.at(7)->Interpolate(xx, yy, zz);
227  offset_z = SCEhistograms.at(8)->Interpolate(xx, yy, zz);
228 
229  theEfieldOffsets = {offset_x, offset_y, offset_z};
230  }
231  return { theEfieldOffsets[0], theEfieldOffsets[1], theEfieldOffsets[2] };
232 }
233 
234 void spacecharge::SpaceChargeICARUS::fixCoords(double* xx, double* yy, double* zz) const{
235  //handle the edge cases by projecting SCE corrections onto boundaries
236  *xx = abs(*xx);
237  if(*xx<61.94){*xx=61.94;}
238  if(*xx>358.489){*xx=358.489;}
239  if(*yy<-181.86){*yy=-181.86;}
240  if(*yy>134.96){*yy=134.96;}
241  if(*zz<-894.951){*zz=-894.951;}
242  if(*zz>894.9509){*zz=894.9509;}
243 }
244 
bool EnableCalEfieldSCE() const override
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
void fixCoords(double *xx, double *yy, double *zz) const
string fname
Definition: demo.py:5
geo::Vector_t GetPosOffsets(geo::Point_t const &point) const override
T abs(T value)
geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const override
SpaceChargeICARUS(fhicl::ParameterSet const &pset)
bool EnableSimEfieldSCE() const override
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
bool EnableCalSpatialSCE() const override
bool EnableSimSpatialSCE() const override
geo::Vector_t GetCalPosOffsets(geo::Point_t const &point, int const &TPCid) const override
TPCID_t TPC
Index of the TPC within its cryostat.
Definition: geo_types.h:406
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
BEGIN_PROLOG could also be cout
bool Configure(fhicl::ParameterSet const &pset)