Add reflection table and interactive mode to xrd
This commit is contained in:
parent
67ea048380
commit
a5c845fa54
3 changed files with 213 additions and 19 deletions
|
|
@ -25,7 +25,9 @@ def prepare_plot(options={}):
|
||||||
rc_params = options['rc_params']
|
rc_params = options['rc_params']
|
||||||
format_params = options['format_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 = {
|
default_format_params = {
|
||||||
'single_column_width': 8.3,
|
'single_column_width': 8.3,
|
||||||
|
|
@ -33,10 +35,16 @@ def prepare_plot(options={}):
|
||||||
'column_type': 'single',
|
'column_type': 'single',
|
||||||
'width_ratio': '1:1',
|
'width_ratio': '1:1',
|
||||||
'aspect_ratio': '1:1',
|
'aspect_ratio': '1:1',
|
||||||
|
'width': None,
|
||||||
|
'height': None,
|
||||||
'compress_width': 1,
|
'compress_width': 1,
|
||||||
'compress_height': 1,
|
'compress_height': 1,
|
||||||
'upscaling_factor': 1.0,
|
'upscaling_factor': 1.0,
|
||||||
'dpi': 600,
|
'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)
|
format_params = aux.update_options(format_params, required_format_params, default_format_params)
|
||||||
|
|
@ -48,14 +56,73 @@ def prepare_plot(options={}):
|
||||||
# Update run commands if any is passed (will pass an empty dictionary if not passed)
|
# Update run commands if any is passed (will pass an empty dictionary if not passed)
|
||||||
update_rc_params(rc_params)
|
update_rc_params(rc_params)
|
||||||
|
|
||||||
|
if not format_params['width']:
|
||||||
width = determine_width(format_params=format_params)
|
width = determine_width(format_params=format_params)
|
||||||
|
|
||||||
|
if not format_params['height']:
|
||||||
height = determine_height(format_params=format_params, width=width)
|
height = determine_height(format_params=format_params, width=width)
|
||||||
|
|
||||||
width, height = scale_figure(format_params=format_params, width=width, height=height)
|
width, height = scale_figure(format_params=format_params, width=width, height=height)
|
||||||
|
|
||||||
|
if format_params['nrows'] == 1 and format_params['ncols'] == 1:
|
||||||
fig, ax = plt.subplots(figsize=(width, height), dpi=format_params['dpi'])
|
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):
|
def adjust_plot(fig, ax, options):
|
||||||
''' A general function to adjust plot according to contents of the options-dictionary '''
|
''' A general function to adjust plot according to contents of the options-dictionary '''
|
||||||
|
|
|
||||||
|
|
@ -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)
|
res = ai.integrate1d(image, bins, unit=options['unit'], filename=filename)
|
||||||
|
|
||||||
if options['return']:
|
if options['return']:
|
||||||
return open_1d_data(filename)
|
return read_diffractogram(filename)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -222,7 +222,7 @@ def read_brml(path, options=None):
|
||||||
return diffractogram
|
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):
|
def read_data(path, kind, options=None):
|
||||||
|
|
||||||
if kind == 'beamline':
|
if kind == 'beamline':
|
||||||
diffractogram = read_diffractogram(path, options=options)
|
diffractogram = read_diffractogram(path)
|
||||||
|
|
||||||
elif kind == 'recx':
|
elif kind == 'recx':
|
||||||
diffractogram = read_brml(path, options=options)
|
diffractogram = read_brml(path, options=options)
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,9 @@ import pandas as pd
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import beamtime.xrd as xrd
|
import ipywidgets as widgets
|
||||||
|
|
||||||
|
import beamtime.xrd as xrd
|
||||||
import beamtime.auxillary as aux
|
import beamtime.auxillary as aux
|
||||||
import beamtime.plotting as btp
|
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)'''
|
plot_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', '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 = {
|
default_options = {
|
||||||
'x_vals': '2th',
|
'x_vals': '2th',
|
||||||
'y_vals': 'I',
|
'y_vals': 'I',
|
||||||
'ylabel': 'Intensity', 'xlabel': '2theta',
|
'ylabel': 'Intensity', 'xlabel': '2theta',
|
||||||
'xunit': 'deg', 'yunit': 'a.u.',
|
'xunit': 'deg', 'yunit': 'a.u.',
|
||||||
|
'line': True,
|
||||||
'scatter': False,
|
'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,
|
'plot_kind': None,
|
||||||
|
'palettes': [('qualitative', 'Dark2_8')],
|
||||||
|
'interactive': False,
|
||||||
'rc_params': {},
|
'rc_params': {},
|
||||||
'format_params': {}
|
'format_params': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
# Prepare plot, and read and process data
|
if options['interactive']:
|
||||||
fig, ax = btp.prepare_plot(options=options)
|
options['interactive'] = False
|
||||||
diffractogram = xrd.io.read_data(path=plot_data['path'], kind=plot_data['plot_kind'], options=options)
|
plot_diffractogram_interactive(plot_data=plot_data, options=options)
|
||||||
|
return
|
||||||
|
|
||||||
if options['scatter']:
|
# Make adjustments to parameters if reflections data is passed
|
||||||
ax.scatter(x= diffractogram[options['x_vals']], y = diffractogram[options['y_vals']])
|
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:
|
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)
|
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
|
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):
|
def prepare_diffractogram_plot(options=None):
|
||||||
# First take care of the options for plotting - set any values not specified to the default values
|
# First take care of the options for plotting - set any values not specified to the default values
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue