class Experiment: def __init__(self, exp_dict): #expName, pointNum, overSampling): """Experiment class constructor. Args: exp_dict (dict): dictionnary of simulation algorithm parameters """ self.xmlExperimentFileName = "xmlFiles/Experiment.xml" self.xmldoc = minidom.parse(self.xmlExperimentFileName) self.name = exp_dict['experimentName'] self.exp_dict = exp_dict self.exp_dict['studyPixelSize'] = 0. self.exp_dict['studyDimensions'] = (0., 0.) self.exp_dict['inVacuum'] = False self.exp_dict['meanShotCount'] = 0 self.exp_dict['meanEnergy'] = 0 self.exp_dict['distSourceToMembrane'] = 0 self.exp_dict['distMembraneToObject'] = 0 self.exp_dict['distObjectToDetector'] = 0 #Parameters units self.exp_dict['studyPixelSize_unit'] = "um" self.exp_dict['studyDimensions_unit'] = "pixels" self.exp_dict['meanEnergy_unit'] = "keV" self.exp_dict['distSourceToMembrane_unit'] = "m" self.exp_dict['distMembraneToObject_unit'] = "m" self.exp_dict['distObjectToDetector_unit'] = "m" self.mySampleofInterest = None self.mySampleType = "" self.myDetector = None self.mySource = None self.myMembrane = None self.myPlate = None self.myAirVolume = None self.Dxreal = [] self.Dyreal = [] self.imageSampleBeforeDetection = [] self.imageReferenceBeforeDetection = [] self.imagePropagBeforeDetection = [] #Set correct values self.defineCorrectValues(exp_dict) self.myDetector.defineCorrectValuesDetector() self.mySource.defineCorrectValuesSource() self.mySampleofInterest.defineCorrectValuesSample() self.myAirVolume.defineCorrectValuesSample() self.myAirVolume.myThickness = ( self.exp_dict['distSourceToMembrane'] + self.exp_dict['distObjectToDetector'] + self.exp_dict['distMembraneToObject']) * 1e6 if self.myPlate is not None: self.myPlate.defineCorrectValuesSample() self.myMembrane.defineCorrectValuesSample() self.exp_dict['magnification'] = ( self.exp_dict['distSourceToMembrane'] + self.exp_dict['distObjectToDetector'] + self.exp_dict['distMembraneToObject']) / ( self.exp_dict['distSourceToMembrane'] + self.exp_dict['distMembraneToObject']) self.getStudyDimensions() #Set experiment data self.mySource.setMySpectrum( self.myDetector.det_param["photonCounting"]) self.myAirVolume.getDeltaBeta(self.mySource.mySpectrum) self.myAirVolume.getMyGeometry(self.exp_dict['studyDimensions'], self.exp_dict['studyPixelSize'], self.exp_dict['overSampling']) if self.myPlate is not None: self.myPlate.getDeltaBeta(self.mySource.mySpectrum) self.myPlate.getMyGeometry(self.exp_dict['studyDimensions'], self.exp_dict['studyPixelSize'], self.exp_dict['overSampling']) self.mySampleofInterest.getDeltaBeta(self.mySource.mySpectrum) self.mySampleofInterest.getMyGeometry(self.exp_dict['studyDimensions'], self.exp_dict['studyPixelSize'], self.exp_dict['overSampling']) self.myMembrane.getDeltaBeta(self.mySource.mySpectrum) self.myMembrane.membranePixelSize = self.exp_dict[ 'studyPixelSize'] * self.exp_dict['distSourceToMembrane'] / ( self.exp_dict['distSourceToMembrane'] + self.exp_dict['distMembraneToObject']) if self.myDetector.det_param['myScintillatorMaterial'] is not None: self.myDetector.getBeta(self.mySource.mySpectrum) self.myDetector.getSpectralEfficiency() #Check if oversampling is ok if self.exp_dict['simulation_type'] == "RayT": if self.exp_dict["overSampling"] < 2: print( f'/!\/!\ OVERSAMPLING FACTOR < MIN OVERSAMPLING FOR RAY-T MODEL: {exp_dict["overSampling"]} < 2' ) if self.exp_dict['simulation_type'] == "Fresnel": if self.mySource.source_dict["myType"] == "Polychromatic": is_overSampling_ok(self.exp_dict, self.myDetector.det_param['myPixelSize'], self.mySource.mySpectrum[-1][0] / 2) elif self.mySource.source_dict["myType"] == "Monochromatic": is_overSampling_ok(self.exp_dict, self.myDetector.det_param['myPixelSize'], self.mySource.source_dict["Energy"]) print('\nCurrent experiment:', self.name) print(f' Experiment in Vacuum: {self.exp_dict["inVacuum"]}') print(" Magnification :", self.exp_dict['magnification']) print(f' Study dimensions: {self.exp_dict["studyDimensions"]} pixels') print(" Sample pixel size =", self.exp_dict["studyPixelSize"], "um") print(" Over-overSampling factor: ", self.exp_dict["overSampling"]) print("\nCurrent detector: ", self.myDetector.myName) print( f' Detector pixel size: {self.myDetector.det_param["myPixelSize"]} um' ) if self.myDetector.det_param['myScintillatorMaterial'] is not None: print( f' Scintillator {self.myDetector.det_param["myScintillatorMaterial"]} of {self.myDetector.det_param["myScintillatorThickness"]}um' ) print(" Detectors dimensions: ", self.myDetector.det_param["myDimensions"]) print("\nCurrent source: ", self.mySource.myName) print(" Source type:", self.mySource.source_dict["myType"]) if self.mySource.source_dict["myType"] == 'Monochromatic': print(f'Energy: {self.mySource.source_dict["Energy"]} keV') else: if "myVoltage" in self.mySource.source_dict: print( f'Source voltage: {self.mySource.source_dict["myVoltage"]} kVp' ) if "myTargetMaterial" in self.mySource.source_dict: print( f'Anode material: {self.mySource.source_dict["myTargetMaterial"]}' ) if self.mySource.source_dict["filterMaterial"] is not None: print( f'filter: {self.mySource.source_dict["filterMaterial"]} of {self.mySource.source_dict["filterThickness"]} mm' ) print("\nCurrent sample:", self.mySampleofInterest.myName) print("\nCurrent membrane:", self.myMembrane.myName) def defineCorrectValues(self, exp_dict): """ Initializes every compound parameters before calculations Args: exp_dict (dictionnary): algorithm parameters. Raises: Exception: sample type not defined. ValueError: experiment not found in xml file. Returns: None. """ #Initialize object source and detector self.mySource = Source() self.myDetector = Detector(exp_dict) for experiment in self.xmldoc.documentElement.getElementsByTagName( "experiment"): correctExperiment = self.getText( experiment.getElementsByTagName("name")[0]) if correctExperiment == self.name: self.exp_dict['distSourceToMembrane'] = float( self.getText( experiment.getElementsByTagName("distSourceToMembrane") [0])) self.exp_dict['distMembraneToObject'] = float( self.getText( experiment.getElementsByTagName("distMembraneToObject") [0])) self.exp_dict['distObjectToDetector'] = float( self.getText( experiment.getElementsByTagName("distObjectToDetector") [0])) self.exp_dict['meanShotCount'] = float( self.getText( experiment.getElementsByTagName("meanShotCount") [0])) #/self.exp_dict['overSampling']**2 for node in experiment.childNodes: if node.localName == "inVacuum": self.exp_dict['inVacuum'] = bool( self.getText( experiment.getElementsByTagName("inVacuum") [0])) if node.localName == "PlateName": self.myPlate = AnalyticalSample() self.myPlate.myName = self.getText( experiment.getElementsByTagName("PlateName")[0]) self.myAirVolume = AnalyticalSample() self.myAirVolume.myName = "air_volume" #Initializing object sample and membrane self.mySampleType = self.getText( experiment.getElementsByTagName("sampleType")[0]) if self.mySampleType == "AnalyticalSample": self.mySampleofInterest = AnalyticalSample() else: raise Exception("sample type not defined") self.myMembrane = AnalyticalSample() #Getting the identity of the objects self.myMembrane.myName = self.getText( experiment.getElementsByTagName("membraneName")[0]) self.mySampleofInterest.myName = self.getText( experiment.getElementsByTagName("sampleName")[0]) self.myDetector.myName = self.getText( experiment.getElementsByTagName("detectorName")[0]) self.mySource.myName = self.getText( experiment.getElementsByTagName("sourceName")[0]) return raise ValueError("experiment not found in xml file") def getText(self, node): return node.childNodes[0].nodeValue def getStudyDimensions(self): """ Calculates the study dimensions considereing the geometry of the set up, the field of view and the sample pixels overoverSampling Returns: None. """ self.precision = (self.myDetector.det_param["myPixelSize"] / self.exp_dict['overSampling'] / self.exp_dict['distObjectToDetector']) self.exp_dict['studyDimensions'] = self.myDetector.det_param[ "myDimensions"] * int(self.exp_dict['overSampling']) self.exp_dict['studyDimensions'][0] = int( self.exp_dict['studyDimensions'][0]) self.exp_dict['studyDimensions'][1] = int( self.exp_dict['studyDimensions'][1]) self.exp_dict['studyPixelSize'] = self.myDetector.det_param[ "myPixelSize"] / self.exp_dict['overSampling'] / self.exp_dict[ 'magnification'] def wavePropagation(self, waveToPropagate, propagationDistance, Energy, magnification): """ Propagation of the wave Args: waveToPropagate (2d numpy array): incident wave. propagationDistance (Float): propagation distance in m. Energy (Float): considered eneregy in keV. magnification (Float): magnification on the considered segment from the source. Returns: TYPE: DESCRIPTION. """ if propagationDistance == 0: return waveToPropagate margin = 15 waveToPropagate = np.pad(waveToPropagate, margin, mode='reflect') #Propagateur de Fresnel k = getk(Energy * 1000) Nx, Ny = waveToPropagate.shape # Nx=self.exp_dict['studyDimensions'][0] # Ny=self.exp_dict['studyDimensions'][1] u, v = np.meshgrid(np.arange(0, Nx), np.arange(0, Ny)) u = (u - (Nx / 2)) v = (v - (Ny / 2)) u_m = u * 2 * pi / (self.exp_dict['studyDimensions'][0] * self.exp_dict['studyPixelSize'] * 1e-6) v_m = v * 2 * pi / (self.exp_dict['studyDimensions'][1] * self.exp_dict['studyPixelSize'] * 1e-6) uv_sqr = np.transpose(u_m**2 + v_m**2) # ie (u2+v2) waveAfterPropagation = np.exp( 1j * k * propagationDistance / magnification) * ifft2( ifftshift( np.exp(-1j * propagationDistance * (uv_sqr) / (2 * k * magnification)) * fftshift(fft2(waveToPropagate)))) waveAfterPropagation = waveAfterPropagation[margin:Nx - margin, margin:Ny - margin] return waveAfterPropagation def refraction(self, intensityRefracted, phi, propagationDistance, Energy, magnification, darkField=0): """ Computes the intensity after propagation with ray-tracing Args: intensityRefracted (2d numpy array): intensity before propagation. phi (2d numpy array): phase. propagationDistance (Float): propagation distance in m. Energy (Float): considered energy of the spectrum (in keV). magnification (Float): magnification of the considered segment from the source. Returns: intensityRefracted2 (2d numpy array): DESCRIPTION. Dx (2d numpy array): displacements along x. Dy (2d numpy array): displacements along y. """ if type(darkField) == int or type(darkField) == float: intensityRefracted2, Dx, Dy = fastRefraction( intensityRefracted, phi, propagationDistance, Energy, magnification, self.exp_dict["studyPixelSize"]) else: intensityRefracted2, Dx, Dy = fastRefractionDF( intensityRefracted, phi, propagationDistance, Energy, magnification, self.exp_dict["studyPixelSize"], darkField) return intensityRefracted2, Dx, Dy # def computeSampleAndReferenceImages_Fresnel(self, pointNum): """ Compute intensity changes on the path of the previously difined experiment to create all the images of the SBI experiment with FRESNEL PROPAGATOR Returns: SampleImage (2d numpy array): sample image simulated with sample and membrane. ReferenceImage (2d numpy array): reference image simulated with membrane. PropagImage (2d numpy array): propagation image simulated with only sample. detectedWhite (2d numpy array): white image without membrane and sample. """ #INITIALIZING PARAMETERS sumIntensity = 0 ibin = 0 if pointNum == 0: if any( elem < self.mySource.mySpectrum[0][0] for elem in self.myDetector.det_param["myBinsThersholds"] ) or any( elem > self.mySource.mySpectrum[-1][0] for elem in self.myDetector.det_param["myBinsThersholds"]): raise Exception( f'At least one of your detector bin threshold is outside your source spectrum. \nYour source spectrum ranges from {self.mySource.mySpectrum[0][0]} to {self.mySource.mySpectrum[-1][0]}' ) # self.myDetector.det_param["myBinsThersholds"].insert(0,self.mySource.mySpectrum[0][0]) self.myDetector.det_param["myBinsThersholds"].append( self.mySource.mySpectrum[-1][0]) nbins = len(self.myDetector.det_param["myBinsThersholds"]) SampleImage = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) ReferenceImage = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) PropagImage = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) detectedWhite = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) #INITIALIZING IMAGES incidentIntensity0 = np.ones( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1]) ) * (self.exp_dict['meanShotCount'] / self.exp_dict['overSampling']**2) self.imageSampleBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imageReferenceBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imagePropagBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) white = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) i = 0 #Calculating everything for each energy of the spectrum for currentEnergy, flux in self.mySource.mySpectrum: print("Current Energy:", currentEnergy) #Taking into account source window and air attenuation of intensity incidentIntensity = incidentIntensity0 * flux if not self.exp_dict['inVacuum']: incidentIntensity, _, _ = self.myAirVolume.setWaveRT( incidentIntensity, currentEnergy) #Take into account the detector scintillator efficiency if given in xml file if self.myDetector.det_param['myScintillatorMaterial'] is not None: for energyData, betaEn in self.myDetector.beta: if energyData == currentEnergy: beta = betaEn k = getk(currentEnergy * 1000) detectedSpectrum = 1 - np.exp( -2 * k * self.myDetector.det_param['myScintillatorThickness'] * 1e-6 * beta) # print("Scintillator efficiency for current energy:", detectedSpectrum) incidentIntensity = incidentIntensity * detectedSpectrum incidentWave = np.sqrt(incidentIntensity) #Passage of the incident wave through the membrane # print("Setting wave through membrane") self.waveSampleAfterMembrane = self.myMembrane.setWave( incidentWave, currentEnergy) magMemObj = (self.exp_dict['distSourceToMembrane'] + self.exp_dict['distMembraneToObject'] ) / self.exp_dict['distSourceToMembrane'] self.waveSampleBeforeSample = self.wavePropagation( self.waveSampleAfterMembrane, self.exp_dict['distMembraneToObject'], currentEnergy, magMemObj) # print("Setting wave through sample for sample image") self.waveSampleAfterSample = self.mySampleofInterest.setWave( self.waveSampleBeforeSample, currentEnergy) #Propagation to detector # print("Propagating waves to detector plane") self.waveSampleBeforeDetection = self.wavePropagation( self.waveSampleAfterSample, self.exp_dict['distObjectToDetector'], currentEnergy, self.exp_dict['magnification']) self.waveReferenceBeforeDetection = self.wavePropagation( self.waveSampleAfterMembrane, self.exp_dict['distObjectToDetector'] + self.exp_dict['distMembraneToObject'], currentEnergy, self.exp_dict['magnification']) #Combining intensities for several energies intensitySampleBeforeDetection = abs( self.waveSampleBeforeDetection)**2 if self.myPlate is not None: intensitySampleBeforeDetection, _, _ = self.myPlate.setWaveRT( intensitySampleBeforeDetection, currentEnergy) intensityReferenceBeforeDetection = abs( self.waveReferenceBeforeDetection)**2 if self.myPlate is not None: intensityReferenceBeforeDetection, _, _ = self.myPlate.setWaveRT( intensityReferenceBeforeDetection, currentEnergy) self.imageSampleBeforeDetection += intensitySampleBeforeDetection self.imageReferenceBeforeDetection += intensityReferenceBeforeDetection sumIntensity += np.mean(intensityReferenceBeforeDetection) self.exp_dict['meanEnergy'] += currentEnergy * np.mean( intensityReferenceBeforeDetection) if pointNum == 0: #We only do it for the first point # print("Setting wave through sample for propag and abs image") self.wavePropagAfterSample = self.mySampleofInterest.setWave( incidentWave, currentEnergy) self.wavePropagBeforeDetection = self.wavePropagation( self.wavePropagAfterSample, self.exp_dict['distObjectToDetector'], currentEnergy, self.exp_dict['magnification']) intensityPropagBeforeDetection = abs( self.wavePropagBeforeDetection)**2 if self.myPlate is not None: intensityPropagBeforeDetection, _, _ = self.myPlate.setWaveRT( intensityPropagBeforeDetection, currentEnergy) self.imagePropagBeforeDetection += intensityPropagBeforeDetection i += 1 incidentIntensityWhite = incidentWave**2 if self.myPlate is not None: incidentIntensityWhite, _, _ = self.myPlate.setWaveRT( incidentWave**2, currentEnergy) white += incidentIntensityWhite if currentEnergy > self.myDetector.det_param["myBinsThersholds"][ ibin] - self.mySource.source_dict["myEnergySampling"] / 2: effectiveSourceSize = self.mySource.source_dict[ "mySize"] * self.exp_dict['distObjectToDetector'] / ( self.exp_dict['distSourceToMembrane'] + self.exp_dict['distMembraneToObject'] ) / self.myDetector.det_param[ 'myPixelSize'] * self.exp_dict['overSampling'] #FWHM #DETECTION IMAGES FOR ENERGY BIN print("Mean energy detected in reference image", self.exp_dict['meanEnergy']) #DETECTION IMAGES FOR ENERGY BIN # print("Detection sample image") SampleImage[ibin] = self.myDetector.detection( self.imageSampleBeforeDetection, effectiveSourceSize, self.exp_dict) # print("Detection reference image") ReferenceImage[ibin] = self.myDetector.detection( self.imageReferenceBeforeDetection, effectiveSourceSize, self.exp_dict) if pointNum == 0: # print("Detection propagation image") PropagImage[ibin] = self.myDetector.detection( self.imagePropagBeforeDetection, effectiveSourceSize, self.exp_dict) detectedWhite[ibin] = self.myDetector.detection( white, effectiveSourceSize, self.exp_dict) self.imageSampleBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imageReferenceBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imagePropagBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) white = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) ibin += 1 self.exp_dict[ 'meanEnergy'] = self.exp_dict['meanEnergy'] / sumIntensity return SampleImage, ReferenceImage, PropagImage, detectedWhite def computeSampleAndReferenceImages_RT(self, pointNum): """ Compute intensity changes on the path of the previously difined experiment to create all the images of the SBI experiment with ray-tracing Returns: SampleImage (2d numpy array): sample image simulated with sample and membrane. ReferenceImage (2d numpy array): reference image simulated with membrane. PropagImage (2d numpy array): propagation image simulated with only sample. detectedWhite (2d numpy array): white image without membrane and sample. 2d numpy array: real Dx from sample to detector. 2d numpy array: real Dy from sample to detector. """ #INITIALIZING PARAMETERS sumIntensity = 0 ibin = 0 if pointNum == 0: if any( elem < self.mySource.mySpectrum[0][0] for elem in self.myDetector.det_param["myBinsThersholds"] ) or any( elem > self.mySource.mySpectrum[-1][0] for elem in self.myDetector.det_param["myBinsThersholds"]): raise Exception( f'At least one of your detector bin threshold is outside your source spectrum. \nYour source spectrum ranges from {self.mySource.mySpectrum[0][0]} to {self.mySource.mySpectrum[-1][0]}' ) # self.myDetector.det_param["myBinsThersholds"].insert(0,self.mySource.mySpectrum[0][0]) self.myDetector.det_param["myBinsThersholds"].append( self.mySource.mySpectrum[-1][0]) nbins = len(self.myDetector.det_param["myBinsThersholds"]) SampleImage = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) ReferenceImage = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) PropagImage = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) detectedWhite = np.zeros( (nbins, self.myDetector.det_param['myDimensions'][0], self.myDetector.det_param['myDimensions'][1])) #INITIALIZING IMAGES incidentIntensity0 = np.ones( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1]) ) * (self.exp_dict['meanShotCount'] / self.exp_dict['overSampling']**2) incidentPhi = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) incidentDF = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imageSampleBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imageReferenceBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imagePropagBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.darkFieldPropag = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) white = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) #Calculating everything for each energy of the spectrum for currentEnergy, flux in self.mySource.mySpectrum: print("Current Energy: %gkev" % currentEnergy) incidentIntensity = incidentIntensity0 * flux if not self.exp_dict['inVacuum']: incidentIntensity, _, _ = self.myAirVolume.setWaveRT( incidentIntensity, currentEnergy) #Take into account the detector scintillator efficiency if given in xml file if self.myDetector.det_param["myScintillatorMaterial"] is not None: for energyData, efficiency in self.myDetector.mySpectralEfficiency: if energyData == currentEnergy: incidentIntensity = incidentIntensity * efficiency #Passage of the incident wave through the membrane # print("Setting wave through membrane") self.IntensitySampleAfterMembrane, phiWaveSampleAfterMembrane, _ = self.myMembrane.setWaveRT( incidentIntensity, currentEnergy, incidentPhi) #Propagation from membrane to object and passage through the object self.IntensitySampleBeforeSample, _, _ = self.refraction( abs(self.IntensitySampleAfterMembrane), phiWaveSampleAfterMembrane, self.exp_dict['distMembraneToObject'], currentEnergy, self.exp_dict['magnification']) # print("Setting wave through sample for sample image") self.IntensitySampleAfterSample, phiWaveSampleAfterSample, DarkField = self.mySampleofInterest.setWaveRT( self.IntensitySampleBeforeSample, currentEnergy, phiWaveSampleAfterMembrane, incidentDF) #Propagation to detector # print("Propagating waves to detector plane") self.imageSampleAfterRefraction, _, _ = self.refraction( abs(self.IntensitySampleAfterSample), phiWaveSampleAfterSample, self.exp_dict['distObjectToDetector'], currentEnergy, self.exp_dict['magnification'], DarkField) self.imageReferenceAfterRefraction, _, _ = self.refraction( abs(self.IntensitySampleBeforeSample), phiWaveSampleAfterMembrane, self.exp_dict['distObjectToDetector'], currentEnergy, self.exp_dict['magnification']) intensitySampleBeforeDetection = self.imageSampleAfterRefraction intensityReferenceBeforeDetection = self.imageReferenceAfterRefraction #Plate attenuation if self.myPlate is not None: intensitySampleBeforeDetection, _, _ = self.myPlate.setWaveRT( intensitySampleBeforeDetection, currentEnergy) intensityReferenceBeforeDetection, _, _ = self.myPlate.setWaveRT( intensityReferenceBeforeDetection, currentEnergy) #Combining intensities for several energies self.imageSampleBeforeDetection += intensitySampleBeforeDetection self.imageReferenceBeforeDetection += intensityReferenceBeforeDetection sumIntensity += np.mean(intensityReferenceBeforeDetection) self.exp_dict['meanEnergy'] += currentEnergy * np.mean( intensityReferenceBeforeDetection) if pointNum == 0: #We only do it for the first point # print("Setting wave through sample for propag and abs image") self.IntensityPropagAfterSample, phiWavePropagAfterSample, DarkFieldPropag = self.mySampleofInterest.setWaveRT( incidentIntensity, currentEnergy, incidentPhi, incidentDF) self.darkFieldPropag += DarkFieldPropag * flux self.imagePropagAfterRefraction, self.Dxreal, self.Dyreal = self.refraction( abs(self.IntensityPropagAfterSample), phiWavePropagAfterSample, self.exp_dict['distObjectToDetector'], currentEnergy, self.exp_dict['magnification'], DarkFieldPropag) intensityPropagBeforeDetection = self.imagePropagAfterRefraction if self.myPlate is not None: intensityPropagBeforeDetection, _, _ = self.myPlate.setWaveRT( intensityPropagBeforeDetection, currentEnergy) incidentIntensity, _, _ = self.myPlate.setWaveRT( incidentIntensity, currentEnergy) white += incidentIntensity self.imagePropagBeforeDetection += intensityPropagBeforeDetection if currentEnergy > self.myDetector.det_param["myBinsThersholds"][ ibin] - self.mySource.source_dict["myEnergySampling"] / 2: effectiveSourceSize = self.mySource.source_dict[ "mySize"] * self.exp_dict['distObjectToDetector'] / ( self.exp_dict['distSourceToMembrane'] + self.exp_dict['distMembraneToObject'] ) / self.myDetector.det_param[ 'myPixelSize'] * self.exp_dict['overSampling'] #FWHM #DETECTION IMAGES FOR ENERGY BIN # print("Detection sample image") SampleImage[ibin] = self.myDetector.detection( self.imageSampleBeforeDetection, effectiveSourceSize, self.exp_dict) # print("Detection reference image") ReferenceImage[ibin] = self.myDetector.detection( self.imageReferenceBeforeDetection, effectiveSourceSize, self.exp_dict) if pointNum == 0: self.imagePropagBeforeDetection = self.imagePropagBeforeDetection # print("Detection propagation image") PropagImage[ibin] = self.myDetector.detection( self.imagePropagBeforeDetection, effectiveSourceSize, self.exp_dict) detectedWhite[ibin] = self.myDetector.detection( white, effectiveSourceSize, self.exp_dict) self.imageSampleBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imageReferenceBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) self.imagePropagBeforeDetection = np.zeros( (self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) white = np.zeros((self.exp_dict['studyDimensions'][0], self.exp_dict['studyDimensions'][1])) ibin += 1 self.exp_dict[ 'meanEnergy'] = self.exp_dict['meanEnergy'] / sumIntensity print("Mean detected energy in reference image", self.exp_dict['meanEnergy']) return SampleImage, ReferenceImage, PropagImage, detectedWhite, self.Dxreal, self.Dyreal, self.darkFieldPropag def saveAllParameters(self, time0, expDict): """ Saves all the experimental and algorithm parameters in a txt file Args: time0 (float): time at the beginning of the calculation. expDict (dictionnary): dictionnary containing algorithm parameters. Returns: None. """ fileName = expDict['filepath'] + self.name + '_' + str( expDict['expID']) + ".txt" print("file name: ", fileName) f = open(fileName, "w+") f.write("EXPERIMENT PARAMETERS - " + expDict['simulation_type'] + " - " + str(expDict['expID'])) for cle, valeur in self.exp_dict.items(): if cle.split('_')[-1] != 'unit': if cle + "_unit" in self.exp_dict: cleUnit = cle + "_unit" f.write(f'\n {cle}: {valeur} {self.exp_dict[cleUnit]}') else: f.write(f'\n {cle}: {valeur}') f.write("\n\nEntire computing time: %gs" % (time.time() - time0)) f.write("\n\nSource parameters:") f.write("\nSource name: %s" % self.mySource.myName) for cle, valeur in self.mySource.source_dict.items(): if cle.split('_')[-1] != 'unit': if cle + "_unit" in self.mySource.source_dict: cleUnit = cle + "_unit" f.write( f'\n {cle}: {valeur} {self.mySource.source_dict[cleUnit]}' ) else: f.write(f'\n {cle}: {valeur}') f.write("\n\nDetector parameters:") f.write("\nDetector name: %s" % self.myDetector.myName) for cle, valeur in self.myDetector.det_param.items(): if cle.split('_')[-1] != 'unit': if cle + "_unit" in self.myDetector.det_param: cleUnit = cle + "_unit" f.write( f'\n {cle}: {valeur} {self.myDetector.det_param[cleUnit]}' ) else: f.write(f'\n {cle}: {valeur}') f.write("\n\nSample informations") f.write("\nSample name: %s" % self.mySampleofInterest.myName) f.write("\nSample type: %s" % self.mySampleType) f.write("\n materials: %s" % self.mySampleofInterest.myMaterials) if self.mySampleofInterest.geom_parameters is not None: for cle, valeur in self.mySampleofInterest.geom_parameters.items(): f.write(f'\n {cle}: {valeur[0]} {valeur[1]}') if self.mySampleofInterest.myGeometryFunction == "openContrastPhantom": f.write("\nContrast Phantom geometry folder: %s" % self.mySampleofInterest.myGeometryFolder) f.write("\n\nMembrane informations:") f.write("\nMembrane name: %s" % self.myMembrane.myName) f.write("\nMembrane type: %s" % self.myMembrane.myType) f.write("\n materials: %s" % self.myMembrane.myMaterials) f.write("\n Membrane geometry function: %s" % self.myMembrane.myGeometryFunction) if self.myMembrane.geom_parameters is not None: for cle, valeur in self.mySampleofInterest.geom_parameters.items(): f.write(f'\n {cle}: {valeur[0]} {valeur[1]}') if self.myMembrane.myGeometryFunction == "getMembraneFromFile": f.write("\nMembrane geometry file: %s" % self.myMembrane.myMembraneFile) if self.myPlate is not None: f.write("\n\nDetectors protection Plate") f.write("Plate thickness: %s" % self.myPlate.myThickness) f.write("Plate Material: %s" % self.myPlate.myMaterials) f.close() return