Merge pull request #11 from rasmusthog/rasmus_htxrd

Rasmus htxrd
This commit is contained in:
Rasmus Vester Thøgersen 2022-07-08 17:44:42 +02:00 committed by GitHub
commit 03b1e4719b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 295 additions and 95 deletions

View file

@ -55,6 +55,8 @@ def prepare_plot(options={}):
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)
# Reset run commands # Reset run commands
plt.rcdefaults() plt.rcdefaults()
@ -125,12 +127,15 @@ def adjust_plot(fig, ax, options):
} }
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)
# Set labels on x- and y-axes # Set labels on x- and y-axes
if not options['hide_y_labels']: if not options['hide_y_labels']:
if not options['yunit']:
ax.set_ylabel(f'{options["ylabel"]}')
else:
ax.set_ylabel(f'{options["ylabel"]} [{options["yunit"]}]') ax.set_ylabel(f'{options["ylabel"]} [{options["yunit"]}]')
else: else:
ax.set_ylabel('') ax.set_ylabel('')
@ -142,7 +147,6 @@ def adjust_plot(fig, ax, options):
else: else:
ax.set_xlabel('') ax.set_xlabel('')
# Set multiple locators # Set multiple locators
if options['y_tick_locators']: if options['y_tick_locators']:
ax.yaxis.set_major_locator(MultipleLocator(options['y_tick_locators'][0])) ax.yaxis.set_major_locator(MultipleLocator(options['y_tick_locators'][0]))
@ -269,7 +273,6 @@ def ipywidgets_update(func, data, options={}, **kwargs):
where key1, key2, key3 etc. are the values in the options-dictionary you want widget control of, and widget1, widget2, widget3 etc. are widgets to control these values, e.g. widgets.IntSlider(value=1, min=0, max=10) where key1, key2, key3 etc. are the values in the options-dictionary you want widget control of, and widget1, widget2, widget3 etc. are widgets to control these values, e.g. widgets.IntSlider(value=1, min=0, max=10)
''' '''
# Update the options-dictionary with the values from the widgets # Update the options-dictionary with the values from the widgets
for key in kwargs: for key in kwargs:
options[key] = kwargs[key] options[key] = kwargs[key]

View file

@ -412,7 +412,6 @@ def read_htxrd(data, options={}, index=0):
if options['save_folder']: if options['save_folder']:
print(options['save_folder'])
for i, (diffractogram, wavelength, timestamp) in enumerate(zip(diffractograms, wavelengths, timestamps)): for i, (diffractogram, wavelength, timestamp) in enumerate(zip(diffractograms, wavelengths, timestamps)):
if not options['save_filename']: if not options['save_filename']:
filename = os.path.basename(data['path'][index]).split('.')[0] + '_' + str(i).zfill(4) +'.xy' filename = os.path.basename(data['path'][index]).split('.')[0] + '_' + str(i).zfill(4) +'.xy'
@ -439,7 +438,8 @@ def save_htxrd_as_xy(diffractogram, wavelength, timestamp, filename, save_path):
[line for line in [line for line in
[f'# Temperature {np.round(diffractogram["T"].mean())}', [f'# Temperature {np.round(diffractogram["T"].mean())}',
f'# Wavelength {wavelength}', f'# Wavelength {wavelength}',
f'# Time {timestamp}' f'# Time {timestamp}',
'# 2th \t I'
] ]
] ]
) )
@ -452,7 +452,7 @@ def save_htxrd_as_xy(diffractogram, wavelength, timestamp, filename, save_path):
f.write('\n') f.write('\n')
diffractogram.to_csv(f, index=False, sep='\t') diffractogram.to_csv(f, index=False, header=False, sep='\t')
def read_xy(data, options={}, index=0): def read_xy(data, options={}, index=0):
@ -460,8 +460,10 @@ def read_xy(data, options={}, index=0):
#if 'wavelength' not in data.keys(): #if 'wavelength' not in data.keys():
# Get wavelength from scan # Get wavelength from scan
if not 'wavelength' in data.keys() or data['wavelength'][index]:
wavelength = find_wavelength_from_xy(path=data['path'][index])
if not 'wavelength' in data.keys() or not data['wavelength'][index]:
wavelength = read_metadata_from_xy(path=data['path'][index])['wavelength']
else: else:
wavelength = data['wavelength'][index] wavelength = data['wavelength'][index]
@ -478,6 +480,7 @@ def read_xy(data, options={}, index=0):
diffractogram = pd.read_csv(f, header=None, delim_whitespace=True) diffractogram = pd.read_csv(f, header=None, delim_whitespace=True)
if diffractogram.shape[1] == 2: if diffractogram.shape[1] == 2:
diffractogram.columns = ['2th', 'I'] diffractogram.columns = ['2th', 'I']
elif diffractogram.shape[1] == 3: elif diffractogram.shape[1] == 3:
@ -488,6 +491,65 @@ def read_xy(data, options={}, index=0):
def read_metadata_from_xy(path):
metadata = {}
wavelength_dict = {'Cu': 1.54059, 'Mo': 0.71073}
with open(path, 'r') as f:
lines = f.readlines()
for line in lines:
# For .xy-files output from EVA
if 'Anode' in line:
anode = line.split()[8].strip('"')
metadata['wavelength'] = wavelength_dict[anode]
elif 'Wavelength' in line:
# For .xy-files output from pyFAI integration
if line.split()[-1] == 'm':
metadata['wavelength'] = float(line.split()[2])*10**10
else:
metadata['wavelength'] = float(line.split()[-1])
# Get temperature - exists in .xy-files saved from HTXRD-runs in .brml-files
if 'Temperature' in line:
metadata['temperature'] = line.split()[-1]
# Get timestamp - exists in .xy-files saved from .brml-files
if 'Time' in line:
metadata['time'] = " ".join(line.split()[2:])
if 'wavelength' not in metadata.keys():
metadata['wavelength'] = None
if 'temperature' not in metadata.keys():
metadata['temperature'] = None
if 'time' not in metadata.keys():
metadata['time'] = None
return metadata
def find_wavelength_from_poni(path):
with open(path, 'r') as f:
lines = f.readlines()
for line in lines:
if 'Wavelength' in line:
wavelength = float(line.split()[-1])*10**10
return wavelength
def strip_headers_from_xy(path: str, filename=None) -> None: def strip_headers_from_xy(path: str, filename=None) -> None:
''' Strips headers from a .xy-file''' ''' Strips headers from a .xy-file'''
@ -534,8 +596,6 @@ def read_data(data, options={}, index=0):
diffractogram, wavelength = read_xy(data=data, options=options, index=index) diffractogram, wavelength = read_xy(data=data, options=options, index=index)
if options['offset'] or options['normalise']: if options['offset'] or options['normalise']:
# Make copy of the original intensities before any changes are made through normalisation or offset, to easily revert back if need to update. # Make copy of the original intensities before any changes are made through normalisation or offset, to easily revert back if need to update.
diffractogram['I_org'] = diffractogram['I'] diffractogram['I_org'] = diffractogram['I']
@ -704,40 +764,4 @@ def translate_wavelengths(data: pd.DataFrame, wavelength: float, to_wavelength=N
def find_wavelength_from_xy(path):
wavelength_dict = {'Cu': 1.54059, 'Mo': 0.71073}
with open(path, 'r') as f:
lines = f.readlines()
for line in lines:
# For .xy-files output from EVA
if 'Anode' in line:
anode = line.split()[8].strip('"')
wavelength = wavelength_dict[anode]
# For .xy-files output from pyFAI integration
elif 'Wavelength' in line:
wavelength = float(line.split()[2])*10**10
else:
wavelength = None
return wavelength
def find_wavelength_from_poni(path):
with open(path, 'r') as f:
lines = f.readlines()
for line in lines:
if 'Wavelength' in line:
wavelength = float(line.split()[-1])*10**10
return wavelength

View file

@ -1,6 +1,6 @@
import seaborn as sns import seaborn as sns
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator) from matplotlib.ticker import MultipleLocator
import pandas as pd import pandas as pd
import numpy as np import numpy as np
@ -21,13 +21,12 @@ def plot_diffractogram(data, options={}):
# Update options # Update options
required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter', 'xlim', 'ylim', 'normalise', 'offset', 'offset_x', 'offset_y', 'offset_change', required_options = ['x_vals', 'y_vals', 'ylabel', 'xlabel', 'xunit', 'yunit', 'line', 'scatter', 'xlim', 'ylim', 'normalise', 'offset', 'offset_x', 'offset_y', 'offset_change',
'reflections_plot', 'reflections_indices', 'reflections_data', 'heatmap', 'cmap', 'plot_kind', 'palettes', 'interactive', 'rc_params', 'format_params', 'interactive_session_active'] 'reflections_plot', 'reflections_indices', 'reflections_data', 'heatmap', 'cmap', 'plot_kind', 'palettes', 'highlight', 'highlight_colours', 'interactive', 'rc_params', 'format_params', 'interactive_session_active']
default_options = { default_options = {
'x_vals': '2th', 'x_vals': '2th', 'y_vals': 'I',
'y_vals': 'I', 'xlabel': '2$\\theta$', 'ylabel': None,
'ylabel': 'Intensity', 'xlabel': '2theta', 'xunit': '$^{\circ}$', 'yunit': None,
'xunit': 'deg', 'yunit': 'a.u.',
'xlim': None, 'ylim': None, 'xlim': None, 'ylim': None,
'normalise': True, 'normalise': True,
'offset': True, 'offset': True,
@ -43,6 +42,8 @@ def plot_diffractogram(data, options={}):
'cmap': 'viridis', 'cmap': 'viridis',
'plot_kind': None, 'plot_kind': None,
'palettes': [('qualitative', 'Dark2_8')], 'palettes': [('qualitative', 'Dark2_8')],
'highlight': None,
'highlight_colours': ['red'],
'interactive': False, 'interactive': False,
'interactive_session_active': False, 'interactive_session_active': False,
'rc_params': {}, 'rc_params': {},
@ -61,13 +62,20 @@ def plot_diffractogram(data, options={}):
data['path'] = [data['path']] data['path'] = [data['path']]
############################################################################################################################################################
##### LOADING DATA #########################################################################################################################################
############################################################################################################################################################
# Check if there is some data stored already, load in data if not. This speeds up replotting in interactive mode. # 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():
# Initialise empty list for diffractograms and wavelengths
# This is to set the default values of the diffractogram y-label and -unit so that the actual yunit and ylable can switch back and forth between these and the heatmap values
options['diff.yunit'] = 'a.u.'
options['diff.ylabel'] = 'Intensity'
# Initialise empty list for diffractograms and wavelengths. If wavelength is not manually passed it should be automatically gathered from the .xy-file
data['diffractogram'] = [None for _ in range(len(data['path']))] data['diffractogram'] = [None for _ in range(len(data['path']))]
# If wavelength is not manually passed it should be automatically gathered from the .xy-file
if 'wavelength' not in data.keys(): if 'wavelength' not in data.keys():
data['wavelength'] = [None for _ in range(len(data['path']))] data['wavelength'] = [None for _ in range(len(data['path']))]
else: else:
@ -75,41 +83,42 @@ def plot_diffractogram(data, options={}):
if not isinstance(data['wavelength'], list): if not isinstance(data['wavelength'], list):
data['wavelength'] = [data['wavelength'] for _ in range(len(data['path']))] data['wavelength'] = [data['wavelength'] for _ in range(len(data['path']))]
# LOAD DIFFRACTOGRAMS
for index in range(len(data['path'])): for index in range(len(data['path'])):
diffractogram, wavelength = xrd.io.read_data(data=data, options=options, index=index) diffractogram, wavelength = xrd.io.read_data(data=data, options=options, index=index)
data['diffractogram'][index] = diffractogram data['diffractogram'][index] = diffractogram
data['wavelength'][index] = wavelength data['wavelength'][index] = wavelength
# FIXME This is a quick fix as the image is not reloaded when passing multiple beamline datasets # FIXME This is a quick fix as the image is not reloaded when passing multiple beamline datasets. Should probably be handled in io?
data['image'] = None data['image'] = None
# Sets the xlim if this has not bee specified
# Sets the xlim if this has not been specified
if not options['xlim']: if not options['xlim']:
options['xlim'] = [data['diffractogram'][0][options['x_vals']].min(), data['diffractogram'][0][options['x_vals']].max()] options['xlim'] = [data['diffractogram'][0][options['x_vals']].min(), data['diffractogram'][0][options['x_vals']].max()]
# Generate heatmap data # GENERATE HEATMAP DATA
data['heatmap'], data['heatmap_xticks'], data['heatmap_xticklabels'] = generate_heatmap(data=data, options=options) data['heatmap'], data['heatmap_xticks'], data['heatmap_xticklabels'], data['heatmap_yticks'], data['heatmap_yticklabels'] = generate_heatmap(data=data, options=options)
options['heatmap_loaded'] = True options['heatmap_loaded'] = True
if options['heatmap']: if options['heatmap']:
options['xlim'] = options['heatmap_xlim'] options['xlim'] = [options['heatmap_xlim'][0], options['heatmap_xlim'][1]]
# If data was already loaded, only do a check to see if the data is in a list or not, and if not, put it in one. This is because it will be looped over later.
else: else:
if not isinstance(data['diffractogram'], list): if not isinstance(data['diffractogram'], list):
data['diffractogram'] = [data['diffractogram']] data['diffractogram'] = [data['diffractogram']]
data['wavelength'] = [data['wavelength']] data['wavelength'] = [data['wavelength']]
############################################################################################################################################################
##### INTERACTIVE SESSION ##################################################################################################################################
############################################################################################################################################################
if options['interactive_session_active']:
if options['offset']:
if (options['offset_x'] != options['current_offset_x']) or (options['offset_y'] != options['current_offset_y']):
for i, (diff, wl) in enumerate(zip(data['diffractogram'], data['wavelength'])):
xrd.io.apply_offset(diff, wl, i, options)
# START INTERACTIVE SESSION
# Start inteactive session with ipywidgets. Disables options['interactive'] in order for the interactive loop to not start another interactive session # Start inteactive session with ipywidgets. Disables options['interactive'] in order for the interactive loop to not recursively start new interactive sessions
if options['interactive']: if options['interactive']:
options['interactive'] = False options['interactive'] = False
options['interactive_session_active'] = True options['interactive_session_active'] = True
@ -117,21 +126,36 @@ def plot_diffractogram(data, options={}):
return return
# If interactive mode is already enabled, update the offsets.
if options['interactive_session_active']:
if options['offset']:
if (options['offset_x'] != options['current_offset_x']) or (options['offset_y'] != options['current_offset_y']):
for i, (diff, wl) in enumerate(zip(data['diffractogram'], data['wavelength'])):
xrd.io.apply_offset(diff, wl, i, options)
############################################################################################################################################################
##### PREPARE THE PLOT AND COLOURS #########################################################################################################################
############################################################################################################################################################
# CREATE AND ASSIGN AXES
# Makes a list out of reflections_data if it only passed as a dict, as it will be looped through later # Makes a list out of reflections_data if it only passed as a dict, as it will be looped through later
if options['reflections_data']: if options['reflections_data']:
if not isinstance(options['reflections_data'], list): if not isinstance(options['reflections_data'], list):
options['reflections_data'] = [options['reflections_data']] options['reflections_data'] = [options['reflections_data']]
# Determine number of subplots and height ratios between them
# Determine the grid layout based on how many sets of reflections data has been passed
if options['reflections_data'] and len(options['reflections_data']) >= 1: if options['reflections_data'] and len(options['reflections_data']) >= 1:
options = determine_grid_layout(options=options) options = determine_grid_layout(options=options)
# Create the Figure and Axes objects
# Prepare plot, and read and process data
fig, ax = btp.prepare_plot(options=options) fig, ax = btp.prepare_plot(options=options)
# Assign the correct axes to the indicies, reflections and figure itself
# Assign the correct axes
if options['reflections_plot'] or options['reflections_indices']: if options['reflections_plot'] or options['reflections_indices']:
if options['reflections_indices']: if options['reflections_indices']:
@ -145,48 +169,157 @@ def plot_diffractogram(data, options={}):
ax = ax[-1] ax = ax[-1]
if len(data['path']) < 10:
# GENERATE COLOURS
# Limit for when it is assumed that each diffractogram should have its own colour - after 8, the default colour palette is used up and starts a new.
# FIXME Should probably allow for more than 8 if wanted - not a priority now
if len(data['path']) < 8:
colours = btp.generate_colours(options['palettes']) colours = btp.generate_colours(options['palettes'])
# Generates the colours of a list of scans to highlight is passed. options['highlight'] and options['highlight_colour'] must be of equal length. Entries in highlight can either be a list or a single number,
# if the latter it will be turned into a list with the same number as element 1 and 2.
elif options['highlight']:
# Make sure that options['highlight'] is a list
if not isinstance(options['highlight'], list):
options['highlight'] = [[options['highlight'], options['highlight']]]
# Make sure that options['highlight_colours] is a list
if not isinstance(options['highlight_colours'], list):
options['highlight_colours'] = [options['highlight_colours']]
colours = []
# Loop through each scan - assign the correct colour to each of the scan intervals in options['highlight']
for i in range(len(data['path'])):
assigned = False
for j, highlight in enumerate(options['highlight']):
# If one of the elements in options['highlight'] is a single number (i.e. only one scan should be highlighted), this is converted into the suitable format to be handled below
if not isinstance(highlight, list):
highlight = [highlight, highlight]
# Assigns the j-th colour if scan number (i) is within the j-th highlight-interval
if i >= highlight[0] and i <= highlight[1]:
colours.append(options['highlight_colours'][j])
assigned = True
# Only assign black to i if not already been given a colour
if not assigned:
colours.append('black')
# Reset the 'assigned' value for the next iteration
assigned = False
# Make a itertools cycle out of the colours
colours = btp.generate_colours(colours, kind='single')
# If there are many scans and no highlight-options have been passed, all scans will be black
else: else:
colours = btp.generate_colours(['black'], kind='single') colours = btp.generate_colours(['black'], kind='single')
############################################################################################################################################################
##### PLOT THE DATA ########################################################################################################################################
############################################################################################################################################################
# PLOT HEATMAP
if options['heatmap']: if options['heatmap']:
# Add locators for y-axis - otherwise it will tend to break (too many ticks) when switching between diffractograms and heatmap in interactive mode. These values will be updated later anyway, and is only
# to allow the initial call to Seaborn to have values that are sensible.
# FIXME A more elegant solution to this?
ax.yaxis.set_major_locator(MultipleLocator(100))
ax.yaxis.set_minor_locator(MultipleLocator(50))
# Call Seaborn to plot the data
sns.heatmap(data['heatmap'], cmap=options['cmap'], cbar=False, ax=ax) sns.heatmap(data['heatmap'], cmap=options['cmap'], cbar=False, ax=ax)
# Set the ticks and ticklabels to match the data point number with 2th values
ax.set_xticks(data['heatmap_xticks'][options['x_vals']]) ax.set_xticks(data['heatmap_xticks'][options['x_vals']])
ax.set_xticklabels(data['heatmap_xticklabels'][options['x_vals']]) ax.set_xticklabels(data['heatmap_xticklabels'][options['x_vals']])
ax.tick_params(axis='x', which='minor', bottom=False, top=False) ax.set_yticks(data['heatmap_yticks'])
ax.set_yticklabels(data['heatmap_yticklabels'])
# Set the labels to the relevant values for heatmap plot
if not options['ylabel'] or options['ylabel'] == options['diff.ylabel']:
options['ylabel'] = options['heatmap.ylabel']
if not options['yunit'] or options['yunit'] == options['diff.yunit']:
options['yunit'] = options['heatmap.yunit']
ax.tick_params(axis='x', which='minor', bottom=False, top=False)
ax.tick_params(axis='y', which='minor', left=False, right=False)
options['hide_y_ticklabels'] = False
options['hide_y_ticks'] = False
# Toggle on the frame around the heatmap - this makes it look better together with axes ticks
for _, spine in ax.spines.items():
spine.set_visible(True)
if options['highlight']:
for i, highlight in enumerate(options['highlight']):
if i < len(options['highlight'])-1 or len(options['highlight']) == 1:
ax.axhline(y=highlight[1], c=options['highlight_colours'][i], ls='--', lw=0.5)
# PLOT DIFFRACTOGRAM
else: else:
for diffractogram in data['diffractogram']: for diffractogram in data['diffractogram']:
# Plot data as line plot
if options['line']: if options['line']:
diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1) diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1)
# Plot data as scatter plot
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)]))
# Set the labels to the relevant values for diffractogram plot
if not options['ylabel'] or options['ylabel'] == options['heatmap.ylabel']:
options['ylabel'] = options['diff.ylabel']
if not options['yunit'] or options['yunit'] == options['heatmap.yunit']:
options['yunit'] = options['diff.yunit']
options['hide_y_ticklabels'] = True
options['hide_y_ticks'] = True
# Adjust the plot to make it prettier
fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options) fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options)
# PLOT REFLECTION TABLES
# 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'][0] options['to_wavelength'] = data['wavelength'][0] # By default, the wavelength of the first diffractogram will be used for these.
# Plot each reflection table in the relevant axis
for reflections_params, axis in zip(options['reflections_data'], ref_axes): for reflections_params, axis in zip(options['reflections_data'], ref_axes):
plot_reflection_table(data=data, reflections_params=reflections_params, ax=axis, options=options) plot_reflection_table(data=data, reflections_params=reflections_params, ax=axis, options=options)
# Print the reflection indices. By default, the wavelength of the first diffractogram will be used for this. # Print the reflection indices.
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'][0] options['to_wavelength'] = data['wavelength'][0] # By default, the wavelength of the first diffractogram will be used for this.
for reflections_params in options['reflections_data']: for reflections_params in options['reflections_data']:
plot_reflection_indices(data=data, reflections_params=reflections_params, ax=indices_ax, options=options) plot_reflection_indices(data=data, reflections_params=reflections_params, ax=indices_ax, options=options)
############################################################################################################################################################
##### UPDATE WIDGET ########################################################################################################################################
############################################################################################################################################################
if options['interactive_session_active']: if options['interactive_session_active']:
options['current_y_offset'] = options['widget'].kwargs['offset_y'] options['current_y_offset'] = options['widget'].kwargs['offset_y']
update_widgets(data=data, options=options) update_widgets(data=data, options=options)
@ -199,10 +332,15 @@ def plot_diffractogram(data, options={}):
def generate_heatmap(data, options={}): def generate_heatmap(data, options={}):
required_options = ['x_tick_locators'] required_options = ['x_tick_locators', 'heatmap_y_tick_locators', 'heatmap_normalise', 'normalisation_range', 'increase_contrast']
default_options = { default_options = {
'x_tick_locators': [0.5, 0.1] 'x_tick_locators': [0.5, 0.1],
'heatmap_y_tick_locators': [10, 5], # Major ticks for every 10 scans, minor for every 5
'heatmap_normalise': False,
'normalisation_range': None,
'increase_contrast': False,
'contrast_factor': 100
} }
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)
@ -212,6 +350,17 @@ def generate_heatmap(data, options={}):
scans = [] scans = []
for i, d in enumerate(data['diffractogram']): for i, d in enumerate(data['diffractogram']):
# Find normalisation factor
if options['heatmap_normalise'] and options['normalisation_range']:
mean_background = d['I'].loc[(d['2th'] > options['normalisation_range'][0]) & (d['2th'] < options['normalisation_range'][1])].mean()
d['I'] = d['I'] / mean_background
if options['increase_contrast']:
d['I'] = d['I']**(1/options['contrast_factor'])
twotheta = np.append(twotheta, d['2th'].to_numpy()) twotheta = np.append(twotheta, d['2th'].to_numpy())
intensities = np.append(intensities, d['I'].to_numpy()) intensities = np.append(intensities, d['I'].to_numpy())
scans = np.append(scans, np.full(len(d['2th'].to_numpy()), int(i))) scans = np.append(scans, np.full(len(d['2th'].to_numpy()), int(i)))
@ -219,6 +368,7 @@ def generate_heatmap(data, options={}):
heatmap = pd.DataFrame({'2th': twotheta, 'scan': scans, 'I': intensities}) heatmap = pd.DataFrame({'2th': twotheta, 'scan': scans, 'I': intensities})
xrd.io.translate_wavelengths(data=heatmap, wavelength=data['wavelength'][0]) xrd.io.translate_wavelengths(data=heatmap, wavelength=data['wavelength'][0])
min_dict = {'2th': heatmap['2th'].min(), '2th_cuka': heatmap['2th_cuka'].min(), '2th_moka': heatmap['2th_moka'].min(), min_dict = {'2th': heatmap['2th'].min(), '2th_cuka': heatmap['2th_cuka'].min(), '2th_moka': heatmap['2th_moka'].min(),
'q': heatmap['q'].min(), 'q2': heatmap['q2'].min(), 'q4': heatmap['q4'].min(), '1/d': heatmap['1/d'].min()} 'q': heatmap['q'].min(), 'q2': heatmap['q2'].min(), 'q4': heatmap['q4'].min(), '1/d': heatmap['1/d'].min()}
@ -235,7 +385,6 @@ def generate_heatmap(data, options={}):
for xval in min_dict.keys(): for xval in min_dict.keys():
# Add xticks labels # Add xticks labels
label_max = aux.floor(max_dict[xval], roundto=options['x_tick_locators'][0]) label_max = aux.floor(max_dict[xval], roundto=options['x_tick_locators'][0])
label_min = aux.ceil(min_dict[xval], roundto=options['x_tick_locators'][0]) label_min = aux.ceil(min_dict[xval], roundto=options['x_tick_locators'][0])
label_steps = (label_max - label_min)/options['x_tick_locators'][0] label_steps = (label_max - label_min)/options['x_tick_locators'][0]
@ -262,7 +411,32 @@ def generate_heatmap(data, options={}):
options['heatmap_xlim'] = xlims options['heatmap_xlim'] = xlims
return heatmap, xticks, xticklabels # Get temperatures if HTXRD-scans
scan_numbers = []
temperatures = []
for i, filename in enumerate(data['path']):
scan_numbers.append(i)
temperatures.append(xrd.io.read_metadata_from_xy(filename)['temperature'])
yticks = scan_numbers[0::options['heatmap_y_tick_locators'][0]]
yticks.append(scan_numbers[-1])
if not temperatures[0]:
yticklabels = yticks
options['heatmap.ylabel'] = 'Scan number'
options['heatmap.yunit'] = None
else:
yticklabels = temperatures[0::options['heatmap_y_tick_locators'][0]]
yticklabels.append(temperatures[-1])
options['heatmap.ylabel'] = 'Temperature'
options['heatmap.yunit'] = '$^\circ$C'
return heatmap, xticks, xticklabels, yticks, yticklabels
@ -349,12 +523,12 @@ def plot_diffractogram_interactive(data, options):
if options['reflections_data']: if options['reflections_data']:
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),
x_vals=widgets.Dropdown(options=['2th', 'd', '1/d', 'q', 'q2', 'q4', '2th_cuka', '2th_moka'], value='2th', description='X-values'),
scatter=widgets.ToggleButton(value=False), scatter=widgets.ToggleButton(value=False),
line=widgets.ToggleButton(value=True), line=widgets.ToggleButton(value=True),
reflections_plot=widgets.ToggleButton(value=True), reflections_plot=widgets.ToggleButton(value=True),
reflections_indices=widgets.ToggleButton(value=False), reflections_indices=widgets.ToggleButton(value=False),
heatmap=widgets.ToggleButton(value=options['heatmap']), heatmap=widgets.ToggleButton(value=options['heatmap']),
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=options['widgets']['ylim']['w'], ylim=options['widgets']['ylim']['w'],
offset_y=widgets.BoundedFloatText(value=options['offset_y'], min=-5, max=5, step=0.01, description='offset_y'), offset_y=widgets.BoundedFloatText(value=options['offset_y'], min=-5, max=5, step=0.01, description='offset_y'),
@ -363,10 +537,10 @@ def plot_diffractogram_interactive(data, options):
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),
x_vals=widgets.Dropdown(options=['2th', 'd', '1/d', 'q', 'q2', 'q4', '2th_cuka', '2th_moka'], value='2th', description='X-values'),
scatter=widgets.ToggleButton(value=False), scatter=widgets.ToggleButton(value=False),
line=widgets.ToggleButton(value=True), line=widgets.ToggleButton(value=True),
heatmap=widgets.ToggleButton(value=options['heatmap']), heatmap=widgets.ToggleButton(value=options['heatmap']),
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=options['widgets']['ylim']['w'], ylim=options['widgets']['ylim']['w'],
offset_y=widgets.BoundedFloatText(value=options['offset_y'], min=-5, max=5, step=0.01, description='offset_y'), offset_y=widgets.BoundedFloatText(value=options['offset_y'], min=-5, max=5, step=0.01, description='offset_y'),
@ -683,4 +857,3 @@ def reverse_diffractograms(diffractograms):
return rev_diffractograms return rev_diffractograms
#def plot_heatmap():