Add plot functionality for single diffractograms

This commit is contained in:
rasmusvt 2021-11-08 17:24:58 +01:00
parent d6734184cc
commit 2b1b9b0d9b
3 changed files with 363 additions and 22 deletions

View file

@ -275,8 +275,8 @@ def prettify_gc_plot(fig, ax, options=None):
# Otherwise apply user input # Otherwise apply user input
else: else:
major_xtick = options['yticks'][0] major_ytick = options['yticks'][0]
minor_xtick = options['yticks'][1] minor_ytick = options['yticks'][1]
# Apply values # Apply values

View file

@ -90,25 +90,7 @@ def integrate_1d(calibrant, bins, path=None, image=None, options=None):
return open_1d_data(filename) return open_1d_data(filename)
def open_1d_data(path, options=None):
with open(path, 'r') as f:
position = 0
current_line = f.readline()
while current_line[0] == '#':
position = f.tell()
current_line = f.readline()
f.seek(position)
df = pd.read_csv(f, header=None, delim_whitespace=True)
df.columns = ['2th', 'I']
return df
@ -165,7 +147,7 @@ def view_integrator(calibrant):
def read_brml(path, options=None): def read_brml(path, options=None):
required_options = ['extract_folder'] required_options = ['extract_folder', 'save_folder']
default_options = { default_options = {
'extract_folder': 'temp', 'extract_folder': 'temp',
'save_folder': None 'save_folder': None
@ -240,8 +222,42 @@ def read_brml(path, options=None):
return diffractogram return diffractogram
def read_diffractogram(path, options=None):
with open(path, 'r') as f:
position = 0
current_line = f.readline()
while current_line[0] == '#':
position = f.tell()
current_line = f.readline()
f.seek(position)
diffractogram = pd.read_csv(f, header=None, delim_whitespace=True)
diffractogram.columns = ['2th', 'I']
return diffractogram
def read_data(path, kind, options=None):
if kind == 'beamline':
diffractogram = read_diffractogram(path, options=options)
elif kind == 'recx':
diffractogram = read_brml(path, options=options)
elif kind == 'image':
diffractogram = get_image_array(path)
return diffractogram

View file

@ -1,2 +1,327 @@
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import numpy from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator)
import pandas as pd
import numpy as np
import math
import beamtime.xrd as xrd
def plot_diffractogram(path, kind, options=None):
# Prepare plot, and read and process data
fig, ax = prepare_diffractogram_plot(options=options)
diffractogram = xrd.io.read_data(path=path, kind=kind, options=options)
# Update options
required_options = ['x_vals', 'y_vals', 'scatter']
default_options = {
'x_vals': '2th',
'y_vals': 'I',
'scatter': False
}
options = update_options(options=options, required_options=required_options, default_options=default_options)
if options['scatter']:
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, kind='scatter')
else:
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax)
fig, ax = prettify_diffractogram_plot(fig=fig, ax=ax, options=options)
return diffractogram, fig, ax
def prepare_diffractogram_plot(options=None):
# First take care of the options for plotting - set any values not specified to the default values
required_options = ['columns', 'width', 'height', 'format', 'dpi', 'facecolor']
default_options = {'columns': 1, 'width': 14, 'format': 'golden_ratio', 'dpi': None, 'facecolor': 'w'}
# Define the required sizes
required_sizes = ['lines', 'axes']
# If none are set at all, just pass the default_options
if not options:
options = default_options
options['height'] = options['width'] * (math.sqrt(5) - 1) / 2
options['figsize'] = (options['width'], options['height'])
# Define default sizes
default_sizes = {
'lines': 3*options['columns'],
'axes': 3*options['columns']
}
# Initialise dictionary if it doesn't exist
if not 'sizes' in options.keys():
options['sizes'] = {}
# Update dictionary with default values where none is supplied
for size in required_sizes:
if size not in options['sizes']:
options['sizes'][size] = default_sizes[size]
# If options is passed, go through to fill out the rest.
else:
# Start by setting the width:
if 'width' not in options.keys():
options['width'] = default_options['width']
# Then set height - check options for format. If not given, set the height to the width scaled by the golden ratio - if the format is square, set the same. This should possibly allow for the tweaking of custom ratios later.
if 'height' not in options.keys():
if 'format' not in options.keys():
options['height'] = options['width'] * (math.sqrt(5) - 1) / 2
elif options['format'] == 'square':
options['height'] = options['width']
options['figsize'] = (options['width'], options['height'])
# After height and width are set, go through the rest of the options to make sure that all the required options are filled
for option in required_options:
if option not in options.keys():
options[option] = default_options[option]
fig, ax = plt.subplots(figsize=(options['figsize']), dpi=options['dpi'], facecolor=options['facecolor'])
plt.rc('lines', linewidth=options['sizes']['lines'])
plt.rc('axes', linewidth=options['sizes']['axes'])
return fig, ax
def prettify_diffractogram_plot(fig, ax, options=None):
##################################################################
######################### UPDATE OPTIONS #########################
##################################################################
# Define the required options
required_options = [
'columns',
'xticks', 'yticks',
'units',
'show_major_ticks', 'show_minor_ticks', 'show_tick_labels',
'xlim', 'ylim',
'hide_x_axis', 'hide_y_axis',
'positions',
'xlabel', 'ylabel',
'sizes',
'title'
]
# Define the default options
default_options = {
'columns': 1,
'xticks': [10, 5], 'yticks': [10000, 5000],
'units': {'2th': '$^o$', 'I': 'arb. u.'},
'show_major_ticks': [True, False, True, False], 'show_minor_ticks': [True, False, True, False], 'show_tick_labels': [True, False, False, False],
'xlim': None,'ylim': None,
'hide_x_axis': False, 'hide_y_axis': False,
'positions': {'xaxis': 'bottom', 'yaxis': 'left'},
'xlabel': None, 'ylabel': None,
'sizes': None,
'title': None
}
options = update_options(options, required_options, default_options)
##################################################################
########################## DEFINE SIZES ##########################
##################################################################
# Define the required sizes
required_sizes = [
'labels',
'legend',
'title',
'line', 'axes',
'tick_labels',
'major_ticks', 'minor_ticks']
# Define default sizes
default_sizes = {
'labels': 30*options['columns'],
'legend': 30*options['columns'],
'title': 30*options['columns'],
'line': 3*options['columns'],
'axes': 3*options['columns'],
'tick_labels': 30*options['columns'],
'major_ticks': 20*options['columns'],
'minor_ticks': 10*options['columns']
}
# Initialise dictionary if it doesn't exist
if not options['sizes']:
options['sizes'] = {}
# Update dictionary with default values where none is supplied
for size in required_sizes:
if size not in options['sizes']:
options['sizes'][size] = default_sizes[size]
##################################################################
########################## AXIS LABELS ###########################
##################################################################
if not options['xlabel']:
options['xlabel'] = prettify_labels(options['x_vals']) + ' [{}]'.format(options['units'][options['x_vals']])
else:
options['xlabel'] = options['xlabel'] + ' [{}]'.format(options['units'][options['x_vals']])
if not options['ylabel']:
options['ylabel'] = prettify_labels(options['y_vals']) + ' [{}]'.format(options['units'][options['y_vals']])
else:
options['ylabel'] = options['ylabel'] + ' [{}]'.format(options['units'][options['y_vals']])
ax.set_xlabel(options['xlabel'], size=options['sizes']['labels'])
ax.set_ylabel(options['ylabel'], size=options['sizes']['labels'])
##################################################################
###################### TICK MARKS & LABELS #######################
##################################################################
ax.tick_params(
direction='in',
which='major',
bottom=options['show_major_ticks'][0], labelbottom=options['show_tick_labels'][0],
left=options['show_major_ticks'][1], labelleft=options['show_tick_labels'][1],
top=options['show_major_ticks'][2], labeltop=options['show_tick_labels'][2],
right=options['show_major_ticks'][3], labelright=options['show_tick_labels'][3],
length=options['sizes']['major_ticks'],
width=options['sizes']['axes'])
ax.tick_params(direction='in', which='minor', bottom=options['show_minor_ticks'][0], left=options['show_minor_ticks'][1], top=options['show_minor_ticks'][2], right=options['show_minor_ticks'][3], length=options['sizes']['minor_ticks'], width=options['sizes']['axes'])
if options['positions']['yaxis'] == 'right':
ax.yaxis.set_label_position("right")
ax.yaxis.tick_right()
if options['hide_x_axis']:
ax.axes.xaxis.set_visible(False)
if options['hide_y_axis']:
ax.axes.yaxis.set_visible(False)
# Otherwise apply user input
if options['xticks']:
major_xtick = options['xticks'][0]
minor_xtick = options['xticks'][1]
if options['yticks']:
major_ytick = options['yticks'][0]
minor_ytick = options['yticks'][1]
# Apply values
ax.xaxis.set_major_locator(MultipleLocator(major_xtick))
ax.xaxis.set_minor_locator(MultipleLocator(minor_xtick))
ax.yaxis.set_major_locator(MultipleLocator(major_ytick))
ax.yaxis.set_minor_locator(MultipleLocator(minor_ytick))
# SET FONTSIZE OF TICK LABELS
plt.xticks(fontsize=options['sizes']['tick_labels'])
plt.yticks(fontsize=options['sizes']['tick_labels'])
##################################################################
########################## AXES LIMITS ###########################
##################################################################
if options['xlim']:
plt.xlim(options['xlim'])
if options['ylim']:
plt.ylim(options['ylim'])
##################################################################
############################# TITLE ##############################
##################################################################
if options['title']:
ax.set_title(options['title'], size=options['sizes']['title'])
##################################################################
############################# LEGEND #############################
##################################################################
if ax.get_legend():
ax.get_legend().remove()
return fig, ax
def prettify_labels(label):
labels_dict = {
'2th': '2$\\theta$',
'I': 'Intensity'
}
return labels_dict[label]
#def plot_diffractograms():
#def plot_heatmap():
def update_options(options, required_options, default_options):
if not options:
options = default_options
else:
for option in required_options:
if option not in options.keys():
options[option] = default_options[option]
return options