From 3da50675a7d18b66f8745334aeac68f967b98b16 Mon Sep 17 00:00:00 2001 From: flavigny <flavigny@lpccaen.in2p3.fr> Date: Thu, 9 Jun 2022 14:22:50 +0200 Subject: [PATCH] * Add HiCARI to NPLib/NPSim/Project and preliminary GeScorer (in progress) --- NPLib/Detectors/Hicari/CMakeLists.txt | 6 + NPLib/Detectors/Hicari/THicariData.cxx | 74 + NPLib/Detectors/Hicari/THicariData.h | 73 + NPLib/Detectors/Hicari/THicariPhysics.cxx | 692 ++++ NPLib/Detectors/Hicari/THicariPhysics.h | 199 + NPLib/Detectors/Hicari/THicariSpectra.cxx | 215 ++ NPLib/Detectors/Hicari/THicariSpectra.h | 65 + .../Detectors/Hicari/CConvexPolyhedron.cc | 909 +++++ .../Detectors/Hicari/CConvexPolyhedron.hh | 130 + NPSimulation/Detectors/Hicari/CMakeLists.txt | 2 + NPSimulation/Detectors/Hicari/Hicari.cc | 3287 +++++++++++++++++ NPSimulation/Detectors/Hicari/Hicari.hh | 353 ++ .../Detectors/Hicari/Hicari_Helper.hh | 210 ++ NPSimulation/Scorers/CMakeLists.txt | 2 +- NPSimulation/Scorers/GeScorers.cc | 551 +++ NPSimulation/Scorers/GeScorers.hh | 388 ++ Projects/Hicari/152Eu.beam | 16 + Projects/Hicari/Exogam.detector | 16 + Projects/Hicari/HiCARI.detector | 19 + Projects/Hicari/PhysicsListOption.txt | 11 + Projects/Hicari/crystalangles.dat | 41 + Projects/Hicari/crystalpositions.dat | 164 + Projects/Hicari/geometry/fall2020/clust.list | 30 + Projects/Hicari/geometry/fall2020/euler.list | 21 + Projects/Hicari/geometry/fall2020/slice.list | 37 + Projects/Hicari/geometry/fall2020/solid.list | 96 + Projects/Hicari/geometry/fall2020/walls.list | 385 ++ Projects/Hicari/plotsegments.py | 26 + Projects/Hicari/segmentpositions.dat | 424 +++ 29 files changed, 8441 insertions(+), 1 deletion(-) create mode 100644 NPLib/Detectors/Hicari/CMakeLists.txt create mode 100644 NPLib/Detectors/Hicari/THicariData.cxx create mode 100644 NPLib/Detectors/Hicari/THicariData.h create mode 100644 NPLib/Detectors/Hicari/THicariPhysics.cxx create mode 100644 NPLib/Detectors/Hicari/THicariPhysics.h create mode 100644 NPLib/Detectors/Hicari/THicariSpectra.cxx create mode 100644 NPLib/Detectors/Hicari/THicariSpectra.h create mode 100644 NPSimulation/Detectors/Hicari/CConvexPolyhedron.cc create mode 100644 NPSimulation/Detectors/Hicari/CConvexPolyhedron.hh create mode 100644 NPSimulation/Detectors/Hicari/CMakeLists.txt create mode 100644 NPSimulation/Detectors/Hicari/Hicari.cc create mode 100644 NPSimulation/Detectors/Hicari/Hicari.hh create mode 100644 NPSimulation/Detectors/Hicari/Hicari_Helper.hh create mode 100644 NPSimulation/Scorers/GeScorers.cc create mode 100644 NPSimulation/Scorers/GeScorers.hh create mode 100644 Projects/Hicari/152Eu.beam create mode 100644 Projects/Hicari/Exogam.detector create mode 100644 Projects/Hicari/HiCARI.detector create mode 100644 Projects/Hicari/PhysicsListOption.txt create mode 100644 Projects/Hicari/crystalangles.dat create mode 100644 Projects/Hicari/crystalpositions.dat create mode 100644 Projects/Hicari/geometry/fall2020/clust.list create mode 100644 Projects/Hicari/geometry/fall2020/euler.list create mode 100644 Projects/Hicari/geometry/fall2020/slice.list create mode 100644 Projects/Hicari/geometry/fall2020/solid.list create mode 100644 Projects/Hicari/geometry/fall2020/walls.list create mode 100644 Projects/Hicari/plotsegments.py create mode 100644 Projects/Hicari/segmentpositions.dat diff --git a/NPLib/Detectors/Hicari/CMakeLists.txt b/NPLib/Detectors/Hicari/CMakeLists.txt new file mode 100644 index 000000000..9eaa4f487 --- /dev/null +++ b/NPLib/Detectors/Hicari/CMakeLists.txt @@ -0,0 +1,6 @@ +add_custom_command(OUTPUT THicariPhysicsDict.cxx COMMAND ${CMAKE_BINARY_DIR}/scripts/build_dict.sh THicariPhysics.h THicariPhysicsDict.cxx THicariPhysics.rootmap libNPHicari.dylib DEPENDS THicariPhysics.h) +add_custom_command(OUTPUT THicariDataDict.cxx COMMAND ${CMAKE_BINARY_DIR}/scripts/build_dict.sh THicariData.h THicariDataDict.cxx THicariData.rootmap libNPHicari.dylib DEPENDS THicariData.h) +add_library(NPHicari SHARED THicariData.cxx THicariPhysics.cxx THicariDataDict.cxx THicariPhysicsDict.cxx THicariSpectra.cxx) +target_link_libraries(NPHicari ${ROOT_LIBRARIES} NPCore) +install(FILES THicariData.h THicariPhysics.h THicariSpectra.h DESTINATION ${CMAKE_INCLUDE_OUTPUT_DIRECTORY}) + diff --git a/NPLib/Detectors/Hicari/THicariData.cxx b/NPLib/Detectors/Hicari/THicariData.cxx new file mode 100644 index 000000000..1a0fa3192 --- /dev/null +++ b/NPLib/Detectors/Hicari/THicariData.cxx @@ -0,0 +1,74 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: F. Flavigny contact : flavigny@lpccaen.in2p3.fr * + * * + * Creation Date : april 2022 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class hold HiCARI Raw data * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + * * + *****************************************************************************/ +#include <iostream> +using namespace std; + +#include "THicariData.h" + + +ClassImp(THicariData) + +THicariData::THicariData() +{ + // Default constructor + Clear(); +} + + + +THicariData::~THicariData() +{ +} + +unsigned int THicariData::Find(const unsigned int& cluindex, const unsigned int& cryindex, const unsigned int& segindex){ + for(unsigned int i = 0 ; i<fHi_Cluster.size(); i++){ + if(fHi_Cluster[i]==cluindex && fHi_Crystal[i]==cryindex && fHi_Segment[i]==segindex) + return i; + } + return 99999; + +} + +void THicariData::Clear() +{ + fHi_Cluster.clear(); + fHi_Crystal.clear(); + fHi_Segment.clear(); + fHi_Energy.clear(); + fHi_Time.clear(); +} + + + +void THicariData::Dump() const +{ + cout << "XXXXXXXXXXXXXXXXXXXXXXXX New Event XXXXXXXXXXXXXXXXX" << endl; + + // RealValues (for simulation purposes) + cout << "Gr_Mult = " << fHi_Cluster.size() << endl; + for (unsigned int i = 0; i < fHi_Cluster.size(); i++) { + cout << "CloverE: " << fHi_Cluster[i] << " CristalE: " << fHi_Crystal[i]; + cout << "Segment: " << fHi_Segment[i]; + cout << " Energy: " << fHi_Energy[i]; + cout << " Time: " << fHi_Time[i] << endl; + } +} diff --git a/NPLib/Detectors/Hicari/THicariData.h b/NPLib/Detectors/Hicari/THicariData.h new file mode 100644 index 000000000..0453ff7b6 --- /dev/null +++ b/NPLib/Detectors/Hicari/THicariData.h @@ -0,0 +1,73 @@ +#ifndef __HICARIDATA__ +#define __HICARIDATA__ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: F.Flavigny contact: flavigny@lpccaen.in2p3.fr * + * * + * Creation Date : april 2022 * + * Last update : april 2022 * + *---------------------------------------------------------------------------* + * Decription: * + * This class hold Hicari Raw data * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + * * + *****************************************************************************/ + + +// STL +#include <vector> +using namespace std; +#include "TObject.h" + + +class THicariData : public TObject { + private: + // real energy value (for npsimulation) + vector<unsigned int> fHi_Cluster; + vector<unsigned int> fHi_Crystal; + vector<unsigned int> fHi_Segment; + vector<double> fHi_Energy; + vector<double> fHi_Time; + //vector<vector<double>> fHi_SegEnergy; + //vector<vector<unsigned int>> fHi_Seg; + + public: + THicariData(); + virtual ~THicariData(); + + void Clear(); + void Clear(const Option_t*) {}; + void Dump() const; + + unsigned int Find(const unsigned int&, const unsigned int&, const unsigned int&); + void AddE(const unsigned int& index, const double en){fHi_Energy[index]+=en;} + void ChangeE(const unsigned int& index, const double en){fHi_Energy[index]=en;} + unsigned int GetMult(){return fHi_Cluster.size();} + + ///////////////////// SETTERS //////////////////////// + void SetCluster(unsigned int clu) { fHi_Cluster.push_back(clu);} + void SetCrystal(unsigned int crys) { fHi_Crystal.push_back(crys);} + void SetSegment(unsigned int seg) { fHi_Segment.push_back(seg);} + void SetEnergy(double ener) { fHi_Energy.push_back(ener);} + void SetTime(double time) { fHi_Time.push_back(time);} + + ///////////////////// GETTERS //////////////////////// + unsigned int GetCluster(Int_t i) {return fHi_Cluster[i];} + unsigned int GetCrystal(Int_t i) {return fHi_Crystal[i];} + unsigned int GetSegment(Int_t i) {return fHi_Segment[i];} + unsigned int GetEnergy(Int_t i) {return fHi_Energy[i];} + unsigned int GetTime(Int_t i) {return fHi_Time[i];} + + ClassDef(THicariData,1) // HicariData structure + }; + +#endif diff --git a/NPLib/Detectors/Hicari/THicariPhysics.cxx b/NPLib/Detectors/Hicari/THicariPhysics.cxx new file mode 100644 index 000000000..2fbfd580e --- /dev/null +++ b/NPLib/Detectors/Hicari/THicariPhysics.cxx @@ -0,0 +1,692 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Sandra GIRON contact address: giron@ipno.in2p3.fr * + * Benjamin LE CROM lecrom@ipno.in2p3.fr * + * Creation Date : march 2014 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class hold exogam treated data * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + *****************************************************************************/ +#include "THicariPhysics.h" +using namespace HICARI_LOCAL; + +// STL +#include <sstream> +#include <iostream> +#include <cmath> +#include <stdlib.h> + +// NPL +#include "RootInput.h" +#include "NPDetectorFactory.h" +#include "RootOutput.h" +#include "NPVDetector.h" +#include "NPOptionManager.h" +// ROOT +#include "TChain.h" + + +/////////////////////////////////////////////////////////////////////////// +ClassImp(THicariPhysics) +/////////////////////////////////////////////////////////////////////////// +THicariPhysics::THicariPhysics() +{ + EventMultiplicity = 0 ; + ECC_Multiplicity = 0 ; + GOCCE_Multiplicity = 0 ; + NumberOfHitClover = 0 ; + NumberOfHitCristal = 0 ; + m_Spectra = NULL; + NumberOfClover=0; + + PreTreatedData = new THicariData ; + EventData = new THicariData ; + EventPhysics = this ; + NumberOfClover = 0 ; + CloverMult = 0 ; + +} + +/////////////////////////////////////////////////////////////////////////// +void THicariPhysics::BuildSimplePhysicalEvent() +{ + + BuildPhysicalEvent(); +} +/////////////////////////////////////////////////////////////////////////// +void THicariPhysics::PreTreat() +{ + ClearPreTreatedData(); +/* + //E + + for(unsigned int i = 0 ; i < EventData -> GetECCEMult(); i++) { + UShort_t cristal_E = 10000 ; UShort_t cristal_T = 2000; + //if(IsValidChannel) + { + int clover = EventData -> GetECCEClover(i); + int cristal = EventData -> GetECCECristal(i); + + if(EventData -> GetECCEEnergy(i) < 3000) cristal_E = CalibrationManager::getInstance()-> ApplyCalibration("EXOGAM/Cl"+ NPL::itoa(clover)+"_Cr"+ NPL::itoa(cristal)+"_Elow", EventData -> GetECCEEnergy(i)); + else cristal_E = CalibrationManager::getInstance()-> ApplyCalibration("EXOGAM/Cl"+ NPL::itoa(clover)+"_Cr"+ NPL::itoa(cristal)+"_Ehigh", EventData -> GetECCEEnergy(i)); + + + if(cristal_E > Threshold_ECC) + { + + PreTreatedData->SetECCEClover ( clover ) ; + PreTreatedData->SetECCECristal( cristal ) ; + PreTreatedData->SetECCEEnergy ( cristal_E ) ; + + bool checkT = false; + for(unsigned int k = 0; k < EventData -> GetECCTMult(); k++){ + if(clover == EventData -> GetECCTClover(k) && cristal == EventData -> GetECCTCristal(k)){ + // cout << EventData -> GetECCTTime(k) << endl; + + if(EventData -> GetECCTTime(k) < 16383) cristal_T = CalibrationManager::getInstance()-> ApplyCalibration("EXOGAM/Cl"+ NPL::itoa(clover)+"_Cr"+ NPL::itoa(cristal)+"_T", EventData -> GetECCTTime(k)); + else cristal_T = 2500; + + //if(cristal_T >5000 && cristal_T !=25000 ) cout << "PreTreat " << cristal_T << " " << EventData -> GetECCTTime(k) << " " << clover << " " << cristal << " " << EventData->GetECCTMult() << endl; + + checkT=true; + PreTreatedData->SetECCTClover (clover ) ; + PreTreatedData->SetECCTCristal( cristal ) ; + PreTreatedData->SetECCTTime ( cristal_T ) ; + + ECC_Multiplicity ++; + GOCCE_Multiplicity++; + } + + } + + if(!checkT) { + PreTreatedData->SetECCTClover (clover ) ; + PreTreatedData->SetECCTCristal( cristal ) ; + PreTreatedData->SetECCTTime ( -1000 ) ; + } + + + } + } + } + + //cout << PreTreatedData-> GetECCTMult() << " " << PreTreatedData-> GetECCEMult() << endl; + + + //GOCCE + + //E + + for(unsigned int i = 0 ; i < EventData -> GetGOCCEEMult(); i++) { + UShort_t segment_E = 25000; + + //if(IsValidChannel) + { + int clover = EventData -> GetGOCCEEClover(i); + int cristal = EventData -> GetGOCCEECristal(i); + int segment = EventData -> GetGOCCEESegment(i); + + if(EventData -> GetGOCCEEEnergy(i) > RawThreshold_GOCCE) + { + segment_E = CalibrationManager::getInstance()->ApplyCalibration("EXOGAM/Cl"+ NPL::itoa(clover)+"_Cr"+ NPL::itoa(cristal)+"_Seg"+ NPL::itoa(segment)+"_E", EventData -> GetGOCCEEEnergy(i)); + + if(segment_E > Threshold_GOCCE) + { + PreTreatedData->SetGOCCEEClover ( clover ) ; + PreTreatedData->SetGOCCEECristal( cristal ) ; + PreTreatedData->SetGOCCEESegment( segment ) ; + PreTreatedData->SetGOCCEEEnergy ( segment_E ) ; + + } + } + else + { + + } + } + } +*/ + //cout << "EXOGAM pretreat ok!" << endl; + return; + +} +/////////////////////////////////////////////////////////////////////////// + +void THicariPhysics::BuildPhysicalEvent() +{ + PreTreat(); +/* + + if(PreTreatedData -> GetECCEMult() != PreTreatedData -> GetECCTMult()) cout << PreTreatedData -> GetECCEMult() << " " << PreTreatedData -> GetECCTMult() << endl; + + + for(unsigned int i = 0 ; i < PreTreatedData -> GetECCEMult(); i++) { + + // cout << i << " " << cristal_E << endl; + // if(PreTreatedData->GetECCTTime(i) > 0) + { + ECC_E.push_back(PreTreatedData->GetECCEEnergy(i)); + ECC_T.push_back(PreTreatedData->GetECCTTime(i)); + ECC_CloverNumber.push_back(PreTreatedData->GetECCEClover(i)); + ECC_CristalNumber.push_back(PreTreatedData->GetECCECristal(i)); + + // cout << "BuildPhys " << PreTreatedData->GetECCEClover(i) << " " << PreTreatedData->GetECCECristal(i)<< " " << PreTreatedData->GetECCTTime(i) << " " << endl; + } + } + + + for(unsigned int j = 0 ; j < PreTreatedData -> GetGOCCEEMult(); j++) { + GOCCE_E.push_back(PreTreatedData->GetGOCCEEEnergy(j)); + GOCCE_CloverNumber.push_back(PreTreatedData->GetGOCCEEClover(j)); + GOCCE_CristalNumber.push_back(PreTreatedData->GetGOCCEECristal(j)); + GOCCE_SegmentNumber.push_back(PreTreatedData->GetGOCCEESegment(j)); + } + + + //int NumberOfHitClover = 0; + + int DetectorID = -1; + + for( unsigned short i = 0 ; i < PreTreatedData->GetECCEMult() ; i++ ) + { + // cout << PreTreatedData->GetECCEClover(i) << endl; + if( PreTreatedData->GetECCEClover(i) != DetectorID) + { + if(i==0) + { + NumberOfHitClover++; + } + else if(PreTreatedData->GetECCEClover(i)!= PreTreatedData->GetECCEClover(i-1) ) + { + NumberOfHitClover++; + } + } + if(NumberOfHitClover == 4) break; + //clover_mult -> Fill(NumberOfHitClover); + + } + + //cout << "NumberOfHitClover " << NumberOfHitClover << endl; + + map<int, vector<int> > MapCristal; + map<int, vector<int> > MapSegment; + + map<int, vector<int> > :: iterator it; // iterator used with MapCristal + map<int, vector<int> > :: iterator at; // iterator used with MapSegment + + vector<int> PositionOfCristal_Buffer_ECC; + vector<int> PositionOfSegment_Buffer_GOCCE; + + + //Fill map Cristal + for(int clo = 0; clo < NumberOfClover; clo++) + { + for(unsigned int k = 0; k < ECC_CloverNumber.size(); k++) + { + if(ECC_CloverNumber.at(k) == clo) // && ECC_CristalNumber.at(k)== cri ) + PositionOfCristal_Buffer_ECC.push_back(k); + } + if(PositionOfCristal_Buffer_ECC.size() != 0) MapCristal[clo] = PositionOfCristal_Buffer_ECC; + + PositionOfCristal_Buffer_ECC.clear(); + + } + + + //Fill map Segment + for(int clo = 0; clo < NumberOfClover; clo++) + { + for(int cri = 0; cri < 4 ; cri++) + { + // for(int seg = 0; seg < 4 ; seg++) + { + for(unsigned int m = 0; m < GOCCE_CloverNumber.size(); m++) + { + if(GOCCE_CloverNumber.at(m) == clo && GOCCE_CristalNumber.at(m) == cri)// && GOCCE_SegmentNumber.at(m) == seg) + { + // PositionOfSegment_Buffer_GOCCE.push_back(4*clo+cri); + PositionOfSegment_Buffer_GOCCE.push_back(m); + } + } + } + if(PositionOfSegment_Buffer_GOCCE.size() != 0) MapSegment[4*clo+cri] = PositionOfSegment_Buffer_GOCCE; + + PositionOfSegment_Buffer_GOCCE.clear(); + } + } + + // Treatment + for(int clo = 0; clo < NumberOfClover ; clo++) + { + double E = 0; double T = 0; + int mult_cristal = 0; + int cristal = -1 , segment; + + int cristal_Emax = 0; int cristal_Emin = 0; + int Emax = 0, Emin = 1000000; + int Tmin = 0, Tmax = 0; + + //ADD-BACK + it = MapCristal.find(clo); + + int cristal_cond = 0; + + if(it != MapCristal.end()) + { + vector<int> PositionOfCristal = it -> second; + + mult_cristal = PositionOfCristal.size(); + //if(mult_cristal!=0) cristal_mult -> Fill(mult_cristal); + + // ADD-BACK + //cout << "boucle" << endl; + + for(unsigned int k = 0; k < PositionOfCristal.size(); k++) + { + int indice = PositionOfCristal.at(k); + + cristal_cond += ECC_CristalNumber.at(indice); + // cout << ECC_CristalNumber.at(k) << " " ECC_E.at(k) << endl; + + if(mult_cristal < 3) + { + E+= ECC_E.at(indice); + + if(ECC_E.at(indice) < Emin) { + cristal_Emin = ECC_CristalNumber.at(indice); + Emin = ECC_E.at(indice); + Tmin = ECC_T.at(indice); + } + + if(ECC_E.at(indice) > Emax) { + cristal_Emax = ECC_CristalNumber.at(indice); + Emax = ECC_E.at(indice); + Tmax = ECC_T.at(indice); + } + } + + else // case of multiplicity = 3 or 4 + { + E = -1; cristal_Emax = -1; cristal_Emin = -1; Tmax = -1; Tmin = -1; + } + + // cout << ECC_E.at(indice) << " " << Emax << " " << cristal_Emax << " " << Emin << " " << cristal_Emin << endl; + + } + + if( (mult_cristal==1) || (mult_cristal ==2 && cristal_cond %2 == 1) ) + { + // cout << cristal_cond << endl; + + //cristal = cristal_Emax; T = Tmax; + //cout << Emax << " " << cristal_Emax << " " << Emin << " " << cristal_Emin << endl; + + if(E > 500) { cristal = cristal_Emax; T = Tmax; } + else { cristal = cristal_Emin; T = Tmin; } + + + // DOPPLER CORRECTION + + at = MapSegment.find(4*clo+cristal); + segment = -1; + + if(at != MapSegment.end()) + { + vector<int> PositionOfSegment = at -> second; // position of segment k in the vector + + int segment_max = -1, E_temp = -1; + + for(unsigned int m = 0; m < PositionOfSegment.size(); m++) // loop on hit segments of cristal cri of clover clo + { + int indice = PositionOfSegment.at(m); + + if(GOCCE_E.at(indice) > 0 && GOCCE_CristalNumber.at(indice) == cristal) + { + if( GOCCE_E.at(indice) > E_temp ) + { + segment_max = GOCCE_SegmentNumber.at(indice) ; + E_temp = GOCCE_E.at(indice); + } + } + } + segment = segment_max; + } + + } + + + if(E > 0 && cristal != -1 && segment != -1) + { + TotalEnergy_lab.push_back(E); + Time.push_back(T); + CloverNumber.push_back(clo); + CristalNumber.push_back(cristal); + SegmentNumber.push_back(segment); + + double theta = GetSegmentAngleTheta(clo, cristal, segment); + + Theta.push_back(theta); + + double doppler_E = DopplerCorrection(E, theta); + DopplerCorrectedEnergy.push_back(doppler_E); + + // cout << E << " " << clo << " " << cristal << " " << segment << " " << theta << " " << doppler_E << endl; + + } + + } // end of condition over CristalMap + + } // loop over NumberOfClover + + CloverMult = GetClover_Mult(); +*/ + //cout << "Hicari fine" << endl; +} + + +double THicariPhysics::DopplerCorrection(double E, double Theta) +{ + double Pi = 3.141592654 ; + TString filename = "configs/beta.txt"; + ifstream file; + //cout << filename << endl; + file.open(filename); + if(!file) cout << filename << " was not opened" << endl; + + double E_corr = 0; + double beta = 0.; + file>>beta; + double gamma = 1./ sqrt(1-beta*beta); + + E_corr = gamma * E * ( 1. - beta * cos(Theta*Pi/180.)); + + return(E_corr); + +} + + +/////////////////////////////////////////////////////////////////////////// + + +void THicariPhysics::Clear() +{ + EventMultiplicity = 0; +/* + ECC_Multiplicity = 0; + GOCCE_Multiplicity = 0; + NumberOfHitClover = 0; + NumberOfHitCristal = 0; + + ECC_CloverNumber .clear() ; + ECC_CristalNumber .clear() ; + GOCCE_CloverNumber .clear() ; + GOCCE_CristalNumber .clear() ; + GOCCE_SegmentNumber .clear() ; + + // ECC + ECC_E.clear() ; + ECC_T.clear(); + + // GOCCE + GOCCE_E.clear() ; + + CristalNumber.clear() ; + SegmentNumber.clear() ; + CloverNumber .clear() ; + + TotalEnergy_lab .clear() ; + Time .clear() ; + DopplerCorrectedEnergy.clear() ; + Position .clear() ; + Theta .clear() ; + +*/ + +} +/////////////////////////////////////////////////////////////////////////// + +//// Innherited from VDetector Class //// + +// Read stream at ConfigFile to pick-up parameters of detector (Position,...) using Token +void THicariPhysics::ReadConfiguration(NPL::InputParser parser){ + vector<NPL::InputBlock*> blocks = parser.GetAllBlocksWithToken("Hicari"); + if(NPOptionManager::getInstance()->GetVerboseLevel()) + cout << "//// " << blocks.size() << " detectors found " << endl; + + vector<string> token = {"ANGLE_FILE"}; + + for(unsigned int i = 0 ; i < blocks.size() ; i++){ + if(blocks[i]->HasTokenList(token)){ + string AngleFile = blocks[i]->GetString("ANGLE_FILE"); + AddClover(AngleFile); + } + + else{ + cout << "ERROR: check your input file formatting " << endl; + exit(1); + } + } +} + +/////////////////////////////////////////////////////////////////////////// +void THicariPhysics::InitSpectra(){ + m_Spectra = new THicariSpectra(NumberOfClover); +} + +/////////////////////////////////////////////////////////////////////////// +void THicariPhysics::FillSpectra(){ + m_Spectra -> FillRawSpectra(EventData); + m_Spectra -> FillPreTreatedSpectra(PreTreatedData); + m_Spectra -> FillPhysicsSpectra(EventPhysics); +} +/////////////////////////////////////////////////////////////////////////// +void THicariPhysics::CheckSpectra(){ + m_Spectra->CheckSpectra(); +} +/////////////////////////////////////////////////////////////////////////// +void THicariPhysics::ClearSpectra(){ + // To be done +} +/////////////////////////////////////////////////////////////////////////// +map< string , TH1*> THicariPhysics::GetSpectra() { + if(m_Spectra) + return m_Spectra->GetMapHisto(); + else{ + map< string , TH1*> empty; + return empty; + } +} +////////////////////////////////////////////////////////////////////////// +void THicariPhysics::AddClover(string AngleFile) +{ + ifstream file; + // TString filename = Form("posBaptiste/angles_exogam_clover%d.txt",NumberOfClover); + // TString filename = Form("posz42_simu50mm/angles_exogam_clover%d.txt",NumberOfClover); + // TString filename = Form("posz42_exp_stat_demiring/angles_exogam_clover%d.txt",NumberOfClover); + + string path = "configs/"; + TString filename = path + AngleFile; + + cout << filename << endl; + file.open(filename); + if(!file) cout << filename << " was not opened" << endl; + + vector <double> Angles; + vector < vector <double> > Segment_angles; + vector < vector < vector <double> > > Cristal_angles; + + Cristal_angles.clear(); + + double angle; string buffer; + + for(int i = 0; i < 4; i++) + { + Segment_angles.clear(); + + for(int j = 0; j < 4; j++) + { + Angles.clear(); + + for(int k = 0; k < 2; k++) + { + file >> buffer >> angle; + + Angles.push_back(angle); // Theta (k = 0) Phi (k = 1) + + //cout << angle << endl; + if(Angles.size()==2) + cout << "Clover " << NumberOfClover << ": Theta=" << Angles[0] << " Phi=" << Angles[1]<< endl; + + } + + Segment_angles.push_back(Angles); + } + + Cristal_angles.push_back(Segment_angles); + } + + Clover_Angles_Theta_Phi.push_back(Cristal_angles); + + file.close(); + + NumberOfClover++; + +} + + +// Add Parameter to the CalibrationManger +void THicariPhysics::AddParameterToCalibrationManager() +{ + + CalibrationManager* Cal = CalibrationManager::getInstance(); + + for(int i = 0 ; i < NumberOfClover ; i++) + { + for( int j = 0 ; j < 4 ; j++) + { + Cal->AddParameter("EXOGAM", "Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_Elow" ,"EXOGAM_Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_Elow"); + Cal->AddParameter("EXOGAM", "Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_Ehigh","EXOGAM_Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_Ehigh"); + Cal->AddParameter("EXOGAM", "Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_T","EXOGAM_Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_T") ; + + for( int k = 0 ; k < 4 ; k++) + { + Cal->AddParameter("EXOGAM", "Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_Seg"+ NPL::itoa(k)+"_E","EXOGAM_Cl"+ NPL::itoa(i)+"_Cr"+ NPL::itoa(j)+"_Seg"+ NPL::itoa(k)+"_E") ; + } + } + } +} + + +// Activated associated Branches and link it to the private member DetectorData address +// In this method mother Branches (Detector) AND daughter leaf (fDetector_parameter) have to be activated +void THicariPhysics::InitializeRootInputRaw() +{ + TChain* inputChain = RootInput::getInstance()->GetChain() ; + inputChain->SetBranchStatus( "Hicari" , true ) ; + inputChain->SetBranchStatus( "fHi_*" , true ) ; + inputChain->SetBranchAddress( "Hicari" , &EventData ) ; + + /* + TList* outputList = RootOutput::getInstance()->GetList(); + clover_mult = new TH1F("clover_mult","clover_mult",20,0,20); + outputList->Add(clover_mult); + cristal_mult = new TH1F("cristal_mult","cristal_mult",20,0,20); + outputList->Add(cristal_mult); + */ +} + +///////////////////////////////////////////////////////////////////// +// Activated associated Branches and link it to the private member DetectorPhysics address +// In this method mother Branches (Detector) AND daughter leaf (parameter) have to be activated +void THicariPhysics::InitializeRootInputPhysics() { + TChain* inputChain = RootInput::getInstance()->GetChain(); + inputChain->SetBranchStatus( "EventMultiplicty" , true ); + inputChain->SetBranchStatus( "ECC_Multiplicity" , true ); + inputChain->SetBranchStatus( "GOCCE_Multiplicity" , true ); + inputChain->SetBranchStatus( "ECC_CloverNumber" , true ); + inputChain->SetBranchStatus( "ECC_CristalNumber" , true ); + inputChain->SetBranchStatus( "GOCCE_CloverNumber" , true ); + inputChain->SetBranchStatus( "GOCCE_CristalNumber" , true ); + inputChain->SetBranchStatus( "GOCCE_SegmentNumber" , true ); + inputChain->SetBranchStatus( "ECC_E" , true ); + inputChain->SetBranchStatus( "ECC_T" , true ); + inputChain->SetBranchStatus( "GOCCE_E" , true ); + inputChain->SetBranchStatus( "CristalNumber" , true ); + inputChain->SetBranchStatus( "SegmentNumber" , true ); + inputChain->SetBranchStatus( "CloverNumber" , true ); + inputChain->SetBranchStatus( "CloverMult" , true ); + inputChain->SetBranchStatus( "TotalEnergy_lab" , true ); + inputChain->SetBranchStatus( "Time" , true ); + inputChain->SetBranchStatus( "DopplerCorrectedEnergy" , true ); + inputChain->SetBranchStatus( "Position" , true ); + inputChain->SetBranchStatus( "Theta" , true ); + inputChain->SetBranchAddress( "EXOGAM" , &EventPhysics ); + +} + +///////////////////////////////////////////////////////////////////// + +// Create associated branches and associated private member DetectorPhysics address +void THicariPhysics::InitializeRootOutput() +{ + TTree* outputTree = RootOutput::getInstance()->GetTree() ; + outputTree->Branch( "Hicari" , "THicariPhysics" , &EventPhysics ) ; + + // control histograms if needed + /* + TList* outputList = RootOutput::getInstance()->GetList(); + controle = new TH1F("controle","histo de controle",20,0,20); + outputList->Add(controle); + */ + +} + + +/////////////////////////////////////////////////////////////////////////// +namespace HICARI_LOCAL +{ + // tranform an integer to a string + string itoa(int value) + { + std::ostringstream o; + + if (!(o << value)) + return "" ; + + return o.str(); + } +} + + ///////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Construct Method to be pass to the DetectorFactory // +//////////////////////////////////////////////////////////////////////////////// +NPL::VDetector* THicariPhysics::Construct(){ + return (NPL::VDetector*) new THicariPhysics(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Registering the construct method to the factory // +//////////////////////////////////////////////////////////////////////////////// +extern "C"{ +class proxy_hicari{ + public: + proxy_hicari(){ + NPL::DetectorFactory::getInstance()->AddToken("Hicari","Hicari"); + NPL::DetectorFactory::getInstance()->AddDetector("Hicari",THicariPhysics::Construct); + } +}; + +proxy_hicari p; +} diff --git a/NPLib/Detectors/Hicari/THicariPhysics.h b/NPLib/Detectors/Hicari/THicariPhysics.h new file mode 100644 index 000000000..9b3e9a74e --- /dev/null +++ b/NPLib/Detectors/Hicari/THicariPhysics.h @@ -0,0 +1,199 @@ +#ifndef TEXOGAMPHYSICS_H +#define TEXOGAMPHYSICS_H +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: S. Giron contact address: giron@ipno.in2p3.fr * + * B. Le Crom lecrom@ipno.in2p3.fr * + * Creation Date : march 2014 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class hold exogam treated data * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + *****************************************************************************/ + + +// STL +#include <vector> +#include <map> + +// NPL +#include "NPCalibrationManager.h" +#include "NPVDetector.h" +#include "THicariData.h" +#include "THicariSpectra.h" +#include "NPInputParser.h" +// ROOT +#include "TVector2.h" +#include "TVector3.h" +#include "TObject.h" +//#include "TH1.h" + +using namespace std ; +// Forward Declaration +class THicariSpectra; + +class THicariPhysics : public TObject, public NPL::VDetector{ + public: + THicariPhysics() ; + ~THicariPhysics() {}; + + + public: + void Clear() ; + void Clear(const Option_t*) {}; + + // Provide Physical Multiplicity + Int_t EventMultiplicity ; + Int_t ECC_Multiplicity ; + Int_t GOCCE_Multiplicity ; + Int_t NumberOfClover ; //! + + // Clover + Int_t NumberOfHitClover ; //! + Int_t NumberOfHitCristal ; //! + vector<int> ECC_CloverNumber ; + vector<int> ECC_CristalNumber ; + vector<int> GOCCE_CloverNumber ; + vector<int> GOCCE_CristalNumber ; + vector<int> GOCCE_SegmentNumber ; + + // ECC + vector<double> ECC_E ; + vector<double> ECC_T ; + + // GOCCE + vector<double> GOCCE_E ; + + // Add-Back and Doppler correction + + vector<int> CristalNumber ; + vector<int> SegmentNumber ; + vector<int> CloverNumber ; + int CloverMult ; + + vector<double> TotalEnergy_lab ; + vector<double> Time ; + vector<double> DopplerCorrectedEnergy ; + vector<double> Position ; + vector<double> Theta ; + + vector < vector < vector < vector <double> > > > Clover_Angles_Theta_Phi; //! + + /* + TH1F* clover_mult ; + TH1F* cristal_mult ; + */ + + public: // Innherited from VDetector Class + + // Read stream at ConfigFile to pick-up parameters of detector (Position,...) using Token + void ReadConfiguration(NPL::InputParser) ; + + + // Add Parameter to the CalibrationManger + void AddParameterToCalibrationManager() ; + + + // Activated associated Branches and link it to the private member DetectorData address + // In this method mother Branches (Detector) AND daughter leaf (fDetector_parameter) have to be activated + void InitializeRootInputRaw() ; + + // Activated associated Branches and link it to the private member DetectorPhysics address + // In this method mother Branches (Detector) AND daughter leaf (parameter) have to be activated + void InitializeRootInputPhysics() ;///////////////////////////////////////////////////////////////////////// + + // Create associated branches and associated private member DetectorPhysics address + void InitializeRootOutput() ; + + // This method is called at each event read from the Input Tree. Aim is to build a tree of calibrated data. + void PreTreat() ; + + // This method is called at each event read from the Input Tree. + void BuildPhysicalEvent() ; + + + // Same as above, but only the simplest event and/or simple method are used (low multiplicity, faster algorythm but less efficient ...). + // This method aimed to be used for analysis performed during experiment, when speed is requiered. + // NB: This method can eventually be the same as BuildPhysicalEvent. + void BuildSimplePhysicalEvent() ; + + double DopplerCorrection(double Energy, double Theta); + + // Those two method all to clear the Event Physics or Data + void ClearEventPhysics() {Clear();} + void ClearEventData() {EventData->Clear();} + void ClearPreTreatedData() {PreTreatedData->Clear();} + + // Method related to the TSpectra classes, aimed at providing a framework for online applications + // Instantiate the Spectra class and the histogramm throught it + void InitSpectra(); + // Fill the spectra hold by the spectra class + void FillSpectra(); + // Used for Online mainly, perform check on the histo and for example change their color if issues are found + void CheckSpectra(); + // Used for Online only, clear all the spectra hold by the Spectra class + void ClearSpectra(); + + private: // Root Input and Output tree classes + + + THicariData* EventData ;//! + THicariData* PreTreatedData ;//! + THicariPhysics* EventPhysics ;//! + + + public: // Specific to EXOGAM Array + // Add a Clover + void AddClover(string AngleFile); + + Int_t GetClover_Mult() { return(CloverNumber.size()); } + // Int_t GetECC_Mult() { return(ECC_CristalNumber.size()); } + // Int_t GetGOCCE_Mult() { return(GOCCE_SegmentNumber.size()); } + + Double_t GetSegmentAnglePhi(int Clover, int Cristal, int Segment) {return(Clover_Angles_Theta_Phi[Clover][Cristal][Segment][1]);}; + Double_t GetSegmentAngleTheta(int Clover, int Cristal, int Segment) {return(Clover_Angles_Theta_Phi[Clover][Cristal][Segment][0]);}; + + // Give and external TMustData object to THicariPhysics. Needed for online analysis for example. + void SetRawDataPointer(THicariData* rawDataPointer) {EventData = rawDataPointer;} + // Retrieve raw and pre-treated data + THicariData* GetRawData() const {return EventData;} + THicariData* GetPreTreatedData() const {return PreTreatedData;} + + + private: // Spectra Class + THicariSpectra* m_Spectra;//! + + public: // Spectra Getter + map< string , TH1*> GetSpectra(); + + public: // Static constructor to be passed to the Detector Factory + static NPL::VDetector* Construct(); + ClassDef(THicariPhysics,1) // HicariPhysics structure + }; + +namespace HICARI_LOCAL +{ + const double Threshold_ECC = 50; + const double Threshold_GOCCE = 0; + const double RawThreshold_ECC = 0; + const double RawThreshold_GOCCE = 0; + + + // tranform an integer to a string + string itoa(int value); + + +} + + +#endif diff --git a/NPLib/Detectors/Hicari/THicariSpectra.cxx b/NPLib/Detectors/Hicari/THicariSpectra.cxx new file mode 100644 index 000000000..c6ae2a70f --- /dev/null +++ b/NPLib/Detectors/Hicari/THicariSpectra.cxx @@ -0,0 +1,215 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: N. de Sereville contact address: deserevi@ipno.in2p3.fr * + * * + * Creation Date : march 2011 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class holds all the online spectra needed for Hicari * + * * + *---------------------------------------------------------------------------* + * Comment: * + * + first version (not complete yet) * + * * + * * + *****************************************************************************/ + +// STL +#include <iostream> +#include <cstdlib> +#include <stdexcept> +#include <string> +using namespace std; + +// NPL +#include "THicariSpectra.h" +#include "NPOptionManager.h" +#include "NPGlobalSystemOfUnits.h" +#include "NPPhysicalConstants.h" +#ifdef NP_SYSTEM_OF_UNITS_H +using namespace NPUNITS; +#endif + + +//////////////////////////////////////////////////////////////////////////////// +THicariSpectra::THicariSpectra(){ + SetName("Hicari"); + fnbinsRaw=16384; + fbinRawMin=0; + fbinRawMax=16384; + fnbinsCal=5000; + fbinCalMin=0; + fbinCalMax=5000; + +} + +//////////////////////////////////////////////////////////////////////////////// +THicariSpectra::THicariSpectra(unsigned int NumberOfClover){ +/* + if(NPOptionManager::getInstance()->GetVerboseLevel()>0) + cout << "************************************************" << endl + << "THicariSpectra : Initalising control spectra for " + << NumberOfClover << " Clover" << endl + << "************************************************" << endl ; + SetName("Hicari"); + fNumberOfClover = NumberOfClover; + fNumberOfSegments=4; + fNumberOfCores=4; + InitRawSpectra(); + InitPreTreatedSpectra(); + InitPhysicsSpectra(); + fnbinsRaw=4096; + fbinRawMin=0; + fbinRawMax=16384; + fnbinsCal=5000; + fbinCalMin=0; + fbinCalMax=5000; +*/ + +} + +//////////////////////////////////////////////////////////////////////////////// +THicariSpectra::~THicariSpectra(){ +} + +//////////////////////////////////////////////////////////////////////////////// +void THicariSpectra::InitRawSpectra(){ +/* + string name; + for (unsigned int i = 0; i < fNumberOfClover; i++) { // loop on number of detectors + for (unsigned int j = 0; j < fNumberOfCores; j++) { // loop on number of cores + + name = Form("HicariEnergyRaw_Clover%d_ECC%d", i+1, j+1); + AddHisto1D(name, name, 16384, 0, 16384, "Hicari/ERAW/ECC"); + name = Form("HicariTimeRaw_Clover%d_ECC%d", i+1, j+1); + AddHisto1D(name, name, 16384, 0, 16384, "Hicari/TRAW/ECC"); + + for (unsigned int k = 0; k < fNumberOfSegments; k++) { // loop on number of segments + name = Form("HicariEnergyRaw_Clover%d_ECC%d_GOCCE%d", i+1, j+1, k+1); + AddHisto1D(name, name, 16384, 0, 16384, "Hicari/ERAW/GOCCE"); + } + } + } // end loop on number of detectors + */ +} + +//////////////////////////////////////////////////////////////////////////////// +void THicariSpectra::InitPreTreatedSpectra() +{ +/* + string name; + for (unsigned int i = 0; i < fNumberOfClover; i++) { // loop on number of detectors + for (unsigned int j = 0; j < fNumberOfCores; j++) { // loop on number of cores + name = Form("HicariEnergyCal_Clover%d_ECC%d", i+1, j+1); + AddHisto1D(name, name, 5000, 0, 5000, "Hicari/ECal/ECC"); + name = Form("HicariTimeCal_Clover%d_ECC%d", i+1, j+1); + AddHisto1D(name, name, 5000, 0, 5000, "Hicari/TCal/ECC"); + + for (unsigned int k = 0; k < fNumberOfSegments; k++) { // loop on number of segments + name = Form("HicariEnergyCal_Clover%d_ECC%d_GOCCE%d", i+1, j+1, k+1); + AddHisto1D(name, name, 5000, 0, 5000, "Hicari/ECal/GOCCE"); + + } + } + } // end loop on number of detectors +*/ +} + +//////////////////////////////////////////////////////////////////////////////// +void THicariSpectra::InitPhysicsSpectra(){ +/* + string name; + name = "HicariEnergyAddBack"; + AddHisto1D(name, name, 5000, 0, 5000, "Hicari/DC"); +*/ +} + + + +//////////////////////////////////////////////////////////////////////////////// +void THicariSpectra::FillRawSpectra(THicariData* RawData){ +/* + string name; + string family; + + // Energy + for (unsigned int i = 0; i < RawData->GetECCEMult(); i++){ + name = Form("HicariEnergyRaw_Clover%d_ECC%d", RawData->GetECCEClover(i)+1,RawData->GetECCECristal(i)+1); + family = "Hicari/ERAW/ECC"; + FillSpectra(family,name + ,RawData->GetECCEEnergy(i)); + } + + for (unsigned int i = 0; i < RawData->GetGOCCEEMult(); i++){ + name = Form("HicariEnergyRaw_Clover%d_ECC%d_GOCCE%d", RawData->GetGOCCEEClover(i)+1,RawData->GetGOCCEECristal(i)+1,RawData->GetGOCCEESegment(i)+1); + family = "Hicari/ERAW/GOCCE"; + + FillSpectra(family,name + ,RawData->GetGOCCEEEnergy(i)); + } + + // Time + for (unsigned int i = 0; i < RawData->GetECCTMult(); i++){ + name = Form("HicariTimeRaw_Clover%d_ECC%d", RawData->GetECCTClover(i)+1,RawData->GetECCTCristal(i)+1); + family = "Hicari/RAW"; + + FillSpectra(family,name + ,RawData->GetECCTTime(i)); + } +*/ +} + +//////////////////////////////////////////////////////////////////////////////// +void THicariSpectra::FillPreTreatedSpectra(THicariData* PreTreatedData){ +/* + string name ; + string family; + // Energy + for (unsigned int i = 0; i < PreTreatedData->GetECCEMult(); i++) { + name = Form("HicariEnergyCal_Clover%d_ECC%d", PreTreatedData->GetECCEClover(i)+1,PreTreatedData->GetECCECristal(i)+1); + family = "Hicari/ECal/ECC"; + + FillSpectra(family,name + ,PreTreatedData->GetECCEEnergy(i)); + } + + for (unsigned int i = 0; i < PreTreatedData->GetGOCCEEMult(); i++) { + name = Form("HicariEnergyCal_Clover%d_ECC%d_GOCCE%d", PreTreatedData->GetGOCCEEClover(i)+1,PreTreatedData->GetGOCCEECristal(i)+1,PreTreatedData->GetGOCCEESegment(i)+1); + family = "Hicari/ECal/GOCCE"; + + FillSpectra(family,name + ,PreTreatedData->GetGOCCEEEnergy(i)); + } + + for (unsigned int i = 0; i < PreTreatedData->GetECCTMult(); i++) { + name = Form("HicariTimeCal_Clover%d_ECC%d", PreTreatedData->GetECCTClover(i)+1,PreTreatedData->GetECCTCristal(i)+1); + family = "Hicari/TCal/ECC"; + + FillSpectra(family,name + ,PreTreatedData->GetECCTTime(i)); + + } + */ +} + +//////////////////////////////////////////////////////////////////////////////// +void THicariSpectra::FillPhysicsSpectra(THicariPhysics* Physics){ +/* + string name; + string family= "Hicari/PHY"; + // Doppler Correct and Add Back + name = "HicariEnergyAddBack"; + family = "Hicari/DC"; + for (unsigned int i = 0; i < Physics->DopplerCorrectedEnergy.size(); i++) { + FillSpectra(family,name + ,Physics->DopplerCorrectedEnergy[i]); + } +*/ +} diff --git a/NPLib/Detectors/Hicari/THicariSpectra.h b/NPLib/Detectors/Hicari/THicariSpectra.h new file mode 100644 index 000000000..2029e39ea --- /dev/null +++ b/NPLib/Detectors/Hicari/THicariSpectra.h @@ -0,0 +1,65 @@ +#ifndef THICARISPECTRA_H +#define THICARISPECTRA_H +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: N. de Sereville contact address: deserevi@ipno.in2p3.fr * + * * + * Creation Date : march 2011 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class holds all the online spectra needed for Hicari * + * * + *---------------------------------------------------------------------------* + * Comment: * + * + first version (not complete yet) * + * * + * * + *****************************************************************************/ + +// NPLib headers +#include "NPVSpectra.h" +#include "THicariData.h" +#include "THicariPhysics.h" + +// ForwardDeclaration +class THicariPhysics ; + +class THicariSpectra:public VSpectra { + public: + // constructor and destructor + THicariSpectra(); + THicariSpectra(unsigned int NumberOfClover); + ~THicariSpectra(); + + private: + // Initialization methods + void InitRawSpectra(); + void InitPreTreatedSpectra(); + void InitPhysicsSpectra(); + + public: + // Filling methods + void FillRawSpectra(THicariData*); + void FillPreTreatedSpectra(THicariData*); + void FillPhysicsSpectra(THicariPhysics*); + + private: // Information on Hicari + unsigned int fNumberOfClover ; + unsigned int fnbinsRaw; + unsigned int fbinRawMin; + unsigned int fbinRawMax; + unsigned int fnbinsCal; + unsigned int fbinCalMin; + unsigned int fbinCalMax; + unsigned int fNumberOfSegments; + unsigned int fNumberOfCores; +}; + +#endif diff --git a/NPSimulation/Detectors/Hicari/CConvexPolyhedron.cc b/NPSimulation/Detectors/Hicari/CConvexPolyhedron.cc new file mode 100644 index 000000000..a21a76dcb --- /dev/null +++ b/NPSimulation/Detectors/Hicari/CConvexPolyhedron.cc @@ -0,0 +1,909 @@ +#include "CConvexPolyhedron.hh" +#include "G4ThreeVector.hh" + +#include "G4VoxelLimits.hh" +#include "G4AffineTransform.hh" + +#include "G4VGraphicsScene.hh" +#include "G4Polyhedron.hh" +#include <iomanip> + +using namespace std; // needed for swap() + +#ifdef G4V10 +using namespace CLHEP; +#endif + + +CConvexPolyhedron::~CConvexPolyhedron() +{ + if(fPoints) delete [] fPoints; + if(cCenter) delete cCenter; + if(fPlanes) delete [] fPlanes; + for(G4int nn = 0; nn < nPlanes; nn++ ) + if(iPlanes[nn]) delete [] iPlanes[nn]; + if(iPlanes) delete [] iPlanes; + if(xyz) delete [] xyz; + if(fff) delete [] fff; +} + +// the copy constructor +CConvexPolyhedron::CConvexPolyhedron(const CConvexPolyhedron& orig) + : G4CSGSolid(orig.GetName()), nPoints(0), fPoints(0), cCenter(0), + nPlanes(0), iPlanes(0), fPlanes(0), + xyz(0), nFacets(0), fff(0) +{ + nPoints = orig.nPoints; + fPoints = new G4Point3D[nPoints]; + cCenter = new G4Point3D; + + G4int nn; + for( nn = 0; nn < nPoints; nn++ ) + fPoints[nn] = orig.fPoints[nn]; + + cCenter = orig.cCenter; + nPlanes = orig.nPlanes; + iPlanes = new G4int*[nPlanes]; + fPlanes = new G4Plane3D[nPlanes]; + + for( nn = 0; nn < nPlanes; nn++ ) { + G4int nSides = *orig.iPlanes[nn]; // how many points + iPlanes[nn] = new int[1+nSides]; + memcpy(iPlanes[nn], orig.iPlanes[nn], (nSides+1)*sizeof(G4int)); + fPlanes[nn] = orig.fPlanes[nn]; + } + + xyz = new P3D[nPoints]; + memcpy(xyz, orig.xyz, nPoints*sizeof(P3D)); + + nFacets = orig.nFacets; + fff = new FAC[nFacets]; + memcpy(fff, orig.fff, nFacets*sizeof(FAC)); + +} + +// constructor for 2 polygonal faces of n/2 points with quadrangular sides +CConvexPolyhedron::CConvexPolyhedron(const G4String& pName, const std::vector<G4Point3D> &pVec) + : G4CSGSolid(pName), nPoints(0), fPoints(0), cCenter(0), + nPlanes(0), iPlanes(0), fPlanes(0), + xyz(0), nFacets(0), fff(0) +{ + nPoints = pVec.size(); + + if(nPoints < 6 || nPoints%2) { + G4cout << "ERROR - CConvexPolyhedron::CConvexPolyhedron(): " << GetName() << G4endl + << " Invalid number of vertices: " << nPoints << G4endl; + G4cerr << "ERROR - CConvexPolyhedron::CConvexPolyhedron(): " << GetName() << G4endl + << " Invalid number of vertices: " << nPoints << G4endl; + G4Exception("CConvexPolyhedron::CConvexPolyhedron()","Error2",FatalException,"Invalid number of vertices"); + } + + G4int nSides = nPoints/2; + fPoints = new G4Point3D[nPoints]; + cCenter = new G4Point3D; + + G4int ii; + for( ii = 0; ii < nPoints; ++ii ) { + fPoints[ii] = pVec[ii]; + *cCenter += fPoints[ii]; + } + *cCenter /= nPoints; + + nPlanes = nSides + 2; + iPlanes = new G4int*[nPlanes]; + fPlanes = new G4Plane3D[nPlanes]; + + iPlanes[0] = new int[1+nSides]; + iPlanes[0][0] = nSides; + for ( ii = 0; ii < nSides; ++ii ) + iPlanes[0][ii+1] = ii; + + iPlanes[1] = new int[1+nSides]; + iPlanes[1][0] = nSides; + for ( ii = 0; ii < nSides; ++ii ) + iPlanes[1][ii+1] = nSides + ii; + + for (ii = 0; ii < nSides; ++ii) { + iPlanes[2+ii] = new G4int[5]; + iPlanes[2+ii][0] = 4; + iPlanes[2+ii][1] = ii; + iPlanes[2+ii][2] = nSides + ii; + iPlanes[2+ii][3] = nSides + (ii+1)%nSides; + iPlanes[2+ii][4] = (ii+1)%nSides; + } + + for( ii = 0; ii < nPlanes; ii++ ) + MakePlane(ii); + +//CheckConvexity(kCarTolerance/2.); +// given that we read the points from a text file, this is a more realistic precision + CheckConvexity(0.05*CLHEP::micrometer); + + G4Point3D cc(0., 0., 0.); + for( ii = 0; ii < nPoints; ii++ ) { // recalculate the points + MakePoint(ii); + cc += fPoints[ii]; + } + cc /= nPoints; + *cCenter = cc; + + CheckConvexity(kCarTolerance/2.); // now we can check with the default precision + + PreparePolyhedron(); + +} + +// generic constructor: the points and descriptors of the faces + CConvexPolyhedron::CConvexPolyhedron(const G4String& pName, const std::vector<G4Point3D> &pVec, + const G4int nFaces, const std::vector<G4int> &theFaces) + : G4CSGSolid(pName), nPoints(0), fPoints(0), cCenter(0), + nPlanes(0), iPlanes(0), fPlanes(0), + xyz(0), nFacets(0), fff(0) +{ + nPoints = pVec.size(); + + if(nPoints < 4) { + G4cout << "ERROR - CConvexPolyhedron::CConvexPolyhedron(): " << GetName() << G4endl + << " Invalid number of vertices: " << nPoints << G4endl; + G4cerr << "ERROR - CConvexPolyhedron::CConvexPolyhedron(): " << GetName() << G4endl + << " Invalid number of vertices: " << nPoints << G4endl; + G4Exception("CConvexPolyhedron::CConvexPolyhedron()","Error3",FatalException,"Invalid number of vertices"); + } + + if(nFaces < 4) { + G4cout << "ERROR - CConvexPolyhedron::CConvexPolyhedron(): " << GetName() << G4endl + << " Invalid number of faces: " << nFaces << G4endl; + G4cerr << "ERROR - CConvexPolyhedron::CConvexPolyhedron(): " << GetName() << G4endl + << " Invalid number of faces: " << nFaces << G4endl; + G4Exception("CConvexPolyhedron::CConvexPolyhedron()","Error4",FatalException,"Invalid number of faces"); + } + + fPoints = new G4Point3D[nPoints]; + cCenter = new G4Point3D; + + G4int ii; + for( ii = 0; ii < nPoints; ++ii ) { + fPoints[ii] = pVec[ii]; + *cCenter += fPoints[ii]; + } + *cCenter /= nPoints; + + nPlanes = nFaces; + iPlanes = new int*[nPlanes]; + fPlanes = new G4Plane3D[nPlanes]; + + G4int nn = 0; + G4int jj, mm; + for ( ii = 0; ii < nPlanes; ++ii ) { + mm = theFaces[nn++]; + iPlanes[ii] = new int[mm+1]; + iPlanes[ii][0] = mm; + for ( jj = 0; jj < mm; jj++ ) + iPlanes[ii][jj+1] = theFaces[nn++]; + } + + for( ii = 0; ii < nPlanes; ii++ ) + MakePlane(ii); + +//CheckConvexity(kCarTolerance/2.); +// given that we read the points from a text file, this is a more realistic precision + CheckConvexity(0.05*CLHEP::micrometer); + + G4Point3D cc(0., 0., 0.); + for( ii = 0; ii < nPoints; ii++ ) { // recalculate the points + MakePoint(ii); + cc += fPoints[ii]; + } + cc /= nPoints; + *cCenter = cc; + + CheckConvexity(kCarTolerance/2.); // now we can check with the default precision + + PreparePolyhedron(); + +} + + + + + +////////////////////////////////////////////////////////////////////////////// +// +// Calculate the coef's of the plane with normal pointing to the outside +// i.e. the ThreeVectors are in anti-clockwise order when viewed from outside + +void CConvexPolyhedron::MakePlane( G4int ii) +{ + G4int np = iPlanes[ii][0]; // how many points + G4int *ip = &iPlanes[ii][1]; // their index into fPoints + G4Point3D *pjj, *pkk; + +// The average of the cross product of the adjacent edges of each point +// see e.g. D.F.Rogers, Proocedural Elements for Computer Graphics, p. 209 + G4Point3D fc(0., 0., 0.); // the center of the face + G4Point3D nv(0., 0., 0.); // its normal vector + for ( G4int nn = 0; nn < np; nn++ ) { + pjj = fPoints + ip[nn]; + pkk = fPoints + ip[(nn+1)%np]; + nv += G4Point3D( (pjj->y() - pkk->y()) * (pjj->z() + pkk->z()) , + (pjj->z() - pkk->z()) * (pjj->x() + pkk->x()) , + (pjj->x() - pkk->x()) * (pjj->y() + pkk->y()) ); + fc += *pjj; + } + nv /= nv.distance(); // normalization of the normal + fc /= np; // the center of the face as average of its points + G4Plane3D pl = G4Plane3D(G4Normal3D(nv), G4Point3D(fc)); + G4double dd = pl.distance(*cCenter); +// the distance of the center of the solid must be negative to agree with the convention +// of GEANT4 which wants the normal vector to point to the outside + if (dd > 0.) { // adjust the equation and the order of the points + pl = G4Plane3D(G4Normal3D(-nv), G4Point3D(fc)); + for ( G4int jj = 0; jj < np/2; jj++ ) + swap(ip[jj], ip[np-jj-1]); + } + fPlanes[ii] = pl; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Calculate the coordinates of the point as intersection of three planes +// +////////////////////////////////////////////////////////////////////////////// +G4bool CConvexPolyhedron::MakePoint( G4int pp) +{ + G4int pl[3]; + G4int npl = 0; + for ( G4int ii = 0; ii < nPlanes; ii++ ) { + G4int np = iPlanes[ii][0]; // how many points + G4int *ip = &iPlanes[ii][1]; // their index into fPoints + for ( G4int jj = 0; jj < np; jj++ ) { + if (ip[jj] == pp) { + pl[npl++] = ii; + break; + } + } + if (npl == 3) { + G4Point3D pnew = SolvePointEq(fPlanes[pl[0]], fPlanes[pl[1]],fPlanes[pl[2]]); + //double dist = fPoints[pp].distance(pnew); + fPoints[pp] = pnew; + return true; + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Determine the intersection of three planes +// +//////////////////////////////////////////////////////////////////////////////// +G4Point3D CConvexPolyhedron::SolvePointEq(G4Plane3D& pl0, G4Plane3D& pl1, G4Plane3D& pl2) +{ + double vm[3][3], mv[3][3]; + double vd[3], pd[3]; + double det; + G4int ii, i1, i2, jj, j1, j2; + + vm[0][0] = pl0.a(); vm[0][1] = pl0.b(); vm[0][2] = pl0.c(); + vm[1][0] = pl1.a(); vm[1][1] = pl1.b(); vm[1][2] = pl1.c(); + vm[2][0] = pl2.a(); vm[2][1] = pl2.b(); vm[2][2] = pl2.c(); + + vd[0] = -pl0.d(); vd[1] = -pl1.d(); vd[2] = -pl2.d(); + + det = 0; + ii = 0; + i1 = 1; + i2 = 2; + for( jj = 0; jj < 3; jj++ ) { + j1 = (jj+1)%3; + j2 = (jj+2)%3; + det += vm[ii][jj]*(vm[i1][j1]*vm[i2][j2] - vm[i1][j2]*vm[i2][j1]); + } + + if(det == 0.) { + G4cout << "CConvexPolyhedron::SolvePointEq : Determinant of matrix is 0." << G4endl; + G4cerr << "CConvexPolyhedron::SolvePointEq : Determinant of matrix is 0." << G4endl; + G4Exception("CConvexPolyhedron::SolvePointEq","Error5",FatalException,"Determinant of matrix is 0."); + } + + det = 1. / det; + for( ii = 0; ii < 3; ii++ ) { + i1 = (ii+1)%3; + i2 = (ii+2)%3; + for( jj = 0; jj < 3; jj++ ) { + j1 = (jj+1)%3; + j2 = (jj+2)%3; + mv[jj][ii] = det * (vm[i1][j1]*vm[i2][j2] - vm[i1][j2]*vm[i2][j1]); + } + } + + + for( ii = 0; ii < 3; ii++ ) { + double val = 0; + for( jj = 0; jj < 3; jj++ ) { + val += mv[ii][jj] * vd[jj]; + } + pd[ii] = val; + } + return G4Point3D(pd[0], pd[1], pd[2]); +} + + +//////////////////////////////////////////////////////////////////////// +// +// If the solid is convex all its defining points must not be kOutside +// +/////////////////////////////////////////////////////////////////////// +void CConvexPolyhedron::CheckConvexity(const G4double dmax) +{ + for ( G4int ii = 0; ii < nPoints; ii++ ) { + for ( G4int jj = ii; jj < nPoints; jj++ ) { + G4ThreeVector p = G4ThreeVector((fPoints[ii] + fPoints[jj])/2.); + for ( G4int i = 0; i < nPlanes; i++ ) { + G4double Dist = fPlanes[i].distance(p); + if (Dist > dmax) { + G4cout << "WARNING - " << GetName() << " point [" + << std::setw( 2) << ii << " + " + << std::setw( 2) << jj << "]/2 is " + << std::setiosflags(std::ios::fixed) << std::setprecision(6) + << std::setw(10) << Dist/CLHEP::mm << " mm outside plane " + << std::setw( 2) << i << G4endl; + } + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +// +// Shifts the plane along its normal (dist > 0 means outwards) +// +////////////////////////////////////////////////////////////////////////// +G4bool CConvexPolyhedron::MovePlane(const G4int nn, const G4double distance) +{ + if(nn < 0 || nn > nPlanes) + return false; + + G4Plane3D pl = fPlanes[nn]; + fPlanes[nn] = G4Plane3D(pl.a(), pl.b(), pl.c(), pl.d()-distance); + +// needs to recalculate figure + + G4int np = iPlanes[nn][0]; // how many points + G4int *ip = &iPlanes[nn][1]; // their index into fPoints + G4Point3D fc(0., 0., 0.); // the center of the face + G4int ii; + for ( ii = 0; ii < np; ii++ ) { + MakePoint(ip[ii]); + fc += fPoints[ip[ii]]; + } + fc /= np; + //double fcDistance = fPlanes[nn].distance(fc); // should be zero + + G4Point3D cc(0., 0., 0.); + for( ii = 0; ii < nPoints; ii++ ) { // recalculate the points and adjust bbox + MakePoint(ii); + cc += fPoints[ii]; + } + cc /= nPoints; + *cCenter = cc; + + CheckConvexity(kCarTolerance/2.); // now we can check with the default precision + + PreparePolyhedron(); + + return true; + +} + +//////////////////////////////////////////////////////////////////////// +// +// Prepares points and facets as used by HepPolyhedron::createPolyhedron() +// +/////////////////////////////////////////////////////////////////////////////// +void CConvexPolyhedron::PreparePolyhedron() +{ +// These comments taken from +// HepPolyhedron::createPolyhedron( G4int Nnodes, G4int Nfaces, +// const double xyz[][3], +// const G4int faces[][4]) +// +//*********************************************************************** +//* * +//* Name: createPolyhedron Date: 05.11.02 * +//* Author: E.Chernyaev (IHEP/Protvino) Revised: * +//* * +//* Function: Creates user defined polyhedron * +//* * +//* Input: Nnodes - number of nodes * +//* Nfaces - number of faces * +//* nodes[][3] - node coordinates * +//* faces[][4] - faces * +//* * +//* The faces of the polyhedron should be either triangles or planar +//* quadrilateral. Nodes of a face are defined by indexes pointing to +//* the elements in the xyz array. Numeration of the elements in the +//* array starts from 1 (like in fortran). The indexes can be positive +//* or negative. Negative sign means that the corresponding edge is +//* invisible. The normal of the face should be directed to exterior +//* of the polyhedron. +//*********************************************************************** + + G4int ii; + + if(!nFacets) { + for (ii = 0; ii < nPlanes; ii++ ) { + G4int *ip = iPlanes[ii]; + G4int nn = *ip; + nFacets += 1 + (nn-3)/2; + } + xyz = new P3D[nPoints]; + fff = new FAC[nFacets]; + } + + for (ii = 0; ii < nPoints; ii++ ) { + xyz[ii][0] = fPoints[ii].x(); + xyz[ii][1] = fPoints[ii].y(); + xyz[ii][2] = fPoints[ii].z(); + } + + G4int iff = 0; + for (ii = 0; ii < nPlanes; ii++ ) { + G4int *ip = iPlanes[ii]; + G4int nn = *ip++; + fff[iff][0] = ip[0]+1; + fff[iff][1] = ip[1]+1; + fff[iff][2] = ip[2]+1; + fff[iff][3] = (nn > 3) ? (ip[3]+1) : (0); +#if 0 + if(nn > 4) { // to make the extra edges invisible + fff[iff][0] *= -1; // it works but produces a lot of annoying messages about + fff[iff][3] *= -1; // different edge visibility in HepPolyhedron::SetReference() + } +#endif + iff++; + for ( G4int jj = 4; jj < nn; jj += 2) { + fff[iff][0] = ip[0]+1; + fff[iff][1] = ip[jj-1]+1; + fff[iff][2] = ip[jj ]+1; + fff[iff][3] = (nn > jj+1) ? (ip[jj+1]+1) : (0); +#if 0 + fff[iff][0] *= -1; // to make the extra edges invisible + fff[iff][1] *= -1; + if(nn > jj+2) { + fff[iff][3] *= -1; + } +#endif + iff++; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// +// Calculate extent under transform and specified limit +// +////////////////////////////////////////////////////////////////////////// +G4bool CConvexPolyhedron::CalculateExtent( const EAxis pAxis, + const G4VoxelLimits& pVoxelLimit, + const G4AffineTransform& pTransform, + G4double& pMin, G4double& pMax) const +{ + G4double xMin, xMax, yMin, yMax, zMin, zMax; + G4bool flag; + + G4bool existsAfterClip = false ; + G4ThreeVectorList* vertices; + pMin = +kInfinity; + pMax = -kInfinity; + + vertices = CreateRotatedVertices(pTransform); // Operator 'new' is called for vertices + + xMin = +kInfinity; yMin = +kInfinity; zMin = +kInfinity; + xMax = -kInfinity; yMax = -kInfinity; zMax = -kInfinity; + + for( G4int nv = 0 ; nv < nPoints ; nv++ ) { + if( (*vertices)[nv].x() > xMax ) xMax = (*vertices)[nv].x(); + if( (*vertices)[nv].y() > yMax ) yMax = (*vertices)[nv].y(); + if( (*vertices)[nv].z() > zMax ) zMax = (*vertices)[nv].z(); + + if( (*vertices)[nv].x() < xMin ) xMin = (*vertices)[nv].x(); + if( (*vertices)[nv].y() < yMin ) yMin = (*vertices)[nv].y(); + if( (*vertices)[nv].z() < zMin ) zMin = (*vertices)[nv].z(); + } + + if ( pVoxelLimit.IsXLimited() ) { + if ( (xMin > pVoxelLimit.GetMaxXExtent() + kCarTolerance) + || (xMax < pVoxelLimit.GetMinXExtent() - kCarTolerance) ) { + delete vertices ; // 'new' in the function called + return false ; + } + else { + if ( xMin < pVoxelLimit.GetMinXExtent() ) { + xMin = pVoxelLimit.GetMinXExtent() ; + } + if ( xMax > pVoxelLimit.GetMaxXExtent() ) { + xMax = pVoxelLimit.GetMaxXExtent() ; + } + } + } + + if ( pVoxelLimit.IsYLimited() ) { + if ( (yMin > pVoxelLimit.GetMaxYExtent() + kCarTolerance) + || (yMax < pVoxelLimit.GetMinYExtent() - kCarTolerance) ) { + delete vertices ; // 'new' in the function called + return false; + } + else { + if ( yMin < pVoxelLimit.GetMinYExtent() ) { + yMin = pVoxelLimit.GetMinYExtent() ; + } + if ( yMax > pVoxelLimit.GetMaxYExtent() ) { + yMax = pVoxelLimit.GetMaxYExtent() ; + } + } + } + + if ( pVoxelLimit.IsZLimited() ) { + if ( (zMin > pVoxelLimit.GetMaxZExtent() + kCarTolerance) + || (zMax < pVoxelLimit.GetMinZExtent() - kCarTolerance) ) { + delete vertices ; // 'new' in the function called + return false; + } + else { + if ( zMin < pVoxelLimit.GetMinZExtent() ) { + zMin = pVoxelLimit.GetMinZExtent() ; + } + if ( zMax > pVoxelLimit.GetMaxZExtent() ) { + zMax = pVoxelLimit.GetMaxZExtent() ; + } + } + } + + switch (pAxis) + { + case kXAxis: + pMin=xMin; + pMax=xMax; + break; + + case kYAxis: + pMin=yMin; + pMax=yMax; + break; + + case kZAxis: + pMin=zMin; + pMax=zMax; + break; + + default: + break; + } + + if ( (pMin != kInfinity) || (pMax != -kInfinity) ) { + existsAfterClip=true; + // Add tolerance to avoid precision troubles + pMin -= kCarTolerance ; + pMax += kCarTolerance ; + } + + delete vertices ; // 'new' was called in CreateRotatedVertices() + flag = existsAfterClip ; + + return flag; +} + +//////////////////////////////////////////////////////////////////////// +// +// Return whether point inside/outside/on surface, using tolerance +// +//////////////////////////////////////////////////////////////////////// +EInside CConvexPolyhedron::Inside( const G4ThreeVector& p ) const +{ + EInside in = kInside; + G4double Dist; + G4int i; + + for ( i = 0; i < nPlanes; i++ ) { + Dist = fPlanes[i].distance(p); + if (Dist > kCarTolerance/2) { + return in=kOutside; + } + else if (Dist>-kCarTolerance/2) { + in=kSurface; + } + } + return in; +} + +///////////////////////////////////////////////////////////////////////////// +// +// Calculate side nearest to p, and return normal +// If 2+ sides equidistant, first side's normal returned (arbitrarily) +// +/////////////////////////////////////////////////////////////////////////////// +G4ThreeVector CConvexPolyhedron::SurfaceNormal( const G4ThreeVector& p ) const +{ + G4double safe = kInfinity; + G4double Dist; + G4int i, imin = 0; + + for ( i = 0; i < nPlanes; i++ ) { + Dist = fabs(fPlanes[i].distance(p)); + if (Dist < safe) { + safe=Dist; + imin=i; + } + } + return G4ThreeVector(fPlanes[imin].normal()); +} + +//////////////////////////////////////////////////////////////////////////// +// +// Calculate distance to shape from outside - return kInfinity if no intersection +// +// ALGORITHM: +// For each component, calculate pair of minimum and maximum intersection +// values for which the particle is in the extent of the shape +// - The smallest (MAX minimum) allowed distance of the pairs is intersect +// +////////////////////////////////////////////////////////////////////////////////// +G4double CConvexPolyhedron::DistanceToIn( const G4ThreeVector& p, const G4ThreeVector& v ) const +{ + G4double snxt; // snxt = default return value + G4double smax, smin; + G4double pdist, Comp, vdist; + + smin = 0; + smax = kInfinity; + + for ( G4int i = 0; i < nPlanes; i++ ) { + pdist = fPlanes[i].distance(p); + Comp = fPlanes[i].a()*v.x() + fPlanes[i].b()*v.y() + fPlanes[i].c()*v.z(); + if (pdist >= -0.5*kCarTolerance) { // Outside the plane -> this is an extent entry distance + if (Comp >= 0) { + return snxt = kInfinity; + } + else { + vdist = -pdist / Comp; + if (vdist > smin) { + if (vdist < smax) + smin = vdist; + else + return snxt = kInfinity; + } + } + } + else { // Inside the plane -> coud be an extent exit distance (smax) + if (Comp > 0) { // Will leave extent + vdist = -pdist / Comp; + if (vdist < smax) { + if (vdist > smin) + smax = vdist; + else + return snxt = kInfinity; + } + } + } + } + + if (smin >= 0 ) { + snxt = smin; + } + else { + snxt = 0; + } + +#if 0 + G4ThreeVector mid = p + 0.5*(smax+smin)*v; + if(Inside(mid) == kOutside) { + // cannot happen if solid is convex + G4cout << " CConvexPolyhedron::DistanceToIn(p,v) middle point outside" << G4endl; + snxt=kInfinity; + } +#endif + + return snxt; + +} + +/////////////////////////////////////////////////////////////////////////// +// +// Calculate exact shortest distance to any boundary from outside +// This is the best fast estimation of the shortest distance to trap +// - Returns 0 is ThreeVector inside +// +////////////////////////////////////////////////////////////////////////////// +G4double CConvexPolyhedron::DistanceToIn( const G4ThreeVector& p ) const +{ + G4double safe,Dist; + G4int i; + + safe = kInfinity; + for ( i = 0; i < nPlanes; i++ ) { + Dist = fPlanes[i].distance(p); + if (Dist > -kCarTolerance/2 && Dist < safe) + safe = Dist; + } + if (safe < 0) safe=0; + return safe; +} + +///////////////////////////////////////////////////////////////////////////////// +// +// Calculate distance to surface of shape from inside +// Calculate distance to x/y/z planes - smallest is exiting distance +// +////////////////////////////////////////////////////////////////////////////////////// +G4double CConvexPolyhedron::DistanceToOut( const G4ThreeVector& p, const G4ThreeVector& v, + const G4bool calcNorm, + G4bool *validNorm, G4ThreeVector *n) const +{ + G4double snxt = kInfinity; + G4double pdist,Comp,vdist; + G4int i, side = -1; + + for ( i = 0; i < nPlanes; i++ ) { + pdist = fPlanes[i].distance(p); + Comp = fPlanes[i].a()*v.x()+fPlanes[i].b()*v.y()+fPlanes[i].c()*v.z(); + if (pdist > 0) { // Outside the plane + if (Comp > 0) { // Leaving immediately + if (calcNorm) { + *validNorm = true; + *n = G4ThreeVector(fPlanes[i].a(), fPlanes[i].b(), fPlanes[i].c()); + } + return snxt = 0; + } + } + else if (pdist < -0.5*kCarTolerance) { // Inside the plane + if (Comp > 0) { // Will leave extent + vdist = -pdist / Comp; + if (vdist < snxt) { + snxt = vdist; + side = i; + } + } + } + else { // On surface + if (Comp > 0) { + if (calcNorm) { + *validNorm = true; + *n = G4ThreeVector(fPlanes[i].a(), fPlanes[i].b(), fPlanes[i].c()); + } + return snxt = 0; + } + } + } + + if (calcNorm) { + *validNorm = true; + *n = G4ThreeVector(fPlanes[side].a(), fPlanes[side].b(), fPlanes[side].c()); + } + return snxt; +} + +////////////////////////////////////////////////////////////////////////////// +// +// Calculate exact shortest distance to any boundary from inside +// - Returns 0 is ThreeVector outside +// +//////////////////////////////////////////////////////////////////////////////// +G4double CConvexPolyhedron::DistanceToOut( const G4ThreeVector& p ) const +{ + G4double safe,Dist; + G4int i; + +#ifdef G4CSGDEBUG + if( Inside(p) == kOutside ) + { + G4cout.precision(16) ; + G4cout << G4endl ; + DumpInfo(); + G4cout << "Position:" << G4endl << G4endl ; + G4cout << "p.x() = " << p.x()/mm << " mm" << G4endl ; + G4cout << "p.y() = " << p.y()/mm << " mm" << G4endl ; + G4cout << "p.z() = " << p.z()/mm << " mm" << G4endl << G4endl ; + G4cout << "CConvexPolyhedron::DistanceToOut(p) - point p is outside ?!" << G4endl ; + G4cerr << "CConvexPolyhedron::DistanceToOut(p) - point p is outside ?!" << G4endl ; + } +#endif + + safe = kInfinity; + for( i = 0; i < nPlanes; i++ ) { + Dist = -fPlanes[i].distance(p); + if(Dist > -kCarTolerance/2 && Dist < safe) + safe = Dist; + } + if (safe < 0) safe=0; + return safe; +} + +////////////////////////////////////////////////////////////////////////// +// +// Create a List containing the transformed vertices +// Note: Caller has deletion resposibility +// +/////////////////////////////////////////////////////////////////////////////// +G4ThreeVectorList* +CConvexPolyhedron::CreateRotatedVertices( const G4AffineTransform& pTransform ) const +{ + G4ThreeVectorList *vertices; + vertices = new G4ThreeVectorList(); + vertices->reserve(nPoints); + if (vertices) { + for ( G4int i = 0; i < nPoints; i++ ) { + vertices->push_back(pTransform.TransformPoint(fPoints[i])); + } + } + else { +// DumpInfo(); + G4Exception("CConvexPolyhedron::CreateRotatedVertices()","error6", FatalException,"Out of memory !"); + } + return vertices; +} + +////////////////////////////////////////////////////////////////////////// +// +// GetEntityType +// +////////////////////////////////////////////////////////////////////////////// +G4GeometryType CConvexPolyhedron::GetEntityType() const +{ + return G4String("CConvexPolyhedron"); +} + +////////////////////////////////////////////////////////////////////////// +// +// Stream object contents to an output stream +// +////////////////////////////////////////////////////////////////////////////// +std::ostream& CConvexPolyhedron::StreamInfo( std::ostream& os ) const +{ + os << "-----------------------------------------------------------\n" + << " *** Dump for solid - " << GetName() << " ***\n" + << " ===================================================\n" + << " Solid type: CConvexPolyhedron\n" + << nPoints << " Points: \n" + << nPlanes << " Planes: \n" + << "-----------------------------------------------------------\n"; + + return os; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Methods for visualisation +// +////////////////////////////////////////////////////////////////////////////// +void CConvexPolyhedron::DescribeYourselfTo ( G4VGraphicsScene& scene ) const +{ +#ifdef G4V47 + scene.AddSolid (*this); +#else + // scene.AddThis (*this); + scene.AddSolid (*this); +#endif +} + +G4Polyhedron* CConvexPolyhedron::CreatePolyhedron () const +{ + //G4cout << __PRETTY_FUNCTION__ << endl; + G4Polyhedron *cpp = new G4Polyhedron(); + //G4cout << "nPoints " << nPoints << ", nFacets " << nFacets << endl; + //for (int ii = 0; ii < nPoints; ii++ ) { + // G4cout << xyz[ii][0] << "\t" << xyz[ii][1] << "\t" << xyz[ii][2] << G4endl; + //} + //G4cout << "------------------------------------------------------------" << endl; + //for (int ii = 0; ii < nFacets; ii++ ) { + // G4cout << fff[ii][0] << "\t" << fff[ii][1] << "\t" << fff[ii][2] << "\t" << fff[ii][3] << G4endl; + //} + + + cpp->createPolyhedron(nPoints, nFacets, xyz, fff); + //G4cout << cpp << endl; + //G4cout << "end " << __PRETTY_FUNCTION__ << endl; + + return cpp; +} + diff --git a/NPSimulation/Detectors/Hicari/CConvexPolyhedron.hh b/NPSimulation/Detectors/Hicari/CConvexPolyhedron.hh new file mode 100644 index 000000000..23a48b149 --- /dev/null +++ b/NPSimulation/Detectors/Hicari/CConvexPolyhedron.hh @@ -0,0 +1,130 @@ +#ifndef CConvexPolyhedron_h +#define CConvexPolyhedron_h + +////////////////////////////////////////////////////////////////////////////////////////////// +/// CConvexPolyhedron (D.B. 30/12/02) +/// +/// Class description: +/// +/// CConvexPolyhedron is a general Convex Polyhedron enclosed by flat surfaces. +/// It is built as a CSG solid +/// fPoints are the nPoints vertices used to define the planes +/// fPlanes the nPlanes enclosing planes +/// The faces can have any (>2) number of sides. +/// The coefficients of plane equations are obtained as an average +/// of the outside normals at each of the defining points. +/// This should avoid (or reduce??) problems of complanarity +/// originated by the precision of the fPoints +/// +/// The class has been written (copied!) following the model of G4Trap (from Geant5.0) +/// G4Trap implements a 6-face convex polyhedron but treats the 2 planes +/// perpendicular to the z axis as a special case (which only complicates the code) +/// +/// HepPolyhedron::createPolyhedron() method is used for visualization +/// Faces with more than 4 sides are decomposed into 4-sided facets +/// +/// To do: +/// ~CConvexPolyhedron() to clear the allocated structures. +/// More general constructors. The (real) one implemented so far assumes that the points +/// are arranged in two surfaces joined by 4-sided faces (as normally used in AGATA). +/// Accessors, Modifiers, ... +////////////////////////////////////////////////////////////////////////////////////////////// + +#include "G4CSGSolid.hh" +#include "G4Point3D.hh" +#include "G4Plane3D.hh" +#include "G4Normal3D.hh" + +class CConvexPolyhedron : public G4CSGSolid +{ + + public: + ///////////////////////////////////////////////////////////////// + /// copy constructor + ///////////////////////////////////////////////////////////////// + CConvexPolyhedron(const CConvexPolyhedron& orig); + + ///////////////////////////////////////////////////////////////// + /// Constructor for MarsView: 2 faces of n/2 points connected by quadrangles + ///////////////////////////////////////////////////////////////// + CConvexPolyhedron(const G4String& pName, const std::vector<G4Point3D>& pVec); + ///////////////////////////////////////////////////////////////// + /// Generic Constructor: points and descriptors of faces + ///////////////////////////////////////////////////////////////// + CConvexPolyhedron(const G4String& pName, const std::vector<G4Point3D>& pVec, + const G4int nFaces, const std::vector<G4int>& theFaces); + + /////////////////////////////////////////////// + /// Destructor + ////////////////////////////////////////////// + virtual ~CConvexPolyhedron() ; + + + private: + G4int nPoints; //> number of points + G4Point3D *fPoints; //> the points as G4Point3D + G4Point3D *cCenter; //> the center of the convex polyhedron (average of fPoints) + + private: + G4int nPlanes; //> number of enclosing planes + G4int **iPlanes; //> descriptors of the planes (number of points, index of each point) + G4Plane3D *fPlanes; //> the equation of the planes + + private: + typedef double P3D[3]; + typedef int FAC[4]; + P3D *xyz; //> the nPoints vertices for HepPolyhedron::createPolyhedron() + int nFacets; + FAC *fff; //> the nFacets facets for HepPolyhedron::createPolyhedron() + + public: + inline G4int GetnPoints () const {return nPoints; }; + inline G4int GetnPlanes () const {return nPlanes; }; + inline G4Point3D GetPoints (G4int nn) {return fPoints[nn]; }; + inline G4Point3D* GetCenter () { return cCenter; }; + + + public: + G4bool MovePlane(const G4int nn, const G4double dist); //> shifts the plane along its normal (+ --> outwards) + G4bool CalculateExtent( const EAxis pAxis, const G4VoxelLimits& pVoxelLimit, + const G4AffineTransform& pTransform, G4double& pMin, G4double& pMax ) const; + + public: + EInside Inside( const G4ThreeVector& p ) const; + + public: + G4ThreeVector SurfaceNormal( const G4ThreeVector& p ) const; + + public: + G4double DistanceToIn( const G4ThreeVector& p, const G4ThreeVector& v) const; + G4double DistanceToIn( const G4ThreeVector& p ) const; + + public: + G4double DistanceToOut( const G4ThreeVector& p ) const; + G4double DistanceToOut( const G4ThreeVector& p, const G4ThreeVector& v, + const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const; + + public: + G4GeometryType GetEntityType() const; + std::ostream& StreamInfo( std::ostream& os ) const; + + ////////////////////////////////////////////////////////////////// + /// Visualisation functions + /////////////////////////////////////////////////////////////////// + public: + void DescribeYourselfTo ( G4VGraphicsScene& scene ) const; + G4Polyhedron* CreatePolyhedron () const; + + protected: + G4ThreeVectorList* CreateRotatedVertices( const G4AffineTransform& pTransform ) const ; + + private: + void MakePlane(G4int ii); //> construct equation of plane from its defining points + G4bool MakePoint(G4int ii); //> determine point as intersection of 3 planes + void CheckConvexity(const G4double dmax); + void PreparePolyhedron(); + G4Point3D SolvePointEq(G4Plane3D& pl0, G4Plane3D& pl1, G4Plane3D& pl2); + +}; + +#endif diff --git a/NPSimulation/Detectors/Hicari/CMakeLists.txt b/NPSimulation/Detectors/Hicari/CMakeLists.txt new file mode 100644 index 000000000..a280bdbde --- /dev/null +++ b/NPSimulation/Detectors/Hicari/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(NPSHicari SHARED Hicari.cc CConvexPolyhedron.cc) +target_link_libraries(NPSHicari NPSCore ${ROOT_LIBRARIES} ${Geant4_LIBRARIES} ${NPLib_LIBRARIES} -lNPHicari) diff --git a/NPSimulation/Detectors/Hicari/Hicari.cc b/NPSimulation/Detectors/Hicari/Hicari.cc new file mode 100644 index 000000000..31d634140 --- /dev/null +++ b/NPSimulation/Detectors/Hicari/Hicari.cc @@ -0,0 +1,3287 @@ +/***************************************************************************** + * Copyright (C) 2009-2019 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Freddy Flavigny contact: flavigny@lpccaen.in2p3.fr * + * * + * Creation Date : april 2022 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class allows to build the HiCARI Ge array geometry * + * it is largely based on HICARI/GRETINA/AGATA simulation packages * + * Since it is a bit generic, it could be used for other geometries/arrays * + * * + *---------------------------------------------------------------------------* + * Comment: WORK IN PROGRESS, Lots of things still missing * + * * + *****************************************************************************/ + +// C++ headers +#include <cmath> +#include <limits> +#include <sstream> +// G4 Geometry object +#include "G4Box.hh" +#include "G4Cons.hh" +#include "G4LogicalVolume.hh" +#include "G4PVPlacement.hh" +#include "G4Para.hh" +#include "G4Polycone.hh" +#include "G4Polyhedra.hh" +#include "G4RotationMatrix.hh" +#include "G4ThreeVector.hh" +#include "G4Transform3D.hh" +#include "G4Trap.hh" +#include "G4Trd.hh" +#include "G4Tubs.hh" + +#include "G4IntersectionSolid.hh" +#include "G4PVReplica.hh" +#include "G4SubtractionSolid.hh" +#include "G4UnionSolid.hh" + +// G4 sensitive +#include "G4MultiFunctionalDetector.hh" +#include "G4SDManager.hh" + +// G4 various object +#include "G4Colour.hh" +#include "G4Material.hh" +#include "G4PVPlacement.hh" +#include "G4Transform3D.hh" +#include "G4VisAttributes.hh" + +// NPTool header +#include "Hicari.hh" +//#include "CalorimeterScorers.hh" +#include "GeScorers.hh" +#include "MaterialManager.hh" +#include "NPOptionManager.h" +#include "NPSDetectorFactory.hh" +#include "NPSHitsMap.hh" +#include "RootOutput.h" +// CLHEP header +#include "CLHEP/Random/RandGauss.h" + +using namespace std; +using namespace CLHEP; + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +namespace Hicari_NS { + // Energy and time Resolution + // const double EnergyThreshold = 10 * keV; + // const double ResoTime = 4.5*ns ; //not used + // const double ResoEnergy = 2. * keV; +} // namespace Hicari_NS +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// Hicari Specific Method +Hicari::Hicari() { + m_Event = new THicariData(); + m_HicariScorer = 0; + + // InitializeMaterials(); + + G4String path = "./"; + if (path.find("./", 0) != string::npos) { + G4int position = path.find("./", 0); + if (position == 0) + path.erase(position, 2); + } + iniPath = path; + + cryostatStatus = false; + // Slot 0 Position (starting point for Euler angle rotations) + cryostatPos0.setX(0.); + cryostatPos0.setY(0.); + cryostatPos0.setZ(406.); + // approximate polygonal feed-through space with cylinder + G4double extend = 93. * mm; + cryostatPos0.setMag(cryostatPos0.mag() - extend); + cryostatZplanes[0] = 0.; + cryostatZplanes[1] = extend; + cryostatZplanes[2] = 145. * mm + extend; + cryostatZplanes[3] = 155. * mm + extend; + cryostatZplanes[4] = 217. * mm + extend; + cryostatZplanes[5] = 217. * mm + extend; + cryostatZplanes[6] = 232. * mm + extend; + cryostatRinner[0] = 0.; + cryostatRinner[1] = 0.; + cryostatRinner[2] = 0.; + cryostatRinner[3] = 0.; + cryostatRinner[4] = 0.; + cryostatRinner[5] = 0.; + cryostatRinner[6] = 0.; + cryostatRouter[0] = 100. * mm; + cryostatRouter[1] = 130. * mm; + cryostatRouter[2] = 130. * mm; + cryostatRouter[3] = 140. * mm; + cryostatRouter[4] = 140. * mm; + cryostatRouter[5] = 165. * mm; + cryostatRouter[6] = 165. * mm; + + readOut = false; + + matCryst = NULL; + matWalls = NULL; + matBackWalls = NULL; + matHole = NULL; + matCryo = NULL; + matCrystName = "Germanium"; + matWallsName = "Al"; + // matBackWallsName = "BackWallMaterial"; + matBackWallsName = "Al"; + // matHoleName = "G4_Galactic"; + matHoleName = "Vacuum"; + matCryoName = "Al"; + + nEuler = 0; + eulerFile = iniPath + "aeuler"; + nPgons = 0; + solidFile = iniPath + "asolid"; + nWalls = 0; + wallsFile = iniPath + "awalls"; + nClAng = 0; + clustFile = iniPath + "aclust"; + sliceFile = iniPath + "aslice"; + + nDets = 0; + iCMin = 0; + iGMin = 0; + maxSec = 1; + maxSli = 1; + + arrayRmin = 0.; + arrayRmax = 0.; + thetaShift = 0.; + phiShift = 0.; + thetaPrisma = 0.; + posShift = G4ThreeVector(); + + useCylinder = true; + usePassive = true; + drawReadOut = false; + makeCapsule = false; + maxSolids = 0; + totSegments = 0; + stepFactor = 1; + stepHasChanged = false; + printVolumes = false; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +Hicari::~Hicari() { + clust.clear(); + pgons.clear(); + euler.clear(); + walls.clear(); + nSegments.clear(); + tSegments.clear(); + pgSegLl.clear(); + pgSegLu.clear(); + pgSegRl.clear(); + pgSegRu.clear(); + segVolume.clear(); + segCenter.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4int Hicari::InitializeMaterials() { + /* + m_Vacuum = MaterialManager::getInstance()->GetMaterialFromLibrary("Vacuum"); + m_Aluminum = MaterialManager::getInstance()->GetMaterialFromLibrary("Al"); + m_Copper = MaterialManager::getInstance()->GetMaterialFromLibrary("Cu"); + + m_BGO = new G4Material("BGO", 7.13*g/cm3, 3, kStateSolid); //BGO does not exist in nptool !! + m_BGO->AddElement(MaterialManager::getInstance()->GetElementFromLibrary("Bi"),4); + m_BGO->AddElement(MaterialManager::getInstance()->GetElementFromLibrary("Ge"),3); + m_BGO->AddElement(MaterialManager::getInstance()->GetElementFromLibrary("O"),12); + + m_CsI = MaterialManager::getInstance()->GetMaterialFromLibrary("CsI"); + */ + + // search the material by its name + // G4Material* ptMaterial = G4Material::GetMaterial(matCrystName); + // G4Material* ptMaterial = G4Material::GetMaterial(""); + G4Material* ptMaterial = MaterialManager::getInstance()->GetMaterialFromLibrary(matCrystName); + if (ptMaterial) { + matCryst = ptMaterial; + G4cout << "\n----> The crystals material is " << matCryst->GetName() << G4endl; + } + else { + G4cout << " Could not find the material " << matCrystName << G4endl; + G4cout << " Could not build the array! " << G4endl; + return 1; + } + + // search the material by its name + // ptMaterial = G4Material::GetMaterial(matWallsName); + ptMaterial = MaterialManager::getInstance()->GetMaterialFromLibrary(matWallsName); + if (ptMaterial) { + matWalls = ptMaterial; + G4cout << "\n----> The wall material is " << matWalls->GetName() << G4endl; + } + else { + G4cout << " Could not find the material " << matWallsName << G4endl; + G4cout << " Could not build the walls! " << G4endl; + } + + // search the material by its name + // ptMaterial = G4Material::GetMaterial(matBackWallsName); + ptMaterial = MaterialManager::getInstance()->GetMaterialFromLibrary(matBackWallsName); + if (ptMaterial) { + matBackWalls = ptMaterial; + G4cout << "\n----> The back wall material is " << matBackWalls->GetName() << G4endl; + } + else { + G4cout << " Could not find the material " << matBackWallsName << G4endl; + G4cout << " Could not build the walls behind the crystals! " << G4endl; + } + + // ptMaterial = G4Material::GetMaterial(matHoleName); + ptMaterial = MaterialManager::getInstance()->GetMaterialFromLibrary(matHoleName); + if (ptMaterial) { + matHole = ptMaterial; + G4cout << "\n----> The hole material is " << matHole->GetName() << G4endl; + } + else { + G4cout << " Could not find the material " << matHoleName << G4endl; + G4cout << " Could not build the capsules! " << G4endl; + } + + // ptMaterial = G4Material::GetMaterial(matCryoName); + ptMaterial = MaterialManager::getInstance()->GetMaterialFromLibrary(matCryoName); + if (ptMaterial) { + matCryo = ptMaterial; + G4cout << "\n----> The cryostat material is " << matCryo->GetName() << G4endl; + } + else { + G4cout << " Could not find the material " << matCryoName << G4endl; + G4cout << " Could not build the cryostats! " << G4endl; + } + + return 0; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// void Hicari::BuildClover(int i_clo, G4LogicalVolume* world) +//{ + +//} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// void Hicari::AddDetector(double X, double Y, double Z, double ThetaX, double ThetaY, double ThetaZ) {} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// Virtual Method of NPS::VDetector class + +// Read stream at Configfile to pick-up parameters of detector (Position,...) +// Called in DetecorConstruction::ReadDetextorConfiguration Method +void Hicari::ReadConfiguration(NPL::InputParser parser) { + + vector<NPL::InputBlock*> blocks = parser.GetAllBlocksWithToken("Hicari"); + if (NPOptionManager::getInstance()->GetVerboseLevel()) + cout << "//// " << blocks.size() << " block found " << endl; + + vector<string> filenames = {"asolid", "aclust", "aeuler", "awalls", "aslice"}; + + for (unsigned int i = 0; i < blocks.size(); i++) { + if (blocks[i]->HasTokenList(filenames)) { + if (NPOptionManager::getInstance()->GetVerboseLevel()) + cout << endl << "//// Hicari " << i + 1 << endl; + solidFile = blocks[i]->GetString("asolid"); + clustFile = blocks[i]->GetString("aclust"); + eulerFile = blocks[i]->GetString("aeuler"); + wallsFile = blocks[i]->GetString("awalls"); + sliceFile = blocks[i]->GetString("aslice"); + // AddDetector(X,Y,Z,ThetaX, ThetaY, ThetaZ); + } + else { + cout << "ERROR: check your input file formatting " << endl; + exit(1); + } + } + + ReadSolidFile(); + ReadClustFile(); + ReadWallsFile(); + ReadEulerFile(); + ReadSliceFile(); +} + +///////////////////////////////////////////////////////////// +///////////////// methods to read the files +///////////////////////////////////////////////////////////// + +void Hicari::ReadSolidFile() { + FILE* fp; + char line[256]; + G4int lline, i1, i2, i3, nvdots, opgon; + float x, y, z, X, Y, Z; + + nPgons = 0; + nDets = 0; + nClus = 0; + + if ((fp = fopen(solidFile, "r")) == NULL) { + G4cout << "\nError opening data file " << solidFile << G4endl; + exit(-1); + } + + G4cout << "\nReading description of crystals from file " << solidFile << " ..." << G4endl; + + pgons.clear(); + + nvdots = 0; + opgon = -1; + maxPgons = -1; + CpolyhPoints* pPg = NULL; + + while (fgets(line, 255, fp) != NULL) { + lline = strlen(line); + if (lline < 2) + continue; + if (line[0] == '#') + continue; + if (sscanf(line, "%d %d %d %f %f %f %f %f %f", &i1, &i2, &i3, &x, &y, &z, &X, &Y, &Z) != 9) { + nPgons++; + break; + } + if (opgon != i1) { // first-pass initializaton for each solid + nPgons++; + opgon = i1; + pgons.push_back(CpolyhPoints()); + pPg = &pgons.back(); + pPg->whichGe = i1; + if (i1 > maxPgons) + maxPgons = i1; + pPg->npoints = 2 * i2; + pPg->tubX = -1. * mm; + pPg->tubY = -1. * mm; + pPg->tubZ = -1. * mm; + pPg->tubr = -1. * mm; + pPg->tubR = -1. * mm; + pPg->tubL = -1. * mm; + pPg->capSpace = -1. * mm; + pPg->capThick = -1. * mm; + pPg->passThick1 = -1. * mm; + pPg->passThick2 = -1. * mm; + pPg->colx = 0.; + pPg->coly = 0.; + pPg->colz = 0.; + pPg->vertex.resize(pPg->npoints); + pPg->cylinderMakesSense = true; + pPg->makeCapsule = true; + pPg->isPlanar = false; + pPg->segSize_x = -1. * mm; + pPg->segSize_y = -1. * mm; + pPg->maxSize_x = -1000. * m; + pPg->maxSize_y = -1000. * m; + pPg->minSize_x = 1000. * m; + pPg->minSize_y = 1000. * m; + pPg->guardThick[0] = -1. * mm; + pPg->guardThick[1] = -1. * mm; + pPg->guardThick[2] = -1. * mm; + pPg->guardThick[3] = -1. * mm; + pPg->nSeg_x = 1; + pPg->nSeg_y = 1; + } + if (i2 == 0 && i3 == 0) { + pPg->tubr = ((G4double)x) * mm; + pPg->tubR = ((G4double)y) * mm; + pPg->tubL = ((G4double)z) * mm; + pPg->tubX = ((G4double)X) * mm; + pPg->tubY = ((G4double)Y) * mm; + pPg->tubZ = ((G4double)Z) * mm; + } + else if (i2 == 0 && i3 == 1) { + pPg->thick = ((G4double)x) * mm; + pPg->passThick1 = ((G4double)y) * mm; + pPg->passThick2 = ((G4double)z) * mm; + pPg->capSpace = ((G4double)X) * mm; + pPg->capThick = ((G4double)Y) * mm; + } + else if (i2 == 0 && i3 == 2) { + pPg->colx = ((G4double)x); + pPg->coly = ((G4double)y); + pPg->colz = ((G4double)z); + } + else if (i2 == 0 && i3 == 3) { // planar + pPg->cylinderMakesSense = false; + pPg->makeCapsule = false; + pPg->isPlanar = true; + pPg->nSeg_x = (G4int)x; + pPg->nSeg_y = (G4int)y; + pPg->guardThick[0] = ((G4double)z) * mm; + pPg->guardThick[1] = ((G4double)X) * mm; + pPg->guardThick[2] = ((G4double)Y) * mm; + pPg->guardThick[3] = ((G4double)Z) * mm; + } + else { + pPg->vertex[i3] = G4Point3D(((G4double)x), ((G4double)y), ((G4double)z)) * mm; + pPg->vertex[i3 + i2] = G4Point3D(((G4double)X), ((G4double)Y), ((G4double)Z)) * mm; + nvdots += 2; + } + } + + fclose(fp); + G4cout << nPgons << " polyhedra for a total of " << nvdots << " vertex points read." << G4endl; + + G4int npt, npg, nn; + G4double tolerance = 0.5 * mm; + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + G4bool isOpen = true; + if( (fp=fopen("asolidG", "w"))==NULL ) + isOpen = false; + #endif + #endif + */ + for (npg = 0; npg < nPgons; npg++) { + pPg = &pgons[npg]; + npt = pPg->npoints; + if (!npt) + continue; + + // calculates z of the two faces of the original polyhedron + pPg->centerFace1 = G4Point3D(); + pPg->centerFace2 = G4Point3D(); + for (nn = 0; nn < npt / 2; nn++) { + pPg->centerFace1 += pPg->vertex[nn]; + pPg->centerFace2 += pPg->vertex[nn + npt / 2]; + } + pPg->centerFace1 /= npt / 2; + pPg->centerFace2 /= npt / 2; + + pPg->zFace1 = pPg->centerFace1.z(); + pPg->zFace2 = pPg->centerFace2.z(); + pPg->zCenter = 0.5 * (pPg->zFace1 + pPg->zFace2); + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + // prints out a modified version of the original file, having the first face at zero z coordinate + if( isOpen ) { + fprintf( fp, "# solid %d\n", npg); + for( G4int iii=0; iii<npt/2; iii++ ) + fprintf( fp, "%4.1d %4.1d %4.1d %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf\n", + pPg->whichGe, npt/2, iii, + pPg->vertex[iii].x()/mm, + pPg->vertex[iii].y()/mm, + pPg->vertex[iii].z()/mm-pPg->zFace1/mm, + pPg->vertex[iii+npt/2].x()/mm, + pPg->vertex[iii+npt/2].y()/mm, + pPg->vertex[iii+npt/2].z()/mm-pPg->zFace1/mm ); + fprintf( fp, "%4.1d %4.1d %4.1d %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf\n", + pPg->whichGe, 0, 0, + pPg->tubr/mm, pPg->tubR/mm, pPg->tubL/mm, pPg->tubX/mm, pPg->tubY/mm, pPg->tubZ/mm ); + fprintf( fp, "%4.1d %4.1d %4.1d %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf\n", + pPg->whichGe, 0, 1, + pPg->thick/mm, pPg->passThick1/mm, pPg->passThick2/mm, pPg->capSpace/mm, pPg->capThick/mm, + (pPg->capSpace+pPg->capThick)/mm ); fprintf( fp, "%4.1d %4.1d %4.1d %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf + %12.6lf\n", pPg->whichGe, 0, 2, pPg->colx, pPg->coly, pPg->colz, 0., 0., 0. ); fprintf( fp, "# end solid %d\n#\n", + npg); + } + #endif + #endif + */ + // calculates the minimum radius of a cylinder surrounding the polyhedron + G4double minR2 = 0.; + G4double theR2; + for (nn = 0; nn < npt; nn++) { + theR2 = pow(pPg->vertex[nn].x(), 2.) + pow(pPg->vertex[nn].y(), 2.); + if (theR2 > minR2) + minR2 = theR2; + } + pPg->minR = sqrt(minR2) + 2. * tolerance; // safety margin! + + // check: to avoid tolerance problems, increase the cylinder length + if (fabs((pPg->zFace2 - pPg->zFace1) - pPg->tubL) < tolerance) + pPg->tubL += 2. * tolerance; + + // check the validity of the cylinder + if (pPg->cylinderMakesSense && (pPg->tubR < 0.)) { + pPg->cylinderMakesSense = false; + G4cout << " Warning! Cylinder will not be built in solid " << pPg->whichGe << G4endl; + } + if (pPg->cylinderMakesSense && (pPg->tubL < 0.)) { + pPg->cylinderMakesSense = false; + G4cout << " Warning! Cylinder will not be built in solid " << pPg->whichGe << G4endl; + } + if (pPg->cylinderMakesSense && (pPg->tubr < 0.)) { + G4cout << " Warning! Setting inner cylinder radius to zero in solid " << pPg->whichGe << G4endl; + pPg->tubr = 0.; + } + if (pPg->cylinderMakesSense && (pPg->tubr > pPg->tubR)) { + pPg->cylinderMakesSense = false; + G4cout << " Warning! Cylinder will not be built in solid " << pPg->whichGe << G4endl; + } + // if the cylinder does not exceed the polyhedron, keep the cylinder coordinates! + if (pPg->zCenter - pPg->tubL / 2. > pPg->zFace1) + pPg->zFace1 = pPg->zCenter - pPg->tubL / 2.; + if (pPg->zCenter + pPg->tubL / 2. < pPg->zFace2) + pPg->zFace2 = pPg->zCenter + pPg->tubL / 2.; + // additional check: if crystal is not long enough, no hole!!! + if ((pPg->zFace1 + pPg->thick) > pPg->zFace2) { + G4cout << " Warning! Setting inner cylinder radius to zero in solid " << pPg->whichGe << G4endl; + pPg->tubr = 0.; + } + + // passive areas + // at the back of the detector + if (pPg->passThick1 < 0.) { + pPg->passThick1 = 0.; + G4cout << " Warning! Passive layer will not be built in solid " << pPg->whichGe << G4endl; + } + else if (pPg->passThick1 > pPg->tubL) { + pPg->passThick1 = pPg->tubL; + G4cout << " Warning! Setting passive layer thickness to " << pPg->tubL / mm << " mm in solid " << pPg->whichGe + << G4endl; + } + + // around the coaxial hole + if (pPg->cylinderMakesSense) { + if (pPg->passThick2 < 0.) { + pPg->passThick2 = 0.; + G4cout << " Warning! Passive layer will not be built in solid " << pPg->whichGe << G4endl; + } + else if (pPg->passThick2 > (pPg->tubR - pPg->tubr) || pPg->passThick2 > pPg->thick) { + pPg->passThick2 = min(pPg->tubR - pPg->tubr, pPg->thick); + G4cout << " Warning! Setting passive layer thickness to " << (pPg->tubR - pPg->tubr) / mm << " mm in solid " + << pPg->whichGe << G4endl; + } + } + + if (pPg->makeCapsule && (pPg->capSpace <= 0.)) { + pPg->makeCapsule = false; + G4cout << " Warning! Capsule will not be built for solid " << pPg->whichGe << G4endl; + } + if (pPg->makeCapsule && (pPg->capThick <= 0.)) { + pPg->makeCapsule = false; + G4cout << " Warning! Capsule will not be built for solid " << pPg->whichGe << G4endl; + } + + // planar detectors + if (pPg->isPlanar) { + // number of segments + if (pPg->nSeg_x <= 0) { + G4cout << " Warning! Invalid segment number for solid " << pPg->whichGe << ", set to 1 instead." << G4endl; + pPg->nSeg_x = 1; + } + if (pPg->nSeg_y <= 0) { + G4cout << " Warning! Invalid segment number for solid " << pPg->whichGe << ", set to 1 instead." << G4endl; + pPg->nSeg_y = 1; + } + + // max, min coordinates + for (nn = 0; nn < pPg->npoints; nn++) { + if (pPg->vertex[nn].x() > pPg->maxSize_x) + pPg->maxSize_x = pPg->vertex[nn].x(); + if (pPg->vertex[nn].y() > pPg->maxSize_y) + pPg->maxSize_y = pPg->vertex[nn].y(); + if (pPg->vertex[nn].x() < pPg->minSize_x) + pPg->minSize_x = pPg->vertex[nn].x(); + if (pPg->vertex[nn].y() < pPg->minSize_y) + pPg->minSize_y = pPg->vertex[nn].y(); + } + + // segment size + pPg->segSize_x = (pPg->maxSize_x - pPg->minSize_x) / pPg->nSeg_x; + pPg->segSize_y = (pPg->maxSize_y - pPg->minSize_y) / pPg->nSeg_y; + } + } + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + fclose(fp); + #endif + #endif + */ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void Hicari::ReadWallsFile() { + FILE* fp; + char line[256]; + G4int lline, i1, i2, i3, i4, i5, i6, nvdots, opgon; + float x, y, z, X, Y, Z; + CpolyhPoints* pPg = NULL; + + nWalls = 0; + nWlTot = 0; + if (!wallsFile) + return; + + if ((fp = fopen(wallsFile, "r")) == NULL) { + G4cout << "\nError opening data file " << wallsFile << G4endl; + G4cout << "No walls included." << G4endl; + return; + } + + G4cout << "\nReading description of walls from file " << wallsFile << " ..." << G4endl; + + walls.clear(); + + nvdots = 0; + opgon = -1; + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + // writes out a modified copy of the original file + G4bool isOpen = true; + FILE *fp1; + if( (fp1=fopen("awallsG","w"))==NULL ) + isOpen = false; + #endif + #endif + */ + while (fgets(line, 255, fp) != NULL) { + lline = strlen(line); + if (lline < 1) + continue; + if (line[0] == '#') + continue; + if (sscanf(line, "%d %d %d %d %d %d %f %f %f %f %f %f", &i1, &i2, &i3, &i4, &i5, &i6, &x, &y, &z, &X, &Y, &Z) != 12) + break; + if (opgon != i3) { + nWalls++; + opgon = i3; + walls.push_back(CpolyhPoints()); + pPg = &walls.back(); + pPg->whichGe = i1; + pPg->whichCrystal = i2; + pPg->whichWall = i3; + pPg->npoints = 2 * i5; + pPg->vertex.resize(pPg->npoints); + } + pPg->vertex[i6] = G4Point3D(((G4double)x), ((G4double)y), ((G4double)z)) * mm; + pPg->vertex[i6 + i5] = G4Point3D(((G4double)X), ((G4double)Y), ((G4double)Z)) * mm; + nvdots += 2; + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + if( isOpen ) { + CclusterAngles *pCa = NULL; + CeulerAngles *pEa = NULL; + for( G4int iii=0; iii<nClAng; iii++ ) { + pCa = &clust[iii]; + if( pCa->whichClus == pPg->whichGe ) break; + } + for( G4int jjj=0; jjj<pCa->nsolids; jjj++ ) { + pEa = &(pCa->solids[jjj]); + if( pEa->numPhys == pPg->whichCrystal ) break; + } + // fprintf( fp1, "%4.1d %4.1d %4.1d %4.1d %4.1d %4.1d %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf\n", + fprintf( fp1, "%4.1d %4.1d %4.1d %4.1d %4.1d %4.1d %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f\n", + pPg->whichGe, pPg->whichCrystal, pPg->whichWall, i4, pPg->npoints/2, i6, + (*(pEa->pTransf) * G4Point3D( x * mm, y * mm, z * mm )).x()/mm, + (*(pEa->pTransf) * G4Point3D( x * mm, y * mm, z * mm )).y()/mm, + (*(pEa->pTransf) * G4Point3D( x * mm, y * mm, z * mm )).z()/mm, + (*(pEa->pTransf) * G4Point3D( X * mm, Y * mm, Z * mm )).x()/mm, + (*(pEa->pTransf) * G4Point3D( X * mm, Y * mm, Z * mm )).y()/mm, + (*(pEa->pTransf) * G4Point3D( X * mm, Y * mm, Z * mm )).z()/mm ); + // ((pEa->rotMat) * G4Point3D( ((G4double)x), ((G4double)y), ((G4double)z) )).x(), + // ((pEa->rotMat) * G4Point3D( ((G4double)x), ((G4double)y), ((G4double)z) )).y(), + // ((pEa->rotMat) * G4Point3D( ((G4double)x), ((G4double)y), ((G4double)z) )).z(), + // ((pEa->rotMat) * G4Point3D( ((G4double)X), ((G4double)Y), ((G4double)Z) )).x(), + // ((pEa->rotMat) * G4Point3D( ((G4double)X), ((G4double)Y), ((G4double)Z) )).y(), + // ((pEa->rotMat) * G4Point3D( ((G4double)X), ((G4double)Y), ((G4double)Z) )).z() ); + } + #endif + #endif + */ + } + + fclose(fp); + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + fclose(fp1); + #endif + #endif + */ + G4cout << nWalls << " polyhedra for a total of " << nvdots << " vertex points read." << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void Hicari::ReadClustFile() { + FILE* fp; + char line[256]; + G4int lline, i1, i2, i3, nsolids, oclust; + float psi, theta, phi; + float x, y, z; + + nClAng = 0; + maxSolids = 0; + + if ((fp = fopen(clustFile, "r")) == NULL) { + G4cout << "\nError opening data file " << clustFile << G4endl; + exit(-1); + } + + G4RotationMatrix rm; + + G4cout << "\nReading description of clusters from file " << clustFile << " ..." << G4endl; + + clust.clear(); + + nsolids = 0; + oclust = -1; + CclusterAngles* pPg = NULL; + CeulerAngles* pEa = NULL; + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + // writes out a modified copy of the original file + G4bool isOpen = true; + FILE *fp1; + if( (fp1=fopen("aclustG","w"))==NULL ) + isOpen = false; + #endif + #endif + */ + while (fgets(line, 255, fp) != NULL) { + lline = strlen(line); + if (lline < 2) + continue; + if (line[0] == '#') + continue; + if (sscanf(line, "%d %d %d %f %f %f %f %f %f", &i1, &i2, &i3, &psi, &theta, &phi, &x, &y, &z) != 9) { + nClAng++; + break; + } + if (oclust != i1) { + nClAng++; + oclust = i1; + clust.push_back(CclusterAngles()); + pPg = &clust.back(); + pPg->whichClus = i1; + pPg->nsolids = 0; + pPg->solids.clear(); + pPg->nwalls = 0; + pPg->pAssV = new G4AssemblyVolume(); + } + pPg->solids.push_back(CeulerAngles()); + pEa = &pPg->solids.back(); + pEa->whichGe = i2; + pEa->numPhys = i3; + + pEa->ps = ((G4double)psi) * deg; + pEa->th = ((G4double)theta) * deg; + pEa->ph = ((G4double)phi) * deg; + + pEa->rotMat.set(0, 0, 0); + pEa->rotMat.rotateZ(((G4double)psi) * deg); + pEa->rotMat.rotateY(((G4double)theta) * deg); + pEa->rotMat.rotateZ(((G4double)phi) * deg); + + pEa->trasl = G4ThreeVector(((G4double)x), ((G4double)y), ((G4double)z)) * mm; + + pEa->pTransf = new G4Transform3D(pEa->rotMat, pEa->trasl); + + pPg->nsolids++; + nsolids++; + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + if( isOpen ) { + CpolyhPoints *pPs = NULL; + for( G4int iii=0; iii<nPgons; iii++ ) { + pPs = &pgons[iii]; + if( pPs->whichGe == pEa->whichGe ) break; + } + // fprintf( fp1, "%4.1d %4.1d %4.1d %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf %12.6lf\n", + fprintf( fp1, "%4.1d %4.1d %4.1d %12.6f %12.6f %12.6f %12.6f %12.6f %12.6f\n", + pPg->whichClus, pEa->whichGe, pEa->numPhys, pEa->ps/deg, pEa->th/deg, pEa->ph/deg, + (*(pEa->pTransf) * G4Point3D( 0., 0., pPs->zFace1)).x()/mm, + (*(pEa->pTransf) * G4Point3D( 0., 0., pPs->zFace1)).y()/mm, + (*(pEa->pTransf) * G4Point3D( 0., 0., pPs->zFace1)).z()/mm ); + } + #endif + #endif + */ + } + + fclose(fp); + /* + #ifdef GRETA + #ifdef GRETA_DEBUG + fclose(fp1); + #endif + #endif + */ + for (G4int ii = 0; ii < nClAng; ii++) { + pPg = &clust[ii]; + if (pPg->nsolids > maxSolids) + maxSolids = pPg->nsolids; + } + + G4cout << " Read " << nClAng << " cluster description for a total of " << nsolids << " individual solids." << G4endl; +} + +void Hicari::ReadEulerFile() { + FILE* fp; + char line[256]; + G4int lline, i1, i2; + float psi, theta, phi, x, y, z; + + if ((fp = fopen(eulerFile, "r")) == NULL) { + G4cout << "\nError opening data file " << eulerFile << G4endl; + exit(-1); + } + + euler.clear(); + + G4cout << "\nReading Euler angles from file " << eulerFile << " ..." << G4endl; + nEuler = 0; + + G4RotationMatrix rm; + CeulerAngles* pEa = NULL; + + while (fgets(line, 255, fp) != NULL) { + lline = strlen(line); + if (lline < 2) + continue; + if (line[0] == '#') + continue; + if (sscanf(line, "%d %d %f %f %f %f %f %f", &i1, &i2, &psi, &theta, &phi, &x, &y, &z) != 8) + break; + euler.push_back(CeulerAngles()); + pEa = &euler[nEuler]; + + pEa->numPhys = i1; + pEa->whichGe = i2; + + pEa->rotMat.set(0, 0, 0); + pEa->rotMat.rotateZ(((G4double)psi) * deg); + pEa->rotMat.rotateY(((G4double)theta) * deg); + pEa->rotMat.rotateZ(((G4double)phi) * deg); + + pEa->ps = ((G4double)psi) * deg; + pEa->th = ((G4double)theta) * deg; + pEa->ph = ((G4double)phi) * deg; + + pEa->trasl = G4ThreeVector(((G4double)x), ((G4double)y), ((G4double)z)) * mm; + + pEa->pTransf = new G4Transform3D(pEa->rotMat, pEa->trasl); + + nEuler++; + } + + fclose(fp); + G4cout << nEuler << " Euler angles read." << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// This method reads the file with the slice planes +void Hicari::ReadSliceFile() { + FILE* fp; + char line[256]; + // G4int ns, npts, sameSlice, nSlices; // REMOVE? + G4int nso, sameSlice, nSlices; + float zz1, ZZ1; + G4double zz, ZZ; + CpolyhPoints* pPg; + + maxSec = 1; // When data file is missing only 1 sector is considered (non-segmented) + maxSli = 1; // When data file is missing only 1 slice is considered + + if ((fp = fopen(sliceFile, "r")) == NULL) { + G4cout << "\nError opening data file " << sliceFile << G4endl; + G4cout << " Warning! No segmentation will be considered." << G4endl; + readOut = false; + // When data file is missing only 1 slice is considered + return; + } + + G4cout << " Reading slice planes from file " << sliceFile << G4endl; + readOut = true; + + // Initializes arrays assuming one slice + // zSliceI[i] is the z coordinate of the i-th plane + // zSliceI[0] = 1st face,..., zSliceI[nSlice] = 2nd face + // so that zSliceI.size() = nslice+1 + G4int nPg; + for (nPg = 0; nPg < nPgons; nPg++) { + pPg = &pgons[nPg]; + // npts = pPg->npoints; // REMOVE? + pPg->zSliceI.clear(); + pPg->zSliceO.clear(); + pPg->zSliceI.push_back(pPg->zFace1); + pPg->zSliceO.push_back(pPg->zFace1); + pPg->zSliceI.push_back(pPg->zFace2); + pPg->zSliceO.push_back(pPg->zFace2); + pPg->nslice = 1; + } + + G4cout << "\nReading slicing planes from data file " << sliceFile << G4endl; + + // first line gives the format + sameSlice = -1; + while (fgets(line, 255, fp)) { + if (line[0] == '#') + continue; + sscanf(line, "%d", &sameSlice); + break; + } + if (sameSlice < 0) { + G4cout << "\nError reading slice type in file " << sliceFile << G4endl; + G4cout << " Warning! Considering only one slice per solid." << G4endl; + return; + } + + if (sameSlice == 0) { + // second line gives number of slices + nSlices = -1; + while (fgets(line, 255, fp)) { + if (line[0] == '#') + continue; + sscanf(line, "%d", &nSlices); + if (nSlices < 1) + break; + if (nSlices > maxSli) + maxSli = nSlices; + // fills the arrays + for (nPg = 0; nPg < nPgons; nPg++) { + pPg = &pgons[nPg]; + zz = pPg->zFace1; + G4double dz = (pPg->zFace2 - pPg->zFace1) / nSlices; + pPg->zSliceI.clear(); + pPg->zSliceO.clear(); + for (G4int kk = 0; kk < nSlices; kk++) { + pPg->zSliceI.push_back(zz + kk * dz); + pPg->zSliceO.push_back(zz + kk * dz); + } + pPg->zSliceI.push_back(pPg->zFace2); + pPg->zSliceO.push_back(pPg->zFace2); + pPg->nslice = nSlices; + if (pPg->npoints / 2 > maxSec) + maxSec = pPg->npoints / 2; + } + break; + } + if (nSlices < 1) { + G4cout << "\nError reading number of slices in file " << sliceFile << G4endl; + G4cout << " Warning! Considering only one slice per solid." << G4endl; + } + fclose(fp); + return; + } + + // variable slices + while (fgets(line, 255, fp)) { + if (line[0] == '#') + continue; + // if( sscanf(line,"%d %lf %lf", &ns, &zz, &ZZ) == 2 ) + if (sscanf(line, "%d %f %f", &nso, &zz1, &ZZ1) == 2) + ZZ1 = zz1; + zz = (G4double)zz1; + ZZ = (G4double)ZZ1; + if (nso < 0 || nso > maxPgons) { // needed to avoid problems in case the minimum index in pgons is not zero + G4cout << " Warning! Solid " << nso << " out of range: ignoring slice " << zz << " -- " << ZZ << G4endl; + continue; + } + for (nPg = 0; nPg < nPgons; nPg++) { + pPg = &pgons[nPg]; + if (pPg->whichGe != nso) + continue; // looks for the right solid + G4double z2 = pPg->zSliceI[pPg->nslice - 1]; + G4double Z2 = pPg->zSliceO[pPg->nslice - 1]; + z2 += zz * mm; + Z2 += ZZ * mm; + if (z2 > pPg->zFace2 || Z2 > pPg->zFace2) { + G4cout << " Warning! Slice " << zz << " -- " << ZZ << " of solid " << nso << " exceeds length of solid " + << "( " << z2 << " -- " << Z2 << " > " << pPg->zFace2 - pPg->zFace1 << " )" << G4endl; + continue; + } + pPg->zSliceI.back() = z2; + pPg->zSliceO.back() = Z2; + pPg->zSliceI.push_back(pPg->zFace2); + pPg->zSliceO.push_back(pPg->zFace2); + pPg->nslice++; + if (pPg->npoints / 2 > maxSec) + maxSec = pPg->npoints / 2; + if (pPg->nslice > maxSli) + maxSli = pPg->nslice; + break; + } + } + fclose(fp); + return; +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +// Construct detector and inialise sensitive part. +// Called After DetecorConstruction::AddDetector Method +void Hicari::ConstructDetector(G4LogicalVolume* world) { + + if (InitializeMaterials()) + return; + + ConstructGeCrystals(); + + if (nWalls) + ConstructTheWalls(); + + ConstructTheCapsules(); + /* + G4int depth; + if(makeCapsule) + depth = 2; + else + depth = 1; + */ + // theDetector->GetGammaSD()->SetDepth(depth); + + ConstructTheClusters(); + PlaceTheClusters(world); + + if (readOut) { + // delete old structures + nSegments.clear(); + + pgSegLl.clear(); + pgSegLu.clear(); + pgSegRl.clear(); + pgSegRu.clear(); + + segVolume.clear(); + segCenter.clear(); + + nSegments.resize(nPgons); + tSegments.resize(nPgons); + totSegments = 0; + + for (G4int ii = 0; ii < nPgons; ii++) { + G4int nn = CalculateSegments(ii); + nSegments[ii] = nn; + tSegments[ii] = totSegments; + totSegments += nn; + } + ConstructSegments(); + } + + WriteCrystalAngles("./crystalangles.dat"); + WriteCrystalPositions("./crystalpositions.dat"); + WriteSegmentPositions("./segmentpositions.dat"); +} + +/////////////////////////////////////////////////////////////////////////////////////// +///////////////// methods to construct and place the actual volumes +///////////////////////////////////////////////////////////////////////////////////// +void Hicari::ConstructGeCrystals() { + + // G4RunManager* runManager = G4RunManager::GetRunManager(); + + // DetectorConstruction* theDetector = (DetectorConstruction*) runManager->GetUserDetectorConstruction(); + + if (!matCryst) { + G4cout << G4endl << "----> Missing material, cannot build the crystals!" << G4endl; + return; + } + + char sName[50]; + + // identity matrix + G4RotationMatrix rm; + rm.set(0, 0, 0); + + G4int ngen, nPg, nGe, nPh = 0, nPt; + + // data to construct the cylinders and the passive parts + // they are generated in their final position to avoid problems in placement + G4double* InnRadGe; + G4double* OutRadGe; + G4double* zSliceGe; + + G4cout << G4endl << "Generating crystals ... " << G4endl; + ngen = 0; + for (nPg = 0; nPg < nPgons; nPg++) { + CpolyhPoints* pPg = &pgons[nPg]; + nGe = pPg->whichGe; + if (nGe < 0) { + G4cout << "ConstructGeCrystals : crystal " << nPg << " skipped because nGe ( " << nGe << " ) out of range " + << G4endl; + continue; + } + nPt = pPg->npoints; + if (nPt < 6) { + G4cout << "ConstructGeCrystals : crystal " << nPg << " skipped because of too few ( " << nPt << " ) points " + << G4endl; + continue; + } + + sprintf(sName, "gePoly%2.2d", nGe); + pPg->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + + cout << nGe << ", colx " << pPg->colx << ", coly " << pPg->coly << ", colz " << pPg->colz << endl; + + pPg->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + + G4double zFace1 = pPg->zFace1; + + pPg->pDetL1 = NULL; + pPg->pDetL2 = NULL; + + if (useCylinder && pPg->cylinderMakesSense) { + + // no coaxial hole! + if (pPg->tubr == 0) { + zSliceGe = new G4double[2]; + zSliceGe[0] = pPg->zCenter - pPg->tubL / 2.; + zSliceGe[1] = pPg->zCenter + pPg->tubL / 2.; + + InnRadGe = new G4double[2]; + InnRadGe[0] = pPg->tubr; + InnRadGe[1] = pPg->tubr; + + OutRadGe = new G4double[2]; + OutRadGe[0] = pPg->tubR; + OutRadGe[1] = pPg->tubR; + + sprintf(sName, "geTubs%2.2d", nGe); + pPg->pCoax = new G4Polycone(G4String(sName), 0. * deg, 360. * deg, 2, zSliceGe, InnRadGe, OutRadGe); + sprintf(sName, "geCapsPolyTubs%2.2d", nGe); + pPg->pCaps = + new G4IntersectionSolid(G4String(sName), pPg->pPoly, pPg->pCoax, G4Transform3D(rm, G4ThreeVector())); + + // passive area behind the detector (placed as daughter of the original crystal) + if (usePassive) { + if (pPg->passThick1 > 0.) { + zSliceGe = new G4double[2]; + zSliceGe[0] = pPg->zCenter + pPg->tubL / 2. - pPg->passThick1; + zSliceGe[1] = pPg->zCenter + pPg->tubL / 2.; + + InnRadGe = new G4double[2]; + InnRadGe[0] = pPg->tubr; + InnRadGe[1] = pPg->tubr; + + OutRadGe = new G4double[2]; + OutRadGe[0] = pPg->tubR; + OutRadGe[1] = pPg->tubR; + + sprintf(sName, "geTubsB%2.2d", nGe); + pPg->pTubs1 = new G4Polycone(G4String(sName), 0. * deg, 360. * deg, 2, zSliceGe, InnRadGe, OutRadGe); + sprintf(sName, "gePassB%2.2d", nGe); + pPg->pCaps1 = + new G4IntersectionSolid(G4String(sName), pPg->pPoly, pPg->pTubs1, G4Transform3D(rm, G4ThreeVector())); + sprintf(sName, "gePassBL%2.2d", nGe); + pPg->pDetL1 = new G4LogicalVolume(pPg->pCaps1, matCryst, G4String(sName), 0, 0, 0); + pPg->pDetL1->SetVisAttributes(pPg->pDetVA); + } + else + pPg->pDetL1 = NULL; + } + } + else { + zSliceGe = new G4double[4]; + zSliceGe[0] = pPg->zCenter - pPg->tubL / 2.; + zSliceGe[1] = zFace1 + pPg->thick; + zSliceGe[2] = zFace1 + pPg->thick + 0.0001; + zSliceGe[3] = pPg->zCenter + pPg->tubL / 2.; + + InnRadGe = new G4double[4]; + InnRadGe[0] = 0.; + InnRadGe[1] = 0.; + InnRadGe[2] = pPg->tubr; + InnRadGe[3] = pPg->tubr; + + OutRadGe = new G4double[4]; + OutRadGe[0] = pPg->tubR; + OutRadGe[1] = pPg->tubR; + OutRadGe[2] = pPg->tubR; + OutRadGe[3] = pPg->tubR; + + sprintf(sName, "gePcone%2.2d", nGe); + pPg->pCoax = new G4Polycone(G4String(sName), 0. * deg, 360. * deg, 4, zSliceGe, InnRadGe, OutRadGe); + sprintf(sName, "geCapsPolyPcone%2.2d", nGe); + pPg->pCaps = + new G4IntersectionSolid(G4String(sName), pPg->pPoly, pPg->pCoax, G4Transform3D(rm, G4ThreeVector())); + + if (usePassive) { + if (pPg->passThick1 > 0.) { + zSliceGe = new G4double[2]; + zSliceGe[0] = pPg->zCenter + pPg->tubL / 2. - pPg->passThick1; + zSliceGe[1] = pPg->zCenter + pPg->tubL / 2.; + + InnRadGe = new G4double[2]; + InnRadGe[0] = pPg->tubr; + InnRadGe[1] = pPg->tubr; + + OutRadGe = new G4double[2]; + OutRadGe[0] = pPg->tubR; + OutRadGe[1] = pPg->tubR; + + // passive area behind the detector (placed later as daughter of the original crystal) + sprintf(sName, "geTubsB%2.2d", nGe); + pPg->pTubs1 = new G4Polycone(G4String(sName), 0. * deg, 360. * deg, 2, zSliceGe, InnRadGe, OutRadGe); + sprintf(sName, "gePassB%2.2d", nGe); + pPg->pCaps1 = + new G4IntersectionSolid(G4String(sName), pPg->pPoly, pPg->pTubs1, G4Transform3D(rm, G4ThreeVector())); + + sprintf(sName, "gePassBL%2.2d", nGe); + pPg->pDetL1 = new G4LogicalVolume(pPg->pCaps1, matCryst, G4String(sName), 0, 0, 0); + pPg->pDetL1->SetVisAttributes(pPg->pDetVA); + } + else + pPg->pDetL1 = NULL; + + if (pPg->passThick2 > 0.) { + // passive area at the coaxial hole (placed later as daughter of the original crystal) + zSliceGe = new G4double[4]; + zSliceGe[0] = pPg->zFace1 + pPg->thick - pPg->passThick2; + zSliceGe[1] = pPg->zFace1 + pPg->thick; + zSliceGe[2] = pPg->zFace1 + pPg->thick; + zSliceGe[3] = pPg->zCenter + pPg->tubL / 2. - pPg->passThick1; + + InnRadGe = new G4double[4]; + InnRadGe[0] = 0.; + InnRadGe[1] = 0.; + InnRadGe[2] = pPg->tubr; + InnRadGe[3] = pPg->tubr; + + OutRadGe = new G4double[4]; + OutRadGe[0] = pPg->tubr + pPg->passThick2; + OutRadGe[1] = pPg->tubr + pPg->passThick2; + OutRadGe[2] = pPg->tubr + pPg->passThick2; + OutRadGe[3] = pPg->tubr + pPg->passThick2; + + sprintf(sName, "geTubsC%2.2d", nGe); + pPg->pCoax2 = new G4Polycone(G4String(sName), 0. * deg, 360. * deg, 4, zSliceGe, InnRadGe, OutRadGe); + sprintf(sName, "gePassC%2.2d", nGe); + pPg->pDetL2 = new G4LogicalVolume(pPg->pCoax2, matCryst, G4String(sName), 0, 0, 0); + pPg->pDetL2->SetVisAttributes(pPg->pDetVA); + } + else + pPg->pDetL2 = NULL; + } + } + sprintf(sName, "geDetCapsL%2.2d", nGe); + pPg->pDetL = new G4LogicalVolume(pPg->pCaps, matCryst, G4String(sName), 0, 0, 0); // intersezione di Poly e Tubs + } + else { + sprintf(sName, "geDetPolyL%2.2d", nGe); + pPg->pDetL = new G4LogicalVolume(pPg->pPoly, matCryst, G4String(sName), 0, 0, 0); // solo i poliedri + + // passive area behind the detector (placed later as daughter of the original crystal) + if (usePassive) { + if (pPg->passThick1 > 0.) { + zSliceGe = new G4double[2]; + zSliceGe[0] = pPg->zCenter + pPg->tubL / 2. - pPg->passThick1; + zSliceGe[1] = pPg->zCenter + pPg->tubL / 2.; + + InnRadGe = new G4double[2]; + InnRadGe[0] = 0.; + InnRadGe[1] = 0.; + + OutRadGe = new G4double[2]; + OutRadGe[0] = pPg->minR; + OutRadGe[1] = pPg->minR; + + sprintf(sName, "geTubsB%2.2d", nGe); + pPg->pTubs1 = new G4Polycone(G4String(sName), 0. * deg, 360. * deg, 2, zSliceGe, InnRadGe, OutRadGe); + sprintf(sName, "gePassB%2.2d", nGe); + pPg->pCaps1 = + new G4IntersectionSolid(G4String(sName), pPg->pPoly, pPg->pTubs1, G4Transform3D(rm, G4ThreeVector())); + sprintf(sName, "gePassBL%2.2d", nGe); + pPg->pDetL1 = new G4LogicalVolume(pPg->pCaps1, matCryst, G4String(sName), 0, 0, 0); + pPg->pDetL1->SetVisAttributes(pPg->pDetVA); + } + else + pPg->pDetL1 = NULL; + } + } + + if (usePassive) { + if (pPg->pDetL1) { + pPg->pDetP1 = NULL; + sprintf(sName, "gePassBP%3.3d", nPh); + pPg->pDetP1 = new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL1, G4String(sName), pPg->pDetL, false, 0); + } + if (pPg->pDetL2) { + pPg->pDetP2 = NULL; + sprintf(sName, "gePassCP%3.3d", nPh); + pPg->pDetP2 = new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL2, G4String(sName), pPg->pDetL, false, 0); + } + } + + pPg->pDetL->SetVisAttributes(pPg->pDetVA); + pPg->pDetL->SetSensitiveDetector(m_HicariScorer); + + ngen++; + + G4cout << "\n Total Ge volume (" << pPg->pCaps->GetName() << ") = " << pPg->pCaps->GetCubicVolume() / cm3 + << " cm3" << G4endl; + G4cout << " Back dead layer volume (" << pPg->pCaps1->GetName() + << ") = " << pPg->pCaps1->GetCubicVolume() / cm3 << " cm3" << G4endl; + G4cout << " Coaxial dead layer volume (" << pPg->pCoax2->GetName() + << ") = " << pPg->pCoax2->GetCubicVolume() / cm3 << " cm3\n" + << G4endl; + } + + G4cout << "Number of generated crystals is " << ngen << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void Hicari::ConstructTheCapsules() { + G4int nPg, nGe, nSid; + G4bool movePlane; + G4double dist1 = 0.; + G4double dist2 = 0.; + char sName[128]; + + CpolyhPoints* pPg = NULL; // germanium + CpolyhPoints* pPv = NULL; // vacuum + CpolyhPoints* pPc = NULL; // capsule + + G4RotationMatrix rm; + rm.set(0, 0, 0); + + if (!matWalls || !matBackWalls || !matHole) { + G4cout << G4endl << "----> Missing materials, cannot build the capsules!" << G4endl; + return; + } + + G4cout << G4endl << "Generating the capsules ... " << G4endl; + + capsI.clear(); + capsO.clear(); + + capsI.resize(nPgons); + capsO.resize(nPgons); + + // dist2 += dist1; + + for (nPg = 0; nPg < nPgons; nPg++) { + pPg = &pgons[nPg]; + + nGe = pPg->whichGe; + + if (pPg->isPlanar) { // planar: no capsule, guardring + // dist1 = pPg->guardThick; + // dist2 = dist1; + + if (makeCapsule) { + pPv = &capsO[nPg]; + sprintf(sName, "plaPoly%2.2d", nGe); + pPv->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + // for( nSid=0; nSid<pPg->pPoly->GetnPlanes()-2; nSid++ ) + // for( nSid=2; nSid<pPg->pPoly->GetnPlanes(); nSid++ ) + // movePlane = pPv->pPoly->MovePlane( nSid, pPg->guardThick[nSid%4] ); + pPv->whichGe = nGe; + sprintf(sName, "plaPolyL%2.2d", nGe); + pPv->pDetL = new G4LogicalVolume(pPv->pPoly, matCryst, G4String(sName), 0, 0, 0); + pPv->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPv->pDetVA->SetForceWireframe(true); // KW commented + pPv->pDetL->SetVisAttributes(pPv->pDetVA); + + pPc = &capsI[nPg]; + sprintf(sName, "plbPoly%2.2d", nGe); + pPc->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + // for( nSid=0; nSid<pPg->pPoly->GetnPlanes()-2; nSid++ ) + // for( nSid=2; nSid<pPg->pPoly->GetnPlanes(); nSid++ ) + // movePlane = pPc->pPoly->MovePlane( nSid, pPg->guardThick[nSid%4] ); + pPc->whichGe = nGe; + sprintf(sName, "plbPolyL%2.2d", nGe); + pPc->pDetL = new G4LogicalVolume(pPc->pPoly, matCryst, G4String(sName), 0, 0, 0); + pPc->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPc->pDetVA->SetForceWireframe(true); // KW commented + pPc->pDetL->SetVisAttributes(pPc->pDetVA); + + new G4PVPlacement(0, G4ThreeVector(), pPc->pDetL, G4String(sName), pPv->pDetL, false, 0); + new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL, G4String(sName), pPc->pDetL, false, 0); + } + else { + pPv = &capsO[nPg]; + sprintf(sName, "plaPoly%2.2d", nGe); + pPv->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + // for( nSid=0; nSid<pPg->pPoly->GetnPlanes()-2; nSid++ ) + // for( nSid=2; nSid<pPg->pPoly->GetnPlanes(); nSid++ ) + // movePlane = pPv->pPoly->MovePlane( nSid, pPg->guardThick[nSid%4] ); + pPv->whichGe = nGe; + sprintf(sName, "plaPolyL%2.2d", nGe); + pPv->pDetL = new G4LogicalVolume(pPv->pPoly, matCryst, G4String(sName), 0, 0, 0); + pPv->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPv->pDetVA->SetForceWireframe(true); + pPv->pDetL->SetVisAttributes(pPv->pDetVA); + new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL, G4String(sName), pPv->pDetL, false, 0); + } + } + else if (!pPg->makeCapsule) { // no capsule + if (makeCapsule) { + pPv = &capsO[nPg]; + sprintf(sName, "cryPoly%2.2d", nGe); + pPv->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + sprintf(sName, "cryCoax%2.2d", nGe); + pPv->pCoax = new G4Polycone(*(pPg->pCoax)); + sprintf(sName, "cryCaps%2.2d", nGe); + pPv->pCaps = + new G4IntersectionSolid(G4String(sName), pPv->pPoly, pPv->pCoax, G4Transform3D(rm, G4ThreeVector())); + pPv->whichGe = nGe; + sprintf(sName, "cryPolyL%2.2d", nGe); + pPv->pDetL = new G4LogicalVolume(pPv->pCaps, matHole, G4String(sName), 0, 0, 0); + pPv->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPv->pDetVA->SetForceWireframe(true); + pPv->pDetVA->SetVisibility(false); + pPv->pDetVA->SetDaughtersInvisible(false); + pPv->pDetL->SetVisAttributes(pPv->pDetVA); + + pPc = &capsI[nPg]; + sprintf(sName, "crzPoly%2.2d", nGe); + pPc->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + sprintf(sName, "crzCoax%2.2d", nGe); + pPc->pCoax = new G4Polycone(*(pPg->pCoax)); + sprintf(sName, "crzCaps%2.2d", nGe); + pPc->pCaps = + new G4IntersectionSolid(G4String(sName), pPc->pPoly, pPc->pCoax, G4Transform3D(rm, G4ThreeVector())); + pPc->whichGe = nGe; + sprintf(sName, "crzPolyL%2.2d", nGe); + pPc->pDetL = new G4LogicalVolume(pPc->pCaps, matHole, G4String(sName), 0, 0, 0); + pPc->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPc->pDetVA->SetForceWireframe(true); + pPc->pDetVA->SetVisibility(false); + pPc->pDetVA->SetDaughtersInvisible(false); + pPc->pDetL->SetVisAttributes(pPc->pDetVA); + + new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL, G4String(sName), pPc->pDetL, false, 0); + new G4PVPlacement(0, G4ThreeVector(), pPc->pDetL, G4String(sName), pPv->pDetL, false, 0); + } + else { + pPv = &capsO[nPg]; + sprintf(sName, "cryPoly%2.2d", nGe); + pPv->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + sprintf(sName, "cryCoax%2.2d", nGe); + pPv->pCoax = new G4Polycone(*(pPg->pCoax)); + sprintf(sName, "cryCaps%2.2d", nGe); + pPv->pCaps = + new G4IntersectionSolid(G4String(sName), pPv->pPoly, pPv->pCoax, G4Transform3D(rm, G4ThreeVector())); + pPv->whichGe = nGe; + sprintf(sName, "cryPolyL%2.2d", nGe); + pPv->pDetL = new G4LogicalVolume(pPv->pCaps, matHole, G4String(sName), 0, 0, 0); + pPv->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPv->pDetVA->SetForceWireframe(true); + pPv->pDetVA->SetVisibility(false); + pPv->pDetVA->SetDaughtersInvisible(false); + pPv->pDetL->SetVisAttributes(pPv->pDetVA); + new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL, G4String(sName), pPv->pDetL, false, 0); + } + } // else if( !pPg->makeCapsule ) + else { + dist1 = pPg->capSpace; + dist2 = dist1 + pPg->capThick; + if (makeCapsule) { + // G4cout << " in in " << G4endl; + // G4cout << " in in " << G4endl; + // G4cout << " in in " << G4endl; + + // for(int nn=0; nn<pPg->npoints; nn++ ) { + // G4cout << pPg->vertex[nn].x() << "\t" << pPg->vertex[nn].y() << "\t" << pPg->vertex[nn].z() << G4endl; + // } + + // vacuum + pPv = &capsI[nPg]; + pPv->whichGe = nGe; + sprintf(sName, "vaPoly%2.2d", nGe); + pPv->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + for (nSid = 0; nSid < pPg->pPoly->GetnPlanes(); nSid++) + movePlane = pPv->pPoly->MovePlane(nSid, dist1); + + sprintf(sName, "vaCoax%2.2d", nGe); + pPv->pTubs = new G4Tubs(G4String(sName), 0., pPg->tubR + dist1, pPg->tubL, 0. * deg, 360. * deg); + + sprintf(sName, "vaCaps%2.2d", nGe); + pPv->pCaps = + new G4IntersectionSolid(G4String(sName), pPv->pPoly, pPv->pTubs, G4Transform3D(rm, G4ThreeVector())); + + sprintf(sName, "geVacPolyL%2.2d", nGe); + pPv->pDetL = new G4LogicalVolume(pPv->pPoly, matHole, G4String(sName), 0, 0, 0); + pPv->pDetVA = new G4VisAttributes(G4Color(0, 0, 0)); + pPv->pDetVA->SetForceWireframe(false); + pPv->pDetVA->SetVisibility(false); + pPv->pDetL->SetVisAttributes(pPv->pDetVA); + + // actual capsule + pPc = &capsO[nPg]; + pPc->whichGe = nGe; + sprintf(sName, "caPoly%2.2d", nGe); + pPc->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + for (nSid = 0; nSid < pPg->pPoly->GetnPlanes(); nSid++) + movePlane = pPc->pPoly->MovePlane(nSid, dist2); + + sprintf(sName, "caCoax%2.2d", nGe); + pPc->pTubs = new G4Tubs(G4String(sName), 0., pPg->tubR + dist2, pPg->tubL, 0. * deg, 360. * deg); + + sprintf(sName, "caCaps%2.2d", nGe); + pPc->pCaps = + new G4IntersectionSolid(G4String(sName), pPc->pPoly, pPc->pTubs, G4Transform3D(rm, G4ThreeVector())); + + sprintf(sName, "geCapPolyL%2.2d", nGe); + pPc->pDetL = new G4LogicalVolume(pPc->pCaps, matWalls, G4String(sName), 0, 0, 0); + pPc->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + // pPc->pDetVA = new G4VisAttributes( G4Color(1, 0, 0.0) ); + pPc->pDetVA->SetForceWireframe(true); + pPc->pDetVA->SetVisibility(true); + pPc->pDetL->SetVisAttributes(pPc->pDetVA); + + new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL, G4String(sName), pPv->pDetL, false, 0); + new G4PVPlacement(0, G4ThreeVector(), pPv->pDetL, G4String(sName), pPc->pDetL, false, 0); + } + else { + pPv = &capsO[nPg]; + sprintf(sName, "cryPoly%2.2d", nGe); + pPv->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + // for( nSid=0; nSid<pPg->pPoly->GetnPlanes(); nSid++ ) + // movePlane = pPv->pPoly->MovePlane( nSid, dist1 ); + pPv->whichGe = nGe; + sprintf(sName, "cryPolyL%2.2d", nGe); + pPv->pDetL = new G4LogicalVolume(pPv->pPoly, matHole, G4String(sName), 0, 0, 0); + pPv->pDetVA = new G4VisAttributes(G4Color(pPg->colx, pPg->coly, pPg->colz)); + pPv->pDetVA->SetForceWireframe(true); + pPv->pDetVA->SetVisibility(false); + pPv->pDetVA->SetDaughtersInvisible(false); + pPv->pDetL->SetVisAttributes(pPv->pDetVA); + new G4PVPlacement(0, G4ThreeVector(), pPg->pDetL, G4String(sName), pPv->pDetL, false, 0); + } + } + } + G4cout << "Number of generated capsules is " << nPgons << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void Hicari::ConstructTheClusters() { + + G4int nCa, nPg, nSo; + CclusterAngles* pCa; + CpolyhPoints* pPg; + CeulerAngles* pEa; + G4RotationMatrix rm; + G4ThreeVector rotatedPos; + G4Transform3D transf; + + G4cout << G4endl << "Building the clusters ..." << G4endl; + + for (nCa = 0; nCa < nClAng; nCa++) { + G4cout << " Cluster #" << nCa << G4endl; + pCa = &clust[nCa]; + for (nSo = 0; nSo < pCa->nsolids; nSo++) { + pEa = &pCa->solids[nSo]; + + rm = pEa->rotMat; + + rotatedPos = pEa->trasl; + + // germanium detectors + for (nPg = 0; nPg < nPgons; nPg++) { + // if( makeCapsule && pgons[nPg].makeCapsule ) + // pPg = &capsO[nPg]; + // else + // pPg = &pgons[nPg]; + pPg = &capsO[nPg]; + + if (pPg->whichGe != pEa->whichGe) + continue; + if (!pPg->pDetL) + continue; + + if (pCa->pAssV) { + transf = G4Transform3D(*(pEa->pTransf)); + pCa->pAssV->AddPlacedVolume(pPg->pDetL, transf); + } + + printf(" Solid %4d %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n", pPg->whichGe, pEa->ps / deg, pEa->th / deg, + pEa->ph / deg, rotatedPos.x() / cm, rotatedPos.y() / cm, rotatedPos.z() / cm); + } + } + // the walls + /* + + #ifdef GRETA + for( nSo=0; nSo<pCa->nsolids; nSo++ ) { + pEa = &pCa->solids[nSo]; + + rm = pEa->rotMat; + + rotatedPos = pEa->trasl; + + for(nPg=0; nPg<nWalls; nPg++) { + pPg = &walls[nPg]; + + if( pPg->whichGe != pCa->whichClus ) + continue; + // if( pPg->whichCrystal != nSo ) + if( pPg->whichCrystal != pEa->numPhys ) + continue; + if( !pPg->pDetL ) + continue; + if( pCa->pAssV ) { + transf = G4Transform3D( *(pEa->pTransf) ); + pCa->pAssV->AddPlacedVolume( pPg->pDetL, transf ); + } + printf( " Wall %4d %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n", + pPg->whichWall, pEa->ps/deg, pEa->th/deg, pEa->ph/deg, rotatedPos.x()/cm, rotatedPos.y()/cm, + rotatedPos.z()/cm ); + } + } + */ + rm.set(0, 0, 0); + G4double psi = 0.; + G4double the = 0.; + G4double phi = 0.; + rotatedPos = G4ThreeVector(); + + // walls + for (nPg = 0; nPg < nWalls; nPg++) { + pPg = &walls[nPg]; + + if (pPg->whichGe != pCa->whichClus) + continue; + if (!pPg->pDetL) + continue; + + if (pCa->pAssV) { + transf = G4Transform3D(rm, rotatedPos); + pCa->pAssV->AddPlacedVolume(pPg->pDetL, transf); + pCa->nwalls++; + } + + printf(" Wall %4d %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n", pPg->whichWall, psi / deg, the / deg, phi / deg, + rotatedPos.x() / cm, rotatedPos.y() / cm, rotatedPos.z() / cm); + } + } +} + +void Hicari::ConstructTheWalls() { + char sName[50]; + G4int ngen, nPg, nGe, nPt; + + if (!matWalls || !matBackWalls) { + G4cout << G4endl << "----> Missing material, cannot build the walls!" << G4endl; + return; + } + + G4cout << G4endl << "Generating walls ... " << G4endl; + + ngen = 0; + for (nPg = 0; nPg < nWalls; nPg++) { + CpolyhPoints* pPg = &walls[nPg]; + nGe = pPg->whichGe; + if (nGe < 0 || nGe >= nPgons) + continue; + nPt = pPg->npoints; + if (nPt >= 6) { + sprintf(sName, "wlPoly%2.2d", nGe); + pPg->pPoly = new CConvexPolyhedron(G4String(sName), pPg->vertex); + + sprintf(sName, "wlDetL%2.2d", nGe); + // Use a different material for the back walls //LR + if (nPg < 18) // LR + pPg->pDetL = new G4LogicalVolume(pPg->pPoly, matWalls, G4String(sName), 0, 0, 0); + else // LR + pPg->pDetL = new G4LogicalVolume(pPg->pPoly, matBackWalls, G4String(sName), 0, 0, 0); // LR + + // LR pPg->pDetVA = new G4VisAttributes( G4Colour(0.5, 0.5, 0.5) ); + // pPg->pDetVA = new G4VisAttributes( G4Colour(1, 1, 1) ); + pPg->pDetVA = new G4VisAttributes(G4Colour(1, 1, 1, 0.3)); // purple + pPg->pDetVA->SetForceWireframe(false); + // orig + pPg->pDetVA->SetVisibility(true); + // KW walls not visible + // pPg->pDetVA->SetVisibility(false); + pPg->pDetL->SetVisAttributes(pPg->pDetVA); + + ngen++; + } + } + G4cout << "Number of generated walls is " << ngen << G4endl; +} + +void Hicari::PlaceTheClusters(G4LogicalVolume* world) { + G4int nGe, nCl, nEa, nCa, nPg, nSol, nPt, indexP; + G4int ii, jj; + + CclusterAngles* pCa = NULL; + CpolyhPoints* pPg = NULL; + CeulerAngles* pEa = NULL; + CeulerAngles* pEc = NULL; + + G4RotationMatrix rm; + G4RotationMatrix rm1; + G4RotationMatrix radd; + G4RotationMatrix rmP; // PRISMA rotation + G4ThreeVector rotatedPos; + G4ThreeVector rotatedPos1; + G4ThreeVector rotatedPos2; + G4Transform3D transf; + + G4int iClTot = 0; + G4int iClMin = -1; + G4int iClMax = -1; + + nDets = 0; + nWlTot = 0; + nClus = 0; + + G4cout << G4endl << "Placing clusters ... " << G4endl; + + // G4RunManager* runManager = G4RunManager::GetRunManager(); + // DetectorConstruction* theDetector = (DetectorConstruction*) runManager->GetUserDetectorConstruction(); + + G4int* iCl = new G4int[nClAng]; + memset(iCl, 0, nClAng * sizeof(G4int)); + + arrayRmin = 1.e10; + arrayRmax = -1.e10; + + crystType.clear(); + crystType.resize(nEuler); + + planarLUT.clear(); + planarLUT.resize(nEuler); + + rmP.set(0, 0, 0); + if (thetaPrisma != 0.) + rmP.rotateX(thetaPrisma); + + // For the cryostats + G4Polycone* Cryostat = new G4Polycone("Cryostat", 0., 360. * deg, 7, cryostatZplanes, cryostatRinner, cryostatRouter); + G4LogicalVolume* logicCryostat = new G4LogicalVolume(Cryostat, matCryo, "Cryostat_log", 0, 0, 0); + + for (nEa = 0; nEa < nEuler; nEa++) { + pEc = &euler[nEa]; + nCl = pEc->whichGe; + if (nCl < 0) + continue; + + nGe = pEc->numPhys; + + for (nCa = 0; nCa < nClAng; nCa++) { + pCa = &clust[nCa]; + if (pCa->whichClus != nCl) + continue; + if (!pCa->pAssV) + continue; + + G4cout << nEa << " nEuler = " << nEuler << " pCa whichClus = " << pCa->whichClus << G4endl; + + rm = pEc->rotMat; + + rotatedPos = pEc->trasl + posShift; + + if ((thetaShift * phiShift != 0.) || (thetaShift + phiShift != 0.)) { + radd.set(0, 0, 0); + radd.rotateY(thetaShift); + radd.rotateZ(phiShift); + rotatedPos = radd(rotatedPos); + rm = radd * rm; + } + + if (thetaPrisma != 0.) { + rotatedPos = rmP(rotatedPos); + rm = rmP * rm; + } + + indexP = 1000 * nGe + maxSolids * nGe; + G4cout << "indexP " << indexP << G4endl; + + transf = G4Transform3D(rm, rotatedPos); + // pCa->pAssV->MakeImprint(theDetector->HallLog(), transf, indexP-1); + pCa->pAssV->MakeImprint(world, transf, indexP - 1); + + // Place a Cryostat //LR + if (cryostatStatus) { + cryostatPos = cryostatPos0; + cryostatPos.rotateZ(pEc->ps); + cryostatPos.rotateY(pEc->th); + cryostatPos.rotateZ(pEc->ph); + cryostatRot = G4RotationMatrix::IDENTITY; + cryostatRot.rotateY(cryostatPos.getTheta()); + cryostatRot.rotateZ(cryostatPos.getPhi()); + + new G4PVPlacement(G4Transform3D(cryostatRot, cryostatPos), logicCryostat, "Cryostat", world, false, 0); + } + + // Since the solids are defined centered in the origin, need to recalculate + // the size of the equivalent shell with the crystals placed + // For this we can neglect the additional rotation radd! + for (nSol = 0; nSol < pCa->nsolids; nSol++) { + pEa = &pCa->solids[nSol]; + + rm1 = pEa->rotMat; + + rotatedPos1 = pEa->trasl; + + for (nPg = 0; nPg < nPgons; nPg++) { + pPg = &pgons[nPg]; + if (pPg->whichGe != pEa->whichGe) + continue; + + for (nPt = 0; nPt < pPg->npoints; nPt++) { + rotatedPos2 = G4ThreeVector(pPg->vertex[nPt]); + rotatedPos2 = rm(rm1(rotatedPos2) + rotatedPos1) + rotatedPos; + arrayRmin = min(arrayRmin, rotatedPos2.mag()); + arrayRmax = max(arrayRmax, rotatedPos2.mag()); + } + // should consider also the centres of the faces!!! + rotatedPos2 = G4ThreeVector(pPg->centerFace1); + rotatedPos2 = rm(rm1(rotatedPos2) + rotatedPos1) + rotatedPos; + arrayRmin = min(arrayRmin, rotatedPos2.mag()); + arrayRmax = max(arrayRmax, rotatedPos2.mag()); + rotatedPos2 = G4ThreeVector(pPg->centerFace2); + rotatedPos2 = rm(rm1(rotatedPos2) + rotatedPos1) + rotatedPos; + arrayRmin = min(arrayRmin, rotatedPos2.mag()); + arrayRmax = max(arrayRmax, rotatedPos2.mag()); + } + } + + nDets += pCa->nsolids; + nWlTot += pCa->nwalls; + nClus++; + + if (iClMin < 0 || nGe < iClMin) + iClMin = nGe; + if (iClMax < 0 || nGe > iClMax) + iClMax = nGe; + + printf("%4d %4d %4d %8d %9.2f %9.2f %9.2f %9.2f %9.2f %9.2f\n", iClTot, nGe, nCl, indexP, pEc->ps / deg, + pEc->th / deg, pEc->ph / deg, pEc->trasl.x() / cm, pEc->trasl.y() / cm, pEc->trasl.z() / cm); + iCl[nCl]++; + iClTot++; + } + } + nClus = iClMax - iClMin + 1; + + // store the crystal type for pulse shape calculations + crystType.resize((1 + iClMax) * maxSolids); + planarLUT.resize((1 + iClMax) * maxSolids); + for (ii = 0; ii < ((G4int)crystType.size()); ii++) + crystType[ii] = -1; + for (ii = 0; ii < ((G4int)planarLUT.size()); ii++) + planarLUT[ii] = 0; // by default, coaxial + + for (nEa = 0; nEa < nEuler; nEa++) { + pEc = &euler[nEa]; + nCl = pEc->whichGe; + if (nCl < 0) + continue; + + nGe = pEc->numPhys; + + for (nCa = 0; nCa < nClAng; nCa++) { + pCa = &clust[nCa]; + if (pCa->whichClus != nCl) + continue; + if (!pCa->pAssV) + continue; + for (ii = 0; ii < ((G4int)pCa->solids.size()); ii++) { + pEa = &pCa->solids[ii]; + crystType[nGe * maxSolids + ii] = pEa->whichGe; + + for (jj = 0; jj < nPgons; jj++) { + pPg = &pgons[jj]; + if (pPg->whichGe != pEa->whichGe) + continue; + if (!pPg->isPlanar) + continue; + planarLUT[nGe * maxSolids + ii] = 1; + } + // G4cout << nGe*maxSolids+ii << " " << pEa->whichGe << G4endl; + } + } + } + + iCMin = iClMin; + iCMax = iClMax; + iGMin = maxSolids * iClMin; + iGMax = maxSolids * (iClMax + 1) - 1; + + // G4cout << " MaxSolids is " << maxSolids << G4endl; + + G4cout << "Number of placed clusters is " << iClTot << " [ "; + for (nPg = 0; nPg < nClAng; nPg++) + G4cout << iCl[nPg] << " "; + G4cout << "]" << G4endl; + G4cout << "Cluster Index ranging from " << iClMin << " to " << iClMax << G4endl; + G4cout << "Detector Index ranging from " << maxSolids * iClMin << " to " << maxSolids * (iClMax + 1) - 1 << G4endl + << G4endl; + G4cout << "Number of placed walls is " << nWlTot << G4endl << G4endl; + delete[] iCl; + + G4cout << "The equivalent shell extends from " << arrayRmin / cm << " cm to " << arrayRmax / cm << " cm" << G4endl + << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// This method calculates the vertexes of the segments for poly nn +// To allow the thickness at the detector axis to be different from the geometrical (outer) slice +// the segments are decomposed into 4 parts: first they are cut into Left and Right of the reference edge. +// Each half is then split into a lower pyramide (quadrangolar base on the external face, tip at z_inner) +// and an upper tetrahedron (based on the upper pyramide-side-face, tip at Z_inner) + +// Warning! these solids are not centered on zero! This avoids a further translation when placing the volumes. + +G4int Hicari::CalculateSegments(G4int iPg) { + G4int sector, slice; + + CpolyhPoints* ppg = &pgons[iPg]; + + if (ppg->isPlanar) + return 0; + + G4int npoints = ppg->npoints; + G4int nsides = npoints / 2; + G4int nslices = ppg->nslice; + G4int nsegs = nsides * nslices; + + // vertices of inner and outer face of crystal + //#ifdef G4V10 + G4Point3D* vertexF1; + G4Point3D* vertexF2; + vertexF1 = new G4Point3D[nsides]; + vertexF2 = new G4Point3D[nsides]; + /* + #else + G4Point3DVector vertexF1; + G4Point3DVector vertexF2; + vertexF1.resize(nsides); + vertexF2.resize(nsides); + #endif + */ + // for consistency, the points taken directly from CConvexPolyhedron + for (sector = 0; sector < nsides; sector++) { + vertexF1[sector] = ppg->pPoly->GetPoints(sector); + vertexF2[sector] = ppg->pPoly->GetPoints(sector + nsides); + } + // center (at cylinder axis) of inner and outer face of crystal + // tubX, tubY should be zero! + G4Point3D centerF1(ppg->tubX, ppg->tubY, ppg->zFace1); + G4Point3D centerF2(ppg->tubX, ppg->tubY, ppg->zFace2); + + G4Plane3D xyPlane; // a plane normal to zAxis + G4Plane3D zzPlane; // a plane passing through the zAxis + G4Point3D pz, p1, pm, p2; // the points on the lower segment-face + G4Point3D PZ, P1, PM, P2; // the points on the upper segment-face + CpolyhPoints *ppsl, *ppsu; // pointers to the lower & upper decomposition of half-segment + nsegs = 0; + G4int isA, isB; + for (slice = 0; slice < nslices; slice++) { + for (sector = 0; sector < nsides; sector++, nsegs++) { + isA = sector; + for (int n = 0; n < 2; n++) { // loop on the two faces of the edge + if (n == 0) { + isB = (isA + nsides - 1) % nsides; // first towards the previous edge + pgSegLl.push_back(CpolyhPoints()); + pgSegLu.push_back(CpolyhPoints()); + ppsl = &pgSegLl.back(); + ppsu = &pgSegLu.back(); + } + else { + isB = (isA + 1) % nsides; // than towards the next edge + pgSegRl.push_back(CpolyhPoints()); + pgSegRu.push_back(CpolyhPoints()); + ppsl = &pgSegRl.back(); + ppsu = &pgSegRu.back(); + } + ppsl->whichGe = iPg; + ppsu->whichGe = iPg; + + xyPlane = G4Plane3D(0., 0., 1., -ppg->zSliceI[slice]); // xy-plane at inner lower-level + pz = XPlaneLine(xyPlane, centerF1, centerF2); // inner lower-point + xyPlane = G4Plane3D(0., 0., 1., -ppg->zSliceO[slice]); // plane at outer lower-level + p1 = XPlaneLine(xyPlane, vertexF1[isA], vertexF2[isA]); // intercept edge + p2 = XPlaneLine(xyPlane, vertexF1[isB], vertexF2[isB]); // intercept next/previous edge + pm = (p1 + p2) / 2; // midpoint at lower-level + + xyPlane = G4Plane3D(0., 0., 1., -ppg->zSliceI[slice + 1]); // plane at inner upper-level + PZ = XPlaneLine(xyPlane, centerF1, centerF2); // inner upper-point + xyPlane = G4Plane3D(0., 0., 1., -ppg->zSliceO[slice + 1]); // plane at outer upper-level + P1 = XPlaneLine(xyPlane, vertexF1[isA], vertexF2[isA]); // intercept edge + P2 = XPlaneLine(xyPlane, vertexF1[isB], vertexF2[isB]); // intercept next/previous edge + PM = (P1 + P2) / 2; // midpoint at loupper-level + + // the points of the lower part + ppsl->vertex.resize(5); + ppsl->npoints = 5; + ppsl->vertex[0] = pz; + ppsl->vertex[1] = p1; + ppsl->vertex[2] = pm; + ppsl->vertex[3] = PM; + ppsl->vertex[4] = P1; + + // description of the pyramide + ppsl->ifaces.clear(); + ppsl->nfaces = 0; + ppsl->ifaces.push_back(4); // the quadrangular basis + ppsl->ifaces.push_back(1); + ppsl->ifaces.push_back(2); + ppsl->ifaces.push_back(3); + ppsl->ifaces.push_back(4); + ppsl->nfaces++; + ppsl->ifaces.push_back(3); // the 4 side triangular faces + ppsl->ifaces.push_back(0); + ppsl->ifaces.push_back(1); + ppsl->ifaces.push_back(2); + ppsl->nfaces++; + ppsl->ifaces.push_back(3); + ppsl->ifaces.push_back(0); + ppsl->ifaces.push_back(2); + ppsl->ifaces.push_back(3); + ppsl->nfaces++; + ppsl->ifaces.push_back(3); + ppsl->ifaces.push_back(0); + ppsl->ifaces.push_back(3); + ppsl->ifaces.push_back(4); + ppsl->nfaces++; + ppsl->ifaces.push_back(3); + ppsl->ifaces.push_back(0); + ppsl->ifaces.push_back(4); + ppsl->ifaces.push_back(1); + ppsl->nfaces++; + ppsl->ifaces.push_back(-1); + + // the points of the upper part + ppsu->vertex.resize(4); + ppsu->npoints = 4; + ppsu->vertex[0] = pz; + ppsu->vertex[1] = P1; + ppsu->vertex[2] = PM; + ppsu->vertex[3] = PZ; + + // description of the tetrahedron + ppsu->ifaces.clear(); + ppsu->nfaces = 0; + ppsu->ifaces.push_back(3); // the "upper" face + ppsu->ifaces.push_back(1); + ppsu->ifaces.push_back(2); + ppsu->ifaces.push_back(3); + ppsu->nfaces++; + ppsu->ifaces.push_back(3); // the 3 "side" faces + ppsu->ifaces.push_back(0); + ppsu->ifaces.push_back(1); + ppsu->ifaces.push_back(2); + ppsu->nfaces++; + ppsu->ifaces.push_back(3); + ppsu->ifaces.push_back(0); + ppsu->ifaces.push_back(2); + ppsu->ifaces.push_back(3); + ppsu->nfaces++; + ppsu->ifaces.push_back(3); + ppsu->ifaces.push_back(0); + ppsu->ifaces.push_back(3); + ppsu->ifaces.push_back(1); + ppsu->nfaces++; + ppsu->ifaces.push_back(-1); + } + } + } + return nsegs; +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void Hicari::ConstructSegments() { + char sName1[50], sName2[50]; + G4int nGe; + G4int iPg, sector, slice; + + G4cout << G4endl << "Generating segments for the ReadOut geometry... " << G4endl; + + G4VisAttributes* segVA[4]; + segVA[0] = new G4VisAttributes(G4Colour(1.0, 0.0, 0.0)); + segVA[1] = new G4VisAttributes(G4Colour(0.0, 1.0, 0.0)); + segVA[2] = new G4VisAttributes(G4Colour(0.0, 0.0, 1.0)); + segVA[3] = new G4VisAttributes(G4Colour(1.0, 0.0, 1.0)); + + G4VisAttributes* altVA = new G4VisAttributes(G4Colour(0.1, 0.1, 0.1)); + altVA->SetForceWireframe(true); + + G4int indexS; // index of segment in pgSeg... + CpolyhPoints* ppgerm; + CpolyhPoints* ppseg = NULL; + nSeg = 0; + G4int* iSeg = new G4int[nPgons]; + memset(iSeg, 0, nPgons * sizeof(G4int)); + + for (iPg = 0; iPg < nPgons; iPg++) { + ppgerm = &pgons[iPg]; + + if (ppgerm->isPlanar) + continue; + + indexS = tSegments[iPg]; + + if (printVolumes) { + G4cout << " Crystal type " << iPg << ": " << G4endl; + G4cout << " Segment volumes:" << G4endl; + G4cout << " Total Coax Passive Back Passive" << G4endl; + G4cout << " Segment [cm3] [cm3] [cm3]" << G4endl; + } + G4double segVol, backPassiveVol, coaxPassiveVol; + + for (slice = 0; slice < ppgerm->nslice; slice++) { + for (sector = 0; sector < ppgerm->npoints / 2; sector++, indexS++) { + nGe = 100 * iPg + 10 * slice + sector; // --> PPPSs (P=CrystalShape, S =Slice, s=sector) + segVol = 0.; + backPassiveVol = 0.; + coaxPassiveVol = 0.; + // the four parts composing the segment + for (int ss = 0; ss < 4; ss++) { + switch (ss) { + case 0: + ppseg = &pgSegLl[indexS]; // the lower segment at the left + sprintf(sName1, "SegmLl_%5.5d", nGe); + sprintf(sName2, "SegmLl_L_%5.5d", nGe); + break; + case 1: + ppseg = &pgSegLu[indexS]; // the upper segment at the left + sprintf(sName1, "SegmLu_%5.5d", nGe); + sprintf(sName2, "SegmLu_L_%5.5d", nGe); + break; + case 2: + ppseg = &pgSegRl[indexS]; // the lower segment at the right + sprintf(sName1, "SegmRl_%5.5d", nGe); + sprintf(sName2, "SegmRl_L_%5.5d", nGe); + break; + case 3: + ppseg = &pgSegRu[indexS]; // the upper segment at the right + sprintf(sName1, "SegmRu_%5.5d", nGe); + sprintf(sName2, "SegmRu_L_%5.5d", nGe); + break; + } + ppseg->pPoly = new CConvexPolyhedron(G4String(sName1), ppseg->vertex, ppseg->nfaces, ppseg->ifaces); + // ppseg->pDetL = new G4LogicalVolume( ppseg->pPoly, matCryst, G4String(sName2), 0, 0, 0 ); + // LR: segment volumes were too large (sum > crystal volume). Intersect with crystal. + G4RotationMatrix rm; + rm.set(0, 0, 0); + ppseg->pCaps = new G4IntersectionSolid(G4String(sName1), ppseg->pPoly, ppgerm->pCaps, + G4Transform3D(rm, G4ThreeVector())); + + // We make these to calculate the dead volume in the segment. + sprintf(sName1, "SegmPassB_%5.5d", nGe); + ppseg->pCaps1 = new G4IntersectionSolid(G4String(sName1), ppseg->pPoly, ppgerm->pCaps1, + G4Transform3D(rm, G4ThreeVector())); + sprintf(sName1, "SegmPassC_%5.5d", nGe); + ppseg->pCaps2 = new G4IntersectionSolid(G4String(sName1), ppseg->pPoly, ppgerm->pCoax2, + G4Transform3D(rm, G4ThreeVector())); + + ppseg->pDetL = new G4LogicalVolume(ppseg->pCaps, matCryst, G4String(sName2), 0, 0, 0); + ppseg->pDetL->SetVisAttributes(segVA[(indexS) % 4]); // in this way they get also the same color + if (drawReadOut) { + new G4PVPlacement(0, G4ThreeVector(), ppseg->pDetL, G4String(sName2), ppgerm->pDetL, false, 0); + ppgerm->pDetL->SetVisAttributes(altVA); + } + // These take a while, so only compute them if we're printing them. + if (printVolumes) { + segVol += ppseg->pCaps->GetCubicVolume(); + backPassiveVol += ppseg->pCaps1->GetCubicVolume(); + coaxPassiveVol += ppseg->pCaps2->GetCubicVolume(); + } + nSeg++; + iSeg[iPg]++; + } + if (printVolumes) { + G4cout << " " << std::setw(8) << nGe << std::fixed << std::setprecision(2) << std::setw(14) << segVol / cm3 + << std::fixed << std::setprecision(2) << std::setw(14) << coaxPassiveVol / cm3 << std::fixed + << std::setprecision(2) << std::setw(14) << backPassiveVol / cm3 << G4endl; + } + } + } + G4cout << " " << iSeg[iPg] << " segments" << G4endl; + } + G4cout << " --> Total number of generated sub-segments (4 sub-segments per segment) is " << nSeg << " [ "; + for (iPg = 0; iPg < nPgons; iPg++) + G4cout << iSeg[iPg] << " "; + G4cout << "]" << G4endl; + + G4cout << G4endl << "Checking consistency of segments ..." << G4endl; + G4int nproblems = 0; + for (iPg = 0; iPg < nPgons; iPg++) { + nproblems += CheckOverlap(iPg, tSegments[iPg], nSegments[iPg]); + } + if (nproblems) + G4cout << nproblems << " points with problems" << G4endl; + else + G4cout << "all OK" << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void Hicari::ShowStatus() { + G4cout << G4endl; + G4int prec = G4cout.precision(3); + G4cout.setf(ios::fixed); + G4cout << " Array composed of " << std::setw(3) << nDets << " detectors" << G4endl; + G4cout << " arranged in " << std::setw(3) << nClus << " clusters" << G4endl; + G4cout << " Array composed of " << std::setw(3) << nWlTot << " walls" << G4endl; + G4cout << " Description of detectors read from " << solidFile << G4endl; + G4cout << " Description of dead materials (walls) read from " << wallsFile << G4endl; + G4cout << " Description of clusters read from " << clustFile << G4endl; + G4cout << " Euler angles for clusters read from " << eulerFile << G4endl; + + if (readOut) { + G4cout << " Slicing planes for read out of segments read from " << sliceFile << G4endl; + G4cout << " Generated " << nSeg << " sub-segments " << G4endl; + } + if (makeCapsule) + G4cout << " The capsules have been generated with the proper thickness and spacing." << G4endl; + else + G4cout << " The capsules have not been generated." << G4endl; + if (useCylinder) + G4cout << " The intersection with a cylinder has been considered in generating the crystals." << G4endl; + else + G4cout << " The intersection with a cylinder has not been considered in generating the crystals." << G4endl; + if (usePassive) + G4cout << " The passivated zones have been considered." << G4endl; + else + G4cout << " The passivated zones have not been considered." << G4endl; + + G4cout << " The detectors material is " << matCrystName << G4endl; + G4cout << " The walls material is " << matWallsName << G4endl; + if (thetaShift || phiShift) + G4cout << " The array is rotated by theta, phi = " << thetaShift / deg << ", " << phiShift / deg << " degrees" + << G4endl; + if (thetaPrisma != 0.) + G4cout << " PRISMA rotation is theta = " << thetaPrisma / deg << " degrees" << G4endl; + if (posShift.mag2()) + G4cout << " The array is shifted by " << posShift / mm << " mm" << G4endl; + + G4cout.unsetf(ios::fixed); + G4cout.precision(prec); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// plane vv = (a,b,c,d) pV=(a,b,c) +// line A-->B = AB +// intercept pX = (pV cross (pA cross pB) - d * AB ) / pV dot AB +G4Point3D Hicari::XPlaneLine(const G4Plane3D& vv, const G4Point3D& pA, const G4Point3D& pB) { + G4Point3D AB; + G4Normal3D pV; + G4Point3D AxB, VAB; + G4double xp; + + pV = vv.normal(); + + AB = pB - pA; + + xp = pV.dot(AB); + if (!xp) + return G4Point3D(); + + AxB = pA.cross(pB); + VAB = pV.cross(AxB); + + G4Point3D pX; + pX = (VAB - vv.d() * AB) / xp; + + return pX; +} + +G4int Hicari::CheckOverlap(G4int iPg, G4int start, G4int nsegs) { + CpolyhPoints** ppsegs = new CpolyhPoints*[4 * nsegs]; // collect here the pointers to all segs of this shape + + G4int nstot = 0; + for (G4int n = 0; n < nsegs; n++) { + ppsegs[nstot++] = &pgSegLl[start + n]; + ppsegs[nstot++] = &pgSegLu[start + n]; + ppsegs[nstot++] = &pgSegRl[start + n]; + ppsegs[nstot++] = &pgSegRu[start + n]; + } + + CpolyhPoints* ppS1; + CpolyhPoints* ppS2; + G4int i1, np1, i2; + G4Point3D pt1; + EInside inside; + + G4int nproblems = 0; + for (i1 = 0; i1 < nstot; i1++) { + ppS1 = ppsegs[i1]; + for (np1 = 0; np1 < ppS1->npoints; np1++) { + pt1 = ppS1->pPoly->GetPoints(np1); + inside = pgons[iPg].pPoly->Inside(G4ThreeVector(pt1)); + if (inside == kOutside) { + printf("Warning: crystal %d : point %3d of segment %3d(%d) is outside its crystal\n", iPg, np1, i1 / 4, i1 % 4); + nproblems++; + } + for (i2 = 0; i2 < nstot; i2++) { + if (i2 == i1) + continue; // no check with itself + ppS2 = ppsegs[i2]; + inside = ppS2->pPoly->Inside(G4ThreeVector(pt1)); + if (inside == kInside) { + printf("Warning: crystal %d : point %3d of segmentL %3d(%d) is inside segment %3d(%d)\n", iPg, np1, i1 / 4, + i1 % 4, i2 / 4, i2 % 4); + nproblems++; + } + } + } + } + delete[] ppsegs; + return nproblems; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4int Hicari::GetSegmentNumber(G4int nGe, G4ThreeVector position) { + if (!readOut) + return 0; + // else if( planarLUT[nGe%1000] ) + // return GetPlanSegmentNumber( nGe, position ); + else + return GetCoaxSegmentNumber(nGe, position); + + return 0; +} + +G4int Hicari::GetCoaxSegmentNumber(G4int nGe, G4ThreeVector position) { + EInside inside; + + CeulerAngles* pEa = NULL; + CclusterAngles* pCa = NULL; + CpolyhPoints* ppgerm = NULL; + CpolyhPoints* ppseg = NULL; + + G4int detNum = nGe % 1000; + G4int cluNum = nGe / 1000; + G4int subIndex = detNum % maxSolids; + + // G4cout << " nGe, det, clu, ind " << nGe << " " << detNum<< " " << cluNum << " " << subIndex << G4endl; + + G4int slice = 0, sector = 0, ss, nCa, nPg, indexS, whichGe; + + G4int whichClus = -100; + + for (nCa = 0; nCa < (G4int)(euler.size()); nCa++) { + pEa = &euler[nCa]; + // G4cout << nCa << " " << pEa->numPhys << " " << pEa->whichGe << G4endl; + if (pEa->numPhys == cluNum) { + whichClus = pEa->whichGe; + break; + } + } + + if (whichClus < 0) { + G4cout << " Warning! Could not find any detector containing this point: " << position / cm << " cm" << G4endl; + return -1; + } + + for (nCa = 0; nCa < nClAng; nCa++) { + pCa = &clust[nCa]; + if (pCa->whichClus != whichClus) + continue; + + whichGe = pCa->solids[subIndex].whichGe; + // G4cout << " whichGe " << whichGe << G4endl; + + for (nPg = 0; nPg < nPgons; nPg++) { + ppgerm = &pgons[nPg]; + if (ppgerm->whichGe != whichGe) + continue; + // G4cout << " ppgerm->whichGe " << nGe << " " << whichGe << " " << ppgerm->whichGe << " " << position/mm << + // G4endl; + indexS = tSegments[nPg]; + for (slice = 0; slice < ppgerm->nslice; slice++) { + for (sector = 0; sector < ppgerm->npoints / 2; sector++, indexS++) { + // the four parts composing the segment + for (ss = 0; ss < 4; ss++) { + switch (ss) { + case 0: + ppseg = &pgSegLl[indexS]; // the lower segment at the left + break; + case 1: + ppseg = &pgSegLu[indexS]; // the upper segment at the left + break; + case 2: + ppseg = &pgSegRl[indexS]; // the lower segment at the right + break; + case 3: + ppseg = &pgSegRu[indexS]; // the upper segment at the right + break; + } + inside = ppseg->pPoly->Inside(position); + if (inside != kOutside) { + // G4cout << "slice = " << slice << " sector = " << sector << G4endl; + return 10 * slice + sector; + } + } + } + } + + G4cout << " Warning! Could not find any segment containing this point: " << position / cm << " cm" << G4endl; + return -1; + } + } + G4cout << " Warning! Could not find any detector containing this point: " << position / cm << " cm" << G4endl; + return -1; +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// Add Detector branch to the EventTree. +// Called After DetecorConstruction::AddDetector Method +void Hicari::InitializeRootOutput() { + RootOutput* pAnalysis = RootOutput::getInstance(); + TTree* pTree = pAnalysis->GetTree(); + if (!pTree->FindBranch("Hicari")) { + pTree->Branch("Hicari", "THicariData", &m_Event); + } + pTree->SetBranchAddress("Hicari", &m_Event); +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// Read sensitive part and fill the Root tree. +// Called at in the EventAction::EndOfEventAvtion +void Hicari::ReadSensitive(const G4Event*) { + + m_Event->Clear(); + + /////////// + GeScorers::PS_GeDetector* Scorer = (GeScorers::PS_GeDetector*)m_HicariScorer->GetPrimitive(0); + + unsigned int size = Scorer->GetMult(); + // std::cout << "in Hicari, mult"<< size << std::endl; + for (unsigned int i = 0; i < size; i++) { + // double Energy = RandGauss::shoot(Scorer->GetEnergy(i),Hicari_NS::ResoEnergy); + double Energy = Scorer->GetEnergy(i); + // if(Energy>Hicari_NS::EnergyThreshold){ + double Time = Scorer->GetTime(i); + + int detCode = Scorer->GetIndex(i); + // detcode = clu_index * 1000 + clu_index * maxSolids (4 in our case) + // int cluNum = detCode / 1000; + int detNum = detCode % 1000; + // int subIndex = detNum % maxSolids; + int fcluster = detNum / 4; // same as clNum + int fcrystalid = detNum % 4; // same as subindex + /* + std::cout << "\t Energy"<< Energy << std::endl; + std::cout << "\t detCode"<< detCode << std::endl; + std::cout << "\t cluNum"<< cluNum << std::endl; + std::cout << "\t detNum"<< detNum << std::endl; + std::cout << "\t subIndex"<< subIndex << std::endl; + std::cout << "\t fcluster"<< fcluster << std::endl; + std::cout << "\t fcrystalid"<< fcrystalid << std::endl; + */ + + G4ThreeVector HitPos = Scorer->GetPos(i); + int segCode = GetSegmentNumber(detCode, HitPos); + // std::cout << "segCode:" << segCode << std::endl; + + // cout << "read detcode " << detCode<< ", segcode " << segCode << ", detNum " << detNum ; + // Modify sector number to match GRETINA data stream + G4int slice = segCode / 10; + G4int sector = segCode % 10; + if (detNum < FIRSTMB) { + // Type B crystal (offset -1) + if (sector > 0) + sector--; + else + sector = 5; + // Type A crystal (offset -2) + if (detNum % 2) { + if (sector > 0) + sector--; + else + sector = 5; + } + } + segCode = sector + 6 * slice; + + // cout << "detNum " << detNum << ", sector " << sector << ", slice " << slice << ", segcode " << segCode; + // mapping MB segments + if (detNum > FIRSTMB - 1 && detNum < FIRSTMB + 4 * MBCLUST) + segCode = MBsegments[segCode]; + else if (detNum > FIRSTMB + 4 * MBCLUST - 1) + segCode = CLsegments[segCode]; + + // FOR 8-fold Super CLOVERS this is wrong!!! + // else if(detNum>FIRSTMB+4*MBCLUST-1) + // segCode = sector + 4 * slice; + // cout << " -> " << segCode << endl; + + // Check if the particle has interact before, if yes, add up the energies. + unsigned int j = m_Event->Find(fcluster, fcrystalid, segCode); + if (j != 99999) { + m_Event->AddE(j, Energy); + } + else { + m_Event->SetCluster(fcluster); + m_Event->SetCrystal(fcrystalid); // equivalent to subindex + m_Event->SetSegment(segCode); + m_Event->SetEnergy(Energy); + m_Event->SetTime(Time); + } + /* + std::cout <<"mult:"<< m_Event->GetMult() << std::endl; + //Blur the enrgies using the resolution + for(unsigned int i =0; i<m_Event->GetMult(); i++){ + std::cout <<"before:"<< m_Event->GetEnergy(i) << std::endl; + double tempE = RandGauss::shoot(m_Event->GetEnergy(i),Hicari_NS::ResoEnergy); + std::cout<<"after:" << tempE << std::endl; + m_Event->ChangeE(i, tempE); + } + */ + } + + /* + //G4int Nhits = gammaCollection->entries(); + + unsigned int Nhits = Scorer->GetMult(); + std::cout << "Nhits, number of interaction points in Hicari: "<< size << std::endl; + + if(Nhits>0) { + + // Packing: consolidate interaction points within segments + // based on proximity. + int MAX_SEGS=8; + int MAX_INTPTS=16; + int MBCLUST=6; + int CLOVERS=4; + double packingRes=0.*mm; + double hitTolerance = 0.00001*mm; + //#define FIRSTMB 800 + //#define MBSEGS 6 + //#define CLSEGS 4 + + G4int trackID[100*MAX_INTPTS]; + G4int detNum[100*MAX_INTPTS]; + G4int segNum[100*MAX_INTPTS]; + G4double measuredEdep[100*MAX_INTPTS]; + G4double segmentEdep[100*MAX_INTPTS]; + G4double measuredX[100*MAX_INTPTS]; + G4double measuredY[100*MAX_INTPTS]; + G4double measuredZ[100*MAX_INTPTS]; + G4double X0[100*MAX_INTPTS]; + G4double Y0[100*MAX_INTPTS]; + G4double Z0[100*MAX_INTPTS]; + G4int NCons[100*MAX_INTPTS]; + G4double packingRes2 = packingRes*packingRes; + + + G4int NMeasured = 0; + G4double totalEdep = 0; + + G4bool foundfirst[(MBCLUST+CLOVERS)*MAXCRYSTALNO][MAXSEGNO]; + for(int cl=0; cl<MBCLUST+CLOVERS; cl++){ + for(int cr=0; cr<MAXCRYSTALNO; cr++){ + for(int se=0; se<MAXSEGNO; se++){ + foundfirst[cl*MAXCRYSTALNO+cr][se] = false; + } + } + } + + + for(G4int i = 0; i < Nhits; i++){ + + G4double x, y, z; + x = Scorer->GetPos(i).getX()/mm; + y = Scorer->GetPos(i).getY()/mm; + z = Scorer->GetPos(i).getZ()/mm; + + G4double en = Scorer->GetEnery(i)/keV; + totalEdep += en; + + NCons[i] = -1; + G4bool processed = false; + + // Initialize a new interaction point for each gamma-ray hit. + if((*gammaCollection)[i]->GetParticleID() == "gamma"){ + + // Combine multiple gamma hits at the same position. + // (This is rare, but it happens.) + if(i > 0 + && (x - measuredX[i-1])*(x - measuredX[i-1]) < hitTolerance*hitTolerance + && (y - measuredY[i-1])*(y - measuredY[i-1]) < hitTolerance*hitTolerance + && (z - measuredZ[i-1])*(z - measuredZ[i-1]) < hitTolerance*hitTolerance){ + + measuredEdep[NMeasured-1] += en; + processed = true; + + } else { + + trackID[NMeasured] = (*gammaCollection)[i]->GetTrackID(); + detNum[NMeasured] = (*gammaCollection)[i]->GetDetNumb(); + segNum[NMeasured] = (*gammaCollection)[i]->GetSegNumb(); + //G4cout << trackID[NMeasured] << "\t" << detNum[NMeasured] << "\t" << segNum[NMeasured] << + G4endl; + + // This becomes the total energy deposit associated with this + // interaction. + measuredEdep[NMeasured] = en; + + // This becomes the barycenter of all energy depositions associated + // with this interaction. + measuredX[NMeasured] = x; + measuredY[NMeasured] = y; + measuredZ[NMeasured] = z; + trackID[NMeasured] = (*gammaCollection)[i]->GetTrackID(); + + // Position of the initial interaction. We use position to identify + // the tracks produced by this interaction. + X0[NMeasured] = (*gammaCollection)[i]->GetPos().getX()/mm; + Y0[NMeasured] = (*gammaCollection)[i]->GetPos().getY()/mm; + Z0[NMeasured] = (*gammaCollection)[i]->GetPos().getZ()/mm; + + //find first interaction for HiCARI + //cout << "interaction in det = " << detNum[NMeasured] << ", seg = "<< segNum[NMeasured] << endl; + if(detNum[NMeasured]>=FIRSTMB){ + if(!foundfirst[detNum[NMeasured]-FIRSTMB][segNum[NMeasured]]){ + // cout << "first interaction in det = " << detNum[NMeasured] << " - FIRSTMB " + <<detNum[NMeasured]-FIRSTMB << ", seg = "<< segNum[NMeasured] << " at (x,y,z) = (" << x <<" ," << y <<" ," << z <<")" + << endl; foundfirst[detNum[NMeasured]-FIRSTMB][segNum[NMeasured]] = true; G4ThreeVector gamma(x,y,z); + firstposition[detNum[NMeasured]-FIRSTMB][segNum[NMeasured]]+=gamma; + firstctr[detNum[NMeasured]-FIRSTMB][segNum[NMeasured]]++; + } + } + + NCons[NMeasured] = 1; + NMeasured++; + processed = true; + } + + // Combine secondary-particle hits with their parent interaction points. + } else { + + // Compare hit i with existing "measured" interaction points. + for(G4int j = 0; j < NMeasured; j++){ + + G4double x0 = (*gammaCollection)[i]->GetTrackOrigin().getX()/mm; + G4double y0 = (*gammaCollection)[i]->GetTrackOrigin().getY()/mm; + G4double z0 = (*gammaCollection)[i]->GetTrackOrigin().getZ()/mm; + + // G4cout << "(*gammaCollection)["<< i <<"]->GetParentTrackID() = " + // << (*gammaCollection)[i]->GetParentTrackID() + // << " trackID[j] = " << trackID[j] + // << " (x0 - X0[" << j << "]) = " << (x0 - X0[j]) + // << " (y0 - Y0[" << j << "]) = " << (y0 - Y0[j]) + // << " (z0 - Z0[" << j << "]) = " << (z0 - Z0[j]) + // << " (*gammaCollection)[" << i << "]->GetDetNumb()" + // << (*gammaCollection)[i]->GetDetNumb() + // << " detNum[" << j << "] = " << detNum[j] << G4endl; + + if( (*gammaCollection)[i]->GetParentTrackID() == trackID[j] // correct parent + && (x0 - X0[j])*(x0 - X0[j]) < hitTolerance*hitTolerance + && (y0 - Y0[j])*(y0 - Y0[j]) < hitTolerance*hitTolerance + && (z0 - Z0[j])*(z0 - Z0[j]) < hitTolerance*hitTolerance // correct interaction point + && (*gammaCollection)[i]->GetDetNumb() == detNum[j]){ // same crystal + + // Energy-weighted average position (barycenter) + measuredX[j] = (measuredEdep[j]*measuredX[j] + en*x)/(measuredEdep[j] + en); + measuredY[j] = (measuredEdep[j]*measuredY[j] + en*y)/(measuredEdep[j] + en); + measuredZ[j] = (measuredEdep[j]*measuredZ[j] + en*z)/(measuredEdep[j] + en); + measuredEdep[j] += en; + + NCons[j]++; + processed = true; + + } + } + } + + // If hit i is not a gamma-ray hit and cannot be consolidated with + // an existing gamma-ray interaction point, it's a positron or an + // electron multiple-scattering event that isn't associated with + // energy deposition in the sensitive volume of GRETINA by a gamma + // ray. (The gamma-ray interaction happened in dead material.) + // We'll initialize a new interaction point and treat it as a + // gamma-ray interaction. + if(!processed){ + + trackID[NMeasured] = (*gammaCollection)[i]->GetTrackID(); + detNum[NMeasured] = (*gammaCollection)[i]->GetDetNumb(); + segNum[NMeasured] = (*gammaCollection)[i]->GetSegNumb(); + measuredEdep[NMeasured] = en; + measuredX[NMeasured] = x; + measuredY[NMeasured] = y; + measuredZ[NMeasured] = z; + + // This is not a gamma ray. We need to trick its siblings into + // treating it as the parent gamma. + trackID[NMeasured] = (*gammaCollection)[i]->GetParentTrackID(); + X0[NMeasured] = (*gammaCollection)[i]->GetTrackOrigin().getX()/mm; + Y0[NMeasured] = (*gammaCollection)[i]->GetTrackOrigin().getY()/mm; + Z0[NMeasured] = (*gammaCollection)[i]->GetTrackOrigin().getZ()/mm; + + NCons[NMeasured] = 1; + NMeasured++; + processed = true; + + } + + if(!processed) + G4cout << "Warning: Could not find a home for hit " << i + << " of event " << event_id + << G4endl; + + if(NMeasured >= 100*MAX_INTPTS){ + G4cout << "Error: too many decomposed hits. Increase hit processing array dimension." + << G4endl; + exit(EXIT_FAILURE); + } + + } + + // Packing: Consolidate the "measured" gamma-ray interaction points + // within a single segment that are closer than the PackingRes + // parameter. + G4int NGammaHits = NMeasured; + for(G4int i = 0; i < NMeasured; i++){ + for(G4int j = i+1; j < NMeasured; j++){ + + if( ( (measuredX[i] - measuredX[j])*(measuredX[i] - measuredX[j]) + + (measuredY[i] - measuredY[j])*(measuredY[i] - measuredY[j]) + + (measuredZ[i] - measuredZ[j])*(measuredZ[i] - measuredZ[j]) + < packingRes2 ) // proximal + && detNum[i] == detNum[j] // same crystal + && segNum[i] == segNum[j] // same segment + && (NCons[i] > 0 && NCons[j] > 0) ){ // not already consolidated + + // Energy-weighted average + measuredX[i] = (measuredEdep[i]*measuredX[i] + + measuredEdep[j]*measuredX[j])/(measuredEdep[i]+measuredEdep[j]); measuredY[i] = (measuredEdep[i]*measuredY[i] + + measuredEdep[j]*measuredY[j])/(measuredEdep[i]+measuredEdep[j]); measuredZ[i] = (measuredEdep[i]*measuredZ[i] + + measuredEdep[j]*measuredZ[j])/(measuredEdep[i]+measuredEdep[j]); measuredEdep[i] += measuredEdep[j]; + + NCons[j] = -1; + NGammaHits--; + + } + + } + + } + + // Calculate the total energy deposited in each segment. + for(G4int i = 0; i < NMeasured; i++) // initialize + if(NCons[i] > 0) + segmentEdep[i] = measuredEdep[i]; + + G4bool singleDetector = true; + for(G4int i = 0; i < NMeasured; i++){ + for(G4int j = i+1; j < NMeasured; j++){ + if(NCons[i] > 0 && NCons[j] > 0 + && detNum[i] == detNum[j] // same crystal + && segNum[i] == segNum[j]){ // same segment + segmentEdep[i] += measuredEdep[j]; + segmentEdep[j] += measuredEdep[i]; + } + if( detNum[i] != detNum[j] ) + singleDetector = false; + } + } + + // Identify events in which the full emitted gamma-ray energy + // is deposited in a single crystal + // (only evaluated for emitted multiplicity = 1 events). + if( eventInfo->GetNEmittedGammas() == 1 ){ + if( singleDetector && + (totalEdep - eventInfo->GetEmittedGammaEnergy(0)) + *(totalEdep - eventInfo->GetEmittedGammaEnergy(0)) + < 0.001*keV*0.001*keV ) + eventInfo->SetFullEnergy(1); + else + eventInfo->SetFullEnergy(0); + } + + + // Write event to the output file + if(fisInBeam){ + //write out zero degree "data" + writeZeroDeg(timestamp,eventInfo->GetATA(), eventInfo->GetBTA(), eventInfo->GetXTA(), eventInfo->GetYTA(), + eventInfo->GetBetaTA()); if(fisMINOS){ writeMINOS(timestamp,eventInfo->GetVertex(), eventInfo->GetBetaRE()); + } + } + + // Fold position resolution measuredX, measuredY, measuredZ + // WARNING: this "smears" positions across the boundaries of + // the active volume, which doesn't correspond to + // the behavior of signal decomposition. + if(posRes > 0){ + for(int i=0; i<NMeasured; i++) { + measuredX[i] += CLHEP::RandGauss::shoot(0, posRes); + measuredY[i] += CLHEP::RandGauss::shoot(0, posRes); + measuredZ[i] += CLHEP::RandGauss::shoot(0, posRes); + } + } + //NMeasured, detNum, segNum + + if(print){ + // Write decomposed gamma event(s) to the output file + cout << "writing NMeasured "<<NMeasured << endl; + for(int nn =0;nn<NMeasured;nn++){ + cout << "detNum: " << detNum[nn] << ", segNum: " << segNum[nn] << ", Ncons " << NCons[nn]; + //for(int jj=0;jj>NCons[nn];jj++) + cout << ", edep " << measuredEdep[nn] <<", segment "<< segmentEdep[nn] << endl; + } + } + writeDecomp(timestamp, + NMeasured, + detNum, segNum, NCons, + measuredX, measuredY, measuredZ, + measuredEdep, segmentEdep); + + }//loop hits + + */ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//////////////////////////////////////////////////////////////// +void Hicari::WriteCrystalAngles(G4String file) { + G4int nGe, nPh, nCl; + G4int iPg, iCa, ne, nSol; + + G4double theta, phi; + + CeulerAngles* peA; + CeulerAngles* peA1; + CclusterAngles* pcA; + CpolyhPoints* ppG; + char line[128]; + + G4RotationMatrix rm, radd, rm1, rmP, frameRot; + G4ThreeVector trasl, trasl1; + G4ThreeVector rotatedPos; + + std::ofstream outFileLMD; + + outFileLMD.open(file); + if (!outFileLMD.is_open()) { + G4cout << " --> Could not open " << file << " output file, aborting ..." << G4endl; + return; + } + + G4cout << " --> Writing out crystal angles to " << file << " file..." << G4endl; + for (ne = 0; ne < nEuler; ne++) { + + peA = &euler[ne]; + nCl = peA->whichGe; + if (nCl < 0) + continue; + nPh = peA->numPhys * maxSolids; + + rm = peA->rotMat; + trasl = peA->trasl + posShift; + + if ((thetaShift * phiShift != 0.) || (thetaShift + phiShift != 0.)) { + radd.set(0, 0, 0); + radd.rotateY(thetaShift); + radd.rotateZ(phiShift); + trasl = radd(trasl); + rm = radd * rm; + } + + if (thetaPrisma != 0.) { + rmP.set(0, 0, 0); + rmP.rotateX(thetaPrisma); + rm = rmP * rm; + trasl = rmP(trasl); + } + + for (iCa = 0; iCa < nClAng; iCa++) { + pcA = &clust[iCa]; + if (pcA->whichClus != nCl) + continue; + + for (nSol = 0; nSol < pcA->nsolids; nSol++) { + peA1 = &pcA->solids[nSol]; + nGe = peA1->whichGe; + if (nGe < 0) + continue; + + rm1 = peA1->rotMat; + + frameRot = rm * rm1; + + trasl1 = peA1->trasl; + + for (iPg = 0; iPg < nPgons; iPg++) { + ppG = &pgons[iPg]; + if (ppG->whichGe != nGe) + continue; // looks for the right solid + rotatedPos = rm(trasl1) + trasl; + + theta = rotatedPos.theta(); + phi = rotatedPos.phi(); + if (phi < 0.) + phi += 360. * deg; + + sprintf(line, " Riv#%4.1d Theta= %9.4f Phi= %9.4f\n", nPh, theta / deg, phi / deg); + // sprintf( line, " %3d %9d %9.4f %9.4f\n", 0, nPh, theta/deg, phi/deg ); + outFileLMD << line; + G4cout << line; + nPh++; + } + } + } + } + outFileLMD.close(); + G4cout << " --> Crystal angles successfully written out to " << file << " file." << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + +// void Hicari::WriteCrystalPositions(std::ofstream &outFileLMD, G4double unit) +void Hicari::WriteCrystalPositions(G4String file, G4double unit) { + G4int nGe, nPh, nCl; + G4int iPg, iCa, ne, nSol; + + CeulerAngles* peA; + CeulerAngles* peA1; + CclusterAngles* pcA; + CpolyhPoints* ppG; + char line[128]; + + G4RotationMatrix rm, radd, rm1, rmP, frameRot; + G4ThreeVector trasl, trasl1; + G4ThreeVector rotatedPos; + + std::ofstream outFileLMD; + outFileLMD.open(file); + if (!outFileLMD.is_open()) { + G4cout << " --> Could not open " << file << " output file, aborting ..." << G4endl; + return; + } + G4cout << " --> Writing out crystal positiond to " << file << " file..." << G4endl; + + for (ne = 0; ne < nEuler; ne++) { + + peA = &euler[ne]; + nCl = peA->whichGe; + if (nCl < 0) + continue; + nPh = peA->numPhys * maxSolids; + + rm = peA->rotMat; + trasl = peA->trasl + posShift; + + if ((thetaShift * phiShift != 0.) || (thetaShift + phiShift != 0.)) { + radd.set(0, 0, 0); + radd.rotateY(thetaShift); + radd.rotateZ(phiShift); + trasl = radd(trasl); + rm = radd * rm; + } + + if (thetaPrisma != 0.) { + rmP.set(0, 0, 0); + rmP.rotateX(thetaPrisma); + rm = rmP * rm; + trasl = rmP(trasl); + } + + for (iCa = 0; iCa < nClAng; iCa++) { + pcA = &clust[iCa]; + if (pcA->whichClus != nCl) + continue; + + for (nSol = 0; nSol < pcA->nsolids; nSol++) { + peA1 = &pcA->solids[nSol]; + nGe = peA1->whichGe; + if (nGe < 0) + continue; + + rm1 = peA1->rotMat; + + frameRot = rm * rm1; + + trasl1 = peA1->trasl; + + for (iPg = 0; iPg < nPgons; iPg++) { + ppG = &pgons[iPg]; + if (ppG->whichGe != nGe) + continue; // looks for the right solid + rotatedPos = rm(trasl1) + trasl; + + sprintf(line, " %3d 0 %10.5f %10.5f %10.5f\n", nPh, rotatedPos.x() / unit, rotatedPos.y() / unit, + rotatedPos.z() / unit); + outFileLMD << line; + sprintf(line, " 1 %10.5f %10.5f %10.5f\n", frameRot.xx(), frameRot.xy(), frameRot.xz()); + outFileLMD << line; + sprintf(line, " 2 %10.5f %10.5f %10.5f\n", frameRot.yx(), frameRot.yy(), frameRot.yz()); + outFileLMD << line; + sprintf(line, " 3 %10.5f %10.5f %10.5f\n", frameRot.zx(), frameRot.zy(), frameRot.zz()); + outFileLMD << line; + nPh++; + } + } + } + } + + outFileLMD.close(); + G4cout << " --> Crystal positions successfully written out to " << file << " file." << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +// void Hicari::WriteSegmentPositions(std::ofstream &outFileLMD, G4double unit) +void Hicari::WriteSegmentPositions(G4String file, G4double unit) { + G4int nGe, nPh, nCl; + G4int iPg, iCa, ne, nSol, sector, slice; + G4double step = 1. * mm / ((G4double)stepFactor); // integration step for CalculateVolumeAndCenter() + + if ((segVolume.size() == 0) || stepHasChanged) { + G4cout << "Calculating volume and center of segments (with step = " << step / mm << "mm ) ..." << G4endl; + segVolume.resize(totSegments); + segCenter.resize(totSegments); + for (iPg = 0; iPg < nPgons; iPg++) { + CalculateVolumeAndCenter(iPg, tSegments[iPg], nSegments[iPg], step); + } + stepHasChanged = false; + } + + CeulerAngles* peA; + CeulerAngles* peA1; + CclusterAngles* pcA; + CpolyhPoints* ppG; + G4int indexS; // index of segment in segCenter + char line[128]; + + G4RotationMatrix rm, rm1, radd, rmP; + G4ThreeVector trasl, trasl1; + G4Point3D centreSeg, rotatedPos; + G4Transform3D clusterToWorld, crystalToCluster, crystalToWorld; + + std::ofstream outFileLMD; + outFileLMD.open(file); + if (!outFileLMD.is_open()) { + G4cout << " --> Could not open " << file << " output file, aborting ..." << G4endl; + return; + } + G4cout << " --> Writing out segment positions to " << file << " file..." << G4endl; + + for (ne = 0; ne < nEuler; ne++) { + + peA = &euler[ne]; + nCl = peA->whichGe; + if (nCl < 0) + continue; + nPh = peA->numPhys * maxSolids; + + trasl = peA->trasl + posShift; + rm = peA->rotMat; + + if ((thetaShift * phiShift != 0.) || (thetaShift + phiShift != 0.)) { + radd.set(0, 0, 0); + radd.rotateY(thetaShift); + radd.rotateZ(phiShift); + trasl = radd(trasl); + rm = radd * rm; + } + + if (thetaPrisma != 0.) { + rmP.set(0, 0, 0); + rmP.rotateX(thetaPrisma); + rm = rmP * rm; + trasl = rmP(trasl); + } + + clusterToWorld = G4Transform3D(rm, trasl); + + for (iCa = 0; iCa < nClAng; iCa++) { + pcA = &clust[iCa]; + if (pcA->whichClus != nCl) + continue; + + for (nSol = 0; nSol < pcA->nsolids; nSol++) { + peA1 = &pcA->solids[nSol]; + nGe = peA1->whichGe; + if (nGe < 0) + continue; + + rm1 = peA1->rotMat; + + trasl1 = peA1->trasl; + + crystalToCluster = G4Transform3D(rm1, trasl1); + + crystalToWorld = clusterToWorld * crystalToCluster; + + for (iPg = 0; iPg < nPgons; iPg++) { + ppG = &pgons[iPg]; + if (ppG->whichGe != nGe) + continue; // looks for the right solid + indexS = tSegments[iPg]; + + for (slice = 0; slice < ppG->nslice; slice++) { + for (sector = 0; sector < ppG->npoints / 2; sector++, indexS++) { + + centreSeg = G4Point3D(segCenter[indexS]); + + // rotatedPos = rm( rm1( centreSeg ) + trasl1 ) + trasl; // old style! + // could be: rotatedPos = clusterToWorld * (crystalToCluster*centreSeg) + rotatedPos = crystalToWorld * centreSeg; + + sprintf(line, " %3d %2d %2d %10.5f %10.5f %10.5f %10.5f\n", nPh, slice, sector, rotatedPos.x() / unit, + rotatedPos.y() / unit, rotatedPos.z() / unit, segVolume[indexS] / unit * unit * unit); + outFileLMD << line; + } + } + + nPh++; + } + } + } + } + + outFileLMD.close(); + G4cout << " --> Segment positions successfully written out to " << file << " file." << G4endl; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//////////////////////////////////////////////////////////////// +void Hicari::CalculateVolumeAndCenter(G4int iPg, G4int start, G4int nsegs, G4double step) { + G4int nse, ss, npts, nn; + G4double xMin, yMin, zMin; + G4double xMax, yMax, zMax; + std::vector<CpolyhPoints*> ppsegs; // collect here the pointers the four sub-segments + ppsegs.resize(4); + for (nse = 0; nse < nsegs; nse++) { + // gather the composing segments + ppsegs[0] = &pgSegLl[start + nse]; + ppsegs[1] = &pgSegLu[start + nse]; + ppsegs[2] = &pgSegRl[start + nse]; + ppsegs[3] = &pgSegRu[start + nse]; + + // define a bounding box enclosing all the sub-segments + // (an own one is more convenient here than a G4BoundingBox object) + xMin = xMax = ppsegs[0]->pPoly->GetPoints(0).x(); + yMin = yMax = ppsegs[0]->pPoly->GetPoints(0).y(); + zMin = zMax = ppsegs[0]->pPoly->GetPoints(0).z(); + for (ss = 0; ss < 4; ss++) { + G4Point3D pts; + npts = ppsegs[ss]->pPoly->GetnPoints(); + for (nn = 0; nn < npts; nn++) { + pts = ppsegs[ss]->pPoly->GetPoints(nn); + xMin = min(xMin, pts.x()); + xMax = max(xMax, pts.x()); + yMin = min(yMin, pts.y()); + yMax = max(yMax, pts.y()); + zMin = min(zMin, pts.z()); + zMax = max(zMax, pts.z()); + } + } + // some rounding of limits + xMin = floor(xMin); + yMin = floor(yMin); + zMin = floor(zMin); + xMax = ceil(xMax); + yMax = ceil(yMax); + zMax = ceil(zMax); + + G4double rr2, rc2 = 0., Rc2 = 0., zch = 0.; + G4bool nowuseCylinder = this->useCylinder && pgons[iPg].cylinderMakesSense; + if (nowuseCylinder) { + rc2 = pow(pgons[iPg].tubr, 2.); + Rc2 = pow(pgons[iPg].tubR, 2.); + zch = pgons[iPg].zFace1 + pgons[iPg].thick; + } + + G4Point3D theCenter(0., 0., 0.); + G4Point3D myPoint; + G4double theVolume; + G4int nseen = 0; + G4int ntot = 0; + G4int ssold = -1; + G4double xx, yy, zz; + G4double dd1 = step; + G4double dd2 = dd1 / 2.; + EInside inside; + G4ThreeVector pnt; + + for (zz = zMin + dd2; zz < zMax; zz += dd1) { + for (yy = yMin + dd2; yy < yMax; yy += dd1) { + for (xx = xMin + dd2; xx < xMax; xx += dd1) { + myPoint.set(xx, yy, zz); + ntot++; + // Intersection with the cylinder: we check directly + // (however, we neglect the passive areas) + if (nowuseCylinder) { + rr2 = myPoint.x() * myPoint.x() + myPoint.y() * myPoint.y(); + if (rr2 > Rc2) + continue; // outside cyl + if ((myPoint.z() > zch) && (rr2 < rc2)) + continue; // coax hole + } + + // check if inside one of the sub-segments composing this segment + pnt = G4ThreeVector(myPoint); + if (ssold >= 0) { // start with the old one + inside = ppsegs[ssold]->pPoly->Inside(pnt); + if (inside == kInside) { + nseen++; + theCenter += myPoint; + continue; // no need to check the others + } + } + for (ss = 0; ss < 4; ss++) { // look into the (other) segments + if (ss == ssold) + continue; + inside = ppsegs[ss]->pPoly->Inside(pnt); + if (inside == kInside) { + nseen++; + theCenter += myPoint; + ssold = ss; + break; // no need to check the others + } + } + ssold = -1; // outside all of them + } + } + } + + theCenter = theCenter / nseen; + theVolume = nseen * pow(dd1, 3.); + printf(" Crystal# %2d Segment# %3d : %6d shot %6d seen --> Volume = %6.3f cm3 Center = (%7.3f %7.3f %7.3f) cm\n", + iPg, nse, ntot, nseen, theVolume / cm3, theCenter.x() / cm, theCenter.y() / cm, theCenter.z() / cm); + segVolume[start + nse] = theVolume; + segCenter[start + nse] = theCenter; + } + ppsegs.clear(); +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//////////////////////////////////////////////////////////////// +// +void Hicari::InitializeScorers() { + + bool already_exist = false; + m_HicariScorer = CheckScorer("HicariScorer", already_exist); + + if (already_exist) + return; + + // Otherwise the scorer is initialised + // vector<int> level({0, 1}); + int level = 1; + /* + m_HicariScorer->RegisterPrimitive( + new CalorimeterScorers::PS_Calorimeter("Cristal",level, 0)); + G4SDManager::GetSDMpointer()->AddNewDetector(m_HicariScorer) ; + */ + + m_HicariScorer->RegisterPrimitive(new GeScorers::PS_GeDetector("Cristal", level, 1)); + G4SDManager::GetSDMpointer()->AddNewDetector(m_HicariScorer); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//////////////////////////////////////////////////////////////////////////////// +// Construct Method to be pass to the DetectorFactory // +//////////////////////////////////////////////////////////////////////////////// +NPS::VDetector* Hicari::Construct() { return (NPS::VDetector*)new Hicari(); } + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//////////////////////////////////////////////////////////////////////////////// +// Registering the construct method to the factory // +//////////////////////////////////////////////////////////////////////////////// +extern "C" { +class proxy_nps_Hicari { + public: + proxy_nps_Hicari() { + NPS::DetectorFactory::getInstance()->AddToken("Hicari", "Hicari"); + NPS::DetectorFactory::getInstance()->AddDetector("Hicari", Hicari::Construct); + } +}; + +proxy_nps_Hicari p_nps_Hicari; +} diff --git a/NPSimulation/Detectors/Hicari/Hicari.hh b/NPSimulation/Detectors/Hicari/Hicari.hh new file mode 100644 index 000000000..ed78439ed --- /dev/null +++ b/NPSimulation/Detectors/Hicari/Hicari.hh @@ -0,0 +1,353 @@ +#ifndef Hicari_h +#define Hicari_h 1 +/***************************************************************************** + * Copyright (C) 2009-2019 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Thomas Goigoux contact address: thomas.goigoux@cea.fr * + * * + * Creation Date : july 2019 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * This class describe Hicari simulation * + * * + *---------------------------------------------------------------------------* + * Comment: * + * * + *****************************************************************************/ + +// C++ header +#include <string> +#include <vector> +using namespace std; + +// G4 headers +#include "G4ThreeVector.hh" +#include "G4RotationMatrix.hh" +#include "G4LogicalVolume.hh" +#include "G4MultiFunctionalDetector.hh" + +// NPTool header +#include "NPSVDetector.hh" +#include "Hicari_Helper.hh" +#include "CConvexPolyhedron.hh" +#include "THicariData.h" +#include "NPInputParser.h" + +#define MAX_SEGS 8 /* max. number of segments to take in events */ +#define MAX_INTPTS (2*MAX_SEGS) /* max. number of interaction points */ +#define FIRSTMB 800 +#define MBSEGS 6 +#define MBCLUST 6 +#define CLOVERS 4 +#define CLSEGS 4 + +class Hicari : public NPS::VDetector{ + //////////////////////////////////////////////////// + /////// Default Constructor and Destructor ///////// + //////////////////////////////////////////////////// + public: + Hicari() ; + virtual ~Hicari() ; + + //////////////////////////////////////////////////// + /////// Specific Function of this Class /////////// + //////////////////////////////////////////////////// + public: + // Spherical + void AddDetector(double X,double Y, double Z, double ThetaX, double ThetaY, double ThetaZ); + + G4int InitializeMaterials(); + void BuildClover(int i_clo, G4LogicalVolume* world); + void BuildSideCatcher(); + void BuildBackCatcher(); + void BuildSideShield(); + void BuildCollimator(); + + //////////////////////////////////////////////////// + ////// Inherite from NPS::VDetector class ///////// + //////////////////////////////////////////////////// + public: + // Read stream at Configfile to pick-up parameters of detector (Position,...) + // Called in DetecorConstruction::ReadDetextorConfiguration Method + void ReadConfiguration(NPL::InputParser) ; + + + // Construct detector and inialise sensitive part. + // Called After DetecorConstruction::AddDetector Method + void ConstructDetector(G4LogicalVolume* world) ; + + // Add Detector branch to the EventTree. + // Called After DetecorConstruction::AddDetector Method + void InitializeRootOutput() ; + + // Read sensitive part and fill the Root tree. + // Called at in the EventAction::EndOfEventAvtion + void ReadSensitive(const G4Event* event) ; + + public: // Scorer + // Initialize all Scorer used by the MUST2Array + void InitializeScorers() ; + + // Associated Scorer + G4MultiFunctionalDetector* m_HicariScorer ; + //////////////////////////////////////////////////// + ///////////Event class to store Data//////////////// + //////////////////////////////////////////////////// + private: + THicariData* m_Event ; + + //////////////////////////////////////////////////// + ///////////////Private intern Data////////////////// + //////////////////////////////////////////////////// + /* + private: // Geometry + // Detector Coordinate (of the front of the Germanium) + vector<double> m_X; + vector<double> m_Y; + vector<double> m_Z; + // Detector orientation + vector<double> m_ThetaX; //rotation angles to X, Y, Z axis + vector<double> m_ThetaY; + vector<double> m_ThetaZ; +*/ + + ///////////////////////////////////////////////// + /// Files from which actual geometry is read + ///////////////////////////////////////////////// + private: + G4String iniPath; //> directory where the files are located + G4String eulerFile; //> angles and positions to place the clusters into space + G4String solidFile; //> shape of the crystals + G4String sliceFile; //> segmentation + G4String wallsFile; //> cryostats + G4String clustFile; //> arrangement of the crystals and cryostats within a cluster + int MBsegments[6] = {2, 3, 5, 4, 1, 0}; + int CLsegments[4] = {2, 1, 0, 3}; + + private: + G4String directoryName; //> for the command line + + ///////////////////////////////////// + /// materials (pointers and names) + ///////////////////////////////////// + private: + G4Material *matCryst; //> crystals + G4Material *matWalls; //> encapsulation + G4Material *matBackWalls; //> behind the crystals + G4Material *matHole; //> vacuum within the cryostat + G4Material *matCryo; //> cryostats + + private: + G4String matCrystName; //> crystals + G4String matWallsName; //> cryostats and encapsulation + G4String matBackWallsName; //> behind the crystals + G4String matHoleName; //> vacuum within the cryostat + G4String matCryoName; //> cryostats + + /////////////////////////////////////////////////////////////////////// + /// structures needed to store geometry data during the construction + /////////////////////////////////////////////////////////////////////// + private: + std::vector<CeulerAngles> euler; //> angles and positions to place the clusters into space + std::vector<CpolyhPoints> pgons; //> shape of the crystals + std::vector<CpolyhPoints> walls; //> cryostats + std::vector<CclusterAngles> clust; //> arrangement of the crystals and cryostats within a cluster + std::vector<CpolyhPoints> capsO; //> encapsulation (outer size) + std::vector<CpolyhPoints> capsI; //> encapsulation (inner size) + + private: + G4int nEuler; //> number of clusters composing the array + G4int nPgons; //> number of different crystal shapes within the array + G4int nClAng; //> number of crystals composing a cluster + G4int nWalls; //> number of cryostat parts within a cluster + G4int maxPgons; //> maximum index of crystal shapes + G4int nDets; + G4int nClus; + G4int iCMin; + G4int iCMax; + G4int iGMin; + G4int iGMax; + G4int maxSec; + G4int maxSli; + + private: + std::vector<G4int> crystType; //> lookup table detector number --> crystal shape + std::vector<G4int> planarLUT; //> lookup table detector number --> planar or not + + private: + G4int nWlTot; //> total number of cryostat parts within the array + G4int maxSolids; //> maximum number of solids within a cluster + + ///////////////////////////////////////////////// + /// structures needed to build the segmentation + //////////////////////////////////////////////// + private: + std::vector<CpolyhPoints> pgSegLl; //> segments on lower Left side of edges + std::vector<CpolyhPoints> pgSegLu; //> segments on upper Left side of edges + std::vector<CpolyhPoints> pgSegRl; //> segments on lower Right side of edges + std::vector<CpolyhPoints> pgSegRu; //> segments on upper Right side of edges + + private: + std::vector<G4int> nSegments; + std::vector<G4int> tSegments; + G4int totSegments; + G4int nSeg; + + private: + std::vector<G4double> segVolume; //> the volume of the (composite) segment + std::vector<G4Point3D> segCenter; //> the center of mass of the (composite) segment + + private: + G4int stepFactor; //> integration step for the calculation of segment volume + G4bool stepHasChanged;//> true: integration step was changed and segment volumes + //> should be recomputed + + //////////////////////////////////////////// + /// size of the equivalent germanium shell + //////////////////////////////////////////// + private: + G4double arrayRmin; //> inner radius + G4double arrayRmax; //> outer radius + + /////////////////////////////////////////// + /// rotation applied to the whole array + ////////////////////////////////////////// + private: + G4double thetaShift; //> theta + G4double phiShift; //> phi + G4double thetaPrisma; //> thetaPrisma + + /////////////////////////////////////////// + /// traslation applied to the whole array + ////////////////////////////////////////// + private: + G4ThreeVector posShift; + + ///////////////// + /// some flags + //////////////// + private: + G4bool usePassive; //> true: passive areas of the crystals will be generated + G4bool drawReadOut; //> true: segments will be visualized + G4bool useAncillary; //> true: ancillary detectors will be constructed + G4bool makeCapsule; //> true: encapsulation will be generated + G4bool useCylinder; //> true: the intersection with the cylinder will be considered + G4bool cryostatStatus; //> true: include cryostats behind clusters //LR + G4bool readOut; //> true: a segmentation have been defined + G4bool printVolumes; //> true: report crystal, segment, and passive volumes + + /////////////////////////////////////////// //LR + /// Cryostats + ////////////////////////////////////////// + public: + void SetCryostats(){cryostatStatus = true;}; //LR + + private: + G4ThreeVector cryostatPos0; //LR + G4ThreeVector cryostatPos; //LR + G4RotationMatrix cryostatRot; //LR + //G4double cryostatRadius; //LR + //G4double cryostatLength; //LR + G4double cryostatZplanes[7]; //LR + G4double cryostatRinner[7]; //LR + G4double cryostatRouter[7]; //LR + + ////////////////////////////// + ///////// Methods /////////// + ////////////////////////////// + private: + void InitData(); + + ////////////////////////// + /// read the input files + ///////////////////////// + private: + void ReadEulerFile(); + void ReadSolidFile(); + void ReadSliceFile(); + void ReadWallsFile(); + void ReadClustFile(); + + ////////////////////////////////////////////////////////////// + /// look for the materials starting from the material names + ///////////////////////////////////////////////////////////// + private: + G4int FindMaterials(); + + ///////////////////////////////////////////////////////// + /// Construct the various elements composing the array + ///////////////////////////////////////////////////////// + private: + void ConstructGeCrystals (); + void ConstructTheCapsules (); + void ConstructTheClusters (); + void ConstructTheWalls (); + + //////////////////////////////// + /// placement of the elements + //////////////////////////////// + private: + void PlaceTheClusters (G4LogicalVolume*); + void ShowStatus (); + + ////////////////////////////////// + /// Construction of the segments + ////////////////////////////////// + + private: + ////////////////////////////// + /// Construct the segments + ////////////////////////////// + void ConstructSegments (); + ///////////////////////////////////////////////////////////////////////////////// + /// Calculate the vertexes of the segments starting from the original polyhedra + ///////////////////////////////////////////////////////////////////////////////// + G4int CalculateSegments ( G4int ); + /////////////////////////////////// + /// Checks for possible overlaps + ////////////////////////////////// + G4int CheckOverlap ( G4int, G4int, G4int ); + ///////////////////////////////////////////////////////////////////////////////////////// + /// Calculates volume and center of the segments (each of them composed of more parts!) + ////////////////////////////////////////////////////////////////////////////////////////// + void CalculateVolumeAndCenter ( G4int, G4int, G4int, G4double ); + //////////////////////////////////////////////////////////////////////////////////////// + /// Calculates the intersection between a plane and a line passing through two points + /////////////////////////////////////////////////////////////////////////////////////// + G4Point3D XPlaneLine ( const G4Plane3D &vv, const G4Point3D &pA, const G4Point3D &pB ); + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + /// Calculates segment number (corresponding to a given detector and position relative to the crystal) + ///////////////////////////////////////////////////////////////////////////////////////////////////////// + G4int GetCoaxSegmentNumber ( G4int, G4ThreeVector ); + + ////////////////////////////////// + /// writes out the information + ///////////////////////////////// + private: + void WritePositions ( std::ofstream &outFileLMD, G4double=1.*mm ); + //void WriteSegmentPositions ( std::ofstream &outFileLMD, G4double=1.*mm ); + void WriteSegmentPositions ( G4String, G4double=1*mm ); + //void WriteCrystalPositions ( std::ofstream &outFileLMD, G4double=1.*mm ); + void WriteCrystalPositions ( G4String, G4double=1*mm ); + void WriteCrystalTransformations ( std::ofstream &outFileLMD, G4double=1.*mm ); + void WriteHeader ( std::ofstream &outFileLMD, G4double=1.*mm ); + void WriteSegmentAngles ( G4String, G4int = 0 ); + void WriteCrystalAngles ( G4String ); + + ////////////////////////////////////////////// + /// public interface to the private method! + //////////////////////////////////////////////// + public: + G4int GetSegmentNumber ( G4int, G4ThreeVector ); + + // Needed for dynamic loading of the library + public: + static NPS::VDetector* Construct(); +}; +#endif diff --git a/NPSimulation/Detectors/Hicari/Hicari_Helper.hh b/NPSimulation/Detectors/Hicari/Hicari_Helper.hh new file mode 100644 index 000000000..3139ee032 --- /dev/null +++ b/NPSimulation/Detectors/Hicari/Hicari_Helper.hh @@ -0,0 +1,210 @@ +#ifndef AgataAncillaryHelper_h +#define AgataAncillaryHelper_h 1 + + +#include "globals.hh" +#include "G4Point3D.hh" +#include "G4ThreeVector.hh" +#include "G4AssemblyVolume.hh" +#include "G4RotationMatrix.hh" +#include "G4Transform3D.hh" +#include <vector> + +using namespace std; + +class CConvexPolyhedron; +class G4Tubs; +class G4Polycone; +class G4IntersectionSolid; +class G4LogicalVolume; +class G4VisAttributes; +class G4VPhysicalVolume; + +//////////////////////////////////////////////////////////////////////////////////// +/// This class handles the information about the encapsulated detectors of AGATA +/// (size, ...) together with the objects actually generating the detectors +/// within the simulation. It is basically a struct, but was written as a class +/// where all members are public since the compiler does not accept to allocate +/// a std::vector with a structure. It is also used for the cryostats. +//////////////////////////////////////////////////////////////////////////////////// +class CpolyhPoints +{ + // default empty creator/destructor + public: + CpolyhPoints() {}; + ~CpolyhPoints() {}; + + /////////////////////////////// + /// All members are public!!! + /////////////////////////////// + public: + G4int whichGe; //> kind of crystal (for the cryostats: cluster they belong to) + G4int whichCrystal; //> for the cryostats: crystal they belong to + G4int whichWall; //> for the cryostats: kind of part composing the cryostat + + public: + G4int npoints; //> number of points composing the solid + G4int nfaces; //> number of faces composing the solid + + public: + std::vector<G4Point3D> vertex; //> 3D-vertexes of the solid + std::vector<G4int> ifaces; //> points (of vertex) forming each face + + //////////////////// + /// Cylinder data + /////////////////// + public: + G4double tubr, tubR, tubL; //> inner and outer radius, length + G4double tubX, tubY, tubZ; //> position of the cylinder with respect to the polyhedron (for the intersection) + G4double thick; //> distance from the front face to the coaxial hole + + public: + G4bool cylinderMakesSense; //> false: dimensions are not compatible with a real coaxial crystal + //> (thus the cylinder will not be built) + + /////////////////// + /// Capsule data + ////////////////// + public: + G4double capThick; //> thickness + G4double capSpace; //> crystal-capsule spacing + + public: + G4bool makeCapsule; //> true: encapsulation will be built + + /////////////////////////// + /// passivated areas size + /////////////////////////// + public: + G4double passThick1; //> at the back of the crystal + G4double passThick2; //> around the coaxial hole + + public: + G4Point3D centerFace1; //> center of front face + G4Point3D centerFace2; //> center of back face + + public: + G4double zFace1; //> z-coordinate of the center of the front face + G4double zFace2; //> z-coordinate of the center of the back face + G4double zCenter; //> z-coordinate of the center of the crystal + + /////////////////// + /// segmentation + /////////////////// + public: + G4int nslice; //> number of slices in which the crystal is divided + std::vector<G4double> zSliceI; //> z-coordinate of the slices at the crystal axis + std::vector<G4double> zSliceO; //> z-coordinate of the slices at the outer surface + + public: + G4double minR; //> minimum radius of a cylinder surrounding the polyhedron + + public: + G4double colx, coly, colz; //> RGB components defining the colour + + /////////////////// + /// planars + /////////////////// + public: + G4double guardThick[4]; //> thickness of the guardring + G4bool isPlanar; //> true: treat detector as a planar + + public: + G4double segSize_x; //> x-size of the segments + G4double segSize_y; //> y-size of the segments + G4double maxSize_x; //> max x-coordinate of the crystal + G4double maxSize_y; //> max y-coordinate of the crystal + G4double minSize_x; //> min x-coordinate of the crystal + G4double minSize_y; //> min y-coordinate of the crystal + G4int nSeg_x; //> number of pixels in x direction + G4int nSeg_y; //> number of pixels in y direction + + + ///////////////////////////////////////////////////// + /// Objects defining the detector in the simulation + ///////////////////////////////////////////////////// + public: + CConvexPolyhedron *pPoly; //> original polyhedron + G4Polycone *pCoax; //> cylinder + G4IntersectionSolid *pCaps; //> their intersection + G4LogicalVolume *pDetL; //> its logical + + public: + G4Polycone *pTubs1; //> cylinder (passive area behind detector) + G4IntersectionSolid *pCaps1; //> intersection with polyhedron + G4LogicalVolume *pDetL1; //> its logical + G4VPhysicalVolume *pDetP1; //> passivated area (back) + + G4Tubs *pTubs; //> cylinder (for capsule KW) + public: + G4Polycone *pCoax2; //> cylinder (passive area at the coaxial hole) + G4IntersectionSolid *pCaps2; //> intersection with polyhedron + G4LogicalVolume *pDetL2; //> its logical + G4VPhysicalVolume *pDetP2; //> passivated area (coax) + + public: + G4VisAttributes *pDetVA; //> visualization attributes +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// This "structure" (written as a class as explained above) handles the transformations needed to +/// place the AGATA clusters into space. +//////////////////////////////////////////////////////////////////////////////////////////////////// +class CeulerAngles +{ + // default empty creator/destructor + public: + CeulerAngles() {}; + ~CeulerAngles() {}; + + // all members are public + public: + G4int whichGe; //> type of cluster which should be placed + G4int numPhys; //> number of cluster which should be placed + + public: + G4double ps, th, ph; //> Rotation angles; they are needed since one cannot easily extract + //> them from the rotation matrix + + public: + G4ThreeVector trasl; //> traslation + + public: + G4RotationMatrix rotMat; //> rotation matrix + + public: + G4Transform3D *pTransf; //> full transformation +}; + +class G4AssemblyVolume; +//////////////////////////////////////////////////////////////////////////////////////////////////// +/// This "structure" (written as a class as explained above) handles the transformations needed to +/// place the crystals within an AGATA cluster +//////////////////////////////////////////////////////////////////////////////////////////////////// +class CclusterAngles +{ + // default empty creator/destructor + public: + CclusterAngles() {}; + ~CclusterAngles() {}; + + // all members are public + public: + G4int whichClus; //> type of cluster + + public: + G4int nsolids; //> number of crystals arranged to form a cluster + std::vector<CeulerAngles> solids; //> each component of this array contains the information + //> needed to place a single crystal within the cluster + + public: + G4int nwalls; //> number of parts composing the cryostat +#ifdef ANTIC + G4int nantic; //> number of parts composing the antiCompton +#endif + + public: + G4AssemblyVolume* pAssV; //> pointer to the G4AssemblyVolume forming the cluster +}; + +#endif diff --git a/NPSimulation/Scorers/CMakeLists.txt b/NPSimulation/Scorers/CMakeLists.txt index 6d6e2df09..224d273f1 100644 --- a/NPSimulation/Scorers/CMakeLists.txt +++ b/NPSimulation/Scorers/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(NPSScorers SHARED CylinderTPCScorers.cc DriftChamberScorers.cc NPSHitsMap.hh CalorimeterScorers.cc InteractionScorers.cc DSSDScorers.cc SiliconScorers.cc PhotoDiodeScorers.cc ObsoleteGeneralScorers.cc DriftElectronScorers.cc TPCScorers.cc MDMScorer.cc NeutronDetectorScorers.cc ProcessScorers.cc PlasticBar.cc) +add_library(NPSScorers SHARED CylinderTPCScorers.cc DriftChamberScorers.cc NPSHitsMap.hh CalorimeterScorers.cc InteractionScorers.cc DSSDScorers.cc SiliconScorers.cc PhotoDiodeScorers.cc ObsoleteGeneralScorers.cc DriftElectronScorers.cc TPCScorers.cc MDMScorer.cc NeutronDetectorScorers.cc ProcessScorers.cc PlasticBar.cc GeScorers.cc) target_link_libraries(NPSScorers ${ROOT_LIBRARIES} ${Geant4_LIBRARIES} ${NPLib_LIBRARIES} -lNPInitialConditions -lNPInteractionCoordinates) diff --git a/NPSimulation/Scorers/GeScorers.cc b/NPSimulation/Scorers/GeScorers.cc new file mode 100644 index 000000000..a51c2e7e4 --- /dev/null +++ b/NPSimulation/Scorers/GeScorers.cc @@ -0,0 +1,551 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Freddy Flavigny contact: flavigny@lpccaen.in2p3.fr * + * * + * Creation Date : April 2022 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * Custom scorer for Germanium detectors * + * * + *---------------------------------------------------------------------------* + * Comment: * + * This new type of scorer is for Ge detectors built using the geometry * + * conventions used in the AGATA/GRETINA/HiCARI simulation codes * + * file (euler, clust, solid, slice) * + *****************************************************************************/ +#include "GeScorers.hh" +#include "G4UnitsTable.hh" +#include "G4StepPoint.hh" +#include "G4VProcess.hh" + +using namespace GeScorers ; +vector<GeData>::iterator GeDataVector::find(const unsigned int& index){ + for(vector<GeData>::iterator it= m_Data.begin() ; it !=m_Data.end() ; it++){ + if((*it).GetIndex()==index) + return it; + } + return m_Data.end(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//PS_GeDetector::PS_GeDetector(G4String name, G4int level,G4int depth){ + //m_NestingLevel = NestingLevel; +//} +PS_GeDetector::PS_GeDetector(G4String name, G4int level,G4int depth) + :G4VPrimitiveScorer(name, depth){ + m_Level = level; + m_Depth = depth; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_GeDetector::~PS_GeDetector(){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4bool PS_GeDetector::ProcessHits(G4Step* aStep, G4TouchableHistory*){ + + G4StepPoint* preStepPoint = aStep->GetPreStepPoint(); + G4TouchableHandle theTouchable = preStepPoint->GetTouchableHandle(); + + G4int detCode = theTouchable->GetReplicaNumber(0); + if(detCode == 0) + detCode = theTouchable->GetReplicaNumber(m_Depth); + + G4int detNum = detCode%1000; + + G4String name = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName(); + + //G4cout << name << ", " << detCode << ", " << detNum << G4endl; + + // Track everything (the primary gamma, all secondary electrons, + // and all secondary gammas). + G4double edep = aStep->GetTotalEnergyDeposit(); + + // Keep the gamma parent of pair-production tracks for hit processing. + //const G4VProcess* test = aStep->GetPostStepPoint()->GetProcessDefinedStep(); + //const G4String& testname = test->GetProcessName(); + //if(edep<0.001*eV && testname != "conv") + if(edep<0.001*eV && + aStep->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName() != "conv") + return false; + + G4ThreeVector position = aStep->GetPostStepPoint()->GetPosition(); + + G4VPhysicalVolume* topVolume; + topVolume = theTouchable->GetVolume(m_Depth); + + + G4ThreeVector frameTrans = topVolume->GetFrameTranslation(); + + const G4RotationMatrix* rot = topVolume->GetFrameRotation(); + + G4RotationMatrix frameRot; + if( rot ) + frameRot = *rot; + + G4ThreeVector posSol = frameRot( position ); + posSol += frameRot( frameTrans ); + + + G4String particlename + = aStep->GetTrack()->GetParticleDefinition()->GetParticleName(); + // cout << particlename << endl; + // Contain Energy, Time + as many copy number as nested volume + //unsigned int mysize = m_NestingLevel.size(); + t_Time = aStep->GetPreStepPoint()->GetGlobalTime(); +/* + t_Level.clear(); + for (unsigned int i = 0; i < mysize; i++) { + t_Level.push_back( + aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber( + m_NestingLevel[i])); + } + + // Check if the particle has interact before, if yes, add up the energies. + + vector<GeData>::iterator it; + it = m_Hit.find(detCode); + if (it != m_Hit.end()) { + it->Add(edep); + } else { + m_Hit.Set(edep, t_Time, detCode, posSol); + } + */ + m_Hit.Set(edep, t_Time, detCode, posSol); + + return true; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_GeDetector::Initialize(G4HCofThisEvent* HCE){ +/* + EvtMap = new NPS::HitsMap<StepInfo>(GetMultiFunctionalDetector()->GetName(), GetName()); + if (HCID < 0) { + HCID = GetCollectionID(0); + } + HCE->AddHitsCollection(HCID, (G4VHitsCollection*)EvtMap); +*/ + + clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_GeDetector::EndOfEvent(G4HCofThisEvent*){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_GeDetector::clear(){ + m_Hit.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_GeDetector::DrawAll(){ + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_GeDetector::PrintAll(){ +/* + G4cout << " MultiFunctionalDet " << detector->GetName() << G4endl ; + G4cout << " PrimitiveScorer " << GetName() << G4endl ; + G4cout << " Number of entries " << EvtMap->entries() << G4endl ; +*/ +} + + +/* +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Images::PS_Images(G4String name, string imageFront,string imageBack,double scalingFront, double scalingBack, double centerOffsetX,double centerOffsetY,unsigned int ignoreValue, G4int depth) :G4VPrimitiveScorer(name, depth){ + m_ImageFront = new NPL::Image(imageFront,scalingFront,scalingFront); + m_ImageBack = new NPL::Image(imageBack,scalingBack,scalingBack); + m_ScalingFront = scalingFront; + m_ScalingBack = scalingBack; + m_CenterOffsetX = centerOffsetX; + m_CenterOffsetY = centerOffsetY; + m_IgnoreValue = ignoreValue; + m_Level = depth; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4bool PS_Images::ProcessHits(G4Step* aStep, G4TouchableHistory*){ + + // contain Energy Time, DetNbr, PixelFront and PixelBack + t_Energy = aStep->GetTotalEnergyDeposit(); + t_Time = aStep->GetPreStepPoint()->GetGlobalTime(); + + t_DetectorNbr = aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(m_Level); + t_Position = aStep->GetPreStepPoint()->GetPosition(); + + // transforming the position to the local volume + t_Position = aStep->GetPreStepPoint()->GetTouchableHandle()->GetHistory()->GetTopTransform().TransformPoint(t_Position); + t_PixelFront = m_ImageFront->GetPixelAtCoordinate(t_Position.x(),t_Position.y()); + t_PixelBack = m_ImageBack->GetPixelAtCoordinate(t_Position.x(),t_Position.y()); + + // If front and back are in inactive part of the wafer, + // nothing is added to the unordered_map + if(t_PixelFront == m_IgnoreValue && t_PixelBack == m_IgnoreValue) + return FALSE; + + + // Check if the particle has interact before, if yes, add up the energies. + vector<GeData>::iterator it; + + it= m_HitFront.find(GeData::CalculateIndex(t_PixelFront,t_DetectorNbr)); + if(it!=m_HitFront.end()){ + it->Add(t_Energy); + } + + else{ + m_HitFront.Set(t_Energy,t_Time,t_PixelFront,t_DetectorNbr); + } + + // Check if the particle has interact before, if yes, add up the energies. + it= m_HitBack.find(GeData::CalculateIndex(t_PixelBack,t_DetectorNbr)); + if(it!=m_HitBack.end()){ + it->Add(t_Energy); + } + + else{ + m_HitBack.Set(t_Energy,t_Time,t_PixelBack,t_DetectorNbr); + } + + return TRUE; + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Images::Initialize(G4HCofThisEvent*){ + clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Images::EndOfEvent(G4HCofThisEvent*){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Images::clear(){ + m_HitFront.clear(); + m_HitBack.clear(); +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Images::GetARGBFront(unsigned int& i,unsigned int& a,unsigned int& r,unsigned int& g,unsigned int& b){ + unsigned int Info = m_HitFront[i]->GetStrip(); + a = (Info>>24)&0xff; + r = (Info>>16)&0xff; + g = (Info>>8)&0xff; + b = (Info>>0)&0xff; +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Images::GetARGBBack(unsigned int& i,unsigned int& a,unsigned int& r,unsigned int& g,unsigned int& b){ + unsigned int Info = m_HitBack[i]->GetStrip(); + a = (Info>>24)&0xff; + r = (Info>>16)&0xff; + g = (Info>>8)&0xff; + b = (Info>>0)&0xff; +} + + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Rectangle::PS_Rectangle(G4String name,G4int Level, G4double StripPlaneLength, G4double StripPlaneWidth, G4int NumberOfStripLength,G4int NumberOfStripWidth,G4int depth,G4String axis) + :G4VPrimitiveScorer(name, depth){ + m_StripPlaneLength = StripPlaneLength; + m_StripPlaneWidth = StripPlaneWidth; + m_NumberOfStripLength = NumberOfStripLength; + m_NumberOfStripWidth = NumberOfStripWidth; + m_StripPitchLength = m_StripPlaneLength / m_NumberOfStripLength; + m_StripPitchWidth = m_StripPlaneWidth / m_NumberOfStripWidth; + m_Level = Level; + if(axis=="xy") + m_Axis=ps_xy; + else if(axis=="yz") + m_Axis=ps_yz; + else if(axis=="xz") + m_Axis=ps_xz; + + + } + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Rectangle::~PS_Rectangle(){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4bool PS_Rectangle::ProcessHits(G4Step* aStep, G4TouchableHistory*){ + + // contain Energy Time, DetNbr, StripFront and StripBack + t_Energy = aStep->GetTotalEnergyDeposit(); + t_Time = aStep->GetPreStepPoint()->GetGlobalTime(); + + t_DetectorNumber = aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(m_Level); + t_Position = aStep->GetPreStepPoint()->GetPosition(); + + t_Position = aStep->GetPreStepPoint()->GetTouchableHandle()->GetHistory()->GetTopTransform().TransformPoint(t_Position); + + if(m_Axis==ps_xy){ + t_StripLengthNumber = (int)((t_Position.x() + m_StripPlaneLength / 2.) / m_StripPitchLength ) + 1 ; + t_StripWidthNumber = (int)((t_Position.y() + m_StripPlaneWidth / 2.) / m_StripPitchWidth ) + 1 ; + } + else if(m_Axis==ps_yz){ + t_StripLengthNumber = (int)((t_Position.y() + m_StripPlaneLength / 2.) / m_StripPitchLength ) + 1 ; + t_StripWidthNumber = (int)((t_Position.z() + m_StripPlaneWidth / 2.) / m_StripPitchWidth ) + 1 ; + } + else if(m_Axis==ps_xz){ + t_StripLengthNumber = (int)((t_Position.x() + m_StripPlaneLength / 2.) / m_StripPitchLength ) + 1 ; + t_StripWidthNumber = (int)((t_Position.z() + m_StripPlaneWidth / 2.) / m_StripPitchWidth ) + 1 ; + } + + //Rare case where particle is close to edge of silicon plan + if (t_StripLengthNumber > m_NumberOfStripLength) t_StripLengthNumber = m_NumberOfStripLength; + if (t_StripWidthNumber > m_NumberOfStripWidth) t_StripWidthNumber = m_NumberOfStripWidth; + + // Check if the particle has interact before, if yes, add up the energies. + vector<GeData>::iterator it; + // Length + it = m_HitLength.find(GeData::CalculateIndex(t_StripLengthNumber,t_DetectorNumber)); + if(it!=m_HitLength.end()){ + it->Add(t_Energy); + } + else + m_HitLength.Set(t_Energy,t_Time,t_StripLengthNumber,t_DetectorNumber); + // Width + it = m_HitWidth.find(GeData::CalculateIndex(t_StripWidthNumber,t_DetectorNumber)); + if(it!=m_HitWidth.end()){ + it->Add(t_Energy); + } + else + m_HitWidth.Set(t_Energy,t_Time,t_StripWidthNumber,t_DetectorNumber); + + +return TRUE; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Rectangle::Initialize(G4HCofThisEvent*){ + clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Rectangle::EndOfEvent(G4HCofThisEvent*){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Rectangle::clear(){ + m_HitLength.clear(); + m_HitWidth.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Rectangle::DrawAll(){ + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Rectangle::PrintAll(){ +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Annular::PS_Annular(G4String name,G4int Level, G4double StripPlaneInnerRadius, G4double StripPlaneOuterRadius, G4double PhiStart,G4double PhiStop, G4int NumberOfStripRing,G4int NumberOfStripSector,G4int NumberOfQuadrant,G4int depth) + :G4VPrimitiveScorer(name, depth){ + + m_StripPlaneInnerRadius = StripPlaneInnerRadius; + m_StripPlaneOuterRadius = StripPlaneOuterRadius; + m_PhiStart = PhiStart; + m_PhiStop = PhiStop; + m_NumberOfStripRing = NumberOfStripRing; + m_NumberOfStripSector = NumberOfStripSector; + m_NumberOfStripQuadrant = NumberOfQuadrant; + m_StripPitchRing = (m_StripPlaneOuterRadius-m_StripPlaneInnerRadius)/m_NumberOfStripRing; + m_StripPitchSector = (m_PhiStop-m_PhiStart)/m_NumberOfStripSector; + m_StripPitchQuadrant = (m_PhiStop-m_PhiStart)/m_NumberOfStripQuadrant; + m_Level = Level; + + m_uz = G4ThreeVector(0,0,1); + } + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Annular::~PS_Annular(){ +} + + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4bool PS_Annular::ProcessHits(G4Step* aStep, G4TouchableHistory*){ + t_Energy = aStep->GetTotalEnergyDeposit(); + + t_Time = aStep->GetPreStepPoint()->GetGlobalTime(); + + t_DetectorNumber = aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(m_Level); + t_Position = aStep->GetPreStepPoint()->GetPosition(); + + //Transform into local coordinates + t_Position = aStep->GetPreStepPoint()->GetTouchableHandle()->GetHistory()->GetTopTransform().TransformPoint(t_Position); + t_StripRingNumber = (int) ((t_Position.rho() - m_StripPlaneInnerRadius) / m_StripPitchRing ) + 1 ; + + // phi() from G4-CLHEP method return azimuth between [-pi;pi] + // we need it in [0;2pi] to calculate sector nbr in [1,NSectors] + // only add 360 if the value is negative + double phi = (t_Position.phi()<0)? t_Position.phi()+2*pi : t_Position.phi() ; + + // factor out the extra 360 degrees before strip/quad calculation + t_StripSectorNumber = (int) ( fmod((phi - m_PhiStart),2*pi) / m_StripPitchSector ) + 1 ; + t_StripQuadrantNumber = (int) ( fmod((phi - m_PhiStart),2*pi) / m_StripPitchQuadrant) + 1 ; + + //Rare case where particle is close to edge of silicon plan + if (t_StripRingNumber > m_NumberOfStripRing) t_StripRingNumber = m_NumberOfStripRing; + if (t_StripSectorNumber > m_NumberOfStripSector) t_StripSectorNumber = m_NumberOfStripSector; + if (t_StripQuadrantNumber > m_NumberOfStripQuadrant) t_StripQuadrantNumber = m_NumberOfStripQuadrant; + + vector<GeData>::iterator it; + // Ring + it = m_HitRing.find(GeData::CalculateIndex(t_StripRingNumber,t_DetectorNumber)); + if(it!=m_HitRing.end()){ + it->Add(t_Energy); + } + else + m_HitRing.Set(t_Energy,t_Time,t_StripRingNumber,t_DetectorNumber); + + //Sector + it = m_HitSector.find(GeData::CalculateIndex(t_StripSectorNumber,t_DetectorNumber)); + if(it!=m_HitSector.end()){ + it->Add(t_Energy); + } + else + m_HitSector.Set(t_Energy,t_Time,t_StripSectorNumber,t_DetectorNumber); + + //Quadrant + it = m_HitQuadrant.find(GeData::CalculateIndex(t_StripQuadrantNumber,t_DetectorNumber)); + if(it!=m_HitQuadrant.end()){ + it->Add(t_Energy); + } + else + m_HitQuadrant.Set(t_Energy,t_Time,t_StripQuadrantNumber,t_DetectorNumber); + + return TRUE; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Annular::Initialize(G4HCofThisEvent*){ + clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Annular::EndOfEvent(G4HCofThisEvent*){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Annular::clear(){ + m_HitRing.clear(); + m_HitSector.clear(); + m_HitQuadrant.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Annular::DrawAll(){ + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Annular::PrintAll(){ +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Resistive::PS_Resistive(G4String name,G4int Level, G4double StripPlaneLength, G4double StripPlaneWidth, G4int NumberOfStripWidth,G4int depth) + :G4VPrimitiveScorer(name, depth){ + m_StripPlaneLength = StripPlaneLength; + m_StripPlaneWidth = StripPlaneWidth; + m_NumberOfStripWidth = NumberOfStripWidth; + m_StripPitchWidth = m_StripPlaneWidth / m_NumberOfStripWidth; + m_Level = Level; + + t_Position = G4ThreeVector(-1000,-1000,-1000); + t_DetectorNumber = -1; + t_StripWidthNumber = -1; + } + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_Resistive::~PS_Resistive(){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4bool PS_Resistive::ProcessHits(G4Step* aStep, G4TouchableHistory*){ + + // contain Energy Total, E1, E2, Time, DetNbr, and StripWidth + t_Energy = aStep->GetTotalEnergyDeposit(); + t_Time = aStep->GetPreStepPoint()->GetGlobalTime(); + + t_DetectorNumber = aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(m_Level); + t_Position = aStep->GetPreStepPoint()->GetPosition(); + t_Position = aStep->GetPreStepPoint()->GetTouchableHandle()->GetHistory()->GetTopTransform().TransformPoint(t_Position); + + t_StripWidthNumber = (int)((t_Position.x() + m_StripPlaneWidth / 2.) / m_StripPitchWidth ) + 1 ; + + // The energy is divided in two depending on the position + // position along the resistive strip + double P = (t_Position.z())/(0.5*m_StripPlaneLength); + // Energy + t_EnergyUp = aStep->GetTotalEnergyDeposit()*(1+P)*0.5; + t_EnergyDown = t_Energy-t_EnergyUp; + + //Rare case where particle is close to edge of silicon plan + if (t_StripWidthNumber > m_NumberOfStripWidth) t_StripWidthNumber = m_NumberOfStripWidth; + + + // Up + vector<GeData>::iterator it; + it = m_HitUp.find(GeData::CalculateIndex(t_DetectorNumber,t_StripWidthNumber)); + if(it!=m_HitUp.end()) + it->Add(t_EnergyUp); + else + m_HitUp.Set(t_EnergyUp,t_Time,t_StripWidthNumber,t_DetectorNumber); + + // Down + it = m_HitDown.find(GeData::CalculateIndex(t_DetectorNumber,t_StripWidthNumber)); + if(it!=m_HitDown.end()) + it->Add(t_EnergyDown); + else + m_HitDown.Set(t_EnergyDown,t_Time,t_StripWidthNumber,t_DetectorNumber); + + // Back + it = m_HitBack.find(GeData::CalculateIndex(t_DetectorNumber,t_StripWidthNumber)); + if(it!=m_HitBack.end()) + it->Add(t_Energy); + else + m_HitBack.Set(t_Energy,t_Time,1,t_DetectorNumber); + + + + return TRUE; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Resistive::Initialize(G4HCofThisEvent* ){ + clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Resistive::EndOfEvent(G4HCofThisEvent*){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Resistive::clear(){ + m_HitUp.clear(); + m_HitDown.clear(); + m_HitBack.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Resistive::DrawAll(){ + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_Resistive::PrintAll(){ +} +*/ diff --git a/NPSimulation/Scorers/GeScorers.hh b/NPSimulation/Scorers/GeScorers.hh new file mode 100644 index 000000000..04c324e36 --- /dev/null +++ b/NPSimulation/Scorers/GeScorers.hh @@ -0,0 +1,388 @@ +#ifndef GeScorers_h +#define GeScorers_h 1 +/***************************************************************************** + * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * * + * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * + * For the list of contributors see $NPTOOL/Licence/Contributors * + *****************************************************************************/ + +/***************************************************************************** + * Original Author: Freddy Flavigny contact flavigny@lpccaen.in2p3.fr * + * * + * Creation Date : April 2022 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * Custom scorer for Ge detectors * + * * + *---------------------------------------------------------------------------* + * Comment: * + * This new style of scorer is aim to become the standard way of doing scorer* + * in NPTool. * + *The index is build using the TrackID, Detector Number and Segment Number. * + *The scorer Hold Energy and time together * + *Only one scorer is needed for a detector * + *****************************************************************************/ +#include "G4VPrimitiveScorer.hh" +#include "NPSHitsMap.hh" +#include "NPImage.h" +#include <unordered_map> +using namespace std; +using namespace CLHEP; + +namespace GeScorers { + // Hold data for Ge hit + class GeData{ + public: + GeData(){}; + GeData(const double& Energy, const double& Time, const unsigned int& Index, const G4ThreeVector& Pos){ + m_Energy=Energy; + m_Time=Time; + m_Index = Index; + m_Pos = Pos; + } + + ~GeData(){}; + + private: + unsigned int m_Index; + double m_Energy; + double m_Time; + G4ThreeVector m_Pos; + + public : // Modifier + inline void Set(const double& Energy, const double& Time, const unsigned int& Index, const G4ThreeVector& Pos){ + m_Energy=Energy; + m_Time=Time; + m_Index=Index; + m_Pos=Pos; + } + + inline void Add(const double& Energy) {m_Energy+=Energy;}; + + public: // Accessor + inline unsigned int GetIndex() const {return m_Index;}; + inline double GetEnergy() const {return m_Energy;}; + inline double GetTime() const {return m_Time;}; + inline G4ThreeVector GetPos() const {return m_Pos;}; + + }; + + // Manage a vector of Ge hit + class GeDataVector{ + public: + GeDataVector(){}; + ~GeDataVector(){}; + + private: + vector<GeData> m_Data; + + public: + vector<GeData>::iterator find(const unsigned int& index) ; + inline void clear(){m_Data.clear();} ; + inline vector<GeData>::iterator end() {return m_Data.end();}; + inline vector<GeData>::iterator begin() {return m_Data.begin();}; + inline unsigned int size() {return m_Data.size();}; + inline void Add(const unsigned int& index,const double& Energy) {find(index)->Add(Energy);}; + inline void Set(const double& Energy, const double& Time, const unsigned int& Index, const G4ThreeVector& Pos) {m_Data.push_back(GeData(Energy,Time,Index,Pos));}; + GeData* operator[](const unsigned int& i){return &m_Data[i];}; + }; + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class PS_GeDetector : public G4VPrimitiveScorer{ + + public: // with description + PS_GeDetector(G4String name,G4int level,G4int depth=0); + ~PS_GeDetector(); + + protected: // with description + G4bool ProcessHits(G4Step*, G4TouchableHistory*); + + public: + void Initialize(G4HCofThisEvent*); + void EndOfEvent(G4HCofThisEvent*); + void clear(); + void DrawAll(); + void PrintAll(); + + private: + // Level at which to find the copy number linked to the detector number + G4int m_Level; + G4int m_Depth; + + private: // inherited from G4VPrimitiveScorer + GeDataVector m_Hit; + + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + G4ThreeVector t_Position; + double t_Energy; + double t_Time; + unsigned int t_Index; + + public: // information accessor + inline unsigned int GetMult() {return m_Hit.size();}; + inline unsigned int GetIndex(const unsigned int& i){return m_Hit[i]->GetIndex();}; + inline double GetEnergy(const unsigned int& i){return m_Hit[i]->GetEnergy();}; + inline double GetTime(const unsigned int& i){return m_Hit[i]->GetTime();}; + inline G4ThreeVector GetPos(const unsigned int& i){return m_Hit[i]->GetPos();}; + }; +/* + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class PS_Images : public G4VPrimitiveScorer{ + + public: // with description + PS_Images(G4String name, string imageFront,string imageBack,double scalingFront, double scalingBack, double centerOffsetX,double centerOffsetY,unsigned int ignoreValue, G4int depth=0); + ~PS_Images(){}; + + protected: // with description + G4bool ProcessHits(G4Step*, G4TouchableHistory*); + + public: + void Initialize(G4HCofThisEvent*); + void EndOfEvent(G4HCofThisEvent*); + void clear(); + void DrawAll(){}; + void PrintAll(){}; + + private: // Geometry of the detector + NPL::Image* m_ImageFront; + NPL::Image* m_ImageBack; + double m_ScalingFront; + double m_ScalingBack; + double m_CenterOffsetX; + double m_CenterOffsetY; + unsigned int m_IgnoreValue; + + // Level at which to find the copy number linked to the detector number + G4int m_Level; + + private: // inherited from G4VPrimitiveScorer + GeDataVector m_HitFront; + GeDataVector m_HitBack; + + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + G4ThreeVector t_Position; + double t_Energy; + double t_Time; + unsigned int t_DetectorNbr; + unsigned int t_PixelFront; + unsigned int t_PixelBack; + + public: // information accessor + inline unsigned int GetFrontMult() {return m_HitFront.size();}; + inline unsigned int GetStripFront(const unsigned int& i){return m_HitFront[i]->GetStrip();}; + inline unsigned int GetDetectorFront(const unsigned int& i){return m_HitFront[i]->GetDetector();}; + inline double GetEnergyFront(const unsigned int& i){return m_HitFront[i]->GetEnergy();}; + inline double GetTimeFront(const unsigned int& i){return m_HitFront[i]->GetTime();}; + inline unsigned int GetBackMult() {return m_HitBack.size();}; + inline unsigned int GetStripBack(const unsigned int& i){return m_HitBack[i]->GetStrip();}; + inline unsigned int GetDetectorBack(const unsigned int& i){return m_HitBack[i]->GetDetector();}; + inline double GetEnergyBack(const unsigned int& i){return m_HitBack[i]->GetEnergy();}; + inline double GetTimeBack(const unsigned int& i){return m_HitBack[i]->GetTime();}; + + void GetARGBFront(unsigned int& i,unsigned int& a,unsigned int& r,unsigned int& g,unsigned int& b); + void GetARGBBack(unsigned int& i,unsigned int& a,unsigned int& r,unsigned int& g,unsigned int& b); + }; + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class PS_Rectangle : public G4VPrimitiveScorer{ + + public: // with description + PS_Rectangle(G4String name, G4int Level, G4double StripPlaneLength, G4double StripPlaneWidth, G4int NumberOfStripLength,G4int NumberOfStripWidth,G4int depth=0,G4String axis="xy"); + ~PS_Rectangle(); + + private: + enum psAxis{ps_xy,ps_yz,ps_xz}; + psAxis m_Axis; + + protected: // with description + G4bool ProcessHits(G4Step*, G4TouchableHistory*); + + public: + void Initialize(G4HCofThisEvent*); + void EndOfEvent(G4HCofThisEvent*); + void clear(); + void DrawAll(); + void PrintAll(); + + private: // Geometry of the detector + double m_StripPlaneLength; + double m_StripPlaneWidth; + unsigned int m_NumberOfStripLength; + unsigned int m_NumberOfStripWidth; + double m_StripPitchLength; + double m_StripPitchWidth; + // Level at which to find the copy number linked to the detector number + int m_Level; + + private: // inherited from G4VPrimitiveScorer + GeDataVector m_HitLength; + GeDataVector m_HitWidth; + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + G4ThreeVector t_Position; + double t_Energy; + double t_Time; + unsigned int t_DetectorNumber; + unsigned int t_StripLengthNumber; + unsigned int t_StripWidthNumber; + + public: + inline unsigned int GetLengthMult() {return m_HitLength.size();}; + inline unsigned int GetStripLength(const unsigned int& i){return m_HitLength[i]->GetStrip();}; + inline unsigned int GetDetectorLength(const unsigned int& i){return m_HitLength[i]->GetDetector();}; + inline double GetEnergyLength(const unsigned int& i){return m_HitLength[i]->GetEnergy();}; + inline double GetTimeLength(const unsigned int& i){return m_HitLength[i]->GetTime();}; + inline unsigned int GetWidthMult() {return m_HitWidth.size();}; + inline unsigned int GetStripWidth(const unsigned int& i){return m_HitWidth[i]->GetStrip();}; + inline unsigned int GetDetectorWidth(const unsigned int& i){return m_HitWidth[i]->GetDetector();}; + inline double GetEnergyWidth(const unsigned int& i){return m_HitWidth[i]->GetEnergy();}; + inline double GetTimeWidth(const unsigned int& i){return m_HitWidth[i]->GetTime();}; + + + public: + static unsigned int CalculateIndex(const unsigned int& Strip,const unsigned int& Detector) {return Detector*1e6+Strip;} + + + }; + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class PS_Annular : public G4VPrimitiveScorer{ + + public: // with description + PS_Annular(G4String name,G4int Level, G4double StripPlaneInnerRadius, G4double StripPlaneOuterRadius, G4double PhiStart,G4double PhiStop, G4int NumberOfStripRing,G4int NumberOfStripSector=1, G4int NumberOfQuadrant=1,G4int depth=0); + ~PS_Annular(); + + protected: // with description + G4bool ProcessHits(G4Step*, G4TouchableHistory*); + + public: + void Initialize(G4HCofThisEvent*); + void EndOfEvent(G4HCofThisEvent*); + void clear(); + void DrawAll(); + void PrintAll(); + + private: // Geometry of the detector + double m_StripPlaneInnerRadius; + double m_StripPlaneOuterRadius; + double m_PhiStart; + double m_PhiStop; + unsigned int m_NumberOfStripRing; + unsigned int m_NumberOfStripSector; + unsigned int m_NumberOfStripQuadrant; + double m_StripPitchRing; + double m_StripPitchSector; + double m_StripPitchQuadrant; + string m_Axis; + // Level at which to find the copy number linked to the detector number + int m_Level; + + + private: // inherited from G4VPrimitiveScorer + GeDataVector m_HitRing; + GeDataVector m_HitSector; + GeDataVector m_HitQuadrant; + + + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + G4ThreeVector t_Position; + double t_Energy; + double t_Time; + unsigned int t_DetectorNumber; + unsigned int t_StripRingNumber; + unsigned int t_StripSectorNumber; + unsigned int t_StripQuadrantNumber; + + public: + inline unsigned int GetRingMult() {return m_HitRing.size();}; + inline unsigned int GetStripRing(const unsigned int& i){return m_HitRing[i]->GetStrip();}; + inline unsigned int GetDetectorRing(const unsigned int& i){return m_HitRing[i]->GetDetector();}; + inline double GetEnergyRing(const unsigned int& i){return m_HitRing[i]->GetEnergy();}; + inline double GetTimeRing(const unsigned int& i){return m_HitRing[i]->GetTime();}; + inline unsigned int GetSectorMult() {return m_HitSector.size();}; + inline unsigned int GetStripSector(const unsigned int& i){return m_HitSector[i]->GetStrip();}; + inline unsigned int GetDetectorSector(const unsigned int& i){return m_HitSector[i]->GetDetector();}; + inline double GetEnergySector(const unsigned int& i){return m_HitSector[i]->GetEnergy();}; + inline double GetTimeSector(const unsigned int& i){return m_HitSector[i]->GetTime();}; + inline unsigned int GetQuadrantMult() {return m_HitQuadrant.size();}; + inline unsigned int GetStripQuadrant(const unsigned int& i){return m_HitQuadrant[i]->GetStrip();}; + inline unsigned int GetDetectorQuadrant(const unsigned int& i){return m_HitQuadrant[i]->GetDetector();}; + inline double GetEnergyQuadrant(const unsigned int& i){return m_HitQuadrant[i]->GetEnergy();}; + inline double GetTimeQuadrant(const unsigned int& i){return m_HitQuadrant[i]->GetTime();}; + + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + G4ThreeVector m_uz ; + + public: + static unsigned int CalculateIndex(const unsigned int& Strip,const unsigned int& Detector) {return Detector*1e6+Strip;} + + + }; + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class PS_Resistive : public G4VPrimitiveScorer{ + + public: // with description + PS_Resistive(G4String name, G4int Level, + G4double StripPlaneLength, G4double StripPlaneWidth, + G4int NumberOfStripWidth,G4int depth=0); + + ~PS_Resistive(); + + protected: // with description + G4bool ProcessHits(G4Step*, G4TouchableHistory*); + + public: + void Initialize(G4HCofThisEvent*); + void EndOfEvent(G4HCofThisEvent*); + void clear(); + void DrawAll(); + void PrintAll(); + + private: // Geometry of the detector + double m_StripPlaneLength; + double m_StripPlaneWidth; + unsigned int m_NumberOfStripWidth; + double m_StripPitchWidth; + // Level at which to find the copy number linked to the detector number + G4int m_Level; + + private: + // Up and Down are each extremities of the resistive strip + GeDataVector m_HitUp; + GeDataVector m_HitDown; + GeDataVector m_HitBack; + + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + G4ThreeVector t_Position; + double t_Energy; + double t_EnergyUp; + double t_EnergyDown; + double t_Time; + unsigned int t_DetectorNumber; + unsigned int t_StripWidthNumber; + public: + inline unsigned int GetUpMult() {return m_HitUp.size();}; + inline unsigned int GetStripUp(const unsigned int& i){return m_HitUp[i]->GetStrip();}; + inline unsigned int GetDetectorUp(const unsigned int& i){return m_HitUp[i]->GetDetector();}; + inline double GetEnergyUp(const unsigned int& i){return m_HitUp[i]->GetEnergy();}; + inline double GetTimeUp(const unsigned int& i){return m_HitUp[i]->GetTime();}; + inline unsigned int GetDownMult() {return m_HitDown.size();}; + inline unsigned int GetStripDown(const unsigned int& i){return m_HitDown[i]->GetStrip();}; + inline unsigned int GetDetectorDown(const unsigned int& i){return m_HitDown[i]->GetDetector();}; + inline double GetEnergyDown(const unsigned int& i){return m_HitDown[i]->GetEnergy();}; + inline double GetTimeDown(const unsigned int& i){return m_HitDown[i]->GetTime();}; + inline unsigned int GetBackMult() {return m_HitBack.size();}; + inline unsigned int GetStripBack(const unsigned int& i){return m_HitBack[i]->GetStrip();}; + inline unsigned int GetDetectorBack(const unsigned int& i){return m_HitBack[i]->GetDetector();}; + inline double GetEnergyBack(const unsigned int& i){return m_HitBack[i]->GetEnergy();}; + inline double GetTimeBack(const unsigned int& i){return m_HitBack[i]->GetTime();}; + + + }; +*/ +} + + +#endif diff --git a/Projects/Hicari/152Eu.beam b/Projects/Hicari/152Eu.beam new file mode 100644 index 000000000..c38928d33 --- /dev/null +++ b/Projects/Hicari/152Eu.beam @@ -0,0 +1,16 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%% 152Eu sourc test reaction %%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Beam + Particle= 152Eu + Energy= 0 + SigmaEnergy= 0 + SigmaThetaX= 0 + SigmaPhiY= 0 + SigmaX= 0 + SigmaY= 0 + MeanThetaX= 0 + MeanPhiY= 0 + MeanX= 0 + MeanY= 0 + ZEmission= 0 diff --git a/Projects/Hicari/Exogam.detector b/Projects/Hicari/Exogam.detector new file mode 100644 index 000000000..cd97e98e9 --- /dev/null +++ b/Projects/Hicari/Exogam.detector @@ -0,0 +1,16 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% EXOGAM setup with one clover +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Exogam clover +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Exogam + X= 0 mm + Y= 0 mm + Z= 20 mm + ThetaX= 0 deg + ThetaY= 0 deg + ThetaZ= 0 deg +% \ No newline at end of file diff --git a/Projects/Hicari/HiCARI.detector b/Projects/Hicari/HiCARI.detector new file mode 100644 index 000000000..c7d184deb --- /dev/null +++ b/Projects/Hicari/HiCARI.detector @@ -0,0 +1,19 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% HICARI test +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Target +% THICKNESS= 1 mm +% RADIUS= 10 mm +% MATERIAL= Vacuum +% ANGLE= 0 deg +% X= 0 mm +% Y= 0 mm +% Z= 0 mm +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +Hicari + asolid= ./geometry/fall2020/solid.list + aclust= ./geometry/fall2020/clust.list + aeuler= ./geometry/fall2020/euler.list + awalls= ./geometry/fall2020/walls.list + aslice= ./geometry/fall2020/slice.list + diff --git a/Projects/Hicari/PhysicsListOption.txt b/Projects/Hicari/PhysicsListOption.txt new file mode 100644 index 000000000..969318113 --- /dev/null +++ b/Projects/Hicari/PhysicsListOption.txt @@ -0,0 +1,11 @@ +EmPhysicsList Option4 +IonBinaryCascadePhysics 0 +DriftElectronPhysics 0 +NPIonInelasticPhysics 0 +EmExtraPhysics 0 +HadronElasticPhysics 0 +StoppingPhysics 0 +OpticalPhysics 0 +HadronPhysicsINCLXX 0 +HadronPhysicsQGSP_BIC_HP 0 +Decay 1 diff --git a/Projects/Hicari/crystalangles.dat b/Projects/Hicari/crystalangles.dat new file mode 100644 index 000000000..032a4784b --- /dev/null +++ b/Projects/Hicari/crystalangles.dat @@ -0,0 +1,41 @@ + Riv# 800 Theta= 34.3392 Phi= 244.3816 + Riv# 801 Theta= 49.3708 Phi= 249.7292 + Riv# 802 Theta= 46.3482 Phi= 229.2142 + Riv# 804 Theta= 45.2846 Phi= 311.6648 + Riv# 805 Theta= 48.3844 Phi= 290.6179 + Riv# 806 Theta= 33.2035 Phi= 296.0157 + Riv# 808 Theta= 25.9279 Phi= 198.4469 + Riv# 809 Theta= 37.5550 Phi= 179.8505 + Riv# 810 Theta= 25.1099 Phi= 163.1138 + Riv# 812 Theta= 36.5876 Phi= 0.6486 + Riv# 813 Theta= 25.0807 Phi= 341.3320 + Riv# 814 Theta= 24.1489 Phi= 17.8283 + Riv# 816 Theta= 33.8606 Phi= 116.9087 + Riv# 817 Theta= 45.9653 Phi= 131.5646 + Riv# 818 Theta= 48.6324 Phi= 111.0129 + Riv# 820 Theta= 33.9715 Phi= 66.1928 + Riv# 821 Theta= 49.0845 Phi= 68.3968 + Riv# 822 Theta= 44.3397 Phi= 48.4692 + Riv# 824 Theta= 81.4843 Phi= 219.3262 + Riv# 825 Theta= 69.8261 Phi= 217.6122 + Riv# 826 Theta= 68.4417 Phi= 230.0746 + Riv# 827 Theta= 80.1267 Phi= 231.1931 + Riv# 828 Theta= 65.7011 Phi= 326.2873 + Riv# 829 Theta= 77.1878 Phi= 329.3560 + Riv# 830 Theta= 80.3768 Phi= 317.6713 + Riv# 831 Theta= 69.0293 Phi= 313.9599 + Riv# 832 Theta= 65.4149 Phi= 144.9694 + Riv# 833 Theta= 77.1333 Phi= 143.1873 + Riv# 834 Theta= 75.6912 Phi= 130.7417 + Riv# 835 Theta= 63.9172 Phi= 132.0251 + Riv# 836 Theta= 71.4937 Phi= 29.1339 + Riv# 837 Theta= 58.6599 Phi= 32.7391 + Riv# 838 Theta= 62.2538 Phi= 47.4059 + Riv# 839 Theta= 75.0749 Phi= 43.0499 + Riv# 40 Theta= 59.2335 Phi= 179.9337 + Riv# 41 Theta= 70.4317 Phi= 158.6643 + Riv# 42 Theta= 81.5749 Phi= 177.6364 + Riv# 43 Theta= 72.5485 Phi= 198.4877 + Riv# 44 Theta= 58.2075 Phi= 13.2036 + Riv# 45 Theta= 72.1975 Phi= 350.7307 + Riv# 46 Theta= 82.9589 Phi= 12.5534 diff --git a/Projects/Hicari/crystalpositions.dat b/Projects/Hicari/crystalpositions.dat new file mode 100644 index 000000000..dca1d3b23 --- /dev/null +++ b/Projects/Hicari/crystalpositions.dat @@ -0,0 +1,164 @@ + 800 0 -56.85428 -118.56635 192.47843 + 1 0.55102 -0.77826 -0.30115 + 2 0.55510 0.61129 -0.56409 + 3 0.62310 0.14366 0.76884 + 801 0 -61.11055 -165.46242 151.33758 + 1 0.43343 0.84633 -0.30963 + 2 -0.74055 0.13870 -0.65753 + 3 -0.51354 0.51428 0.68687 + 802 0 -109.77479 -127.23906 160.32054 + 1 -0.91107 -0.06807 -0.40659 + 2 0.31549 -0.74998 -0.58137 + 3 -0.26536 -0.65794 0.70476 + 804 0 108.96202 -122.44758 162.28865 + 1 0.91395 -0.07665 0.39852 + 2 0.31784 0.74576 -0.58551 + 3 -0.25232 0.66179 0.70595 + 805 0 60.44177 -160.65008 152.47637 + 1 -0.42657 0.85260 0.30184 + 2 -0.73762 -0.13481 -0.66163 + 3 -0.52341 -0.50487 0.68640 + 806 0 55.64915 -114.01814 193.85776 + 1 -0.55898 -0.77596 0.29229 + 2 0.55073 -0.61095 -0.56871 + 3 0.61987 -0.15692 0.76885 + 808 0 -99.07704 -33.04866 214.82679 + 1 0.43764 0.76534 -0.47195 + 2 -0.88309 0.46461 -0.06546 + 3 0.16917 0.44542 0.87919 + 809 0 -144.80434 0.37784 188.33888 + 1 -0.82572 -0.03404 -0.56306 + 2 0.04042 -0.99918 0.00114 + 3 -0.56264 -0.02181 0.82642 + 810 0 -96.94836 29.42961 216.19073 + 1 0.49645 -0.73129 -0.46770 + 2 0.84306 0.53457 0.05903 + 3 0.20685 -0.42361 0.88191 + 812 0 141.72125 1.60433 190.92638 + 1 0.83164 -0.04753 0.55328 + 2 0.05252 0.99860 0.00685 + 3 -0.55283 0.02336 0.83297 + 813 0 96.13401 -32.47981 216.81075 + 1 -0.42785 0.77659 0.46245 + 2 -0.88916 -0.45351 -0.06106 + 3 0.16230 -0.43732 0.88454 + 814 0 93.16180 29.96183 218.27154 + 1 -0.50997 -0.72905 0.45653 + 2 0.83598 -0.54509 0.06335 + 3 0.20266 0.41396 0.88745 + 816 0 -59.48765 117.21257 195.90058 + 1 0.54340 0.78078 -0.30838 + 2 -0.56338 0.61152 0.55556 + 3 0.62235 -0.12815 0.77218 + 817 0 -112.04723 126.35881 163.28520 + 1 -0.90872 0.05978 -0.41310 + 2 -0.31069 -0.75779 0.57378 + 3 -0.27875 0.64975 0.70719 + 818 0 -63.22537 164.59671 155.27179 + 1 0.44013 -0.84056 -0.31583 + 2 0.74575 0.14627 0.64997 + 3 -0.50014 -0.52160 0.69122 + 820 0 53.51153 121.28569 196.74792 + 1 -0.65174 0.70093 0.28971 + 2 -0.47487 -0.67496 0.56474 + 3 0.59139 0.23049 0.77274 + 821 0 65.67005 165.83657 154.58970 + 1 -0.31582 -0.89538 0.31393 + 2 0.75599 -0.03752 0.65351 + 3 -0.57336 0.44372 0.68874 + 822 0 109.49898 123.63192 169.00217 + 1 0.89509 0.19444 0.40126 + 2 -0.41005 0.71248 0.56942 + 3 -0.17517 -0.67421 0.71746 + 824 0 -195.49713 -160.16206 37.84102 + 1 -0.70658 -0.08326 -0.70272 + 2 0.69797 -0.24557 -0.67271 + 3 -0.11655 -0.96580 0.23163 + 825 0 -191.11746 -147.24499 88.64188 + 1 0.08326 -0.70658 -0.70272 + 2 0.24557 0.69797 -0.67271 + 3 0.96580 -0.11655 0.23163 + 826 0 -153.95123 -183.95799 94.77266 + 1 0.70658 0.08326 -0.70272 + 2 -0.69797 0.24557 -0.67271 + 3 0.11655 0.96580 0.23163 + 827 0 -158.33090 -196.87507 43.97180 + 1 -0.08326 0.70658 -0.70272 + 2 -0.24557 -0.69797 -0.67271 + 3 -0.96580 0.11655 0.23163 + 828 0 193.52790 -129.12885 105.04145 + 1 0.54648 -0.37668 0.74798 + 2 0.79369 -0.05205 -0.60609 + 3 0.26723 0.92488 0.27052 + 829 0 213.34112 -126.39091 56.39270 + 1 0.37668 0.54648 0.74798 + 2 0.05205 0.79369 -0.60609 + 3 -0.92488 0.26723 0.27052 + 830 0 184.59624 -168.13904 42.33618 + 1 -0.54648 0.37668 0.74798 + 2 -0.79369 0.05205 -0.60609 + 3 -0.26723 -0.92488 0.27052 + 831 0 164.78303 -170.87697 90.98492 + 1 -0.37668 -0.54648 0.74798 + 2 -0.05205 -0.79369 -0.60609 + 3 0.92488 -0.26723 0.27052 + 832 0 -190.64776 133.64461 106.52229 + 1 -0.69680 0.05297 -0.71530 + 2 -0.70788 -0.21159 0.67390 + 3 -0.11565 0.97592 0.18493 + 833 0 -193.43420 144.77406 55.18876 + 1 -0.05297 -0.69680 -0.71530 + 2 0.21159 -0.70788 0.67390 + 3 -0.97592 -0.11565 0.18493 + 834 0 -156.78241 182.00847 61.27193 + 1 0.69680 -0.05297 -0.71530 + 2 0.70788 0.21159 0.67390 + 3 0.11565 -0.97592 0.18493 + 835 0 -153.99597 170.87902 112.60546 + 1 0.05297 0.69680 -0.71530 + 2 -0.21159 0.70788 0.67390 + 3 0.97592 0.11565 0.18493 + 836 0 182.45600 101.69516 69.91678 + 1 0.55949 0.33705 0.75721 + 2 -0.78429 -0.08017 0.61519 + 3 0.26805 -0.93807 0.21949 + 837 0 164.72743 105.91203 119.25921 + 1 -0.33705 0.55949 0.75721 + 2 0.08017 -0.78429 0.61519 + 3 0.93807 0.26805 0.21949 + 838 0 135.29803 147.16582 105.15973 + 1 -0.55949 -0.33705 0.75721 + 2 0.78429 0.08017 0.61519 + 3 -0.26805 0.93807 0.21949 + 839 0 153.02660 142.94895 55.81730 + 1 0.33705 -0.55949 0.75721 + 2 -0.08017 0.78429 0.61519 + 3 -0.93807 -0.26805 0.21949 + 40 0 -137.85360 0.15942 82.06820 + 1 0.27783 -0.40231 -0.87233 + 2 0.82661 0.56276 0.00373 + 3 0.48941 -0.72211 0.48891 + 41 0 -141.46769 55.25763 53.98610 + 1 -0.43775 0.11381 -0.89186 + 2 -0.76302 -0.57172 0.30155 + 3 -0.47558 0.81252 0.33711 + 42 0 -158.56703 6.54511 23.50611 + 1 -0.12733 0.12229 -0.98429 + 2 -0.83002 -0.55643 0.03824 + 3 -0.54301 0.82185 0.17236 + 43 0 -145.83036 -48.75933 48.33905 + 1 -0.00775 -0.40237 -0.91545 + 2 0.77309 0.57824 -0.26070 + 3 0.63425 -0.70974 0.30659 + 44 0 120.48771 28.26806 76.71167 + 1 -0.07753 0.50578 0.85917 + 2 -0.90448 -0.39822 0.15280 + 3 0.41942 -0.76525 0.48834 + 45 0 135.86329 -22.17374 44.20482 + 1 0.24784 -0.22511 0.94228 + 2 0.87748 0.46439 -0.11986 + 3 -0.41060 0.85655 0.31262 + 46 0 141.11306 31.42204 17.85602 + 1 -0.07079 -0.22979 0.97066 + 2 0.87832 0.44688 0.16985 + 3 -0.47280 0.86458 0.17020 diff --git a/Projects/Hicari/geometry/fall2020/clust.list b/Projects/Hicari/geometry/fall2020/clust.list new file mode 100644 index 000000000..b8b28870e --- /dev/null +++ b/Projects/Hicari/geometry/fall2020/clust.list @@ -0,0 +1,30 @@ +# Euler angles (degree) and shifts (mm) for clusters +# cl cr cr# psi(Rx) theta(Ry) phi(Rz) dx dy dz +# GRETINA Quad + 0 1 0 61.745083 9.71628188639 -75.4362897191 7.85106014643 -30.2191365671 182.346272251 + 0 0 1 147.068200 16.3669293026 16.7040485896 49.9309226799 14.9838405296 177.503206324 + 0 1 2 61.745083 9.71628080091 104.563712815 -7.85106043878 30.2191322001 182.346268763 + 0 0 3 147.068200 16.3669295272 -163.295955915 -49.9309223876 -14.9838361627 177.503198524 +# +# +# GRETINA Triple + 1 1 0 61.745083 9.71628188639 -75.4362897191 7.85106014643 -30.2191365671 182.346272251 + 1 0 1 147.068200 16.3669293026 16.7040485896 49.9309226799 14.9838405296 177.503206324 + 1 1 2 61.745083 9.71628080091 104.563712815 -7.85106043878 30.2191322001 182.346268763 +# +# AGATA Triple + 2 2 0 -179.728796 9.424198 -2.941715 34.927900 -1.628323 -44.096715 + 2 3 1 177.231534 9.424198 115.416685 -13.861478 32.994962 -44.227057 + 2 4 2 -178.705246 9.424198 -120.418975 -17.286848 -30.890029 -44.167278 +# +# Miniball Triple + 3 5 0 0.0000000 4.125000 0.000000 36.101367 0.000000 0.0000000 + 3 5 1 0.0000000 4.125000 240.000000 -18.050683 -31.264701 0.0000000 + 3 5 2 0.0000000 4.125000 120.000000 -18.050683 31.264701 0.0000000 +# +# Clover IMP + 4 6 0 0.0000000 0.000000 270.000000 26.300000 -26.300000 0.0000000 + 4 6 1 0.0000000 0.000000 180.000000 -26.300000 -26.300000 0.0000000 + 4 6 2 0.0000000 0.000000 90.000000 -26.300000 26.300000 0.0000000 + 4 6 3 0.0000000 0.000000 0.000000 26.300000 26.300000 0.0000000 + diff --git a/Projects/Hicari/geometry/fall2020/euler.list b/Projects/Hicari/geometry/fall2020/euler.list new file mode 100644 index 000000000..315b56237 --- /dev/null +++ b/Projects/Hicari/geometry/fall2020/euler.list @@ -0,0 +1,21 @@ +#Configuration as setup March 2020 +# Euler angles (degrees) and shifts (mm) of clusters +# cl cl# psi (Rz) theta (Ry) phi (Rz) dx dy dz +## MB forward arm +## Jiseok 2021/09/01 +## MB forward arm + 200 3 168.0158466 43.77796415 -119.4343906 -75.91321113 -137.0892744 168.0455129 + 201 3 73.11435182 43.75758184 -61.33642759 75.01764585 -132.371934 169.5409306 + 202 3 117.5106493 30.14612846 -179.7983502 -113.6099144 -1.08040217 206.4521382 + 203 3 2.721400853 29.47456402 0.3555923069 110.339021 -0.3045474769 208.6695592 + 204 3 190.7302043 43.4971038 120.2414692 -78.25342139 136.0560364 171.4858571 + 205 3 160.3480597 43.26407512 60.65824166 76.22685339 136.918055 173.446588 +##### SC middle arm + 206 4 6.881322786 76.60682864 -136.249746 -174.7241806 -172.0600231 66.30683724 + 207 4 196.1160688 74.30480677 -39.01797391 189.0620714 -148.6339428 73.68881069 + 208 4 173.2418041 79.34276541 136.7072222 -173.715085 157.8265356 83.89710924 + 209 4 -15.94716279 77.3210333 39.09187162 158.8770134 124.4304891 87.53825147 +##### RCNP middle arm + 10 0 250 70.4005 178.705 23.527 -0.53 -8.3797 +##### LBNL middle arm + 11 1 -105 70.4846 10 -38.4593 0 -13.6308 diff --git a/Projects/Hicari/geometry/fall2020/slice.list b/Projects/Hicari/geometry/fall2020/slice.list new file mode 100644 index 000000000..1977c3d8d --- /dev/null +++ b/Projects/Hicari/geometry/fall2020/slice.list @@ -0,0 +1,37 @@ +############ Segmentation ################ +## format: +## 0 --> all solids the same number of slices +## nSlices +######################################### +## alt. format: +## 1 --> keep reading! +## nsolid zNext(inner) [zNext(outer)] +###################################### + 1 + 0 8.0 + 0 14.0 + 0 16.0 + 0 18.0 + 0 20.0 + 1 8.0 + 1 14.0 + 1 16.0 + 1 18.0 + 1 20.0 + 2 20.50 8.00 + 2 7.50 13.00 + 2 15.50 15.00 + 2 15.50 18.00 + 2 15.50 18.00 + 3 20.50 8.00 + 3 7.50 13.00 + 3 15.50 15.00 + 3 15.50 18.00 + 3 15.50 18.00 + 4 20.50 8.00 + 4 7.50 13.00 + 4 15.50 15.00 + 4 15.50 18.00 + 4 15.50 18.00 +# 6 31.0 31.00 +########################### diff --git a/Projects/Hicari/geometry/fall2020/solid.list b/Projects/Hicari/geometry/fall2020/solid.list new file mode 100644 index 000000000..ae8265203 --- /dev/null +++ b/Projects/Hicari/geometry/fall2020/solid.list @@ -0,0 +1,96 @@ +# First, GRETINA and AGATA crystals +# Cylinder centered on z-axis and front face on z=0 +# cr #s p# x,y,z of front (inner) face x,y,z of back (outer) face +# +# solid 0 - GRETINA Type A + 0 6 0 -26.601460 14.309190 0.000000 -41.812290 22.456740 90.000000 + 0 6 1 0.873900 33.434270 0.000000 -0.370500 51.303560 90.000000 + 0 6 2 29.035060 18.806490 0.000000 43.813450 28.353050 90.000000 + 0 6 3 29.035060 -16.720150 0.000000 43.813450 -27.057040 90.000000 + 0 6 4 -2.106240 -31.359840 0.000000 -3.350650 -49.229140 90.000000 + 0 6 5 -26.601460 -14.309190 0.000000 -41.812290 -22.456740 90.000000 + 0 0 0 5.000000 40.000000 90.000000 0.000000 0.000000 0.000000 + 0 0 1 15.000000 1.500000 3.500000 0.500000 0.800000 1.300000 + 0 0 2 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# end solid 0 +# +# solid 1 - GRETINA Type B + 1 6 0 -29.035060 18.819560 0.000000 -43.813450 28.366120 90.000000 + 1 6 1 0.326440 34.622460 0.000000 0.497910 52.215310 90.000000 + 1 6 2 27.760980 18.624430 0.000000 43.529680 27.121990 90.000000 + 1 6 3 27.246880 -16.340780 0.000000 42.755280 -25.546310 90.000000 + 1 6 4 1.233470 -33.020040 0.000000 1.932060 -51.721310 90.000000 + 1 6 5 -29.035060 -16.661720 0.000000 -43.813450 -26.998620 90.000000 + 1 0 0 5.000000 40.000000 90.000000 0.000000 0.000000 0.000000 + 1 0 1 15.000000 1.500000 3.500000 0.500000 0.800000 1.300000 + 1 0 2 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 +# end solid 1 +# +# solid 2 - AGATA Type A + 2 6 0 33.906177 -0.000000 0.000000 48.844467 -0.070710 90.00000 + 2 6 1 15.358631 30.461479 0.000000 22.153453 43.765160 90.00000 + 2 6 2 -20.780862 27.320467 0.000000 -28.562085 39.357292 90.00000 + 2 6 3 -33.865099 -3.186191 0.000000 -47.398084 -4.559934 90.00000 + 2 6 4 -20.861304 -27.597830 0.000000 -28.566730 -39.911479 90.00000 + 2 6 5 15.586726 -29.970097 0.000000 22.461355 -43.232708 90.00000 + 2 0 0 5.000000 40.000000 90.000000 0.000000 0.000000 0.000000 + 2 0 1 13.000000 1.000000 0.600000 0.400000 0.800000 1.300000 + 2 0 2 1.000000 0.000000 0.000000 0.000000 0.000000 0.000000 +# end solid 2 +# +# solid 3 - AGATA Type B + 3 6 0 34.768773 0.000000 0.000000 49.689796 0.721528 90.00000 + 3 6 1 15.189995 29.100143 0.000000 21.480233 42.649698 90.00000 + 3 6 2 -21.610036 27.946520 0.000000 -29.959278 41.037150 90.00000 + 3 6 3 -34.515980 1.715443 0.000000 -48.660064 3.028171 90.00000 + 3 6 4 -17.845056 -29.899266 0.000000 -24.681675 -42.444404 90.00000 + 3 6 5 21.121422 -28.647387 0.000000 29.962271 -40.688852 90.00000 + 3 0 0 5.000000 40.000000 90.000000 0.000000 0.000000 0.000000 + 3 0 1 13.000000 1.000000 0.600000 0.400000 0.800000 1.300000 + 3 0 2 0.000000 1.000000 0.000000 0.000000 0.000000 0.000000 +# end solid 3 +# +# solid 4 - AGATA Type C + 4 6 0 34.368758 0.000000 0.000000 49.844467 -0.337546 90.00000 + 4 6 1 20.008679 28.248525 0.000000 28.153453 40.513380 90.00000 + 4 6 2 -16.582470 29.653241 0.000000 -22.562085 42.479888 90.00000 + 4 6 3 -33.870627 1.539298 0.000000 -47.398084 1.903863 90.00000 + 4 6 4 -17.834223 -30.216677 0.000000 -24.566730 -43.851923 90.00000 + 4 6 5 15.063353 -29.838670 0.000000 21.461355 -43.323070 90.00000 + 4 0 0 5.000000 40.000000 90.000000 0.000000 0.000000 0.000000 + 4 0 1 13.000000 1.000000 0.600000 0.400000 0.800000 1.300000 + 4 0 2 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 +# end solid 4 +# +# solid 5 - MiniBall crystal (modified KW according to spec sheet) + 5 6 0 34.000000 0.000000 0.000000 39.625319 0.000000 78.00000 + 5 6 1 17.000000 29.444864 0.000000 19.812660 34.316533 78.00000 + 5 6 2 -17.000000 29.444864 0.000000 -19.812660 34.316533 78.00000 + 5 6 3 -34.000000 0.000000 0.000000 -39.625319 0.000000 78.00000 + 5 6 4 -17.000000 -29.444864 0.000000 -19.812660 -34.316533 78.00000 + 5 6 5 17.000000 -29.444864 0.000000 19.812660 -34.316533 78.00000 + 5 0 0 5.000000 35.000000 78.000000 0.000000 0.000000 0.000000 + 5 0 1 15.000000 1.000000 0.600000 0.700000 0.700000 1.500000 + 5 0 2 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 +# end solid 5 +# +# solid 6 - Clover crystal (IMP, updated@Aug27,2021,zqchen) + 6 4 0 -26.000000 -26.00000 0.000000 -26.000000 -26.000000 90.00000 + 6 4 1 16.073600 -26.00000 0.000000 53.352800 -26.000000 90.00000 + 6 4 2 16.073600 16.07360 0.000000 53.352800 53.352800 90.00000 + 6 4 3 -26.000000 16.07360 0.000000 -26.000000 53.352800 90.00000 + 6 0 0 5.000000 30.000000 90.000000 0.000000 0.000000 0.000000 + 6 0 1 15.000000 1.000000 0.600000 0.100000 0.300000 0.500000 + 6 0 2 0.000000 255.00000 255.000000 0.000000 0.000000 0.000000 +# end solid 6 +# +##Shape# nSides Point# x y z x' y' z' +##Shape# 0 0 holeR cylR cylL cylX cylY cylZ +##Shape# 0 1 holeL thickB thickC capS capT capS+capT+tol +##Shape# 0 2 colX colY colZ 0. 0. 0. +## +## Where the cylinder has radius cylR and length cylL and is intersected with the polyhedron through a traslation (cylX cylY cylZ); +## the coaxial hole has a radius holeR and is (cylL-holeL) long. The passivated areas are thickB (back) and thickC (coaxial) thick. +## The crystal-encapsulation spacing is capS and the capsule is capT thick; tol is a mechanical tolerance. +## The RGB color components for visualization are (colX colY colZ). + diff --git a/Projects/Hicari/geometry/fall2020/walls.list b/Projects/Hicari/geometry/fall2020/walls.list new file mode 100644 index 000000000..53d4543fb --- /dev/null +++ b/Projects/Hicari/geometry/fall2020/walls.list @@ -0,0 +1,385 @@ +# External walls (canister) of the cluster (in the cluster reference frame) +# cl# cr# w# cf np p# + 0 0 0 0 6 0 -73.607477 8.602324 168.560938 -74.029073 8.453634 169.993144 + 0 0 0 0 6 1 -42.316656 20.291093 178.349618 -42.460848 20.262813 179.870023 + 0 0 0 0 6 2 -16.561390 -4.210078 183.526216 -16.698626 -4.225321 185.049678 + 0 0 0 0 6 3 -26.041921 -42.369140 177.638206 -26.169880 -42.421770 178.982273 + 0 0 0 0 6 4 -60.229975 -47.920740 167.552609 -60.658451 -48.028924 168.986301 + 0 0 0 0 6 5 -81.045414 -21.865762 163.896729 -81.450259 -21.987252 165.335944 + 0 1 1 0 6 0 -16.457548 -4.254679 183.536167 -16.595392 -4.281997 185.059405 + 0 1 1 0 6 1 16.557569 4.288707 183.530516 16.724985 4.322168 185.050684 + 0 1 1 0 6 2 42.320146 -20.297903 178.346698 42.455628 -20.267841 179.867675 + 0 1 1 0 6 3 32.840678 -54.709219 173.052067 32.880322 -54.973692 174.528361 + 0 1 1 0 6 4 0.516619 -65.741109 172.615560 0.607613 -65.988478 174.092477 + 0 1 1 0 6 5 -26.056820 -42.378490 177.631446 -26.191289 -42.445897 179.147895 + 0 2 2 0 6 0 16.467731 4.264049 183.535053 16.615361 4.300513 185.057196 + 0 2 2 0 6 1 -16.542914 -4.293299 183.531909 -16.696173 -4.331330 185.053442 + 0 2 2 0 6 2 -42.320781 20.297253 178.346780 -42.456873 20.266568 179.867834 + 0 2 2 0 6 3 -32.840673 54.709222 173.052067 -32.880317 54.973697 174.528361 + 0 2 2 0 6 4 -0.516615 65.741112 172.615559 -0.607607 65.988480 174.092477 + 0 2 2 0 6 5 26.055948 42.378695 177.631373 26.189582 42.446301 179.147753 + 0 3 3 0 6 0 73.941718 -7.936540 168.410715 74.352583 -7.799676 169.846939 + 0 3 3 0 6 1 42.316654 -20.291099 178.349619 42.460845 -20.262819 179.870024 + 0 3 3 0 6 2 16.561385 4.210075 183.526218 16.698620 4.225319 185.049678 + 0 3 3 0 6 3 26.041916 42.369137 177.638206 26.190963 42.446721 179.153083 + 0 3 3 0 6 4 60.229970 47.920738 167.552613 60.658447 48.028921 168.986303 + 0 3 3 0 6 5 81.045408 21.865758 163.896731 81.450253 21.987249 165.335947 + 0 0 4 0 4 0 -109.932028 12.628260 256.757122 -111.164386 13.801139 256.509474 + 0 0 4 0 4 1 -62.956916 29.580006 271.402002 -64.216353 30.743114 271.145911 + 0 0 4 0 4 2 -41.205703 19.104367 180.187650 -42.465138 20.267474 179.931558 + 0 0 4 0 4 3 -72.386170 7.851682 170.463181 -73.618527 9.024561 170.215532 + 0 0 5 0 4 0 -121.395917 -33.095684 249.672615 -123.006687 -33.451059 249.189513 + 0 0 5 0 4 1 -109.934527 12.624990 256.756143 -111.160564 13.804359 256.510820 + 0 0 5 0 4 2 -72.388666 7.848423 170.462204 -73.614704 9.027792 170.216881 + 0 0 5 0 4 3 -79.821016 -21.799995 165.868759 -81.431788 -22.155370 165.385657 + 0 0 6 0 4 0 -90.154236 -71.426794 255.225073 -90.712617 -73.067204 254.929529 + 0 0 6 0 4 1 -121.395285 -33.099863 249.672440 -123.008486 -33.446206 249.189417 + 0 0 6 0 4 2 -79.820383 -21.804164 165.868586 -81.433583 -22.150507 165.385563 + 0 0 6 0 4 3 -59.566821 -46.653865 169.471796 -60.125202 -48.294275 169.176251 + 0 0 7 0 4 0 -39.107601 -62.636329 270.326326 -39.563483 -64.258889 270.061121 + 0 0 7 0 4 1 -90.148148 -71.429716 255.226539 -90.708090 -73.070210 254.930549 + 0 0 7 0 4 2 -59.560722 -46.656791 169.473265 -60.120675 -48.297280 169.177272 + 0 0 7 0 4 3 -25.743647 -40.830830 179.478356 -26.199519 -42.453394 179.213153 + 0 1 8 0 4 0 0.480556 -97.942898 262.749964 0.120512 -99.654809 262.481761 + 0 1 8 0 4 1 -39.099384 -62.636698 270.305193 -39.555468 -64.262926 270.055325 + 0 1 8 0 4 2 -25.735422 -40.831203 179.457224 -26.191507 -42.457441 179.207355 + 0 1 8 0 4 3 0.480550 -64.217827 174.456559 0.120511 -65.929726 174.188359 + 0 1 9 0 4 0 49.172695 -81.293442 263.412694 50.437688 -82.448405 263.166824 + 0 1 9 0 4 1 0.482515 -97.943287 262.749815 0.120155 -99.654736 262.481788 + 0 1 9 0 4 2 0.482512 -64.218216 174.456409 0.120153 -65.929653 174.188386 + 0 1 9 0 4 3 32.058159 -53.419390 174.882708 33.323140 -54.574362 174.636836 + 0 1 10 0 4 0 62.957542 -29.578935 271.389506 64.217009 -30.744853 271.142057 + 0 1 10 0 4 1 49.178021 -81.286434 263.413627 50.440034 -82.442795 263.167652 + 0 1 10 0 4 2 32.063484 -53.412383 174.883639 33.325495 -54.568754 174.637664 + 0 1 10 0 4 3 41.206325 -19.103290 180.175153 42.465803 -20.269211 179.927704 + 0 3 11 0 4 0 109.932020 -12.628264 256.757126 111.164377 -13.801143 256.509477 + 0 3 11 0 4 1 62.956907 -29.580010 271.402004 64.216343 -30.743119 271.145913 + 0 3 11 0 4 2 41.205696 -19.104369 180.187651 42.465132 -20.267477 179.931560 + 0 3 11 0 4 3 72.386163 -7.851684 170.463185 73.618521 -9.024565 170.215535 + 0 3 12 0 4 0 121.395909 33.095679 249.672620 123.006680 33.451055 249.189518 + 0 3 12 0 4 1 109.934518 -12.624994 256.756148 111.160555 -13.804364 256.510823 + 0 3 12 0 4 2 72.388661 -7.848426 170.462206 73.614698 -9.027795 170.216883 + 0 3 12 0 4 3 79.821011 21.799992 165.868762 81.431782 22.155367 165.385660 + 0 3 13 0 4 0 90.154229 71.426790 255.225076 90.712610 73.067200 254.929532 + 0 3 13 0 4 1 121.395278 33.099859 249.672445 123.008479 33.446202 249.189422 + 0 3 13 0 4 2 79.820377 21.804161 165.868589 81.433576 22.150505 165.385566 + 0 3 13 0 4 3 59.566816 46.653862 169.471797 60.125197 48.294272 169.176253 + 0 3 14 0 4 0 39.107594 62.636326 270.326327 39.563475 64.258885 270.061122 + 0 3 14 0 4 1 90.148141 71.429712 255.226542 90.708083 73.070206 254.930551 + 0 3 14 0 4 2 59.560717 46.656788 169.473266 60.120669 48.297277 169.177273 + 0 3 14 0 4 3 25.743641 40.830829 179.478356 26.199513 42.453392 179.213153 + 0 2 15 0 4 0 -0.480548 97.942902 262.749962 -0.120505 99.654812 262.481761 + 0 2 15 0 4 1 39.099391 62.636703 270.305191 39.555474 64.262930 270.055324 + 0 2 15 0 4 2 25.735426 40.831205 179.457225 26.191512 42.457444 179.207355 + 0 2 15 0 4 3 -0.480546 64.217831 174.456561 -0.120506 65.929729 174.188360 + 0 2 16 0 4 0 -49.172689 81.293447 263.412694 -50.437681 82.448409 263.166824 + 0 2 16 0 4 1 -0.482508 97.943291 262.749814 -0.120148 99.654740 262.481787 + 0 2 16 0 4 2 -0.482507 64.218219 174.456412 -0.120148 65.929656 174.188388 + 0 2 16 0 4 3 -32.058154 53.419393 174.882709 -33.323136 54.574366 174.636838 + 0 2 17 0 4 0 -62.957535 29.578939 271.389506 -64.217002 30.744857 271.142058 + 0 2 17 0 4 1 -49.178013 81.286438 263.413627 -50.440027 82.442799 263.167652 + 0 2 17 0 4 2 -32.063480 53.412386 174.883641 -33.325489 54.568756 174.637666 + 0 2 17 0 4 3 -41.206321 19.103293 180.175153 -42.465799 20.269214 179.927704 + 0 0 18 0 6 0 -108.508463 10.380790 259.677657 -116.605370 7.950979 288.461961 + 0 0 18 0 6 1 -62.932433 26.827649 273.886361 -71.029340 24.397838 302.670664 + 0 0 18 0 6 2 -27.254790 -7.152930 281.053885 -35.351698 -9.582741 309.838187 + 0 0 18 0 6 3 -40.578637 -60.303139 272.819295 -48.675544 -62.732950 301.603598 + 0 0 18 0 6 4 -89.885047 -68.797762 258.232533 -97.981954 -71.227573 287.016836 + 0 0 18 0 6 5 -119.308307 -32.700910 253.002987 -127.405214 -35.130721 281.787290 + 0 1 19 0 6 0 -23.885524 -8.027934 281.337962 -22.612376 -12.928334 310.907629 + 0 1 19 0 6 1 24.819332 4.625822 281.337963 26.092479 -0.274578 310.907629 + 0 1 19 0 6 2 60.514670 -29.371625 274.166880 61.787817 -34.272025 303.736546 + 0 1 19 0 6 3 47.099151 -79.713211 266.401693 48.372298 -84.613611 295.971359 + 0 1 19 0 6 4 1.217592 -95.402642 265.777049 2.490739 -100.303042 295.346716 + 0 1 19 0 6 5 -37.198465 -61.134642 273.110112 -35.925318 -66.035042 302.679779 + 0 2 20 0 6 0 23.885531 8.027938 281.337961 22.612384 12.928338 310.907628 + 0 2 20 0 6 1 -24.819325 -4.625818 281.337963 -26.092471 0.274583 310.907629 + 0 2 20 0 6 2 -60.514662 29.371629 274.166880 -61.787809 34.272030 303.736547 + 0 2 20 0 6 3 -47.099144 79.713214 266.401693 -48.372290 84.613615 295.971360 + 0 2 20 0 6 4 -1.217584 95.402646 265.777048 -2.490731 100.303047 295.346715 + 0 2 20 0 6 5 37.198473 61.134646 273.110111 35.925326 66.035047 302.679777 + 0 3 21 0 6 0 108.508454 -10.380795 259.677660 116.605360 -7.950984 288.461963 + 0 3 21 0 6 1 62.932424 -26.827653 273.886363 71.029330 -24.397842 302.670666 + 0 3 21 0 6 2 27.254781 7.152926 281.053885 35.351687 9.582737 309.838189 + 0 3 21 0 6 3 40.578628 60.303135 272.819297 48.675535 62.732946 301.603600 + 0 3 21 0 6 4 89.885040 68.797758 258.232537 97.981946 71.227569 287.016840 + 0 3 21 0 6 5 119.308299 32.700905 253.002991 127.405206 35.130716 281.787294 +## AGATA now... + 2 0 3 2 4 0 18.285154 -33.910246 -46.681338 18.817882 -34.898816 -46.778066 + 2 0 3 2 4 1 54.999505 -32.391967 -52.754328 55.633443 -33.376352 -52.867797 + 2 0 3 2 4 2 82.885361 -49.178344 59.053586 83.519299 -50.162728 58.940117 + 2 0 3 2 4 3 27.741811 -51.458741 68.174984 28.274539 -52.447311 68.078256 + 2 0 4 3 4 0 55.016018 -32.380997 -52.756972 55.649956 -33.365381 -52.870441 + 2 0 4 3 4 1 70.525636 -0.019671 -55.052248 71.629905 -0.022693 -55.235322 + 2 0 4 3 4 2 106.453408 -0.026326 55.565538 107.557678 -0.029349 55.382464 + 2 0 4 3 4 3 82.901875 -49.167373 59.050942 83.535813 -50.151758 58.937473 + 2 0 5 4 4 0 70.525742 0.000329 -55.052096 71.630012 -0.002693 -55.235170 + 2 0 5 4 4 1 57.693661 27.457106 -52.691113 58.356466 28.398684 -52.792962 + 2 0 5 4 4 2 86.935759 41.755775 59.156775 87.598564 42.697354 59.054926 + 2 0 5 4 4 3 106.453515 -0.006327 55.565691 107.557785 -0.009349 55.382617 + 2 0 6 5 4 0 57.677609 27.468712 -52.688353 58.340414 28.410291 -52.790202 + 2 0 6 5 4 1 21.132912 31.594694 -46.595407 21.764694 32.539775 -46.692083 + 2 0 6 5 4 2 32.072845 47.959721 68.303926 32.704626 48.904802 68.207250 + 2 0 6 5 4 3 86.919707 41.767382 59.159535 87.582512 42.708961 59.057686 + 2 0 7 0 6 0 17.832114 -31.323933 -44.860951 17.668587 -31.315530 -45.847454 + 2 0 7 0 6 1 53.591783 -29.845134 -50.776025 53.428256 -29.836731 -51.762528 + 2 0 7 0 6 2 67.908771 0.027731 -52.894804 67.745244 0.036134 -53.881307 + 2 0 7 0 6 3 56.233329 25.009649 -50.746632 56.069802 25.018052 -51.733135 + 2 0 7 0 6 4 20.426845 29.052285 -44.776764 20.263318 29.060688 -45.763267 + 2 0 7 0 6 5 0.975928 -0.044310 -41.800352 0.812401 -0.035906 -42.786855 + 2 0 8 1 6 0 26.312253 -45.113000 51.537526 29.582790 -45.281065 71.267588 + 2 0 8 1 6 1 76.494774 -43.037760 43.236741 79.765311 -43.205826 62.966803 + 2 0 8 1 6 2 97.105436 -0.032939 40.186559 100.375972 -0.201005 59.916620 + 2 0 8 1 6 3 80.197726 36.144451 43.297419 83.468263 35.976385 63.027480 + 2 0 8 1 6 4 30.067808 41.804235 51.655373 33.338345 41.636170 71.385435 + 2 0 8 1 6 5 2.055205 -0.099771 55.941909 5.325742 -0.267837 75.671971 + 2 1 9 2 4 0 21.081671 31.554030 -46.590110 21.742777 32.542978 -46.691274 + 2 1 9 2 4 1 5.805841 65.181885 -52.719755 6.478251 66.145950 -52.816383 + 2 1 9 2 4 2 9.109828 98.356505 59.115545 9.782237 99.320570 59.018917 + 2 1 9 2 4 3 32.021604 47.919057 68.309223 32.682710 48.908005 68.208059 + 2 1 10 3 4 0 5.789469 65.193017 -52.722590 6.461879 66.157082 -52.819218 + 2 1 10 3 4 1 -26.236566 66.995165 -55.274284 -26.678880 68.021957 -55.459728 + 2 1 10 3 4 2 -39.625818 101.109136 55.230972 -40.068132 102.135928 55.045528 + 2 1 10 3 4 3 9.093456 98.367637 59.112710 9.765865 99.331702 59.016082 + 2 1 11 4 4 0 -26.254908 66.987186 -55.274394 -26.697223 68.013978 -55.459839 + 2 1 11 4 4 1 -50.950294 37.394811 -52.597269 -52.126407 37.542295 -52.703166 + 2 1 11 4 4 2 -77.134880 56.176189 59.295076 -78.310993 56.323673 59.189180 + 2 1 11 4 4 3 -39.644160 101.101158 55.230862 -40.086475 102.127950 55.045417 + 2 1 12 5 4 0 -50.953016 37.375188 -52.594521 -52.129129 37.522673 -52.700418 + 2 1 12 5 4 1 -34.632547 1.522792 -46.056959 -35.764022 1.572216 -46.144974 + 2 1 12 5 4 2 -52.625381 2.308737 69.116793 -53.756856 2.358160 69.028777 + 2 1 12 5 4 3 -77.137602 56.156566 59.297824 -78.313715 56.304051 59.191928 + 2 1 13 0 6 0 18.979779 29.896018 -44.768024 19.050057 29.748124 -45.754527 + 2 1 13 0 6 1 3.957700 62.965273 -50.795848 4.027978 62.817379 -51.782352 + 2 1 13 0 6 2 -25.138312 64.602545 -53.114091 -25.068034 64.454651 -54.100594 + 2 1 13 0 6 3 -47.983205 37.227607 -50.637570 -47.912927 37.079713 -51.624073 + 2 1 13 0 6 4 -32.048770 2.223241 -44.254643 -31.978492 2.075347 -45.241146 + 2 1 13 0 6 5 -0.442250 0.842638 -41.796032 -0.371972 0.694744 -42.782535 + 2 1 14 1 6 0 27.077631 43.679531 51.664113 25.672070 46.637412 71.394175 + 2 1 14 1 6 1 6.079593 89.904120 43.238350 4.674033 92.862001 62.968412 + 2 1 14 1 6 2 -36.080691 92.276536 39.879204 -37.486252 95.234416 59.609266 + 2 1 14 1 6 3 -68.939324 52.902177 43.441273 -70.344885 55.860057 63.171335 + 2 1 14 1 6 4 -46.593953 3.814428 52.392257 -47.999514 6.772308 72.122319 + 2 1 14 1 6 5 -0.906085 1.818738 55.946229 -2.311645 4.776619 75.676291 + 2 2 15 2 4 0 -36.041114 -61.186684 -55.148302 -36.637157 -62.158524 -55.337498 + 2 2 15 2 4 1 2.426096 -62.969224 -52.170648 3.019953 -63.996203 -52.267737 + 2 2 15 2 4 2 4.001333 -95.070296 59.940339 4.595190 -96.097275 59.843250 + 2 2 15 2 4 3 -54.425001 -92.362865 55.417697 -55.021044 -93.334705 55.228501 + 2 2 16 3 4 0 2.443376 -62.959557 -52.167812 3.037233 -63.986537 -52.264901 + 2 2 16 3 4 1 18.219312 -33.830224 -46.672580 18.792903 -34.894623 -46.776728 + 2 2 16 3 4 2 27.675970 -51.378719 68.183743 28.249561 -52.443118 68.079595 + 2 2 16 3 4 3 4.018613 -95.060629 59.943175 4.612470 -96.087608 59.846086 + 2 2 17 6 4 0 -34.609774 1.501779 -46.055120 -35.761299 1.552078 -46.144695 + 2 2 17 6 4 1 -53.782188 -29.987880 -52.173638 -54.947036 -29.959462 -52.267464 + 2 2 17 6 4 2 -81.375160 -44.969646 59.936409 -82.540008 -44.941228 59.842582 + 2 2 17 6 4 3 -52.602608 2.287723 69.118632 -53.754133 2.338022 69.029057 + 2 2 18 7 4 0 -53.782418 -30.007674 -52.176490 -54.947266 -29.979256 -52.270317 + 2 2 18 7 4 1 -36.058165 -61.176230 -55.148239 -36.654208 -62.148070 -55.337435 + 2 2 18 7 4 2 -54.442051 -92.352412 55.417760 -55.038094 -93.324252 55.228565 + 2 2 18 7 4 3 -81.375390 -44.989441 59.933556 -82.540238 -44.961023 59.839730 + 2 2 19 0 6 0 -34.611289 -58.868599 -52.973082 -34.528383 -58.727396 -53.959586 + 2 2 19 0 6 1 0.820197 -60.510467 -50.230416 0.903103 -60.369264 -51.216919 + 2 2 19 0 6 2 16.276691 -31.970965 -44.846455 16.359597 -31.829762 -45.832958 + 2 2 19 0 6 3 -0.520629 -0.800578 -41.796545 -0.437723 -0.659375 -42.783048 + 2 2 19 0 6 4 -32.084244 0.578151 -44.251818 -32.001337 0.719354 -45.238321 + 2 2 19 0 6 5 -50.870233 -30.276827 -50.247016 -50.787327 -30.135624 -51.233519 + 2 2 20 1 6 0 -49.545858 -84.199288 40.067751 -51.203979 -87.023344 59.797812 + 2 2 20 1 6 1 1.505812 -86.564983 44.019537 -0.152310 -89.389039 63.749599 + 2 2 20 1 6 2 23.130373 -46.636508 51.552022 21.472252 -49.460564 71.282084 + 2 2 20 1 6 3 -1.067809 -1.732517 55.945716 -2.725930 -4.556572 75.675778 + 2 2 20 1 6 4 -46.712772 0.261299 52.395082 -48.370893 -2.562757 72.125144 + 2 2 20 1 6 5 -73.011913 -42.933626 44.002202 -74.670034 -45.757682 63.732264 +# +##########HiCARI-2020 campaign, walls of MINIBALL cluster############# +#deduced from CAD drawing;Sep10,2021,zqchen +#**********front and back wall****************** +3 0 0 2 6 0 74.267 0 -7.7 74.267 0 -6.2 +3 0 0 2 6 1 54.692 33.37 -7.7 54.692 33.37 -6.2 +3 0 0 2 6 2 19.307 33.441 -7.7 19.307 33.441 -6.2 +3 0 0 2 6 3 0 0 -7.7 0 0 -6.2 +3 0 0 2 6 4 19.307 -33.441 -7.7 19.307 -33.441 -6.2 +3 0 0 2 6 5 54.692 -33.37 -7.7 54.692 -33.37 -6.2 +3 0 1 2 6 0 96.386 0 111.62 96.386 0 112.62 +3 0 1 2 6 1 70.866 42.505 111.62 70.866 42.505 112.62 +3 0 1 2 6 2 25.17 43.596 111.62 25.17 43.596 112.62 +3 0 1 2 6 3 0 0 111.62 0 0 112.62 +3 0 1 2 6 4 25.17 -43.596 111.62 25.17 -43.596 112.62 +3 0 1 2 6 5 70.866 -43.505 111.62 70.866 -43.505 112.62 +3 0 8 2 6 0 -37.134 -64.317 -7.7 -37.134 -64.317 -6.2 +3 0 8 2 6 1 1.553 -64.05 -7.7 1.553 -64.05 -6.2 +3 0 8 2 6 2 19.307 -33.441 -7.7 19.307 -33.441 -6.2 +3 0 8 2 6 3 0 0 -7.7 0 0 -6.2 +3 0 8 2 6 4 -38.614 0 -7.7 -38.614 0 -6.2 +3 0 8 2 6 5 -56.246 -30.68 -7.7 -56.246 -30.68 -6.2 +3 0 9 2 6 0 -48.193 -83.473 111.62 -48.193 -83.473 112.62 +3 0 9 2 6 1 2.244 -83.124 111.62 2.244 -83.124 112.62 +3 0 9 2 6 2 25.17 -43.596 111.62 25.17 -43.596 112.62 +3 0 9 2 6 3 0 0 111.62 0 0 112.62 +3 0 9 2 6 4 -50.34 0 111.62 -50.34 0 112.62 +3 0 9 2 6 5 -73.109 -39.619 111.62 -73.109 -39.619 112.62 +3 0 16 2 6 0 -37.134 64.317 -7.7 -37.134 64.317 -6.2 +3 0 16 2 6 1 -56.246 30.68 -7.7 -56.246 30.68 -6.2 +3 0 16 2 6 2 -38.614 0 -7.7 -38.614 0 -6.2 +3 0 16 2 6 3 0 0 -7.7 0 0 -6.2 +3 0 16 2 6 4 19.307 33.441 -7.7 19.307 33.441 -6.2 +3 0 16 2 6 5 1.553 64.05 -7.7 1.553 64.05 -6.2 +3 0 17 2 6 0 -48.193 83.473 111.62 -48.193 83.473 112.62 +3 0 17 2 6 1 -73.109 39.619 111.62 -73.109 39.619 112.62 +3 0 17 2 6 2 -50.34 0 111.62 -50.34 0 112.62 +3 0 17 2 6 3 0 0 111.62 0 0 112.62 +3 0 17 2 6 4 25.17 43.596 111.62 25.17 43.596 112.62 +3 0 17 2 6 5 2.244 83.124 111.62 2.244 83.124 112.62 +#**********side wall***** +3 0 2 2 4 0 96.386 0 111.62 94.6249 0 111.62 +3 0 2 2 4 1 70.866 42.505 111.62 69.3631 41.6035 111.62 +3 0 2 2 4 2 54.692 33.37 -6.2 53.1959 32.4572 -6.2 +3 0 2 2 4 3 74.267 0 -6.2 72.5059 0 -6.2 +3 0 3 2 4 0 70.866 42.505 111.62 69.3631 41.6035 111.62 +3 0 3 2 4 1 25.17 43.596 111.62 24.2999 42.0889 111.62 +3 0 3 2 4 2 19.307 33.441 -6.2 18.4369 31.9339 -6.2 +3 0 3 2 4 3 54.692 33.37 -6.2 53.1959 32.4572 -6.2 +3 0 4 2 4 0 25.17 43.596 111.62 24.2999 42.0889 111.62 +3 0 4 2 4 1 2.244 83.124 111.62 2.19667 81.3709 111.62 +3 0 4 2 4 2 1.553 64.05 -6.2 1.51049 62.2968 -6.2 +3 0 4 2 4 3 19.307 33.441 -6.2 18.4369 31.9339 -6.2 +3 0 5 2 4 0 2.244 83.124 111.62 2.19667 81.3709 111.62 +3 0 5 2 4 1 -48.193 83.473 111.62 -47.3125 81.9479 111.62 +3 0 5 2 4 2 -37.134 64.317 -6.2 -36.2535 62.7919 -6.2 +3 0 5 2 4 3 1.553 64.05 -6.2 1.51049 62.2968 -6.2 +3 0 10 2 4 0 -48.193 83.473 111.62 -47.3125 81.9479 111.62 +3 0 10 2 4 1 -73.109 39.619 111.62 -71.5671 38.7834 111.62 +3 0 10 2 4 2 -56.246 30.68 -6.2 -54.7064 29.8402 -6.2 +3 0 10 2 4 3 -37.134 64.317 -6.2 -36.2535 62.7919 -6.2 +3 0 11 2 4 0 -73.109 39.619 111.62 -71.5671 38.7834 111.62 +3 0 11 2 4 1 -50.34 0 111.62 -48.5997 0 111.62 +3 0 11 2 4 2 -38.614 0 -6.2 -36.8737 0 -6.2 +3 0 11 2 4 3 -56.246 30.68 -6.2 -54.7064 29.8402 -6.2 +3 0 12 2 4 0 -50.34 0 111.62 -48.5997 0 111.62 +3 0 12 2 4 1 -73.109 -39.619 111.62 -71.5671 -38.7834 111.62 +3 0 12 2 4 2 -56.246 -30.68 -6.2 -54.7064 -29.8402 -6.2 +3 0 12 2 4 3 -38.614 0 -6.2 -36.8737 0 -6.2 +3 0 13 2 4 0 -73.109 -39.619 111.62 -71.5671 -38.7834 111.62 +3 0 13 2 4 1 -48.193 -83.473 111.62 -47.3125 -81.9479 111.62 +3 0 13 2 4 2 -37.134 -64.317 -6.2 -36.2535 -62.7919 -6.2 +3 0 13 2 4 3 -56.246 -30.68 -6.2 -54.7064 -29.8402 -6.2 +3 0 18 2 4 0 -48.193 -83.473 111.62 -47.3125 -81.9479 111.62 +3 0 18 2 4 1 2.244 -83.124 111.62 2.19667 -81.3709 111.62 +3 0 18 2 4 2 1.553 -64.05 -6.2 1.51049 -62.2968 -6.2 +3 0 18 2 4 3 -37.134 -64.317 -6.2 -36.2535 -62.7919 -6.2 +3 0 19 2 4 0 2.244 -83.124 111.62 2.19667 -81.3709 111.62 +3 0 19 2 4 1 25.17 -43.596 111.62 24.2999 -42.0889 111.62 +3 0 19 2 4 2 19.307 -33.441 -6.2 18.4369 -31.9339 -6.2 +3 0 19 2 4 3 1.553 -64.05 -6.2 1.51049 -62.2968 -6.2 +3 0 20 2 4 0 25.17 -43.596 111.62 24.2999 -42.0889 111.62 +3 0 20 2 4 1 70.866 -43.505 111.62 69.3715 -42.5875 111.62 +3 0 20 2 4 2 54.692 -33.37 -6.2 53.195 -32.4566 -6.2 +3 0 20 2 4 3 19.307 -33.441 -6.2 18.4369 -31.9339 -6.2 +3 0 21 2 4 0 70.866 -43.505 111.62 69.3715 -42.5875 111.62 +3 0 21 2 4 1 96.386 0 111.62 94.6249 0 111.62 +3 0 21 2 4 2 74.267 0 -6.2 72.5059 0 -6.2 +3 0 21 2 4 3 54.692 -33.37 -6.2 53.195 -32.4566 -6.2 +##########end;HiCARI-2020 campaign, walls of MINIBALL cluster######### +# +########################walls of IMP Clover;Aug27,zqchen################## +#cl#; order;wall#;useless;nsides;order;x,y,z;X,Y,Z +#sides///////////////////////////outer surface//////////inner surface//// +4 0 2 0 4 0 0.00 62.00 36.25 0.00 60.50 36.25 +4 0 2 0 4 1 62.00 62.00 36.25 60.50 60.50 36.25 +4 0 2 0 4 2 62.00 62.00 140.00 60.00 60.00 138.00 +4 0 2 0 4 3 0.00 62.00 140.00 0.00 60.00 138.00 +4 0 3 0 4 0 62.00 62.00 36.25 60.50 60.50 36.25 +4 0 3 0 4 1 62.00 0.00 36.25 60.50 0.00 36.25 +4 0 3 0 4 2 62.00 0.00 140.00 60.00 0.00 138.00 +4 0 3 0 4 3 62.00 62.00 140.00 60.00 60.00 138.00 +4 1 10 0 4 0 62.00 0.00 36.25 60.50 -0.00 36.25 +4 1 10 0 4 1 62.00 -62.00 36.25 60.50 -60.50 36.25 +4 1 10 0 4 2 62.00 -62.00 140.00 60.00 -60.00 138.00 +4 1 10 0 4 3 62.00 -0.00 140.00 60.00 -0.00 138.00 +4 1 11 0 4 0 62.00 -62.00 36.25 60.50 -60.50 36.25 +4 1 11 0 4 1 0.00 -62.00 36.25 0.00 -60.50 36.25 +4 1 11 0 4 2 0.00 -62.00 140.00 0.00 -60.00 138.00 +4 1 11 0 4 3 62.00 -62.00 140.00 60.00 -60.00 138.00 +4 2 18 0 4 0 0.00 -62.00 36.25 -0.00 -60.50 36.25 +4 2 18 0 4 1 -62.00 -62.00 36.25 -60.50 -60.50 36.25 +4 2 18 0 4 2 -62.00 -62.00 140.00 -60.00 -60.00 138.00 +4 2 18 0 4 3 -0.00 -62.00 140.00 0.00 -60.00 138.00 +4 2 19 0 4 0 -62.00 -62.00 36.25 -60.50 -60.50 36.25 +4 2 19 0 4 1 -62.00 0.00 36.25 -60.50 -0.00 36.25 +4 2 19 0 4 2 -62.00 -0.00 140.00 -60.00 -0.00 138.00 +4 2 19 0 4 3 -62.00 -62.00 140.00 -60.00 -60.00 138.00 +4 3 26 0 4 0 -62.00 0.00 36.25 -60.50 0.00 36.25 +4 3 26 0 4 1 -62.00 62.00 36.25 -60.50 60.50 36.25 +4 3 26 0 4 2 -62.00 62.00 140.00 -60.00 60.00 138.00 +4 3 26 0 4 3 -62.00 0.00 140.00 -60.00 0.00 138.00 +4 3 27 0 4 0 -62.00 62.00 36.25 -60.50 60.50 36.25 +4 3 27 0 4 1 0.00 62.00 36.25 -0.00 60.50 36.25 +4 3 27 0 4 2 -0.00 62.00 140.00 0.00 60.00 138.00 +4 3 27 0 4 3 -62.00 62.00 140.00 -60.00 60.00 138.00 +#front and back walls/////////////outer surface//////////////////inner surface//////// +4 0 0 0 4 0 0.00 0.00 -7.00 0.00 0.00 -5.50 +4 0 0 0 4 1 44.10 0.00 -7.00 42.60 0.00 -5.50 +4 0 0 0 4 2 44.10 44.10 -7.00 42.60 42.60 -5.50 +4 0 0 0 4 3 0.00 44.00 -7.00 0.00 42.60 -5.50 +4 0 1 0 4 0 0.00 0.00 138.00 0.00 0.00 140.00 +4 0 1 0 4 1 60.00 0.00 138.00 62.00 0.00 140.00 +4 0 1 0 4 2 60.00 60.00 138.00 62.00 62.00 140.00 +4 0 1 0 4 3 0.00 60.00 138.00 0.00 62.00 140.00 +4 1 8 0 4 0 0.00 0.00 -7.00 0.00 -0.00 -5.50 +4 1 8 0 4 1 0.00 -44.10 -7.00 0.00 -42.60 -5.50 +4 1 8 0 4 2 44.10 -44.10 -7.00 42.60 -42.60 -5.50 +4 1 8 0 4 3 44.10 0.00 -7.00 42.60 -0.00 -5.50 +4 1 9 0 4 0 0.00 -0.00 138.00 0.00 0.00 140.00 +4 1 9 0 4 1 0.00 -60.00 138.00 0.00 -62.00 140.00 +4 1 9 0 4 2 60.00 -60.00 138.00 62.00 -62.00 140.00 +4 1 9 0 4 3 60.00 -0.00 138.00 62.00 0.00 140.00 +4 2 16 0 4 0 0.00 0.00 -7.00 -0.00 -0.00 -5.50 +4 2 16 0 4 1 -44.10 0.00 -7.00 -42.60 -0.00 -5.50 +4 2 16 0 4 2 -44.10 -44.10 -7.00 -42.60 -42.60 -5.50 +4 2 16 0 4 3 0.00 -44.10 -7.00 -0.00 -42.60 -5.50 +4 2 17 0 4 0 -0.00 -0.00 138.00 0.00 0.00 140.00 +4 2 17 0 4 1 -60.00 -0.00 138.00 -62.00 0.00 140.00 +4 2 17 0 4 2 -60.00 -60.00 138.00 -62.00 -62.00 140.00 +4 2 17 0 4 3 -0.00 -60.00 138.00 0.00 -62.00 140.00 +4 3 24 0 4 0 0.00 0.00 -7.00 -0.00 0.00 -5.50 +4 3 24 0 4 1 0.00 44.10 -7.00 -0.00 42.60 -5.50 +4 3 24 0 4 2 -44.10 44.10 -7.00 -42.60 42.60 -5.50 +4 3 24 0 4 3 -44.10 0.00 -7.00 -42.60 0.00 -5.50 +4 3 25 0 4 0 -0.00 0.00 138.00 0.00 0.00 140.00 +4 3 25 0 4 1 -0.00 60.00 138.00 0.00 62.00 140.00 +4 3 25 0 4 2 -60.00 60.00 138.00 -62.00 62.00 140.00 +4 3 25 0 4 3 -60.00 0.00 138.00 -62.00 0.00 140.00 +#front-side walls/////////////////outer surface//////////inner surface//// +4 0 4 0 4 0 0.00 44.10 -7.00 0.00 42.60 -5.50 +4 0 4 0 4 1 44.10 44.10 -7.00 42.60 42.60 -5.50 +4 0 4 0 4 2 62.00 62.00 36.25 60.50 60.50 36.25 +4 0 4 0 4 3 0.00 62.00 36.25 0.00 60.50 36.25 +4 0 5 0 4 0 44.10 44.10 -7.00 42.60 42.60 -5.50 +4 0 5 0 4 1 44.10 0.00 -7.00 42.60 0.00 -5.50 +4 0 5 0 4 2 62.00 0.00 36.25 60.50 0.00 36.25 +4 0 5 0 4 3 62.00 62.00 36.25 60.50 60.50 36.25 +4 1 12 0 4 0 44.10 0.00 -7.00 42.60 -0.00 -5.50 +4 1 12 0 4 1 44.10 -44.10 -7.00 42.60 -42.60 -5.50 +4 1 12 0 4 2 62.00 -62.00 36.25 60.50 -60.50 36.25 +4 1 12 0 4 3 62.00 0.00 36.25 60.50 -0.00 36.25 +4 1 13 0 4 0 44.10 -44.10 -7.00 42.60 -42.60 -5.50 +4 1 13 0 4 1 0.00 -44.10 -7.00 0.00 -42.60 -5.50 +4 1 13 0 4 2 0.00 -62.00 36.25 0.00 -60.50 36.25 +4 1 13 0 4 3 62.00 -62.00 36.25 60.50 -60.50 36.25 +4 2 20 0 4 0 0.00 -44.10 -7.00 -0.00 -42.60 -5.50 +4 2 20 0 4 1 -44.10 -44.10 -7.00 -42.60 -42.60 -5.50 +4 2 20 0 4 2 -62.00 -62.00 36.25 -60.50 -60.50 36.25 +4 2 20 0 4 3 0.00 -62.00 36.25 -0.00 -60.50 36.25 +4 2 21 0 4 0 -44.10 -44.10 -7.00 -42.60 -42.60 -5.50 +4 2 21 0 4 1 -44.10 0.00 -7.00 -42.60 -0.00 -5.50 +4 2 21 0 4 2 -62.00 0.00 36.25 -60.50 -0.00 36.25 +4 2 21 0 4 3 -62.00 -62.00 36.25 -60.50 -60.50 36.25 +4 3 28 0 4 0 -44.10 0.00 -7.00 -42.60 0.00 -5.50 +4 3 28 0 4 1 -44.10 44.10 -7.00 -42.60 42.60 -5.50 +4 3 28 0 4 2 -62.00 62.00 36.25 -60.50 60.50 36.25 +4 3 28 0 4 3 -62.00 0.00 36.25 -60.50 0.00 36.25 +4 3 29 0 4 0 -44.10 44.10 -7.00 -42.60 42.60 -5.50 +4 3 29 0 4 1 0.00 44.10 -7.00 -0.00 42.60 -5.50 +4 3 29 0 4 2 0.00 62.00 36.25 -0.00 60.50 36.25 +4 3 29 0 4 3 -62.00 62.00 36.25 -60.50 60.50 36.25 +########################walls of IMP Clover;Aug27,end################## + diff --git a/Projects/Hicari/plotsegments.py b/Projects/Hicari/plotsegments.py new file mode 100644 index 000000000..949ea0864 --- /dev/null +++ b/Projects/Hicari/plotsegments.py @@ -0,0 +1,26 @@ +import numpy as np +import matplotlib.pyplot as plt + +txt = np.loadtxt('segmentpositions.dat') +x = txt[:,3] +y = txt[:,4] +z = txt[:,5] + +#fig, ax = plt.subplots(2,2) +#ax[0,0].scatter(x,y, marker='o') +#ax[0,0].set_xlabel('X (mm)') +#ax[0,0].set_ylabel('Y (mm)') +#ax[0,1].scatter(z,x, color='red') +#ax[0,1].set_xlabel('Z(mm)') +#ax[0,1].set_ylabel('X(mm)') +#fig.tight_layout() + +fig2 = plt.figure() +ax2 = fig2.add_subplot(projection='3d') +ax2.scatter(x, z, y, marker='o') +ax2.set_xlabel('X(mm)') +ax2.set_ylabel('Z(mm)') +ax2.set_zlabel('Y(mm)') + + +plt.show() diff --git a/Projects/Hicari/segmentpositions.dat b/Projects/Hicari/segmentpositions.dat new file mode 100644 index 000000000..21eaaf79f --- /dev/null +++ b/Projects/Hicari/segmentpositions.dat @@ -0,0 +1,424 @@ + 800 0 0 -57.12165 -129.38362 237.05854 44184.00000 + 800 0 1 -77.63980 -123.93228 232.98205 44104.00000 + 800 0 2 -89.54823 -135.92883 219.51589 44104.00000 + 800 0 3 -80.95398 -153.39233 210.10871 44184.00000 + 800 0 4 -60.41759 -158.80951 214.13865 44104.00000 + 800 0 5 -48.50917 -146.81296 227.60481 44104.00000 + 801 0 0 -64.26405 -208.07938 168.02055 44184.00000 + 801 0 1 -53.10506 -197.45103 183.18118 44104.00000 + 801 0 2 -62.47211 -181.44648 194.27975 44104.00000 + 801 0 3 -83.01034 -176.04948 190.23211 44184.00000 + 801 0 4 -94.15058 -186.63801 175.02988 44104.00000 + 801 0 5 -84.78352 -202.64255 163.93132 44104.00000 + 802 0 0 -145.92695 -143.93719 183.09474 44184.00000 + 802 0 1 -137.33085 -161.36922 173.63105 44104.00000 + 802 0 2 -117.64106 -168.18739 179.36600 44104.00000 + 802 0 3 -106.52175 -157.58242 194.57210 44184.00000 + 802 0 4 -115.09323 -140.11519 203.99311 44104.00000 + 802 0 5 -134.78303 -133.29701 198.25816 44104.00000 + 804 0 0 144.84986 -139.26204 185.39294 44184.00000 + 804 0 1 133.51447 -128.72629 200.48720 44104.00000 + 804 0 2 113.76240 -135.59541 205.94028 44104.00000 + 804 0 3 105.32003 -153.00921 196.30620 44184.00000 + 804 0 4 116.63128 -163.50950 181.16919 44104.00000 + 804 0 5 136.38335 -156.64038 175.71610 44104.00000 + 805 0 0 63.42858 -203.36922 168.92705 44184.00000 + 805 0 1 83.99150 -197.89119 165.12086 44104.00000 + 805 0 2 93.21031 -181.95005 176.43275 44104.00000 + 805 0 3 81.87818 -171.46619 191.56554 44184.00000 + 805 0 4 61.29698 -176.90415 195.33016 44104.00000 + 805 0 5 52.07817 -192.84529 184.01828 44104.00000 + 806 0 0 55.38613 -125.11669 238.36870 44184.00000 + 806 0 1 46.90313 -142.49242 228.70164 44104.00000 + 806 0 2 58.98355 -154.39467 215.30517 44104.00000 + 806 0 3 79.56269 -148.93665 211.55835 44184.00000 + 806 0 4 88.02800 -131.52647 221.17885 44104.00000 + 806 0 5 75.94757 -119.62423 234.57531 44104.00000 + 808 0 0 -108.70645 -54.79454 254.05512 44184.00000 + 808 0 1 -99.10397 -36.54232 260.53420 44104.00000 + 808 0 2 -108.56210 -17.45720 256.87812 44104.00000 + 808 0 3 -127.63501 -16.59947 246.73819 44184.00000 + 808 0 4 -137.20891 -34.84773 240.20587 44104.00000 + 808 0 5 -127.75079 -53.93285 243.86196 44104.00000 + 809 0 0 -185.44092 1.29808 209.60605 44184.00000 + 809 0 1 -177.12683 -17.83914 215.26048 44104.00000 + 809 0 2 -159.28172 -18.71258 227.42002 44104.00000 + 809 0 3 -149.72749 -0.44995 233.94095 44184.00000 + 809 0 4 -158.00748 18.68720 228.23647 44104.00000 + 809 0 5 -175.85259 19.56065 216.07694 44104.00000 + 810 0 0 -105.13434 50.04954 256.34393 44184.00000 + 810 0 1 -124.17801 50.93057 246.15118 44104.00000 + 810 0 2 -134.90715 32.71065 241.68071 44104.00000 + 810 0 3 -126.60657 13.58599 247.39716 44184.00000 + 810 0 4 -107.53457 12.70139 257.53649 44104.00000 + 810 0 5 -96.80543 30.92131 262.00697 44104.00000 + 812 0 0 182.09037 3.01719 212.67056 44184.00000 + 812 0 1 172.18580 21.13767 219.06414 44104.00000 + 812 0 2 154.21274 20.00264 231.01177 44104.00000 + 812 0 3 146.12086 0.74567 236.58135 44184.00000 + 812 0 4 155.99191 -17.37521 230.13733 44104.00000 + 812 0 5 173.96498 -16.24019 218.18970 44104.00000 + 813 0 0 105.59092 -54.17901 256.10683 44184.00000 + 813 0 1 124.74016 -53.04402 246.13948 44104.00000 + 813 0 2 133.98671 -33.82780 242.63185 44104.00000 + 813 0 3 124.09605 -15.72158 249.08701 44184.00000 + 813 0 4 104.91880 -16.85287 259.00080 44104.00000 + 813 0 5 95.67225 -36.06909 262.50842 44104.00000 + 814 0 0 100.60330 50.60360 258.55817 44184.00000 + 814 0 1 92.46289 31.35499 264.08578 44104.00000 + 814 0 2 103.48410 13.28804 259.70593 44104.00000 + 814 0 3 122.66007 14.44619 249.79277 44184.00000 + 814 0 4 130.77284 33.69096 244.21142 44104.00000 + 814 0 5 119.75162 51.75791 248.59127 44104.00000 + 816 0 0 -60.21246 127.50545 240.59960 44184.00000 + 816 0 1 -51.47014 145.02906 231.44402 44104.00000 + 816 0 2 -63.21389 157.20470 217.99398 44104.00000 + 816 0 3 -83.71523 151.87256 213.68203 44184.00000 + 816 0 4 -92.43888 134.31531 222.79085 44104.00000 + 816 0 5 -80.69513 122.13967 236.24088 44104.00000 + 817 0 0 -148.41210 142.85365 185.86809 44184.00000 + 817 0 1 -137.44863 132.01572 201.02300 44104.00000 + 817 0 2 -117.80966 138.73025 207.04723 44104.00000 + 817 0 3 -109.10862 156.29143 197.92439 44184.00000 + 817 0 4 -120.04708 167.09461 182.72665 44104.00000 + 817 0 5 -139.68605 160.38009 176.70242 44104.00000 + 818 0 0 -66.48469 207.02025 172.42088 44184.00000 + 818 0 1 -86.96852 201.66913 168.04959 44104.00000 + 818 0 2 -96.48051 185.55225 178.85854 44104.00000 + 818 0 3 -85.52106 174.76552 194.05282 44184.00000 + 818 0 4 -65.01810 180.07727 198.38225 44104.00000 + 818 0 5 -55.50611 196.19415 187.57331 44104.00000 + 820 0 0 51.13807 133.86435 240.80033 44184.00000 + 820 0 1 71.29914 126.35331 238.69186 44104.00000 + 820 0 2 85.38428 136.61599 225.91096 44104.00000 + 820 0 3 79.32669 154.40305 215.22191 44184.00000 + 820 0 4 59.14809 161.87989 217.28359 44104.00000 + 820 0 5 45.06294 151.61722 230.06449 44104.00000 + 821 0 0 71.54116 208.62468 170.05510 44184.00000 + 821 0 1 58.19164 199.72297 184.54232 44104.00000 + 821 0 2 65.01707 183.38483 196.93360 44104.00000 + 821 0 3 85.20091 175.92716 194.85379 44184.00000 + 821 0 4 98.53142 184.78930 180.32486 44104.00000 + 821 0 5 91.70599 201.12743 167.93358 44104.00000 + 822 0 0 145.08998 137.80153 194.24049 44184.00000 + 822 0 1 139.03217 155.55512 183.49607 44104.00000 + 822 0 2 119.68787 164.41689 187.28184 44104.00000 + 822 0 3 106.37621 155.53660 201.81696 44184.00000 + 822 0 4 112.40972 137.74852 212.51794 44104.00000 + 822 0 5 131.75402 128.88675 208.73217 44104.00000 + 824 0 0 -221.53340 -198.42351 61.24100 69756.00000 + 824 0 1 -237.52340 -178.12748 56.24781 53477.00000 + 824 0 2 -237.95559 -184.93260 34.19870 40644.00000 + 824 0 3 -222.01741 -201.59941 35.12166 53477.00000 + 825 0 0 -218.99149 -190.92659 90.72521 69756.00000 + 825 0 1 -215.13810 -181.31008 114.91642 53477.00000 + 825 0 2 -231.38842 -165.56388 110.37282 40644.00000 + 825 0 3 -234.78671 -170.05610 87.99132 53477.00000 + 826 0 0 -197.42066 -212.23438 94.28344 69756.00000 + 826 0 1 -176.40836 -227.72255 97.62116 53477.00000 + 826 0 2 -175.65895 -220.61376 119.56571 40644.00000 + 826 0 3 -191.91435 -204.25063 118.74731 53477.00000 + 827 0 0 -199.96257 -219.73130 64.79923 69756.00000 + 827 0 1 -198.79366 -224.53996 38.95255 53477.00000 + 827 0 2 -182.22612 -239.98247 43.39159 40644.00000 + 827 0 3 -179.14505 -235.79394 65.87765 53477.00000 + 828 0 0 228.64539 -167.28769 105.26408 69756.00000 + 828 0 1 239.76563 -144.51011 112.33960 53477.00000 + 828 0 2 229.90810 -147.05833 133.05181 40644.00000 + 828 0 3 216.80069 -165.54924 128.69955 53477.00000 + 829 0 0 240.14474 -165.69862 77.02893 69756.00000 + 829 0 1 247.92203 -161.24865 52.28520 53477.00000 + 829 0 2 259.61733 -142.95289 60.10471 40644.00000 + 829 0 3 252.14614 -142.79928 81.94087 53477.00000 + 830 0 0 223.46156 -189.92873 68.87070 69756.00000 + 830 0 1 206.99552 -208.37458 59.86177 53477.00000 + 830 0 2 216.51539 -205.55276 39.02744 40644.00000 + 830 0 3 229.96046 -187.33546 43.50182 53477.00000 + 831 0 0 211.96221 -191.51780 97.10584 69756.00000 + 831 0 1 198.83912 -191.63604 119.91617 53477.00000 + 831 0 2 186.80616 -209.65820 111.97454 40644.00000 + 831 0 3 194.61500 -210.08542 90.26051 53477.00000 + 832 0 0 -218.91807 177.11936 106.17438 69756.00000 + 832 0 1 -234.44899 156.02618 103.64279 53477.00000 + 832 0 2 -231.76291 152.33401 126.26607 40644.00000 + 832 0 3 -215.79717 168.37219 130.79729 53477.00000 + 833 0 0 -220.53528 183.57875 76.38102 69756.00000 + 833 0 1 -220.17394 185.85362 50.16585 53477.00000 + 833 0 2 -235.94108 169.02223 49.29323 40644.00000 + 833 0 3 -236.19013 162.98054 71.56644 53477.00000 + 834 0 0 -199.26302 205.18916 79.91161 69756.00000 + 834 0 1 -178.61982 221.46599 81.12149 53477.00000 + 834 0 2 -180.98299 224.85394 58.41473 40644.00000 + 834 0 3 -197.27164 209.11997 53.96699 53477.00000 + 835 0 0 -197.64581 198.72976 109.70498 69756.00000 + 835 0 1 -192.89488 191.63854 134.59843 53477.00000 + 835 0 2 -176.80483 208.16571 135.38757 40644.00000 + 835 0 3 -176.87868 214.51162 113.19784 53477.00000 + 836 0 0 210.00986 141.65944 88.16577 69756.00000 + 836 0 1 222.27088 118.93947 93.26591 53477.00000 + 836 0 2 228.80397 118.42668 71.13639 40644.00000 + 836 0 3 216.73713 136.45562 63.26186 53477.00000 + 837 0 0 199.72041 144.10685 116.80352 69756.00000 + 837 0 1 188.89021 143.07921 140.76581 53477.00000 + 837 0 2 202.22060 124.74972 145.12365 40644.00000 + 837 0 3 211.19298 121.57443 124.09810 53477.00000 + 838 0 0 182.63995 168.05006 108.62035 69756.00000 + 838 0 1 164.96716 186.37326 101.95153 53477.00000 + 838 0 2 158.09224 186.60835 123.98197 40644.00000 + 838 0 3 170.50091 168.85712 131.95559 53477.00000 + 839 0 0 192.92940 165.60264 79.98260 69756.00000 + 839 0 1 198.34783 162.23353 54.45163 53477.00000 + 839 0 2 184.67562 180.28530 49.99470 40644.00000 + 839 0 3 176.04506 183.73831 71.11934 53477.00000 + 40 0 0 -150.63483 -7.81697 67.63203 4276.00000 + 40 0 1 -149.83763 11.89011 68.90313 4109.00000 + 40 0 2 -141.23047 20.06838 84.19411 4030.00000 + 40 0 3 -133.00056 8.60308 98.96943 3867.00000 + 40 0 4 -133.37929 -10.77058 98.45024 3908.00000 + 40 0 5 -142.32095 -19.59308 82.55820 4194.00000 + 40 1 0 -160.95809 -8.40115 71.86836 8371.00000 + 40 1 1 -160.08423 12.80948 73.27282 8045.00000 + 40 1 2 -150.82385 21.56709 89.71886 7867.00000 + 40 1 3 -141.97766 9.27611 105.61456 7582.00000 + 40 1 4 -142.38948 -11.55392 105.04617 7665.00000 + 40 1 5 -151.99341 -21.05514 87.96280 8257.00000 + 40 2 0 -174.92913 -9.11362 77.75742 11049.00000 + 40 2 1 -173.95072 13.92595 79.32816 10620.00000 + 40 2 2 -163.88460 23.59016 97.24646 10455.00000 + 40 2 3 -154.25299 10.16855 114.56884 10114.00000 + 40 2 4 -154.72449 -12.57452 113.87567 10218.00000 + 40 2 5 -165.16865 -22.94104 95.31094 10960.00000 + 40 3 0 -190.29368 -9.64015 85.01161 14146.00000 + 40 3 1 -189.24805 14.78220 86.67206 13536.00000 + 40 3 2 -178.58078 25.20643 105.71640 13603.00000 + 40 3 3 -168.25064 11.02409 124.35148 13405.00000 + 40 3 4 -168.82382 -13.42319 123.42344 13364.00000 + 40 3 5 -179.95356 -24.48504 103.63816 14245.00000 + 40 4 0 -206.93957 -10.08083 93.95065 16645.00000 + 40 4 1 -205.83381 15.11405 95.66497 15647.00000 + 40 4 2 -194.81853 26.03233 115.33608 16324.00000 + 40 4 3 -184.19010 11.72407 134.47194 16557.00000 + 40 4 4 -184.92663 -13.80322 133.22022 15927.00000 + 40 4 5 -196.39750 -25.24779 112.88767 17140.00000 + 40 5 0 -221.72955 -10.15085 102.27200 11753.00000 + 40 5 1 -220.65384 15.20772 103.98558 10975.00000 + 40 5 2 -209.49416 26.14969 123.82029 11554.00000 + 40 5 3 -198.88573 11.96136 142.83981 11729.00000 + 40 5 4 -199.71826 -13.73658 141.55906 11158.00000 + 40 5 5 -211.15535 -25.26058 121.22709 12047.00000 + 41 0 0 -137.16666 63.14974 70.36599 3501.00000 + 41 0 1 -143.13908 44.49990 71.23662 3897.00000 + 41 0 2 -151.46731 37.00859 55.91170 4157.00000 + 41 0 3 -153.74620 48.70085 39.42024 4130.00000 + 41 0 4 -147.01413 67.59155 40.34094 3678.00000 + 41 0 5 -139.07235 73.82628 55.77828 3305.00000 + 41 1 0 -146.40355 67.02533 75.30414 6854.00000 + 41 1 1 -152.82144 47.03902 76.21126 7628.00000 + 41 1 2 -161.80812 38.94406 59.67642 8166.00000 + 41 1 3 -164.26550 51.55016 41.89316 8129.00000 + 41 1 4 -157.02774 71.87338 42.87425 7205.00000 + 41 1 5 -148.48023 78.55501 59.51798 6490.00000 + 41 2 0 -159.00907 72.34342 81.95289 9105.00000 + 41 2 1 -166.01243 50.59255 82.87542 10156.00000 + 41 2 2 -175.82578 41.72455 64.79046 10822.00000 + 41 2 3 -178.54116 55.47020 45.33928 10786.00000 + 41 2 4 -170.65860 77.60747 46.43410 9611.00000 + 41 2 5 -161.30984 84.91276 64.65038 8679.00000 + 41 3 0 -173.38702 78.19431 89.23004 12171.00000 + 41 3 1 -180.89730 54.86349 89.98269 13208.00000 + 41 3 2 -191.36111 45.61308 70.50409 13925.00000 + 41 3 3 -194.35103 60.11677 49.68652 14037.00000 + 41 3 4 -186.00096 83.90039 50.69256 12814.00000 + 41 3 5 -175.89132 91.82593 70.42652 11631.00000 + 41 4 0 -189.51898 84.57185 97.01748 15725.00000 + 41 4 1 -197.45026 60.44598 97.18371 15838.00000 + 41 4 2 -208.45478 50.80466 76.65836 16510.00000 + 41 4 3 -211.56855 65.65936 55.21138 17049.00000 + 41 4 4 -202.96855 90.45359 55.97099 16117.00000 + 41 4 5 -192.20875 99.16531 76.85717 15053.00000 + 41 5 0 -204.24065 89.91963 103.11104 11582.00000 + 41 5 1 -212.43887 65.68122 103.11035 11228.00000 + 41 5 2 -223.63469 55.90129 82.26612 11687.00000 + 41 5 3 -226.69390 70.85916 60.74760 12035.00000 + 41 5 4 -218.01459 95.74400 61.46149 11568.00000 + 41 5 5 -206.98684 104.76162 82.57514 11116.00000 + 42 0 0 -159.01888 14.82064 42.65544 4276.00000 + 42 0 1 -159.99528 -4.88238 41.44817 4109.00000 + 42 0 2 -163.32258 -13.18002 24.27668 4030.00000 + 42 0 3 -165.82827 -1.84411 7.46260 3867.00000 + 42 0 4 -165.01642 17.51975 7.82752 3908.00000 + 42 0 5 -161.54243 26.46585 25.66696 4194.00000 + 42 1 0 -169.66291 15.87881 45.88693 8371.00000 + 42 1 1 -170.72453 -5.32758 44.54934 8045.00000 + 42 1 2 -174.29927 -14.21372 26.07827 7867.00000 + 42 1 3 -177.00274 -2.06160 7.99474 7582.00000 + 42 1 4 -176.12700 18.75794 8.39791 7665.00000 + 42 1 5 -172.38567 28.39169 27.56933 8257.00000 + 42 2 0 -184.16963 17.23504 50.14065 11049.00000 + 42 2 1 -185.32874 -5.80045 48.63428 10620.00000 + 42 2 2 -189.24640 -15.60365 28.52611 10455.00000 + 42 2 3 -192.19803 -2.33304 8.82455 10114.00000 + 42 2 4 -191.21292 20.39842 9.33479 10218.00000 + 42 2 5 -187.15127 30.90922 30.17275 10960.00000 + 42 3 0 -200.62501 18.48088 54.21962 14146.00000 + 42 3 1 -201.84424 -5.93754 52.62099 13536.00000 + 42 3 2 -206.03856 -16.50810 31.27121 13603.00000 + 42 3 3 -209.24841 -2.48672 10.10014 13405.00000 + 42 3 4 -208.12527 21.94813 10.83229 13364.00000 + 42 3 5 -203.79519 33.16369 33.03938 14245.00000 + 42 4 0 -219.14025 19.71641 57.80375 16645.00000 + 42 4 1 -220.37795 -5.47548 56.13642 15647.00000 + 42 4 2 -224.71873 -16.54465 34.08809 16324.00000 + 42 4 3 -228.00906 -2.40227 12.33865 16557.00000 + 42 4 4 -226.76453 23.11353 13.40943 15927.00000 + 42 4 5 -222.33735 34.71733 36.25071 17140.00000 + 42 5 0 -235.84349 20.49836 60.69918 11753.00000 + 42 5 1 -237.11055 -4.85589 59.05376 10975.00000 + 42 5 2 -241.44387 -15.95217 36.78774 11554.00000 + 42 5 3 -244.68099 -1.93047 15.14281 11729.00000 + 42 5 4 -243.48558 23.75926 16.29431 11158.00000 + 42 5 5 -239.02944 35.44108 39.11266 12047.00000 + 43 0 0 -153.16736 -56.58280 33.04047 3501.00000 + 43 0 1 -157.59249 -37.69792 35.87308 3897.00000 + 43 0 2 -154.05540 -30.09830 52.90444 4157.00000 + 43 0 3 -145.86808 -41.92413 67.29152 4130.00000 + 43 0 4 -141.99646 -61.05453 62.59415 3678.00000 + 43 0 5 -145.85333 -67.38160 45.70191 3305.00000 + 43 1 0 -163.59279 -60.01390 35.10534 6854.00000 + 43 1 1 -168.33219 -39.77537 38.17207 7628.00000 + 43 1 2 -164.51607 -31.56353 56.54849 8166.00000 + 43 1 3 -155.68732 -44.31367 72.06248 8129.00000 + 43 1 4 -151.51989 -64.89471 67.01926 7205.00000 + 43 1 5 -155.68807 -71.67533 48.81576 6490.00000 + 43 2 0 -177.76440 -64.72668 37.99367 9105.00000 + 43 2 1 -182.89595 -42.70149 41.39319 10156.00000 + 43 2 2 -178.70925 -33.70629 61.48217 10822.00000 + 43 2 3 -169.07203 -47.60842 78.46802 10786.00000 + 43 2 4 -164.55010 -70.02610 72.95515 9611.00000 + 43 2 5 -169.11671 -77.43949 53.03564 8679.00000 + 43 3 0 -193.72637 -69.89171 41.52255 12171.00000 + 43 3 1 -199.07960 -46.27010 45.35144 13208.00000 + 43 3 2 -194.50049 -36.88666 66.92596 13925.00000 + 43 3 3 -184.24281 -51.55465 85.15501 14037.00000 + 43 3 4 -179.36894 -75.63721 79.43906 12814.00000 + 43 3 5 -184.33042 -83.67913 57.87150 11631.00000 + 43 4 0 -211.38959 -75.50528 45.77178 15725.00000 + 43 4 1 -216.66628 -51.08083 50.30977 15838.00000 + 43 4 2 -211.82863 -41.30011 73.03155 16510.00000 + 43 4 3 -201.28320 -56.32281 91.83162 17049.00000 + 43 4 4 -196.10069 -81.42861 86.16316 16117.00000 + 43 4 5 -201.31848 -90.26560 63.30310 15053.00000 + 43 5 0 -226.84960 -80.17077 50.42787 11582.00000 + 43 5 1 -232.22293 -55.62557 55.26228 11228.00000 + 43 5 2 -227.32631 -45.70324 78.35008 11687.00000 + 43 5 3 -216.69758 -60.83224 97.17259 12035.00000 + 43 5 4 -211.42843 -86.03239 91.49074 11568.00000 + 43 5 5 -216.59480 -95.18250 68.28947 11116.00000 + 44 0 0 130.91467 40.04293 62.99978 4276.00000 + 44 0 1 134.56855 20.62272 62.64669 4109.00000 + 44 0 2 128.26882 9.51959 77.20058 4030.00000 + 44 0 3 117.93293 17.62006 92.85454 3867.00000 + 44 0 4 113.95855 36.56212 93.92895 3908.00000 + 44 0 5 120.42997 48.41427 78.82948 4194.00000 + 44 1 0 140.91553 42.58595 67.28621 8371.00000 + 44 1 1 144.83335 21.67758 66.94242 8045.00000 + 44 1 2 138.04618 9.77239 82.59884 7867.00000 + 44 1 3 126.94391 18.44639 99.43623 7582.00000 + 44 1 4 122.67510 38.81423 100.58127 7665.00000 + 44 1 5 129.61992 51.56992 84.35129 8257.00000 + 44 2 0 154.47036 45.93913 73.23612 11049.00000 + 44 2 1 158.69831 23.21771 72.90766 10620.00000 + 44 2 2 151.35364 10.13290 89.95562 10455.00000 + 44 2 3 139.25709 19.61402 108.30649 10114.00000 + 44 2 4 134.61630 41.86319 109.48438 10218.00000 + 44 2 5 142.16132 55.76686 91.85047 10960.00000 + 44 3 0 169.44781 49.31465 80.53349 14146.00000 + 44 3 1 173.92116 25.22801 80.18077 13536.00000 + 44 3 2 166.17973 11.17967 98.28758 13603.00000 + 44 3 3 153.25441 21.13732 118.00808 13405.00000 + 44 3 4 148.32744 45.08329 119.09204 13364.00000 + 44 3 5 156.36438 59.91421 100.29990 14245.00000 + 44 4 0 185.72158 52.75883 89.50502 16645.00000 + 44 4 1 190.31009 27.90411 89.14244 15647.00000 + 44 4 2 182.35064 13.24748 107.83276 16324.00000 + 44 4 3 169.11492 23.22024 128.06221 16557.00000 + 44 4 4 164.10003 48.27776 128.91255 15927.00000 + 44 4 5 172.37454 63.60091 109.60697 17140.00000 + 44 5 0 200.25927 55.47628 97.82754 11753.00000 + 44 5 1 204.91368 30.46938 97.45082 10975.00000 + 44 5 2 196.82157 15.74420 116.30201 11554.00000 + 44 5 3 183.63021 25.61433 136.40570 11729.00000 + 44 5 4 178.67020 50.86146 137.24128 11158.00000 + 44 5 5 186.89402 66.25412 117.94274 12047.00000 + 45 0 0 133.71425 -32.12031 59.87429 3501.00000 + 45 0 1 135.37635 -12.73789 62.28327 3897.00000 + 45 0 2 141.55739 -2.36178 47.63870 4157.00000 + 45 0 3 146.11581 -11.87993 30.24627 4130.00000 + 45 0 4 143.79756 -31.81074 29.60158 3678.00000 + 45 0 5 137.71386 -40.88880 44.46202 3305.00000 + 45 1 0 143.66612 -34.20872 64.49214 6854.00000 + 45 1 1 145.46392 -13.43132 67.04796 7628.00000 + 45 1 2 152.13114 -2.22395 51.24818 8166.00000 + 45 1 3 157.04614 -12.48571 32.49356 8129.00000 + 45 1 4 154.55663 -33.92606 31.79059 7205.00000 + 45 1 5 148.00301 -43.67104 47.81567 6490.00000 + 45 2 0 157.25235 -37.07977 70.70169 9105.00000 + 45 2 1 159.22615 -14.45853 73.41873 10156.00000 + 45 2 2 166.49982 -2.19030 56.13888 10822.00000 + 45 2 3 171.89305 -13.36678 35.62879 10786.00000 + 45 2 4 169.18299 -36.72273 34.88914 9611.00000 + 45 2 5 162.01463 -47.37960 52.42895 8679.00000 + 45 3 0 172.69564 -40.12109 77.49658 12171.00000 + 45 3 1 174.80706 -15.83804 80.17489 13208.00000 + 45 3 2 182.60553 -2.94043 61.53856 13925.00000 + 45 3 3 188.41283 -14.68165 39.60486 14037.00000 + 45 3 4 185.61404 -39.73427 38.64077 12814.00000 + 45 3 5 177.86859 -51.28626 57.64098 11631.00000 + 45 4 0 189.97466 -43.32136 84.75956 15725.00000 + 45 4 1 192.30856 -18.12457 86.91941 15838.00000 + 45 4 2 200.52882 -4.64184 67.27283 16510.00000 + 45 4 3 206.52472 -16.64556 44.68323 17049.00000 + 45 4 4 203.70432 -42.71594 43.39014 16117.00000 + 45 4 5 195.52065 -55.26995 63.47307 15053.00000 + 45 5 0 205.62036 -45.70179 90.41674 11582.00000 + 45 5 1 208.18640 -20.32240 92.41989 11228.00000 + 45 5 2 216.55668 -6.63649 72.46720 11687.00000 + 45 5 3 222.52129 -18.74691 49.79773 12035.00000 + 45 5 4 219.64311 -44.91939 48.45151 11568.00000 + 45 5 5 211.27059 -57.84890 68.73558 11116.00000 + 46 0 0 143.72825 21.94685 36.26164 4276.00000 + 46 0 1 140.25100 41.39821 36.67829 4109.00000 + 46 0 2 141.34704 51.58378 20.25166 4030.00000 + 46 0 3 146.04129 42.48855 2.56733 3867.00000 + 46 0 4 149.58880 23.47122 1.33930 3908.00000 + 46 0 5 148.50617 12.56925 18.37813 4194.00000 + 46 1 0 154.39219 23.04760 39.41224 8371.00000 + 46 1 1 150.65943 43.98859 39.82262 8045.00000 + 46 1 2 151.84298 54.90572 22.14953 7867.00000 + 46 1 3 156.89116 45.16422 3.13333 7582.00000 + 46 1 4 160.70275 24.71576 1.82375 7665.00000 + 46 1 5 159.53594 12.97889 20.13317 8257.00000 + 46 2 0 168.90429 24.64337 43.56329 11049.00000 + 46 2 1 164.85443 47.39619 43.95585 10620.00000 + 46 2 2 166.13934 59.41251 24.72705 10455.00000 + 46 2 3 171.65228 48.77052 4.00681 10114.00000 + 46 2 4 175.78687 26.43209 2.64675 10218.00000 + 46 2 5 174.53228 13.63759 22.54452 10960.00000 + 46 3 0 185.28771 26.79762 47.55234 14146.00000 + 46 3 1 180.98545 50.91443 47.96664 13536.00000 + 46 3 2 182.34732 63.83788 27.56390 13603.00000 + 46 3 3 188.25507 52.64284 5.31786 13405.00000 + 46 3 4 192.64001 28.60130 4.03883 13364.00000 + 46 3 5 191.30463 14.95205 25.24278 14245.00000 + 46 4 0 203.66779 29.46385 51.05235 16645.00000 + 46 4 1 199.20933 54.34150 51.46173 15647.00000 + 46 4 2 200.59056 67.83821 30.40399 16324.00000 + 46 4 3 206.59405 56.59021 7.57173 16557.00000 + 46 4 4 211.10827 31.44441 6.54121 15927.00000 + 46 4 5 209.77584 17.34534 28.34517 17140.00000 + 46 5 0 220.16898 32.21939 53.90037 11753.00000 + 46 5 1 215.70316 57.25954 54.34496 10975.00000 + 46 5 2 217.06740 70.79842 33.07248 11554.00000 + 46 5 3 222.99379 59.64728 10.35421 11729.00000 + 46 5 4 227.59615 34.33708 9.38992 11158.00000 + 46 5 5 226.25256 20.15759 31.16457 12047.00000 -- GitLab