Select Git revision
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
bg_subtraction.py 37.58 KiB
import numpy as np
import pathlib
from functions.utils import round_to_multiple, find_nearest, shorten_matrix_elements, getIfile
from functions.export import outputDatFile
rootdir = str(pathlib.Path(__file__).parent.resolve())
class Processing_Data:
""" Class to filter, average, rebin, BG-subtract and generate PDFs from XRD/TS data.
Raises:
Exception: _description_
"""
#----------------------------------------------------------------------------------------#
# Get Start and End of ramp #
#----------------------------------------------------------------------------------------#
def getTempPoints(self,rampTemp,holdTemp):
"""
Arguments
----------
rampTemp: temperature the ramp is defined to start
holdTemp: temperature the plato is defined to start
"""
# Logging the event
self.logger['Scan idizes of the ramp satrt and end collected'] = { 'Temperature the ramp is set to start': rampTemp,
'Temperatrue the plato is set to start': holdTemp}
# Set initial status varibles
ramp_started = False
plato_started = False
plato_ended = False
# Normalize the file index for start and end scan given
if self.startScan > 0:
if self.endScan < self.number_of_files*self.number_of_steps:
file_index = np.linspace(self.startScan,self.endScan,self.number_of_files)
else:
file_index = np.linspace(self.startScan,self.number_of_files*self.number_of_steps,self.number_of_files)
else:
if self.endScan < self.number_of_files*self.number_of_steps:
file_index = np.linspace(1,self.endScan,self.number_of_files)
else:
file_index = np.linspace(1,self.number_of_files*self.number_of_steps,self.number_of_files)
# Give feedback to the user about the status of the integration.
# --> If more .metadata files are available the .chi/.dat.
if len(file_index) < len(self.temp_array):
print('\n\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
print(' Live integration lags behind by ' + str(len(self.temp_array) - len(file_index)) + ' scans')
print(' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n')
# Here we loop over the temperature array
for i,j in enumerate(self.temp_array):
# And check if this is still below the temperature threshold of the ramp.
if j > rampTemp and ramp_started is False:
# If the threshold is reached, this experimantal temperature is logged and
# the status varible is updated
print('Ramp start: ', file_index[i],'Temp: ', j)
self.rampstart_index = int(file_index[i])
ramp_started = True
self.logger['Ramp Start'] = { 'Index': file_index[i],
'Temperature': j}
# Here we check if the ramp has finished and the final temperature is reached
if j > holdTemp and plato_started is False:
# If the threshold is reached, this experimantal temperature is logged and
# the status varible is updated
print('Plato start: ',file_index[i],'Temp: ', j)
self.platostart_index = int(file_index[i])
plato_started = True
self.logger['Plato Start'] = { 'Index': file_index[i],
'Temperature': j}
# Finally we check when the cooldown is reached
if j < holdTemp-5 and plato_ended is False and plato_started is True:
# If the threshold is reached, this experimantal temperature is logged and
# the status varible is updated
print('Plato endet: ', file_index[i],'Temp: ', j)
plato_ended = True
self.platoend_index = int(file_index[i])
self.logger['Plato End'] = { 'Index': file_index[i],
'Temperature': j}
# If a threshold is never reached an error is risen.
if 'platostart_index' not in dir(self):
raise Exception(f"Temperature always below the defined set tempertaure of {holdTemp}. Temperature is at max {max(self.temp_array)}")
# If no cooldown is measured we stop
if 'platoend_index' not in dir(self):
self.platoend_index = len(self.temp_array)
return self.logger, self.rampstart_index, self.platoend_index, self.platoend_index
#----------------------------------------------------------------------------------------#
# Get parts of ramps and platos #
#----------------------------------------------------------------------------------------#
def getRampPlatoLists(self,heat_ranges):
""" Check which parts of the data belong to a plato (befor starting the temperature ramp and when holding the final temperature)
and which parts belong to a temperature ramp.
Arguments
----------
heat ranges: heat ranges dictionary including the start and end of the temp ramp
"""
# Logging the event
self.logger['I(q) for Ramp and Plato where collected in lists'] = { 'Heatrages input': heat_ranges,}
# Create the empty lists
plato_file_list = []
self.plato_list = [[],[]]
ramp_file_list = []
self.ramp_list = [[],[]]
# Step one is the plato at room temperature befor ramping
step = 1
# Give user feedback about the determined temperatures
print(heat_ranges)
# Loop over every I(q) from each scan
for i, j in enumerate(self.I):
# If step is odd it´s a plato
if step % 2 != 0:
plato_file_list.append(j)
# If step is even it´s ramp
if step % 2 == 0:
ramp_file_list.append(j)
# Here we check when the ramp starts and account for averaging
if i == round_to_multiple(heat_ranges["ramp1_start"],self.average) /self.average:
# We put the array of all I(q) from the first plato (at room temperature) as a first element of a list of all platos
self.plato_list[0].append(plato_file_list)
plato_file_list = []
# We move on to the first ramp
step = 2
# Here we check when the first set temperature starts and account for averaging
if i == round_to_multiple(heat_ranges["ramp1_end"],self.average) /self.average:
# We put the array of all I(q) from the first ramp as a first element of a list of all ramps
self.ramp_list[0].append(ramp_file_list)
ramp_file_list = []
step = 3
# Here we check when second ramp starts (if set) and account for averaging
if i == round_to_multiple(heat_ranges["ramp2_start"],self.average) /self.average:
# We put the array of all I(q) from the second plato (at the first set temperature) as a first element of a list of all platos
self.plato_list[0].append(plato_file_list)
plato_file_list = []
# It´s rare but we also can move on to a second ramp
step = 4
# Here we check when the second set temperature (if set) starts and account for averaging
if i == round_to_multiple(heat_ranges["ramp2_end"],self.average) /self.average:
# We put the array of all I(q) from the second ramp as a first element of a list of all ramps
self.ramp_list[0].append(ramp_file_list)
ramp_file_list = []
# It´s rare but we also can move on to a second hold tmperature
step = 5
# It´s rare but we also can put the array of all I(q) from the third plato (at the second set temperature) as a first element of a list of all platos
self.plato_list[0].append(plato_file_list)
plato_file_list = []
return self.logger, self.plato_list, self.ramp_list
#----------------------------------------------------------------------------------------#
# Background Subtraction #
#----------------------------------------------------------------------------------------#
def bgSubtraction(self, heat_ranges, outputPath, bg_sampleName: str = "background_undifiend_by_user", plato_bg_list = None, ramp_bg_list = None, mode: str='last',
Qmaxinst: float=30, FactorMax: float=0.99,single_BG_file: str=None, empty_glas_int: float=0, correction: list = 0,
empty_glas: str=None, Qmin: float=None, Qmax: float=None, qparts: int=30, convergence_critierium: float= 0.9, convergence_step: float=0.001,
use_PDF_maximization: bool=False, R_limits: list = [1.8, 2.5], grid_size: int=8, reducing_steps: int=5, starting_step_width: float=0.1):
"""Automated BG subtraction
Args:
heat_ranges (dict): heat ranges dictionary including the start and end of the temp ramp.
outputPath (str): Path to where .dat generated after BG subtration are saved.
bg_sampleName (str): Name of the BG sample for .dat output. Defaults to "background_undifiend_by_user".
plato_bg_list (list): list of array from the plato related background scans. Not needed for single background file. Defaults to None.
ramp_bg_list (list): list of array from the ramp related background scans. Not needed for single background file. Defaults to None.
mode (str, optional): Choose "last" to repeat the last background scan or "average" to use an everage of the plato. Defaults to 'last'.
FactorMax (float, optional): Maximum factor allowed for the background intesity subtracted from the data. Defaults to 0.99.
single_BG_file (str, optional): Path to a single background if only one background file should be subtracted from all data. Defaults to None.
empty_glas_int (float, optional): Intensity with which a constant contribution of glas is removed from each scan. Defaults to 0.
empty_glas (str, optional): Path to the empty glas file. Defaults to None.
Qmin (float, optional): Minimum Q that is included in the BG subtrastion (this can purposly differ from Qmin for PDF generation). Defaults to None.
Qmax (float, optional): Maximum Q that is included in the BG subtrastion (this can purposly differ from Qmax for PDF generation). Defaults to None.
use_PDF_maximization (bool, optional): Make a rought PDF around the expected Peak and maximize the PDF iterativ. Defaults to False.
R_limits (list): List containing the Q-range for the PDF maximization [lowest Q, higherst Q].Defaults to [2,4].
reducing_steps (int, optional): Number of improved steps after which the step width is reduced. Defaults to 5.
starting_step_width (float, optional): Starting scattering range allowed for the random values generated around the current best value. Defaults to 0.1.
Returns:
self: updated self varibles
"""
self.flipps = 0
self.alltime_low = 1e10
self.alltime_low_area = 1e10
self.alltime_low_area2 = 1e10
self.time_average = None
# Logging the event
self.logger['Background was subtracted'] = {'heat ranges used': heat_ranges,
'Name of the background': bg_sampleName,
'Mode used for shorter background array': mode,
'Maximum factor allowed': FactorMax,
'Path to single background file (if used)': single_BG_file,
'Q cutted at Qmaxinst': Qmaxinst,}
# FInding the corresponding Qmax and Qmin in the q array, or which number is closest to it and getting the index
if Qmax is not None:
Qmax = find_nearest(self.q,Qmax)[0]
else:
Qmax = None
if Qmin is not None:
Qmin = find_nearest(self.q,Qmin)[0]
else:
Qmin = 0
self.closest_Qmax = Qmax
# self.q = self.q[Qmin:Qmax]
# shorten_matrix_elements(self.I,[Qmin,Qmax])
if isinstance(correction, (int, float)):
correction = [float(correction)] * len(self.I)
# Loading empty glas contrebution if given
if empty_glas is not None:
self.q_empty_glas, self.I_empty_glas = np.loadtxt(empty_glas,skiprows=1).T
else:
self.q_empty_glas = 0
self.I_empty_glas = 0
# Setting new lists for factors
self.factor_list = []
self.raw_factor_list = []
self.subtracted_I = []
# If the BG is temperature or time dependent one has two options if the data set is shorter then the real experiment
if single_BG_file is None:
# Setting new lists for ramps and platos
self.plato_bg_list = plato_bg_list
self.ramp_bg_list = ramp_bg_list
# The first option is to use the last scan over and over
if mode == 'last':
# Then we append the last scan as many times as scans are missing to mich the real experiment
for i,j in enumerate(self.plato_list[0]):
if len(j) > len(self.plato_bg_list[0][i]):
for k in range(int(len(j)-len(self.plato_bg_list[0][i]))):
self.plato_bg_list[0][i].append(self.plato_bg_list[0][i][-1])
# Or one can average over the final temperature plato
# However the scale is often changing and I recoment using the first option
if mode == 'average':
average = 0
average_list = []
# First we load all data files and add them up
for i,j in enumerate(self.plato_bg_list[0]):
for a,b in enumerate(j):
average = average + getIfile(b)
# Then we devide by the number of all scans forming the overall average
average = average/len(j)
# Then we append the averaged scan as many times as plato scans of the final temperature exsist
average_list.append(average)
average = 0
self.bg_matrix = self.plato_bg_list[0][0] + self.ramp_bg_list[0][0] + self.plato_bg_list[0][1]
if self.glas_Gr is True:
self.bg_matrix_Gr = self.plato_bg_list[1][0] + self.ramp_bg_list[1][0] + self.plato_bg_list[1][1]
# Cropping the BG data as well in q before subtraction (mask affected data), so it does not form artefacts in the data
# shorten_matrix_elements(self.plato_bg_list[0][0],[0,Qmax])
# shorten_matrix_elements(self.plato_bg_list[0][1],[0,Qmax])
# shorten_matrix_elements(self.ramp_bg_list[0][0],[0,Qmax])
# shorten_matrix_elements(self.bg_matrix,[0,Qmax])
# If one single BG is sufficient one can use this as well (a long exposed or averaged file works nicely)
if single_BG_file is not None:
# We get the single background file
self.I_bg = getIfile(single_BG_file)
# Then we loop over all I(q)
for i,j in enumerate(self.I):
# We can determine the BG scaling factor eighter by the intensity of the glas peak in the PDF or
# by letting the minimum of the scan to be at the lowest point to be exactly 0 (within the given Q range)
if self.glas_Gr is True:
self.factor = max(self.Gr[i]) / max(self.Gr_bg)
print('max Gr: ' + str(max(self.Gr[i])))
print('max Gr bg: ' + str(max(self.Gr_bg)))
# If the factor is not determined from the glas peak intensity (for some organic it is highly overshadowed)
else:
self.factor = np.trapz(y=(j[Qmin:Qmax]), x=self.q[Qmin:Qmax], dx=1e-10) / np.trapz(y=self.I_bg[Qmin:Qmax], x=self.q[Qmin:Qmax], dx=1e-10)
# positive_parts = 0
# negative_parts = 0
# I_condition = True
# while I_condition:
# for qpart in range(qparts):
# I_processed = j - self.factor* self.I_bg
# absolute_integral_I = np.trapz(y=(abs(I_processed)), x=self.q[Qmin:Qmax], dx=1e-10)
# positive_integral_of_I = (absolute_integral_I + np.trapz(y=I_processed, x=self.q[Qmin:Qmax], dx=1e-10)) / 2
# negative_integral_of_I = absolute_integral_I - positive_integral_of_I
# part_value = positive_integral_of_I - negative_integral_of_I
# if part_value > 0:
# positive_parts += 1
# else:
# negative_parts += 1
# if positive_parts / negative_parts > convergence_critierium:
# I_condition = False
# else:
# self.factor = self.factor - convergence_step
print(f"Initial BG-factor guess is: {self.factor}")
# I_bg_frac = j[Qmin:Qmax] / self.I_bg[Qmin:Qmax]
#self.factor = min(I_bg_frac)
# Check if the calculated factor is over the allowed limit, otherwise it is reseted
if FactorMax is not None:
if self.factor > FactorMax:
self.factor = FactorMax
if i ==0:
outputDatFile(rootdir + '/../processed/' +self.sampleName +'/Dat_files/bg_linaer_max_Dat/',self.q,[self.I_bg],(i+1)*self.average,'background_'+self.sampleName, clear_folder=True)
else:
outputDatFile(rootdir + '/../processed/' +self.sampleName +'/Dat_files/bg_linaer_max_Dat/',self.q,[self.I_bg],(i+1)*self.average,'background_'+self.sampleName)
# After creating the .dat of the BG the PDFs can be calculated in monte carlo style
# for maximization of the G(r)
if use_PDF_maximization is True:
# self.factor, maxvalue = self.monte_carlo_PDF_maximization(rootdir + '/../processed/' + self.sampleName + '/Dat_files/meas_Dat/' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
# rootdir + '/../processed/' + self.sampleName + '/Dat_files/bg_linaer_max_Dat/' + 'background_' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
# outputPath, scan_number=i, R_limits = R_limits)
#r"C:\Users\admin\Nextcloud\Python_Code\ProjectPDF\PDF_generation\From_server\PDF_generation\processed\cell2_fe3s4_in_bnoh_160c_60min\empty_glasinlet_0p3m-00001.dat",outputPath)
self.factor, maxvalue = self.linear_grid_PDF_maximization(rootdir + '/../processed/' + self.sampleName + '/Dat_files/meas_Dat/' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
rootdir + '/../processed/' + self.sampleName + '/Dat_files/bg_linaer_max_Dat/' + 'background_' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
outputPath, scan_number=i, R_limits = R_limits,
grid_size=grid_size, reducing_steps=reducing_steps, starting_step_width=starting_step_width)
# Aplly the current factor to the data
subtracted_I = j - self.factor*self.I_bg
self.I[i] = j - self.factor*self.I_bg
else:
#
I = 0
# Counter for the files in a ramp or plato processed already
count = 0
# Offset between the number of room temperature files between BG and experimantal run
self.bg_offset = 0
# If the BG scans have less data points then the experimantal run we start later in the experimantal run,
# by setting the count to when the offset between the two data sets
# --> Thereby the earliest data is ignored as we don´t have enought BG files
# (it would be better to treat it the same way as the end of run data, but mostly it should´t differ so I did´t include it so fare)
if len(self.plato_bg_list[0][0]) > (round_to_multiple(heat_ranges["ramp1_start"],self.average)/self.average):
self.bg_offset = int(len(self.plato_bg_list[0][0]) - (round_to_multiple(heat_ranges["ramp1_start"],self.average)/self.average) - 1)
print('BG is offset by: ' + str(self.bg_offset) + ' number of averaged scans')
count = self.bg_offset
# Steps are used in the same manner as in getRampPlatoLists (step 1 is the room temperature plato)
step = 1
# Now we can loop over every I(q) from each scan in the experimantel run
for i,j in enumerate(self.I):
self.current_I = j
# Here we check when the ramp starts and account for averaging
if i > round_to_multiple(heat_ranges["ramp1_start"],self.average)/self.average and step < 2:
step = 2
# We reset the counter after each step
count = 0
# Here we check when the first set temperature starts and account for averaging
if i-1 == round_to_multiple(heat_ranges["ramp1_end"],self.average)/self.average:
step = 3
# We reset the counter after each step
count = 0
# Here we check when second ramp starts (if set) and account for averaging
if i-1 == round_to_multiple(heat_ranges["ramp2_start"],self.average)/self.average:
step = 4
# We reset the counter after each step
count = 0
# Here we check when the second set temperature (if set) starts and account for averaging
if i-1 == round_to_multiple(heat_ranges["ramp2_end"],self.average)/self.average:
step = 5
# We reset the counter after each step
count = 0
# The ramps should have the same nbumber of files in BG and experimantel run, so they are not so complicated
if step == 2:
# If better implemented this doesn´t need to be a try function :(
try:
# Reshape the order of the BG to match the experimantel temperature curve
self.I_bg = self.ramp_bg_list[0][0][count]
if self.glas_Gr is True:
self.Gr_bg = self.ramp_bg_list[1][0][count]
# Give the user feedback what scan is in process and where in the run it is
print('Scan: ' + str(count),' in Ramping with lenght: ' + str(len(self.ramp_bg_list[0][0])-1), ' step in procedure: ' + str(step))
except:
# This should be taken over by the automation
# (if averaging and temperature differneces between BG and experimantel run make up for a unfortuned 1 scan differece in the end)
print('optimize step 2')
if step == 4:
# If better implemented this doesn´t need to be a try function :(
try:
# Reshape the order of the BG to match the experimantel temperature curve
self.I_bg = self.ramp_bg_list[0][1][count]
if self.glas_Gr is True:
self.Gr_bg = self.ramp_bg_list[1][1][count]
# Give the user feedback what scan is in process and where in the run it is
print('Scan: ' + str(count),' in Ramping with lenght: ' + str(len(self.ramp_bg_list[0][1])-1), ' step in procedure: ' + str(step))
except:
# This should be taken over by the automation
# (if averaging and temperature differneces between BG and experimantel run make up for a unfortuned 1 scan differece in the end)
print('optimize step 4')
# The platos will most of the time have diffent numbers of files in BG and experimantel run, so we use the extended versions of the BG run we created in the beginning
# with last copies the last scan until it matches the experimantal run leght or average which uses an average of the BG plato and extends it
if mode == 'last':
# If better implemented this doesn´t need to be a try function :(
if step == 1:
# Reshape the order of the BG to match the experimantel temperature curve
self.I_bg = self.plato_bg_list[0][0][count]
if self.glas_Gr is True:
self.Gr_bg = self.plato_bg_list[1][0][count]
# Give the user feedback what scan is in process and where in the run it is
print('Scan: ' + str(count),' in Plato with lenght: ' + str(len(self.plato_bg_list[0][0])-1), ' step in procedure: ' + str(step))
# If better implemented this doesn´t need to be a try function :(
if step == 3:
try:
# Reshape the order of the BG to match the experimantel temperature curve
self.I_bg = self.plato_bg_list[0][1][count]
if self.glas_Gr is True:
self.Gr_bg = self.plato_bg_list[1][1][count]
# Give the user feedback what scan is in process and where in the run it is
print('Scan: ' + str(count),' in Plato with lenght: ' + str(len(self.plato_bg_list[0][1])-1), ' step in procedure: ' + str(step))
except:
# This should be taken over by the automation
# (if averaging and temperature differneces between BG and experimantel run make up for a unfortuned 1 scan differece in the end)
print('optimize step 3')
# If better implemented this doesn´t need to be a try function :(
if step == 5:
try:
# Reshape the order of the BG to match the experimantel temperature curve
self.I_bg = self.plato_bg_list[0][2][count]
if self.glas_Gr is True:
self.Gr_bg = self.plato_bg_list[1][2][count]
# Give the user feedback what scan is in process and where in the run it is
print('Scan: ' + str(count),' in Plato with lenght: ' + str(len(self.plato_bg_list[0][2])-1), ' step in procedure: ' + str(step))
except:
# This should be taken over by the automation
# (if averaging and temperature differneces between BG and experimantel run make up for a unfortuned 1 scan differece in the end)
print('optimize step 5')
# This is for the average of the BG plato that is extended, here the BG platos are simply the average of the current plato
if mode == 'average':
if step == 1:
self.I_bg = average_list[0]
if step == 3:
self.I_bg = average_list[1]
if step == 5:
self.I_bg = average_list[2]
# Here we subtract the empty glas file with a constant scale before determaning the factor for the subtraction
if empty_glas_int != 0:
# Here we also shorten the leght to be matching to Qmaxinst
self.I_empty_glas = self.I_empty_glas[:len(j)]
j = j - self.I_empty_glas*max(j)*empty_glas_int
# We can determine the BG scaling factor eighter by the intensity of the glas peak in the PDF or
# by letting the minimum of the scan to be at the lowest point to be exactly 0 (within the given Q range)
if self.glas_Gr is True:
self.factor = max(self.Gr[i]) / max(self.Gr_bg)
print('max Gr: ' + str(max(self.Gr[i])))
print('max Gr bg: ' + str(max(self.Gr_bg)))
# If the factor is not determined from the glas peak intensity (for some organic it is highly overshadowed)
else:
reduced_I = j[Qmin:Qmax]
reduced_bg_I = self.I_bg[Qmin:Qmax]
reduced_q = self.q[Qmin:Qmax]
self.factor = (np.trapz(y=reduced_I, x=reduced_q , dx=1e-10) )/ np.trapz(y=reduced_bg_I, x=reduced_q , dx=1e-10) + correction[i]
# I_condition = True
# counter = 0
# while I_condition:
# print(self.factor)
# positive_parts = 0
# negative_parts = 0
# for qpart in range(qparts):
# part_start = int((len(reduced_I) / qparts) * qpart)
# part_end = int((len(reduced_I) / qparts) * (qpart+1) - 1)
# if qpart == qparts -1:
# if len(reduced_I) % qparts != 0:
# part_end = None
# I_processed = reduced_I[part_start:part_end] - self.factor* reduced_bg_I[part_start:part_end]
# # print(part_start,part_end)
# absolute_integral_I = np.trapz(y=(abs(I_processed)), x=reduced_q[part_start:part_end] , dx=1e-10)
# integral_I = np.trapz(y=I_processed, x=reduced_q[part_start:part_end], dx=1e-10)
# positive_integral_of_I = (absolute_integral_I + integral_I) / 2
# negative_integral_of_I = positive_integral_of_I - absolute_integral_I
# # part_value = positive_integral_of_I + negative_integral_of_I
# if integral_I > 0:
# positive_parts += 1
# else:
# negative_parts += 1
# print((positive_parts / negative_parts) )
# if (positive_parts / negative_parts) > convergence_critierium:
# if (positive_parts / negative_parts) < 0.95:
# I_condition = False
# else:
# self.factor = self.factor + (convergence_step/13)
# else:
# self.factor = self.factor - convergence_step
# counter += 1
# if counter % 10 == 0:
# convergence_step *= 0.1
print(f"Initial BG-factor guess is: {self.factor}")
# I_bg_frac = j[Qmin:Qmax] / self.I_bg[Qmin:Qmax]
# self.factor = min(I_bg_frac)
# Check if the calculated factor is over the allowed limit, otherwise it is reseted
if FactorMax is not None:
if self.factor > FactorMax:
self.factor = FactorMax
# For the creation of the PDFs, which are needed for the monte carlo BG subtraction,
# we need the BG in the correct order (ramp-BG with the same time as ramp-experimental)
# Therefore we now create the .dat after sorting it
# If we reprocess with different averages we need to clear the folder, therefore we do this for the first scan.
if i ==0:
outputDatFile(rootdir + '/../processed/' +self.sampleName +'/Dat_files/bg_linaer_max_Dat/',self.q,[self.I_bg],(i+1)*self.average,'background_'+self.sampleName, clear_folder=True)
else:
outputDatFile(rootdir + '/../processed/' +self.sampleName +'/Dat_files/bg_linaer_max_Dat/',self.q,[self.I_bg],(i+1)*self.average,'background_'+self.sampleName)
# After creating the .dat of the BG the PDFs can be calculated in monte carlo style
# for maximization of the G(r)
if use_PDF_maximization is True:
# self.factor, maxvalue = self.monte_carlo_PDF_maximization(rootdir + '/../processed/' + self.sampleName + '/Dat_files/meas_Dat/' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
# rootdir + '/../processed/' + self.sampleName + '/Dat_files/bg_linaer_max_Dat/' + 'background_' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
# outputPath, scan_number=i, R_limits = R_limits)
#r"C:\Users\admin\Nextcloud\Python_Code\ProjectPDF\PDF_generation\From_server\PDF_generation\processed\cell2_fe3s4_in_bnoh_160c_60min\empty_glasinlet_0p3m-00001.dat",outputPath)
self.factor, maxvalue = self. linear_grid_PDF_maximization(rootdir + '/../processed/' + self.sampleName + '/Dat_files/meas_Dat/' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
rootdir + '/../processed/' + self.sampleName + '/Dat_files/bg_linaer_max_Dat/' + 'background_' + self.sampleName + "_" + str((i+1)*self.average).zfill(5)+".txt",
outputPath, scan_number=i, R_limits = R_limits)
else:
# The user gets the feedback about the calculated BG scale
print('BG_scale: ' + str(self.factor))
# Here we apply the BG factor and subtract the BG from the experimantal I(q)
subtracted_I = j - self.factor*self.I_bg
self.I[i] = j - self.factor*self.I_bg
# We store the BG subtracted I(q) and the BG scaling factor in self varibles for later access.
self.subtracted_I.append(subtracted_I)
self.factor_list.append(self.factor)
# AT last the counter for each scans in each step is increased by 1.
count = count + 1
print("Total negative G(r) amplitude corrections preformed:" + str(self.flipps))
return self.logger