Merge pull request #1 from rasmusvt/rasmus_multidiff
Integrating multiple diffractograms into master branch
This commit is contained in:
commit
c637bdce6a
4 changed files with 276 additions and 94 deletions
2
beamtime/feature_list.txt
Normal file
2
beamtime/feature_list.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
- Must allow for automatic normalisation between different diffractograms, must only happen upon reading data
|
||||||
|
-
|
||||||
|
|
@ -313,6 +313,17 @@ def update_widgets(options):
|
||||||
|
|
||||||
if widget['state'] != options['x_vals']:
|
if widget['state'] != options['x_vals']:
|
||||||
for arg in widget[f'{options["x_vals"]}_default']:
|
for arg in widget[f'{options["x_vals"]}_default']:
|
||||||
|
|
||||||
|
# If new min value is larger than previous max, or new max value is smaller than previous min, set the opposite first
|
||||||
|
if arg == 'min':
|
||||||
|
if widget[f'{options["x_vals"]}_default']['min'] > getattr(widget['w'], 'max'):
|
||||||
|
setattr(widget['w'], 'max', widget[f'{options["x_vals"]}_default']['max'])
|
||||||
|
|
||||||
|
elif arg == 'max':
|
||||||
|
if widget[f'{options["x_vals"]}_default']['max'] < getattr(widget['w'], 'min'):
|
||||||
|
setattr(widget['w'], 'min', widget[f'{options["x_vals"]}_default']['min'])
|
||||||
|
|
||||||
|
|
||||||
setattr(widget['w'], arg, widget[f'{options["x_vals"]}_default'][arg])
|
setattr(widget['w'], arg, widget[f'{options["x_vals"]}_default'][arg])
|
||||||
|
|
||||||
widget['state'] = options['x_vals']
|
widget['state'] = options['x_vals']
|
||||||
|
|
@ -366,16 +377,20 @@ def update_rc_params(rc_params):
|
||||||
plt.rcParams.update({key: rc_params[key]})
|
plt.rcParams.update({key: rc_params[key]})
|
||||||
|
|
||||||
|
|
||||||
def generate_colours(palettes):
|
def generate_colours(palettes, kind=None):
|
||||||
|
|
||||||
# Creates a list of all the colours that is passed in the colour_cycles argument. Then makes cyclic iterables of these.
|
if kind == 'single':
|
||||||
colour_collection = []
|
colour_cycle = itertools.cycle(palettes)
|
||||||
for palette in palettes:
|
|
||||||
mod = importlib.import_module("palettable.colorbrewer.%s" % palette[0])
|
|
||||||
colour = getattr(mod, palette[1]).mpl_colors
|
|
||||||
colour_collection = colour_collection + colour
|
|
||||||
|
|
||||||
colour_cycle = itertools.cycle(colour_collection)
|
else:
|
||||||
|
# Creates a list of all the colours that is passed in the colour_cycles argument. Then makes cyclic iterables of these.
|
||||||
|
colour_collection = []
|
||||||
|
for palette in palettes:
|
||||||
|
mod = importlib.import_module("palettable.colorbrewer.%s" % palette[0])
|
||||||
|
colour = getattr(mod, palette[1]).mpl_colors
|
||||||
|
colour_collection = colour_collection + colour
|
||||||
|
|
||||||
|
colour_cycle = itertools.cycle(colour_collection)
|
||||||
|
|
||||||
|
|
||||||
return colour_cycle
|
return colour_cycle
|
||||||
|
|
@ -27,7 +27,7 @@ def get_image_headers(path):
|
||||||
return image.header
|
return image.header
|
||||||
|
|
||||||
|
|
||||||
def integrate_1d(data, options={}):
|
def integrate_1d(data, options={}, index=0):
|
||||||
''' Integrates an image file to a 1D diffractogram.
|
''' Integrates an image file to a 1D diffractogram.
|
||||||
|
|
||||||
Required content of data:
|
Required content of data:
|
||||||
|
|
@ -40,10 +40,12 @@ def integrate_1d(data, options={}):
|
||||||
df: DataFrame contianing 1D diffractogram if option 'return' is True
|
df: DataFrame contianing 1D diffractogram if option 'return' is True
|
||||||
'''
|
'''
|
||||||
|
|
||||||
required_options = ['unit', 'save', 'save_filename', 'save_extension', 'save_folder', 'overwrite']
|
required_options = ['unit', 'nbins', 'save', 'save_filename', 'save_extension', 'save_folder', 'overwrite']
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
'unit': '2th_deg',
|
'unit': '2th_deg',
|
||||||
|
'nbins': 3000,
|
||||||
|
'extract_folder': 'tmp',
|
||||||
'save': False,
|
'save': False,
|
||||||
'save_filename': None,
|
'save_filename': None,
|
||||||
'save_extension': '_integrated.xy',
|
'save_extension': '_integrated.xy',
|
||||||
|
|
@ -51,51 +53,57 @@ def integrate_1d(data, options={}):
|
||||||
'overwrite': False}
|
'overwrite': False}
|
||||||
|
|
||||||
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
if not isinstance(data['path'], list):
|
||||||
|
data['path'] = [data['path']]
|
||||||
|
|
||||||
|
|
||||||
# Get image array from filename if not passed
|
# Get image array from filename if not passed
|
||||||
if 'image' not in data.keys():
|
if 'image' not in data.keys():
|
||||||
data['image'] = get_image_array(data['path'])
|
data['image'] = get_image_array(data['path'][index])
|
||||||
|
|
||||||
# Instanciate the azimuthal integrator from pyFAI from the calibrant (.poni-file)
|
# Instanciate the azimuthal integrator from pyFAI from the calibrant (.poni-file)
|
||||||
ai = pyFAI.load(data['calibrant'])
|
ai = pyFAI.load(data['calibrant'])
|
||||||
|
|
||||||
# Determine filename
|
# Determine filename
|
||||||
filename = make_filename(data=data, options=options)
|
filename = make_filename(options=options, path=data['path'][index])
|
||||||
|
|
||||||
# Make save_folder if this does not exist already
|
# Make save_folder if this does not exist already
|
||||||
if not os.path.isdir(options['save_folder']):
|
if not os.path.isdir(options['extract_folder']):
|
||||||
os.makedirs(options['save_folder'])
|
os.makedirs(options['extract_folder'])
|
||||||
|
|
||||||
|
|
||||||
res = ai.integrate1d(data['image'], data['nbins'], unit=options['unit'], filename=filename)
|
res = ai.integrate1d(data['image'], options['nbins'], unit=options['unit'], filename=filename)
|
||||||
|
|
||||||
data['path'] = filename
|
data['path'][index] = filename
|
||||||
diffractogram = read_xy(data=data, options=options)
|
diffractogram, wavelength = read_xy(data=data, options=options, index=index)
|
||||||
|
|
||||||
if not options['save']:
|
if not options['save']:
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
shutil.rmtree('tmp')
|
shutil.rmtree(f'tmp')
|
||||||
|
|
||||||
|
|
||||||
|
# Reset this option
|
||||||
|
options['save_folder'] = None
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_filename(data, options):
|
def make_filename(options, path=None):
|
||||||
|
|
||||||
# Define save location for integrated diffractogram data
|
# Define save location for integrated diffractogram data
|
||||||
if not options['save']:
|
if not options['save']:
|
||||||
options['save_folder'] = 'tmp'
|
filename = os.path.join(options['extract_folder'], 'tmp_diff.dat')
|
||||||
filename = os.path.join(options['save_folder'], 'tmp_diff.dat')
|
|
||||||
|
|
||||||
elif options['save']:
|
elif options['save']:
|
||||||
|
|
||||||
# Case 1: No filename is given.
|
# Case 1: No filename is given.
|
||||||
if not options['save_filename']:
|
if not options['save_filename']:
|
||||||
# If a path is given instead of an image array, the path is taken as the trunk of the savename
|
# If a path is given instead of an image array, the path is taken as the trunk of the savename
|
||||||
if data['path']:
|
if path:
|
||||||
# Make filename by joining the save_folder, the filename (with extension deleted) and adding the save_extension
|
# Make filename by joining the save_folder, the filename (with extension deleted) and adding the save_extension
|
||||||
filename = os.path.join(options['save_folder'], os.path.split(data['path'])[-1].split('.')[0] + options['save_extension'])
|
filename = os.path.join(options['save_folder'], os.path.split(path)[-1].split('.')[0] + options['save_extension'])
|
||||||
else:
|
else:
|
||||||
# Make filename just "integrated.dat" in the save_folder
|
# Make filename just "integrated.dat" in the save_folder
|
||||||
filename = os.path.join(options['save_folder'], 'integrated.xy')
|
filename = os.path.join(options['save_folder'], 'integrated.xy')
|
||||||
|
|
@ -176,7 +184,10 @@ def view_integrator(calibrant):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def read_brml(data, options={}):
|
def read_brml(data, options={}, index=0):
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: Can't read RECX1-data, apparently must be formatted differently from RECX2. Check the RawData-files and compare between the two files.
|
||||||
|
|
||||||
|
|
||||||
required_options = ['extract_folder', 'save_folder']
|
required_options = ['extract_folder', 'save_folder']
|
||||||
|
|
@ -194,7 +205,7 @@ def read_brml(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
# Extract the RawData0.xml file from the brml-file
|
# Extract the RawData0.xml file from the brml-file
|
||||||
with zipfile.ZipFile(data['path'], 'r') as brml:
|
with zipfile.ZipFile(data['path'][index], 'r') as brml:
|
||||||
for info in brml.infolist():
|
for info in brml.infolist():
|
||||||
if "RawData" in info.filename:
|
if "RawData" in info.filename:
|
||||||
brml.extract(info.filename, options['extract_folder'])
|
brml.extract(info.filename, options['extract_folder'])
|
||||||
|
|
@ -213,31 +224,66 @@ def read_brml(data, options={}):
|
||||||
|
|
||||||
for chain in root.findall('./DataRoutes/DataRoute'):
|
for chain in root.findall('./DataRoutes/DataRoute'):
|
||||||
|
|
||||||
for scantype in chain.findall('ScanInformation/ScanMode'):
|
|
||||||
if scantype.text == 'StillScan':
|
|
||||||
|
|
||||||
if chain.get('Description') == 'Originally measured data.':
|
# Get the scan type to be able to handle different data formats
|
||||||
for scandata in chain.findall('Datum'):
|
scantype = chain.findall('ScanInformation')[0].get('VisibleName')
|
||||||
|
|
||||||
|
# Check if the chain is the right one to extract the data from
|
||||||
|
if chain.get('Description') == 'Originally measured data.':
|
||||||
|
|
||||||
|
|
||||||
|
if scantype == 'TwoTheta':
|
||||||
|
for scandata in chain.findall('Datum'):
|
||||||
|
scandata = scandata.text.split(',')
|
||||||
|
twotheta, intensity = float(scandata[2]), float(scandata[3])
|
||||||
|
|
||||||
|
if twotheta > 0:
|
||||||
|
diffractogram.append({'2th': twotheta, 'I': intensity})
|
||||||
|
|
||||||
|
elif scantype == 'Coupled TwoTheta/Theta':
|
||||||
|
for scandata in chain.findall('Datum'):
|
||||||
|
scandata = scandata.text.split(',')
|
||||||
|
twotheta, intensity = float(scandata[2]), float(scandata[4])
|
||||||
|
|
||||||
|
if twotheta > 0:
|
||||||
|
diffractogram.append({'2th': twotheta, 'I': intensity})
|
||||||
|
|
||||||
|
elif scantype == 'Still (Eiger2R_500K (1D mode))':
|
||||||
|
|
||||||
|
start = float(chain.findall('ScanInformation/ScaleAxes/ScaleAxisInfo/Start')[0].text)
|
||||||
|
stop = float(chain.findall('ScanInformation/ScaleAxes/ScaleAxisInfo/Stop')[0].text)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for scandata in chain.findall('Datum'):
|
||||||
scandata = scandata.text.split(',')
|
scandata = scandata.text.split(',')
|
||||||
scandata = [float(i) for i in scandata]
|
raw = [float(i) for i in scandata]
|
||||||
twotheta, intensity = float(scandata[2]), float(scandata[3])
|
|
||||||
|
|
||||||
|
intensity = []
|
||||||
else:
|
for r in raw:
|
||||||
if chain.get('Description') == 'Originally measured data.':
|
if r > 601:
|
||||||
for scandata in chain.findall('Datum'):
|
intensity.append(r)
|
||||||
scandata = scandata.text.split(',')
|
|
||||||
twotheta, intensity = float(scandata[2]), float(scandata[3])
|
intensity = np.array(intensity)
|
||||||
|
|
||||||
if twotheta > 0:
|
|
||||||
diffractogram.append({'2th': twotheta, 'I': intensity})
|
|
||||||
|
|
||||||
|
twotheta = np.linspace(start, stop, len(intensity))
|
||||||
|
|
||||||
|
diffractogram = {'2th': twotheta, 'I': intensity}
|
||||||
|
|
||||||
|
|
||||||
if 'wavelength' not in data.keys():
|
|
||||||
for chain in root.findall('./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1'):
|
#if 'wavelength' not in data.keys():
|
||||||
data['wavelength'] = float(chain.attrib['Value'])
|
# Find wavelength
|
||||||
|
for chain in root.findall('./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1'):
|
||||||
|
wavelength = float(chain.attrib['Value'])
|
||||||
|
|
||||||
|
|
||||||
diffractogram = pd.DataFrame(diffractogram)
|
diffractogram = pd.DataFrame(diffractogram)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -249,15 +295,16 @@ def read_brml(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
def read_xy(data, options={}):
|
def read_xy(data, options={}, index=0):
|
||||||
|
|
||||||
if 'wavelength' not in data.keys():
|
#if 'wavelength' not in data.keys():
|
||||||
find_wavelength_from_xy(data=data)
|
# Get wavelength from scan
|
||||||
|
wavelength = find_wavelength_from_xy(path=data['path'][index])
|
||||||
|
|
||||||
with open(data['path'], 'r') as f:
|
with open(data['path'][index], 'r') as f:
|
||||||
position = 0
|
position = 0
|
||||||
|
|
||||||
current_line = f.readline()
|
current_line = f.readline()
|
||||||
|
|
@ -276,37 +323,70 @@ def read_xy(data, options={}):
|
||||||
diffractogram.columns = ['2th', 'I', 'sigma']
|
diffractogram.columns = ['2th', 'I', 'sigma']
|
||||||
|
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
def read_data(data, options={}):
|
def read_data(data, options={}, index=0):
|
||||||
|
|
||||||
beamline_extensions = ['mar3450', 'edf', 'cbf']
|
beamline_extensions = ['mar3450', 'edf', 'cbf']
|
||||||
file_extension = data['path'].split('.')[-1]
|
file_extension = data['path'][index].split('.')[-1]
|
||||||
|
|
||||||
if file_extension in beamline_extensions:
|
if file_extension in beamline_extensions:
|
||||||
diffractogram = integrate_1d(data=data, options=options)
|
diffractogram, wavelength = integrate_1d(data=data, options=options, index=index)
|
||||||
|
|
||||||
elif file_extension == 'brml':
|
elif file_extension == 'brml':
|
||||||
diffractogram = read_brml(data=data, options=options)
|
diffractogram, wavelength = read_brml(data=data, options=options, index=index)
|
||||||
|
|
||||||
elif file_extension in['xy', 'xye']:
|
elif file_extension in['xy', 'xye']:
|
||||||
diffractogram = read_xy(data=data, options=options)
|
diffractogram, wavelength = read_xy(data=data, options=options, index=index)
|
||||||
|
|
||||||
|
|
||||||
diffractogram = translate_wavelengths(data=diffractogram, wavelength=data['wavelength'])
|
if options['normalise']:
|
||||||
|
diffractogram['I'] = diffractogram['I'] / diffractogram['I'].max()
|
||||||
|
|
||||||
|
|
||||||
|
if options['offset']:
|
||||||
|
diffractogram = apply_offset(diffractogram, wavelength, index, options)
|
||||||
|
|
||||||
|
|
||||||
|
diffractogram = translate_wavelengths(data=diffractogram, wavelength=wavelength)
|
||||||
|
|
||||||
|
return diffractogram, wavelength
|
||||||
|
|
||||||
|
|
||||||
|
def apply_offset(diffractogram, wavelength, index, options):
|
||||||
|
#Apply offset along y-axis
|
||||||
|
diffractogram['I_org'] = diffractogram['I'] # make copy of original intensities
|
||||||
|
diffractogram['I'] = diffractogram['I'] + index*options['offset_y']
|
||||||
|
|
||||||
|
# Apply offset along x-axis
|
||||||
|
relative_shift = (wavelength / 1.54059)*options['offset_x'] # Adjusts the offset-factor to account for wavelength, so that offset_x given is given in 2th_cuka-units
|
||||||
|
diffractogram['2th_org'] = diffractogram['2th']
|
||||||
|
diffractogram['2th'] = diffractogram['2th'] + index*relative_shift
|
||||||
|
|
||||||
|
|
||||||
return diffractogram
|
return diffractogram
|
||||||
|
|
||||||
|
|
||||||
|
def revert_offset(diffractogram,which=None):
|
||||||
|
|
||||||
|
if which == 'both':
|
||||||
|
diffractogram['2th'] = diffractogram['2th_org']
|
||||||
|
diffractogram['I'] = diffractogram['I_org']
|
||||||
|
|
||||||
|
if which == 'y':
|
||||||
|
diffractogram['I'] = diffractogram['I_org']
|
||||||
|
|
||||||
|
if which == 'x':
|
||||||
|
diffractogram['2th'] = diffractogram['2th_org']
|
||||||
|
|
||||||
|
return diffractogram
|
||||||
|
|
||||||
def load_reflection_table(data, options={}):
|
def load_reflection_table(data, options={}):
|
||||||
|
|
||||||
required_options = ['wavelength', 'to_wavelength']
|
required_options = ['ref_wavelength', 'to_wavelength']
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
'wavelength': 1.54059,
|
'ref_wavelength': 1.54059,
|
||||||
'to_wavelength': None
|
'to_wavelength': None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -333,7 +413,7 @@ def load_reflection_table(data, options={}):
|
||||||
# Set the new modified headers as the headers of
|
# Set the new modified headers as the headers of
|
||||||
reflections.columns = headers
|
reflections.columns = headers
|
||||||
|
|
||||||
reflections = translate_wavelengths(data=reflections, wavelength=options['wavelength'], to_wavelength=options['to_wavelength'])
|
reflections = translate_wavelengths(data=reflections, wavelength=options['ref_wavelength'], to_wavelength=options['to_wavelength'])
|
||||||
|
|
||||||
#print(reflections)
|
#print(reflections)
|
||||||
|
|
||||||
|
|
@ -342,6 +422,8 @@ def load_reflection_table(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
def translate_wavelengths(data, wavelength, to_wavelength=None):
|
def translate_wavelengths(data, wavelength, to_wavelength=None):
|
||||||
|
# FIXME Somewhere here there is an invalid arcsin-argument. Not sure where.
|
||||||
|
|
||||||
pd.options.mode.chained_assignment = None
|
pd.options.mode.chained_assignment = None
|
||||||
|
|
||||||
# Translate to CuKalpha
|
# Translate to CuKalpha
|
||||||
|
|
@ -378,8 +460,7 @@ def translate_wavelengths(data, wavelength, to_wavelength=None):
|
||||||
|
|
||||||
|
|
||||||
if to_wavelength:
|
if to_wavelength:
|
||||||
|
if to_wavelength >= cuka:
|
||||||
if to_wavelength > cuka:
|
|
||||||
max_2th = 2*np.arcsin(cuka/to_wavelength) * 180/np.pi
|
max_2th = 2*np.arcsin(cuka/to_wavelength) * 180/np.pi
|
||||||
else:
|
else:
|
||||||
max_2th = data['2th_cuka'].max()
|
max_2th = data['2th_cuka'].max()
|
||||||
|
|
@ -395,19 +476,24 @@ def translate_wavelengths(data, wavelength, to_wavelength=None):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_wavelength_from_xy(data):
|
def find_wavelength_from_xy(path):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
wavelength_dict = {'Cu': 1.54059, 'Mo': 0.71073}
|
wavelength_dict = {'Cu': 1.54059, 'Mo': 0.71073}
|
||||||
|
|
||||||
with open(data['path'], 'r') as f:
|
with open(path, 'r') as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
|
|
||||||
for line in lines:
|
for line in lines:
|
||||||
|
# For .xy-files output from EVA
|
||||||
if 'Anode' in line:
|
if 'Anode' in line:
|
||||||
anode = line.split()[8].strip('"')
|
anode = line.split()[8].strip('"')
|
||||||
data['wavelength'] = wavelength_dict[anode]
|
wavelength = wavelength_dict[anode]
|
||||||
|
|
||||||
|
# For .xy-files output from pyFAI integration
|
||||||
elif 'Wavelength' in line:
|
elif 'Wavelength' in line:
|
||||||
data['wavelength'] = float(line.split()[2])*10**10
|
wavelength = float(line.split()[2])*10**10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return wavelength
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@ def plot_diffractogram(data, options={}):
|
||||||
data (dict): Must include path = string to diffractogram data, and plot_kind = (recx, beamline, image)'''
|
data (dict): Must include path = string to diffractogram data, and plot_kind = (recx, beamline, image)'''
|
||||||
|
|
||||||
# Update options
|
# Update options
|
||||||
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter', 'xlim', 'ylim',
|
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter', 'xlim', 'ylim', 'normalise', 'offset', 'offset_x', 'offset_y',
|
||||||
'reflections_plot', 'reflections_indices', 'reflections_data', 'plot_kind', 'palettes', 'interactive', 'rc_params', 'format_params']
|
'reflections_plot', 'reflections_indices', 'reflections_data', 'plot_kind', 'palettes', 'interactive', 'rc_params', 'format_params', 'interactive_session_active']
|
||||||
|
|
||||||
default_options = {
|
default_options = {
|
||||||
'x_vals': '2th',
|
'x_vals': '2th',
|
||||||
|
|
@ -28,6 +28,10 @@ def plot_diffractogram(data, options={}):
|
||||||
'ylabel': 'Intensity', 'xlabel': '2theta',
|
'ylabel': 'Intensity', 'xlabel': '2theta',
|
||||||
'xunit': 'deg', 'yunit': 'a.u.',
|
'xunit': 'deg', 'yunit': 'a.u.',
|
||||||
'xlim': None, 'ylim': None,
|
'xlim': None, 'ylim': None,
|
||||||
|
'normalise': True,
|
||||||
|
'offset': True,
|
||||||
|
'offset_x': 0,
|
||||||
|
'offset_y': 1,
|
||||||
'line': True, # whether or not to plot diffractogram as a line plot
|
'line': True, # whether or not to plot diffractogram as a line plot
|
||||||
'scatter': False, # whether or not to plot individual data points
|
'scatter': False, # whether or not to plot individual data points
|
||||||
'reflections_plot': False, # whether to plot reflections as a plot
|
'reflections_plot': False, # whether to plot reflections as a plot
|
||||||
|
|
@ -41,21 +45,43 @@ def plot_diffractogram(data, options={}):
|
||||||
'format_params': {},
|
'format_params': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if 'offset_y' not in options.keys():
|
||||||
|
if len(data['path']) > 10:
|
||||||
|
default_options['offset_y'] = 0.05
|
||||||
|
|
||||||
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
|
||||||
|
|
||||||
|
# Convert data['path'] to list to allow iteration over this to accommodate both single and multiple diffractograms
|
||||||
|
if not isinstance(data['path'], list):
|
||||||
|
data['path'] = [data['path']]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Check if there is some data stored already, load in data if not. This speeds up replotting in interactive mode.
|
||||||
if not 'diffractogram' in data.keys():
|
if not 'diffractogram' in data.keys():
|
||||||
diffractogram = xrd.io.read_data(data=data, options=options)
|
# Initialise empty list for diffractograms and wavelengths
|
||||||
data['diffractogram'] = diffractogram
|
data['diffractogram'] = [None for _ in range(len(data['path']))]
|
||||||
|
data['wavelength'] = [None for _ in range(len(data['path']))]
|
||||||
|
|
||||||
|
for index in range(len(data['path'])):
|
||||||
|
diffractogram, wavelength = xrd.io.read_data(data=data, options=options, index=index)
|
||||||
|
|
||||||
|
data['diffractogram'][index] = diffractogram
|
||||||
|
data['wavelength'][index] = wavelength
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
diffractogram = data['diffractogram']
|
if not isinstance(data['diffractogram'], list):
|
||||||
|
data['diffractogram'] = [data['diffractogram']]
|
||||||
|
data['wavelength'] = [data['wavelength']]
|
||||||
|
|
||||||
# Sets the xlim if this has not bee specified
|
# Sets the xlim if this has not bee specified
|
||||||
if not options['xlim']:
|
if not options['xlim']:
|
||||||
options['xlim'] = [diffractogram[options['x_vals']].min(), diffractogram[options['x_vals']].max()]
|
options['xlim'] = [diffractogram[options['x_vals']].min(), diffractogram[options['x_vals']].max()]
|
||||||
|
|
||||||
|
|
||||||
# Start inteactive session with ipywidgets
|
# Start inteactive session with ipywidgets. Disables options['interactive'] in order for the interactive loop to not start another interactive session
|
||||||
if options['interactive']:
|
if options['interactive']:
|
||||||
options['interactive'] = False
|
options['interactive'] = False
|
||||||
options['interactive_session_active'] = True
|
options['interactive_session_active'] = True
|
||||||
|
|
@ -74,7 +100,6 @@ def plot_diffractogram(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
# Prepare plot, and read and process data
|
# Prepare plot, and read and process data
|
||||||
|
|
||||||
fig, ax = btp.prepare_plot(options=options)
|
fig, ax = btp.prepare_plot(options=options)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -92,14 +117,18 @@ def plot_diffractogram(data, options={}):
|
||||||
|
|
||||||
ax = ax[-1]
|
ax = ax[-1]
|
||||||
|
|
||||||
colours = btp.generate_colours(options['palettes'])
|
if len(data['path']) < 10:
|
||||||
|
colours = btp.generate_colours(options['palettes'])
|
||||||
|
else:
|
||||||
|
colours = btp.generate_colours(['black'], kind='single')
|
||||||
|
|
||||||
|
|
||||||
if options['line']:
|
for diffractogram in data['diffractogram']:
|
||||||
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1)
|
if options['line']:
|
||||||
|
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1)
|
||||||
|
|
||||||
if options['scatter']:
|
if options['scatter']:
|
||||||
ax.scatter(x=diffractogram[options['x_vals']], y = diffractogram[options['y_vals']], c=[(1,1,1,0)], edgecolors=[next(colours)], linewidths=plt.rcParams['lines.markeredgewidth'], zorder=2) #, edgecolors=np.array([next(colours)]))
|
ax.scatter(x=diffractogram[options['x_vals']], y = diffractogram[options['y_vals']], c=[(1,1,1,0)], edgecolors=[next(colours)], linewidths=plt.rcParams['lines.markeredgewidth'], zorder=2) #, edgecolors=np.array([next(colours)]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -107,18 +136,18 @@ def plot_diffractogram(data, options={}):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Make the reflection plots
|
# Make the reflection plots. By default, the wavelength of the first diffractogram will be used for these.
|
||||||
if options['reflections_plot'] and options['reflections_data']:
|
if options['reflections_plot'] and options['reflections_data']:
|
||||||
options['xlim'] = ax.get_xlim()
|
options['xlim'] = ax.get_xlim()
|
||||||
options['to_wavelength'] = data['wavelength']
|
options['to_wavelength'] = data['wavelength'][0]
|
||||||
|
|
||||||
for reference, axis in zip(options['reflections_data'], ref_axes):
|
for reference, axis in zip(options['reflections_data'], ref_axes):
|
||||||
plot_reflection_table(data=reference, ax=axis, options=options)
|
plot_reflection_table(data=reference, ax=axis, options=options)
|
||||||
|
|
||||||
# Print the reflection indices
|
# Print the reflection indices. By default, the wavelength of the first diffractogram will be used for this.
|
||||||
if options['reflections_indices'] and options['reflections_data']:
|
if options['reflections_indices'] and options['reflections_data']:
|
||||||
options['xlim'] = ax.get_xlim()
|
options['xlim'] = ax.get_xlim()
|
||||||
options['to_wavelength'] = data['wavelength']
|
options['to_wavelength'] = data['wavelength'][0]
|
||||||
|
|
||||||
for reference in options['reflections_data']:
|
for reference in options['reflections_data']:
|
||||||
plot_reflection_indices(data=reference, ax=indices_ax, options=options)
|
plot_reflection_indices(data=reference, ax=indices_ax, options=options)
|
||||||
|
|
@ -127,6 +156,8 @@ def plot_diffractogram(data, options={}):
|
||||||
if options['interactive_session_active']:
|
if options['interactive_session_active']:
|
||||||
btp.update_widgets(options=options)
|
btp.update_widgets(options=options)
|
||||||
|
|
||||||
|
xrd.io.up
|
||||||
|
|
||||||
|
|
||||||
return diffractogram, fig, ax
|
return diffractogram, fig, ax
|
||||||
|
|
||||||
|
|
@ -149,18 +180,40 @@ def determine_grid_layout(options):
|
||||||
|
|
||||||
def plot_diffractogram_interactive(data, options):
|
def plot_diffractogram_interactive(data, options):
|
||||||
|
|
||||||
|
|
||||||
|
minmax = {'2th': [None, None], '2th_cuka': [None, None], '2th_moka': [None, None], 'd': [None, None], '1/d': [None, None], 'q': [None, None], 'q2': [None, None], 'q4': [None, None]}
|
||||||
|
|
||||||
|
update_minmax(minmax, data)
|
||||||
|
|
||||||
|
ymin, ymax = None, None
|
||||||
|
for index, diffractogram in enumerate(data['diffractogram']):
|
||||||
|
if not ymin or (ymin > (diffractogram['I'].min())): #+index*options['offset_y'])):
|
||||||
|
ymin = diffractogram['I'].min()#+index*options['offset_y']
|
||||||
|
|
||||||
|
if not ymax or (ymax < (diffractogram['I'].max())):#+index*options['offset_y'])):
|
||||||
|
ymax = diffractogram['I'].max()#+index*options['offset_y']
|
||||||
|
|
||||||
|
|
||||||
|
ymin_start = ymin - 0.1*ymax
|
||||||
|
ymax_start = ymax+0.2*ymax
|
||||||
|
ymin = ymin - 5*ymax
|
||||||
|
ymax = ymax*5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
options['widgets'] = {
|
options['widgets'] = {
|
||||||
'xlim': {
|
'xlim': {
|
||||||
'w': widgets.FloatRangeSlider(value=[data['diffractogram']['2th'].min(), data['diffractogram']['2th'].max()], min=data['diffractogram']['2th'].min(), max=data['diffractogram']['2th'].max(), step=0.5, layout=widgets.Layout(width='95%')),
|
'w': widgets.FloatRangeSlider(value=[minmax['2th'][0], minmax['2th'][1]], min=minmax['2th'][0], max=minmax['2th'][1], step=0.5, layout=widgets.Layout(width='95%')),
|
||||||
'2th_default': {'min': data['diffractogram']['2th'].min(), 'max': data['diffractogram']['2th'].max(), 'value': [data['diffractogram']['2th'].min(), data['diffractogram']['2th'].max()], 'step': 0.5},
|
'state': '2th',
|
||||||
'2th_cuka_default': {'min': data['diffractogram']['2th_cuka'].min(), 'max': data['diffractogram']['2th_cuka'].max(), 'value': [data['diffractogram']['2th_cuka'].min(), data['diffractogram']['2th_cuka'].max()], 'step': 0.5},
|
'2th_default': {'min': minmax['2th'][0], 'max': minmax['2th'][1], 'value': [minmax['2th'][0], minmax['2th'][1]], 'step': 0.5},
|
||||||
'2th_moka_default': {'min': data['diffractogram']['2th_moka'].min(), 'max': data['diffractogram']['2th_moka'].max(), 'value': [data['diffractogram']['2th_moka'].min(), data['diffractogram']['2th_moka'].max()], 'step': 0.5},
|
'2th_cuka_default': {'min': minmax['2th_cuka'][0], 'max': minmax['2th_cuka'][1], 'value': [minmax['2th_cuka'][0], minmax['2th_cuka'][1]], 'step': 0.5},
|
||||||
'd_default': {'min': data['diffractogram']['d'].min(), 'max': data['diffractogram']['d'].max(), 'value': [data['diffractogram']['d'].min(), data['diffractogram']['d'].max()], 'step': 0.5},
|
'2th_moka_default': {'min': minmax['2th_moka'][0], 'max': minmax['2th_moka'][1], 'value': [minmax['2th_moka'][0], minmax['2th_moka'][1]], 'step': 0.5},
|
||||||
'1/d_default': {'min': data['diffractogram']['1/d'].min(), 'max': data['diffractogram']['1/d'].max(), 'value': [data['diffractogram']['1/d'].min(), data['diffractogram']['1/d'].max()], 'step': 0.5},
|
'd_default': {'min': minmax['d'][0], 'max': minmax['d'][1], 'value': [minmax['d'][0], minmax['d'][1]], 'step': 0.5},
|
||||||
'q_default': {'min': data['diffractogram']['q'].min(), 'max': data['diffractogram']['q'].max(), 'value': [data['diffractogram']['q'].min(), data['diffractogram']['q'].max()], 'step': 0.5},
|
'1/d_default': {'min': minmax['1/d'][0], 'max': minmax['1/d'][1], 'value': [minmax['1/d'][0], minmax['1/d'][1]], 'step': 0.5},
|
||||||
'q2_default': {'min': data['diffractogram']['q2'].min(), 'max': data['diffractogram']['q2'].max(), 'value': [data['diffractogram']['q2'].min(), data['diffractogram']['q2'].max()], 'step': 0.5},
|
'q_default': {'min': minmax['q'][0], 'max': minmax['q'][1], 'value': [minmax['q'][0], minmax['q'][1]], 'step': 0.5},
|
||||||
'q4_default': {'min': data['diffractogram']['q4'].min(), 'max': data['diffractogram']['q4'].max(), 'value': [data['diffractogram']['q4'].min(), data['diffractogram']['q4'].max()], 'step': 0.5},
|
'q2_default': {'min': minmax['q2'][0], 'max': minmax['q2'][1], 'value': [minmax['q2'][0], minmax['q2'][1]], 'step': 0.5},
|
||||||
'state': '2th'
|
'q4_default': {'min': minmax['q4'][0], 'max': minmax['q4'][1], 'value': [minmax['q4'][0], minmax['q4'][1]], 'step': 0.5}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +225,10 @@ def plot_diffractogram_interactive(data, options):
|
||||||
reflections_plot=widgets.ToggleButton(value=True),
|
reflections_plot=widgets.ToggleButton(value=True),
|
||||||
reflections_indices=widgets.ToggleButton(value=False),
|
reflections_indices=widgets.ToggleButton(value=False),
|
||||||
x_vals=widgets.Dropdown(options=['2th', 'd', '1/d', 'q', 'q2', 'q4', '2th_cuka', '2th_moka'], value='2th', description='X-values'),
|
x_vals=widgets.Dropdown(options=['2th', 'd', '1/d', 'q', 'q2', 'q4', '2th_cuka', '2th_moka'], value='2th', description='X-values'),
|
||||||
xlim=options['widgets']['xlim']['w'])
|
xlim=options['widgets']['xlim']['w'],
|
||||||
|
ylim=widgets.FloatRangeSlider(value=[ymin_start, ymax_start], min=ymin, max=ymax, step=0.5, layout=widgets.Layout(width='95%')),
|
||||||
|
offset_y=widgets.FloatSlider(value=options['offset_y'], min=-5, max=5)
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), data=widgets.fixed(data), options=widgets.fixed(options),
|
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), data=widgets.fixed(data), options=widgets.fixed(options),
|
||||||
|
|
@ -184,6 +240,29 @@ def plot_diffractogram_interactive(data, options):
|
||||||
display(w)
|
display(w)
|
||||||
|
|
||||||
|
|
||||||
|
def update_minmax(minmax, data):
|
||||||
|
''' Finds minimum and maximum values of each column and updates the minmax dictionary to contain the correct values.
|
||||||
|
|
||||||
|
Input:
|
||||||
|
minmax (dict): contains '''
|
||||||
|
|
||||||
|
for index, diffractogram in enumerate(data['diffractogram']):
|
||||||
|
if not minmax['2th'][0] or diffractogram['2th'].min() < minmax['2th'][0]:
|
||||||
|
minmax['2th'][0] = diffractogram['2th'].min()
|
||||||
|
min_index = index
|
||||||
|
|
||||||
|
if not minmax['2th'][1] or diffractogram['2th'].max() > minmax['2th'][1]:
|
||||||
|
minmax['2th'][1] = diffractogram['2th'].max()
|
||||||
|
max_index = index
|
||||||
|
|
||||||
|
minmax['2th_cuka'][0], minmax['2th_cuka'][1] = data['diffractogram'][min_index]['2th_cuka'].min(), data['diffractogram'][max_index]['2th_cuka'].max()
|
||||||
|
minmax['2th_moka'][0], minmax['2th_moka'][1] = data['diffractogram'][min_index]['2th_moka'].min(), data['diffractogram'][max_index]['2th_moka'].max()
|
||||||
|
minmax['d'][0], minmax['d'][1] = data['diffractogram'][max_index]['d'].min(), data['diffractogram'][min_index]['d'].max() # swapped, intended
|
||||||
|
minmax['1/d'][0], minmax['1/d'][1] = data['diffractogram'][min_index]['1/d'].min(), data['diffractogram'][max_index]['1/d'].max()
|
||||||
|
minmax['q'][0], minmax['q'][1] = data['diffractogram'][min_index]['q'].min(), data['diffractogram'][max_index]['q'].max()
|
||||||
|
minmax['q2'][0], minmax['q2'][1] = data['diffractogram'][min_index]['q2'].min(), data['diffractogram'][max_index]['q2'].max()
|
||||||
|
minmax['q4'][0], minmax['q4'][1] = data['diffractogram'][min_index]['q4'].min(), data['diffractogram'][max_index]['q4'].max()
|
||||||
|
|
||||||
def update_widgets(options):
|
def update_widgets(options):
|
||||||
|
|
||||||
for widget in options['widgets'].values():
|
for widget in options['widgets'].values():
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue