diff --git a/beamtime/plotting.py b/beamtime/plotting.py index 3430a2a..dd9a481 100644 --- a/beamtime/plotting.py +++ b/beamtime/plotting.py @@ -313,6 +313,17 @@ def update_widgets(options): if widget['state'] != options['x_vals']: 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]) widget['state'] = options['x_vals'] diff --git a/beamtime/xrd/io.py b/beamtime/xrd/io.py index 6b0bb7a..3e29b80 100644 --- a/beamtime/xrd/io.py +++ b/beamtime/xrd/io.py @@ -27,7 +27,7 @@ def get_image_headers(path): return image.header -def integrate_1d(data, options={}): +def integrate_1d(data, options={}, index=0): ''' Integrates an image file to a 1D diffractogram. Required content of data: @@ -51,11 +51,14 @@ def integrate_1d(data, options={}): 'overwrite': False} 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 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) ai = pyFAI.load(data['calibrant']) @@ -70,18 +73,18 @@ def integrate_1d(data, options={}): res = ai.integrate1d(data['image'], data['nbins'], unit=options['unit'], filename=filename) - data['path'] = filename - diffractogram = read_xy(data=data, options=options) + data['path'][index] = filename + diffractogram, wavelength = read_xy(data=data, options=options) if not options['save']: os.remove(filename) shutil.rmtree('tmp') - return diffractogram + return diffractogram, wavelength -def make_filename(data, options): +def make_filename(options, path=None): # Define save location for integrated diffractogram data if not options['save']: @@ -93,7 +96,7 @@ def make_filename(data, options): # Case 1: No filename is given. 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 data['path']: + if path: # 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']) else: @@ -176,12 +179,12 @@ def view_integrator(calibrant): -def read_brml(data, options={}): +def read_brml(data, options={}, index=0): required_options = ['extract_folder', 'save_folder'] default_options = { - 'extract_folder': 'tmp', + 'extract_folder': 'tmp/', 'save_folder': None } @@ -194,7 +197,7 @@ def read_brml(data, options={}): # 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(): if "RawData" in info.filename: brml.extract(info.filename, options['extract_folder']) @@ -233,9 +236,10 @@ def read_brml(data, options={}): diffractogram.append({'2th': twotheta, 'I': intensity}) - if 'wavelength' not in data.keys(): - for chain in root.findall('./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1'): - data['wavelength'] = float(chain.attrib['Value']) + #if 'wavelength' not in data.keys(): + # Find wavelength + for chain in root.findall('./FixedInformation/Instrument/PrimaryTracks/TrackInfoData/MountedOptics/InfoData/Tube/WaveLengthAlpha1'): + wavelength = float(chain.attrib['Value']) diffractogram = pd.DataFrame(diffractogram) @@ -249,15 +253,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(): - find_wavelength_from_xy(data=data) + #if 'wavelength' not in data.keys(): + # 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 current_line = f.readline() @@ -276,37 +281,37 @@ def read_xy(data, options={}): 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'] - file_extension = data['path'].split('.')[-1] + file_extension = data['path'][index].split('.')[-1] 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': - diffractogram = read_brml(data=data, options=options) + diffractogram, wavelength = read_brml(data=data, options=options, index=index) 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']) + diffractogram = translate_wavelengths(data=diffractogram, wavelength=wavelength) - return diffractogram + return diffractogram, wavelength def load_reflection_table(data, options={}): - required_options = ['wavelength', 'to_wavelength'] + required_options = ['ref_wavelength', 'to_wavelength'] default_options = { - 'wavelength': 1.54059, + 'ref_wavelength': 1.54059, 'to_wavelength': None } @@ -333,7 +338,7 @@ def load_reflection_table(data, options={}): # Set the new modified headers as the headers of 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) @@ -378,6 +383,7 @@ def translate_wavelengths(data, wavelength, to_wavelength=None): if to_wavelength: + if to_wavelength > cuka: max_2th = 2*np.arcsin(cuka/to_wavelength) * 180/np.pi @@ -395,19 +401,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} - with open(data['path'], 'r') as f: + 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('"') - data['wavelength'] = wavelength_dict[anode] + wavelength = wavelength_dict[anode] + # For .xy-files output from pyFAI integration elif 'Wavelength' in line: - data['wavelength'] = float(line.split()[2])*10**10 + wavelength = float(line.split()[2])*10**10 + + + return wavelength diff --git a/beamtime/xrd/plot.py b/beamtime/xrd/plot.py index daa7eaf..cec2d1e 100644 --- a/beamtime/xrd/plot.py +++ b/beamtime/xrd/plot.py @@ -43,12 +43,25 @@ def plot_diffractogram(data, 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']] + + if not 'diffractogram' in data.keys(): - diffractogram = xrd.io.read_data(data=data, options=options) - data['diffractogram'] = diffractogram + # Initialise empty list for diffractograms and wavelengths + 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: - 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 if not options['xlim']: @@ -95,11 +108,12 @@ def plot_diffractogram(data, options={}): colours = btp.generate_colours(options['palettes']) - if options['line']: - diffractogram.plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=next(colours), zorder=1) + for diffractogram in data['diffractogram']: + 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)])) + 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)])) @@ -110,7 +124,7 @@ def plot_diffractogram(data, options={}): # Make the reflection plots if options['reflections_plot'] and options['reflections_data']: 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): plot_reflection_table(data=reference, ax=axis, options=options) @@ -118,7 +132,7 @@ def plot_diffractogram(data, options={}): # Print the reflection indices if options['reflections_indices'] and options['reflections_data']: options['xlim'] = ax.get_xlim() - options['to_wavelength'] = data['wavelength'] + options['to_wavelength'] = data['wavelength'][0] for reference in options['reflections_data']: plot_reflection_indices(data=reference, ax=indices_ax, options=options) @@ -149,17 +163,54 @@ def determine_grid_layout(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]} + + 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() + 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() + + + + # options['widgets'] = { + # '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%')), + # '2th_default': {'min': data['diffractogram']['2th'].min(), 'max': data['diffractogram']['2th'].max(), 'value': [data['diffractogram']['2th'].min(), data['diffractogram']['2th'].max()], 'step': 0.5}, + # '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_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}, + # 'd_default': {'min': data['diffractogram']['d'].min(), 'max': data['diffractogram']['d'].max(), 'value': [data['diffractogram']['d'].min(), data['diffractogram']['d'].max()], '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}, + # 'q_default': {'min': data['diffractogram']['q'].min(), 'max': data['diffractogram']['q'].max(), 'value': [data['diffractogram']['q'].min(), data['diffractogram']['q'].max()], '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}, + # 'q4_default': {'min': data['diffractogram']['q4'].min(), 'max': data['diffractogram']['q4'].max(), 'value': [data['diffractogram']['q4'].min(), data['diffractogram']['q4'].max()], 'step': 0.5}, + # 'state': '2th' + # } + # } + options['widgets'] = { '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%')), - '2th_default': {'min': data['diffractogram']['2th'].min(), 'max': data['diffractogram']['2th'].max(), 'value': [data['diffractogram']['2th'].min(), data['diffractogram']['2th'].max()], 'step': 0.5}, - '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_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}, - 'd_default': {'min': data['diffractogram']['d'].min(), 'max': data['diffractogram']['d'].max(), 'value': [data['diffractogram']['d'].min(), data['diffractogram']['d'].max()], '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}, - 'q_default': {'min': data['diffractogram']['q'].min(), 'max': data['diffractogram']['q'].max(), 'value': [data['diffractogram']['q'].min(), data['diffractogram']['q'].max()], '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}, - 'q4_default': {'min': data['diffractogram']['q4'].min(), 'max': data['diffractogram']['q4'].max(), 'value': [data['diffractogram']['q4'].min(), data['diffractogram']['q4'].max()], 'step': 0.5}, + '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': minmax['2th'][0], 'max': minmax['2th'][1], 'value': [minmax['2th'][0], minmax['2th'][1]], '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}, + '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}, + 'd_default': {'min': minmax['d'][0], 'max': minmax['d'][1], 'value': [minmax['d'][0], minmax['d'][1]], '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}, + 'q_default': {'min': minmax['q'][0], 'max': minmax['q'][1], 'value': [minmax['q'][0], minmax['q'][1]], 'step': 0.5}, + 'q2_default': {'min': minmax['q2'][0], 'max': minmax['q2'][1], 'value': [minmax['q2'][0], minmax['q2'][1]], 'step': 0.5}, + 'q4_default': {'min': minmax['q4'][0], 'max': minmax['q4'][1], 'value': [minmax['q4'][0], minmax['q4'][1]], 'step': 0.5}, 'state': '2th' } }