// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // The code was written by : // ^Claudio Andenna claudio.andenna@ispesl.it, claudio.andenna@iss.infn.it // *Barbara Caccia barbara.caccia@iss.it // with the support of Pablo Cirrone (LNS, INFN Catania Italy) // with the contribute of Alessandro Occhigrossi* // // ^INAIL DIPIA - ex ISPESL and INFN Roma, gruppo collegato Sanità, Italy // *Istituto Superiore di Sanità and INFN Roma, gruppo collegato Sanità, Italy // Viale Regina Elena 299, 00161 Roma (Italy) // tel (39) 06 49902246 // fax (39) 06 49387075 // // more information: // http://g4advancedexamples.lngs.infn.it/Examples/medical-linac // //*******************************************************// #include #include "ML2ExpVoxels.hh" #include "G4SystemOfUnits.hh" CML2ExpVoxels::CML2ExpVoxels(G4bool bData, G4int saveEvents, G4int seed, G4String FileExperimentalData, G4String FileExperimentalDataOut):startCurve(0), stopCurve(0),chi2Factor(0) { char a[10]; sprintf(a,"%d", seed); seedName = (G4String)a; saving_in_Selected_Voxels_every_events = saveEvents; nRecycling = 1; fullFileOut = FileExperimentalDataOut+seedName+".m"; fullFileIn = FileExperimentalData; nParticle = nTotalEvents = 0; // define the extremes of global-volume containing all experimental voxels G4double extr = 100000000000.; minZone.set(extr, extr, extr); maxZone.set(-extr, -extr, -extr); bHasExperimentalData = bData; } CML2ExpVoxels::~CML2ExpVoxels(void) { delete [] startCurve; delete [] stopCurve; delete [] chi2Factor; delete [] nVoxelsgeometry; } G4bool CML2ExpVoxels::loadData(void) { bHasExperimentalData = true; std::ifstream in; Svoxel voxel; voxel.volumeId = 0; G4ThreeVector pos, halfSize; G4double expDose; in.open(fullFileIn, std::ios::in); if (in) { G4String appo; char a[1000]; in.getline(a,1000,'\n'); headerText1 = (G4String)a; in.getline(a,1000,'\n'); in >> nCurves; startCurve = new G4int[nCurves]; stopCurve = new G4int[nCurves]; chi2Factor = new G4double[nCurves]; for (int i = 0; i < nCurves; i++) { chi2Factor[i] = 0.; in >> startCurve[i]; in >> stopCurve[i]; in >> chi2Factor[i]; } in.getline(a,1000,'\n'); in.getline(a,1000,'\n'); headerText2 = (G4String)a; std::string line; while ( !in.eof() ) { in >> pos; in >> halfSize; if (bHasExperimentalData) { in >> expDose; voxel.expDose = expDose/100.*(joule/kg); // input data in cGy } else { voxel.expDose = 0.; } voxel.pos=pos; voxel.halfSize = halfSize; voxel.depEnergy = 0.; voxel.depEnergy2 = 0.; voxel.nEvents = 0; voxel.depEnergyNorm = 0.; voxel.depEnergyNormError = 0.; vec_voxels.push_back(voxel); // calculate the actual extremes of the global-volume containing all the experimental data if ( minZone.getX()>pos.getX()-halfSize.getX() ) { minZone.setX(pos.getX()-halfSize.getX()); } if ( maxZone.getX()pos.getY()-halfSize.getY() ) { minZone.setY(pos.getY()-halfSize.getY()); } if ( maxZone.getY()pos.getZ()-halfSize.getZ() ) { minZone.setZ(pos.getZ()-halfSize.getZ()); } if ( maxZone.getZ()GetPreStepPoint()->GetPosition(); depEnergy = aStep->GetTotalEnergyDeposit(); density = aStep->GetPreStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetMaterial()->GetDensity(); G4ThreeVector minPos, maxPos; G4bool newEvent=false; G4double voxelMass, dose; // check if the event is inside the global-volume if (minZone.getX() <= pos.getX() && pos.getX() < maxZone.getX() && minZone.getY() <= pos.getY() && pos.getY() < maxZone.getY() && minZone.getZ() <= pos.getZ() && pos.getZ() < maxZone.getZ()) { // look for the voxel containing the event for (int i = 0; i < (int)vec_voxels.size(); i++) { minPos = vec_voxels[i].pos-vec_voxels[i].halfSize; maxPos = vec_voxels[i].pos+vec_voxels[i].halfSize; if ( minPos.getX() <= pos.getX() && pos.getX() < maxPos.getX() && minPos.getY() <= pos.getY() && pos.getY() < maxPos.getY() && minPos.getZ() <= pos.getZ() && pos.getZ() < maxPos.getZ() ) { voxelVolume = vec_voxels[i].halfSize.getX()*vec_voxels[i].halfSize.getY()*vec_voxels[i].halfSize.getZ()*8.; voxelMass = density*voxelVolume; // calculate the dose dose=depEnergy/(voxelMass*nRecycling); vec_voxels[i].nEvents++; nVoxelsgeometry[i]++; vec_voxels[i].depEnergy += dose; vec_voxels[i].depEnergy2 += dose*dose; newEvent = true; Sparticle *particle = new Sparticle; particle -> dir = aStep -> GetPreStepPoint() -> GetMomentumDirection(); particle -> pos = aStep -> GetPreStepPoint() -> GetPosition(); particle -> kinEnergy = dose; // I use the same kinEnergy name to store the dose particle -> nPrimaryPart = -1; particle -> partPDGE = aStep -> GetTrack() -> GetDefinition() -> GetPDGEncoding(); particle -> primaryParticlePDGE = -1; particle -> volumeId = i; // voxel index where the dose is accumulating particle -> volumeName = "-1"; } } if ( newEvent ) { // save data nTotalEvents++; if ( nTotalEvents%saving_in_Selected_Voxels_every_events == 0 && nTotalEvents > 0 ) { saveResults(); } } } } G4int CML2ExpVoxels::getMinNumberOfEvents() { int n = vec_voxels[0].nEvents; for (int i = 0; i < (int)vec_voxels.size(); i++) { if ( n > vec_voxels[i].nEvents ) { n = vec_voxels[i].nEvents; } } return n; } G4int CML2ExpVoxels::getMaxNumberOfEvents() { int n = nVoxelsgeometry[0]; for ( int i = 0; i < (int)vec_voxels.size(); i++) { if ( n < nVoxelsgeometry[i] ) { n = nVoxelsgeometry[i]; } } return n; } void CML2ExpVoxels::saveHeader() { std::ofstream out; out.open(fullFileOut, std::ios::out); out << "% " << headerText1 << G4endl; out << "n" << seedName << "=" << nCurves << ";" << G4endl; out << "fh" << seedName << "=[" << G4endl; for (int i = 0; i< nCurves; i++) { out << startCurve[i] << '\t'; out << stopCurve[i] << '\t'; out << chi2Factor[i] << G4endl; } out << "];" << G4endl; out << "% x [mm], y [mm], z [mm], Dx [mm], Dy [mm], Dz [mm], expDose [Gy], Calculated dose [Gy], Calculated dose2 [Gy^2], nEvents, normDose [Gy], normDoseError [Gy]"; out << G4endl; out.close(); } void CML2ExpVoxels::saveResults() { if (nTotalEvents > 0) { calculateNormalizedEd(vec_voxels); saveHeader(); std::ofstream out; out.open(fullFileOut, std::ios::app); out << "d" << seedName << "=[" << G4endl; for (int i=0; i<(int)vec_voxels.size(); i++) { out << vec_voxels[i].pos.getX()/mm << '\t' << vec_voxels[i].pos.getY()/mm << '\t' << vec_voxels[i].pos.getZ()/mm << '\t'; out << vec_voxels[i].halfSize.getX()/mm << '\t' << vec_voxels[i].halfSize.getY()/mm << '\t' << vec_voxels[i].halfSize.getZ()/mm << '\t'; out << vec_voxels[i].expDose/(joule/kg) << '\t' << vec_voxels[i].depEnergy/(joule/kg) << '\t' << vec_voxels[i].depEnergy2/((joule/kg)*(joule/kg)) << '\t' << vec_voxels[i].nEvents << '\t'; out << vec_voxels[i].depEnergyNorm/(joule/kg) << '\t' << vec_voxels[i].depEnergyNormError/(joule/kg); out << G4endl; } out << "];" << G4endl; out.close(); } } void CML2ExpVoxels::calculateNormalizedEd(std::vector &vox) { int i,j; G4double cs, cc; int n; G4double d2, dd; G4double v; for (j = 0; j < nCurves; j++) { cs = cc = 0.; for (i = startCurve[j]-1;i0.) { chi2Factor[j] = cs/cc; } for (i = startCurve[j]-1; i < stopCurve[j]; i++) { dd = vox[i].depEnergy*vox[i].depEnergy; d2 = vox[i].depEnergy2; n = vox[i].nEvents; vox[i].depEnergyNorm = chi2Factor[j]*vox[i].depEnergy; v = n*d2-dd; if (v < 0.) { v=0; } if (n > 1) { vox[i].depEnergyNormError = chi2Factor[j]*std::sqrt(v/(n-1)); } if (n == 1) { vox[i].depEnergyNormError = vox[i].depEnergyNorm; } } } }