Add reflection table and interactive mode to xrd

This commit is contained in:
rasmusvt 2022-03-12 22:26:06 +01:00
parent 67ea048380
commit a5c845fa54
3 changed files with 213 additions and 19 deletions

View file

@ -25,7 +25,9 @@ def prepare_plot(options={}):
rc_params = options['rc_params']
format_params = options['format_params']
required_format_params = ['single_column_width', 'double_column_width', 'column_type', 'width_ratio', 'aspect_ratio', 'compress_width', 'compress_height', 'upscaling_factor', 'dpi']
required_format_params = ['single_column_width', 'double_column_width', 'column_type', 'width_ratio', 'aspect_ratio',
'width', 'height', 'compress_width', 'compress_height', 'upscaling_factor', 'dpi',
'nrows', 'ncols', 'grid_ratio_height', 'grid_ratio_width']
default_format_params = {
'single_column_width': 8.3,
@ -33,10 +35,16 @@ def prepare_plot(options={}):
'column_type': 'single',
'width_ratio': '1:1',
'aspect_ratio': '1:1',
'width': None,
'height': None,
'compress_width': 1,
'compress_height': 1,
'upscaling_factor': 1.0,
'dpi': 600,
'nrows': 1,
'ncols': 1,
'grid_ratio_height': None,
'grid_ratio_width': None
}
format_params = aux.update_options(format_params, required_format_params, default_format_params)
@ -48,13 +56,72 @@ def prepare_plot(options={}):
# Update run commands if any is passed (will pass an empty dictionary if not passed)
update_rc_params(rc_params)
width = determine_width(format_params=format_params)
height = determine_height(format_params=format_params, width=width)
if not format_params['width']:
width = determine_width(format_params=format_params)
if not format_params['height']:
height = determine_height(format_params=format_params, width=width)
width, height = scale_figure(format_params=format_params, width=width, height=height)
fig, ax = plt.subplots(figsize=(width, height), dpi=format_params['dpi'])
if format_params['nrows'] == 1 and format_params['ncols'] == 1:
fig, ax = plt.subplots(figsize=(width, height), dpi=format_params['dpi'])
return fig, ax
return fig, ax
else:
if not format_params['grid_ratio_height']:
format_params['grid_ratio_height'] = [1 for i in range(format_params['nrows'])]
if not format_params['grid_ratio_width']:
format_params['grid-ratio_width'] = [1 for i in range(format_params['ncols'])]
fig, axes = plt.subplots(nrows=format_params['nrows'], ncols=format_params['ncols'], figsize=(width,height),
gridspec_kw={'height_ratios': format_params['grid_ratio_height'], 'width_ratios': format_params['grid_ratio_width']},
facecolor='w', dpi=format_params['dpi'])
return fig, axes
def prepare_plots(options={}):
rc_params = options['rc_params']
format_params = options['format_params']
required_options = ['single_column_width', 'double_column_width', 'column_type', 'width_ratio', 'aspect_ratio', 'compress_width', 'compress_height', 'upscaling_factor', 'dpi']
default_options = {
'single_column_width': 8.3,
'double_column_width': 17.1,
'column_type': 'single',
'width_ratio': '1:1',
'aspect_ratio': '1:1',
'compress_width': 1,
'compress_height': 1,
'upscaling_factor': 1.0,
'dpi': 600,
}
format_params = aux.update_options(format_params, required_options, default_options)
# Reset run commands
plt.rcdefaults()
# Update run commands if any is passed (will pass an empty dictionary if not passed)
update_rc_params(rc_params)
width = determine_width(format_params)
height = determine_height(format_params, width)
width, height = scale_figure(options=format_params, width=width, height=height)
if options['plot_kind'] == 'relative':
fig, axes = plt.subplots(nrows=1, ncols=options['number_of_frames'], figsize=(width,height), facecolor='w', dpi=format_params['dpi'])
elif options['plot_kind'] == 'absolute':
fig, axes = plt.subplots(nrows=2, ncols=options['number_of_frames'], figsize=(width,height), gridspec_kw={'height_ratios': [1,5]}, facecolor='w', dpi=format_params['dpi'])
return fig, axes
def adjust_plot(fig, ax, options):

View file

@ -87,7 +87,7 @@ def integrate_1d(calibrant, bins, path=None, image=None, options=None):
res = ai.integrate1d(image, bins, unit=options['unit'], filename=filename)
if options['return']:
return open_1d_data(filename)
return read_diffractogram(filename)
@ -222,7 +222,7 @@ def read_brml(path, options=None):
return diffractogram
def read_diffractogram(path, options=None):
def read_diffractogram(path):
@ -248,7 +248,7 @@ def read_diffractogram(path, options=None):
def read_data(path, kind, options=None):
if kind == 'beamline':
diffractogram = read_diffractogram(path, options=options)
diffractogram = read_diffractogram(path)
elif kind == 'recx':
diffractogram = read_brml(path, options=options)

View file

@ -5,8 +5,9 @@ import pandas as pd
import numpy as np
import math
import beamtime.xrd as xrd
import ipywidgets as widgets
import beamtime.xrd as xrd
import beamtime.auxillary as aux
import beamtime.plotting as btp
@ -18,42 +19,168 @@ def plot_diffractogram(plot_data, options={}):
plot_data (dict): Must include path = string to diffractogram data, and plot_kind = (recx, beamline, image)'''
# Update options
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'scatter', 'plot_kind', 'rc_params', 'format_params']
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter',
'reflections', 'plot_kind', 'palettes', 'interactive', 'rc_params', 'format_params']
default_options = {
'x_vals': '2th',
'y_vals': 'I',
'ylabel': 'Intensity', 'xlabel': '2theta',
'xunit': 'deg', 'yunit': 'a.u.',
'line': True,
'scatter': False,
'reflections': False,
'reflection_data': None, # Should be passed as a dictionary on the form {path: rel_path, colour: [r,g,b], min_alpha: 0-1]
'plot_kind': None,
'palettes': [('qualitative', 'Dark2_8')],
'interactive': False,
'rc_params': {},
'format_params': {}
'format_params': {},
}
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
# Prepare plot, and read and process data
fig, ax = btp.prepare_plot(options=options)
diffractogram = xrd.io.read_data(path=plot_data['path'], kind=plot_data['plot_kind'], options=options)
if options['interactive']:
options['interactive'] = False
plot_diffractogram_interactive(plot_data=plot_data, options=options)
return
if options['scatter']:
ax.scatter(x= diffractogram[options['x_vals']], y = diffractogram[options['y_vals']])
# Make adjustments to parameters if reflections data is passed
if options['reflections']:
options['format_params']['nrows'] = 2
#diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, kind='scatter')
if not 'grid_ratio_height' in options['format_params'].keys():
options['format_params']['grid_ratio_height'] = [1,10]
else:
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax)
options['format_params']['nrows'] = 1
# Prepare plot, and read and process data
fig, ax = btp.prepare_plot(options=options)
if options['reflections']:
reflection_ax = ax[0]
ax = ax[1]
colours = btp.generate_colours(options['palettes'])
diffractogram = xrd.io.read_data(path=plot_data['path'], kind=plot_data['plot_kind'], options=options)
if options['line']:
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1)
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)]))
fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options)
if options['reflections'] and options['reflection_data']:
plot_reflection_table(plot_data=options['reflection_data'], ax=reflection_ax, options=options)
return diffractogram, fig, ax
def plot_diffractogram_interactive(plot_data, options):
if options['reflections']:
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), plot_data=widgets.fixed(plot_data), options=widgets.fixed(options),
scatter=widgets.ToggleButton(value=False),
line=widgets.ToggleButton(value=True),
reflections=widgets.ToggleButton(value=True))
else:
w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_diffractogram), plot_data=widgets.fixed(plot_data), options=widgets.fixed(options),
scatter=widgets.ToggleButton(value=False),
line=widgets.ToggleButton(value=True))
display(w)
def plot_reflection_table(plot_data, ax=None, options={}):
''' Plots a reflection table from output generated by VESTA.
Required contents of plot_data:
path (str): relative path to reflection table file'''
required_options = ['reflections_colour', 'min_alpha', 'format_params', 'rc_params']
default_options = {
'reflections_colour': [0,0,0],
'min_alpha': 0,
'format_params': {},
'rc_params': {}
}
if 'colour' in plot_data.keys():
options['reflections_colour'] = plot_data['colour']
if 'min_alpha' in plot_data.keys():
options['min_alpha'] = plot_data['min_alpha']
options = aux.update_options(options=options, required_options=required_options, default_options=default_options)
if not ax:
_, ax = btp.prepare_plot(options)
reflection_table = load_reflection_table(plot_data['path'])
reflections, intensities = reflection_table['2th'], reflection_table['I']
for ref, intensity in zip(reflections, intensities):
rel_intensity = (intensity / intensities.max())*(1-options['min_alpha']) + options['min_alpha']
ax.axvline(x=ref, c=options['reflections_colour'], alpha=rel_intensity)
ax.tick_params(which='both', bottom=False, labelbottom=False, right=False, labelright=False, left=False, labelleft=False, top=False, labeltop=False)
if options['xlim']:
ax.set_xlim(options['xlim'])
def load_reflection_table(path):
# VESTA outputs the file with a header that has a space between the parameter and units - so there is some extra code to rectify the issue
# that ensues from this formatting
reflections = pd.read_csv(path, delim_whitespace=True)
# Remove the extra column that appears from the headers issue
reflections.drop(reflections.columns[-1], axis=1, inplace=True)
with open(path, 'r') as f:
line = f.readline()
headers = line.split()
# Delete the fourth element which is '(Å)'
del headers[4]
# Change name of column to avoid using greek letters
headers[7] = '2th'
# Set the new modified headers as the headers of
reflections.columns = headers
return reflections
def prepare_diffractogram_plot(options=None):
# First take care of the options for plotting - set any values not specified to the default values