diff --git a/.gitignore b/.gitignore
index b6e4761..0498486 100644
--- a/.gitignore
+++ b/.gitignore
@@ -127,3 +127,7 @@ dmypy.json
# Pyre type checker
.pyre/
+
+# Mac
+.DS_Store
+.idea/
diff --git a/notebooks/__code/__init__.py b/notebooks/__code/__init__.py
new file mode 100644
index 0000000..5ac2af1
--- /dev/null
+++ b/notebooks/__code/__init__.py
@@ -0,0 +1,6 @@
+from qtpy.uic import loadUi
+
+__all__ = ['load_ui']
+
+def load_ui(ui_filename, baseinstance):
+ return loadUi(ui_filename, baseinstance=baseinstance)
diff --git a/notebooks/__code/array.py b/notebooks/__code/array.py
new file mode 100644
index 0000000..941ba60
--- /dev/null
+++ b/notebooks/__code/array.py
@@ -0,0 +1,23 @@
+import numpy as np
+
+
+def exclude_y_value_when_error_is_nan(axis, error_axis):
+ axis_cleaned = []
+ error_axis_cleaned = []
+
+ for _x, _error in zip(axis, error_axis):
+ if (_x == "None") or (_error == "None") or (_x is None) or (_error is None):
+ axis_cleaned.append(np.NaN)
+ error_axis_cleaned.append(np.NaN)
+ else:
+ axis_cleaned.append(np.float(_x))
+ error_axis_cleaned.append(np.float(_error))
+
+ return axis_cleaned, error_axis_cleaned
+
+
+def check_size(x_axis=None, y_axis=None):
+ size_x = len(x_axis)
+ size_y = len(y_axis)
+ min_len = np.min([size_x, size_y])
+ return x_axis[:min_len], y_axis[:min_len]
diff --git a/notebooks/__code/bragg_edge.py b/notebooks/__code/bragg_edge.py
new file mode 100644
index 0000000..dd7085c
--- /dev/null
+++ b/notebooks/__code/bragg_edge.py
@@ -0,0 +1,763 @@
+from __code.ipywe import fileselector
+import random
+import os
+import glob
+from IPython.core.display import HTML
+from IPython.display import display
+import numpy as np
+from collections import OrderedDict
+from plotly.offline import iplot
+import plotly.graph_objs as go
+from ipywidgets import widgets
+import pyqtgraph as pg
+try:
+ from PyQt4.QtGui import QFileDialog
+ from PyQt4 import QtCore, QtGui
+ from PyQt4.QtGui import QMainWindow
+except ImportError:
+ from PyQt5.QtWidgets import QFileDialog
+ from PyQt5 import QtCore, QtGui
+ from PyQt5.QtWidgets import QApplication, QMainWindow
+
+from neutronbraggedge.experiment_handler import *
+from neutronbraggedge.braggedge import BraggEdge as BraggEdgeLibrary
+from neutronbraggedge.material_handler.retrieve_material_metadata import RetrieveMaterialMetadata
+from NeuNorm.normalization import Normalization
+
+from __code import file_handler
+from __code.ui_roi_selection import Ui_MainWindow as UiMainWindow
+
+
+class BraggEdge:
+
+ list_of_elements = ['Fe']
+ data = []
+ spectra_file = None
+
+ label_width = '15%'
+
+ def __init__(self, working_dir='./'):
+ self.working_dir = working_dir
+ self.ipts_folder = working_dir
+
+ def full_list_elements(self):
+ retrieve_material = RetrieveMaterialMetadata(material='all')
+ self.list_returned = retrieve_material.full_list_material()
+
+ # import pprint
+ # pprint.pprint(list_returned)
+
+ box4 = widgets.HBox([widgets.Label("List of elements",
+ layout=widgets.Layout(width=self.label_width)),
+ widgets.Select(options=self.list_returned,
+ layout=widgets.Layout(width='20%'))])
+
+ box5 = widgets.HBox([widgets.Label("Nbr Bragg Edges",
+ layout=widgets.Layout(width=self.label_width)),
+ widgets.IntText(8,
+ layout=widgets.Layout(width='20%'))])
+
+ vertical_box = widgets.VBox([box4, box5])
+ display(vertical_box)
+
+ self.list_elements_ui = box4.children[1]
+ self.nbr_bragg_edges_ui = box5.children[1]
+
+ def list_elements(self):
+ retrieve_material = RetrieveMaterialMetadata(material='all')
+ self.list_returned = retrieve_material.full_list_material()
+
+ # import pprint
+ # pprint.pprint(list_returned)
+
+ box4 = widgets.HBox([widgets.Label("List of elements",
+ layout=widgets.Layout(width=self.label_width)),
+ widgets.Text(','.join(self.list_of_elements),
+ layout=widgets.Layout(width='20%'))])
+
+ box5 = widgets.HBox([widgets.Label("Nbr Bragg Edges",
+ layout=widgets.Layout(width=self.label_width)),
+ widgets.Text(str(8),
+ layout=widgets.Layout(width='20%'))])
+
+ vertical_box = widgets.VBox([box4, box5])
+ display(vertical_box)
+
+ self.list_elements_ui = box4.children[1]
+ self.nbr_bragg_edges_ui = box5.children[1]
+
+ def exp_setup(self):
+
+ box2 = widgets.HBox([widgets.Label("dSD (m)",
+ layout=widgets.Layout(width=self.label_width)),
+ widgets.Text(str(16.08),
+ layout=widgets.Layout(width='20%'))])
+
+ box3 = widgets.HBox([widgets.Label("detector offset (microns)",
+ layout=widgets.Layout(width=self.label_width)),
+ widgets.Text(str(3700),
+ layout=widgets.Layout(width='20%'))])
+
+ vertical_box = widgets.VBox([box2, box3])
+ display(vertical_box)
+
+ self.dSD_ui = box2.children[1]
+ self.detector_offset_ui = box3.children[1]
+
+ def list_powder_bragg_edges(self):
+
+ list_of_elements_selected = self.list_elements_ui.value
+ list_of_elements = list_of_elements_selected.split(',')
+ list_of_elements = [_element.strip() for _element in list_of_elements]
+ number_of_bragg_edges = np.int(self.nbr_bragg_edges_ui.value)
+
+ _handler = BraggEdgeLibrary(material=list_of_elements,
+ number_of_bragg_edges=number_of_bragg_edges)
+ self.bragg_edges = _handler.bragg_edges
+ self.hkl = _handler.hkl
+ self.handler = _handler
+
+ def select_working_folder(self):
+ select_data = fileselector.FileSelectorPanel(instruction='Select Data Folder ...',
+ start_dir=self.working_dir,
+ next=self.load_data,
+ type='directory',
+ multiple=False)
+ select_data.show()
+
+ def load_data(self, folder_selected):
+ list_files = glob.glob(os.path.join(folder_selected, '*.fits'))
+
+ if list_files == []:
+ list_files = glob.glob(os.path.join(folder_selected, '*.tif*'))
+
+ else: #fits
+ # keep only files of interest
+ list_files = [file for file in list_files if not "_SummedImg.fits" in file]
+ list_files = [file for file in list_files if ".fits" in file]
+
+ # sort list of files
+ list_files.sort()
+
+ o_norm = Normalization()
+ o_norm.load(file=list_files, notebook=True)
+
+ self.data = o_norm.data['sample']['data']
+ self.list_files = o_norm.data['sample']['file_name']
+
+ display(HTML('' + str(len(list_files)) + \
+ ' files have been loaded'))
+
+ # define time spectra file
+ folder = os.path.dirname(self.list_files[0])
+ spectra_file = glob.glob(os.path.join(folder, '*_Spectra.txt'))
+ if spectra_file:
+ self.spectra_file = spectra_file[0]
+ display(HTML(' Spectra File automatically located: ' + \
+ self.spectra_file + ''))
+
+ else:
+ #ask for spectra file
+ self.select_time_spectra_file()
+
+ def load_time_spectra(self):
+ _tof_handler = TOF(filename=self.spectra_file)
+ _exp = Experiment(tof=_tof_handler.tof_array,
+ distance_source_detector_m=np.float(self.dSD_ui.value),
+ detector_offset_micros=np.float(self.detector_offset_ui.value))
+ self.lambda_array = _exp.lambda_array * 1e10 # to be in Angstroms
+ self.tof_array = _tof_handler.tof_array
+
+ def save_time_spectra(self, file):
+ self.spectra_file = file
+ display(HTML(' Spectra File : ' + \
+ self.spectra_file + ''))
+
+ def select_time_spectra_file(self):
+ self.working_dir = os.path.dirname(self.list_files[0])
+
+ self.time_spectra_ui = fileselector.FileSelectorPanel(instruction='Select Time Spectra File ...',
+ start_dir=self.working_dir,
+ next=self.save_time_spectra,
+ filters={'spectra_file': "_Spectra.txt"},
+ multiple=False)
+ self.time_spectra_ui.show()
+
+ def select_just_time_spectra_file(self):
+ self.time_spectra_ui = fileselector.FileSelectorPanel(instruction='Select Time Spectra File ...',
+ start_dir=self.working_dir,
+ filters={'spectra_file': "*_Spectra.txt"},
+ multiple=False)
+ self.time_spectra_ui.show()
+
+ def how_many_data_to_use_to_select_sample_roi(self):
+ nbr_images = len(self.data)
+ init_value = np.int(nbr_images/10)
+ if init_value == 0:
+ init_value = 1
+ box1 = widgets.HBox([widgets.Label("Nbr of images to use:",
+ layout=widgets.Layout(width='15')),
+ widgets.IntSlider(value=init_value,
+ max=nbr_images,
+ min=1,
+ layout=widgets.Layout(width='50%'))])
+ box2 = widgets.Label("(The more you select, the longer it will take to display the preview!)")
+ vbox = widgets.VBox([box1, box2])
+ display(vbox)
+ self.number_of_data_to_use_ui = box1.children[1]
+
+ def define_sample_roi(self):
+ nbr_data_to_use = np.int(self.number_of_data_to_use_ui.value)
+ nbr_images = len(self.data)
+ list_of_indexes_to_keep = random.sample(list(range(nbr_images)), nbr_data_to_use)
+
+ final_array = []
+ for _index in list_of_indexes_to_keep:
+ final_array.append(self.data[_index])
+ final_image = np.mean(final_array, axis=0)
+ self.final_image = final_image
+
+ def calculate_counts_vs_file_index_of_regions_selected(self, list_roi=[]):
+
+ counts_vs_file_index = []
+ for _data in self.data:
+
+ _array_data = []
+
+ for _roi in list_roi.keys():
+
+ x0 = np.int(list_roi[_roi]['x0'])
+ y0 = np.int(list_roi[_roi]['y0'])
+ x1 = np.int(list_roi[_roi]['x1'])
+ y1 = np.int(list_roi[_roi]['y1'])
+
+ _array_data.append(np.mean(_data[y0:y1, x0:x1]))
+
+ counts_vs_file_index.append(np.mean(_array_data))
+
+ self.counts_vs_file_index = counts_vs_file_index
+
+ def plot(self):
+
+ bragg_edges = self.bragg_edges
+ hkl = self.hkl
+ lambda_array = self.lambda_array
+ sum_cropped_data = self.final_image
+
+ # format hkl labels
+ _hkl_formated = {}
+ for _material in hkl:
+ _hkl_string = []
+ for _hkl in hkl[_material]:
+ _hkl_s = ",".join(str(x) for x in _hkl)
+ _hkl_s = _material + "\n" + _hkl_s
+ _hkl_string.append(_hkl_s)
+ _hkl_formated[_material] = _hkl_string
+
+ trace = go.Scatter(
+ x=self.lambda_array,
+ y=self.counts_vs_file_index,
+ mode='markers')
+
+ layout = go.Layout(
+ width="100%",
+ height=500,
+ title="Sum Counts vs TOF",
+ xaxis=dict(
+ title="Lambda (Angstroms)"
+ ),
+ yaxis=dict(
+ title="Sum Counts"
+ ),
+ )
+
+ max_x = 6
+ y_off = 1
+
+ for y_index, _material in enumerate(bragg_edges):
+ for _index, _value in enumerate(bragg_edges[_material]):
+ if _value > max_x:
+ continue
+ bragg_line = {"type": "line",
+ 'x0': _value,
+ 'x1': _value,
+ 'yref': "paper",
+ 'y0': 0,
+ 'y1': 1,
+ 'line': {
+ 'color': 'rgb(255, 0, 0)',
+ 'width': 1
+ }}
+ layout.shapes.append(bragg_line)
+ y_off = 1 - 0.25 * y_index
+
+ # add labels to plots
+ _annot = dict(
+ x=_value,
+ y=y_off,
+ text=_hkl_formated[_material][_index],
+ yref="paper",
+ font=dict(
+ family="Arial",
+ size=16,
+ color="rgb(150,50,50)"
+ ),
+ showarrow=True,
+ arrowhead=3,
+ ax=0,
+ ay=-25)
+
+ layout.annotations.append(_annot)
+
+ data = [trace]
+
+ figure = go.Figure(data=data, layout=layout)
+ iplot(figure)
+
+ def select_output_folder(self):
+ self.select_folder(message='output',
+ next_function=self.export_table)
+
+ def export_table(self, output_folder):
+ material = self.handler.material[0]
+ lattice = self.handler.lattice[material]
+ crystal_structure = self.handler.crystal_structure[material]
+ metadata = ["# material: {}".format(material),
+ "# crystal structure: {}".format(crystal_structure),
+ "# lattice: {} Angstroms".format(lattice),
+ "#",
+ "# hkl, d(angstroms), BraggEdge"]
+ data = []
+ bragg_edges = self.bragg_edges[material]
+ hkl = self.hkl[material]
+ for _index in np.arange(len(bragg_edges)):
+ _hkl_str = [str(i) for i in hkl[_index]]
+ _hkl = "".join(_hkl_str)
+ _bragg_edges = np.float(bragg_edges[_index])
+ _d = _bragg_edges/2.
+ _row = "{}, {}, {}".format(_hkl, _d, _bragg_edges)
+ data.append(_row)
+
+ output_file_name = os.path.join(output_folder, 'bragg_edges_of_{}.txt'.format(material))
+
+ file_handler.make_ascii_file(metadata=metadata,
+ data=data,
+ dim='1d',
+ output_file_name=output_file_name)
+
+ display(HTML('File created : ' + \
+ output_file_name + ''))
+
+ def select_folder(self, message="", next_function=None):
+ folder_widget = fileselector.FileSelectorPanel(instruction='select {} folder'.format(message),
+ start_dir=self.working_dir,
+ next=next_function,
+ type='directory',
+ multiple=False)
+ folder_widget.show()
+
+
+class Interface(QMainWindow):
+
+ roi_width = 0.01
+ roi_selected = {} #nice formatting of list_roi for outside access
+
+ live_data = []
+ o_norm = None
+ roi_column_width = 70
+ integrated_image = None
+ integrated_image_size = {'width': -1, 'height': -1}
+
+ list_roi = {} # 'row": {'x0':None, 'y0': None, 'x1': None, 'y1': None}
+ default_roi = {'x0': 0, 'y0': 0, 'x1': 50, 'y1': 50, 'id': None}
+
+ def __init__(self, parent=None, data=None):
+
+ display(HTML('Check UI that poped up \
+ (maybe hidden behind this browser!)'))
+
+ self.live_data = data
+
+ QMainWindow.__init__(self, parent=parent)
+ self.ui = UiMainWindow()
+ self.ui.setupUi(self)
+ self.init_statusbar()
+ self.setWindowTitle("Background ROI Selection Tool")
+
+ self.ui.image_view = pg.ImageView()
+ self.ui.image_view.ui.roiBtn.hide()
+ self.ui.image_view.ui.menuBtn.hide()
+
+ top_layout = QtGui.QVBoxLayout()
+ top_layout.addWidget(self.ui.image_view)
+ self.ui.widget.setLayout(top_layout)
+ self.init_widgets()
+ self.integrate_images()
+ self.display_image()
+
+ def init_widgets(self):
+ nbr_columns = self.ui.table_roi.columnCount()
+ for _col in range(nbr_columns):
+ self.ui.table_roi.setColumnWidth(_col, self.roi_column_width)
+
+ def init_statusbar(self):
+ self.eventProgress = QtGui.QProgressBar(self.ui.statusbar)
+ self.eventProgress.setMinimumSize(20, 14)
+ self.eventProgress.setMaximumSize(540, 100)
+ self.eventProgress.setVisible(False)
+ self.ui.statusbar.addPermanentWidget(self.eventProgress)
+
+ # def __get_recap(self, data_array):
+ # if data_array:
+ # [height, width] = np.shape(data_array[0])
+ # nbr_sample = len(data_array)
+ # else:
+ # nbr_sample = '0'
+ # [height, width] = ['N/A', 'N/A']
+ #
+ # return [nbr_sample, height, width]
+
+ # def __built_html_table_row_3_columns(self, name, nbr, height, width):
+ # _html = '
' + str(name) + ' | ' + str(nbr) + ' | ' + str(height) + \
+ # '*' + str(width) + ' |
'
+ # return _html
+ #
+ # def recap(self):
+ # """Display nbr of files loaded and size. This can be used to figure why a normalization failed"""
+ # [nbr_sample, height_sample, width_sample] = self.__get_recap(self.o_norm.data['sample']['data'])
+ # [nbr_ob, height_ob, width_ob] = self.__get_recap(self.o_norm.data['ob']['data'])
+ # [nbr_df, height_df, width_df] = self.__get_recap(self.o_norm.data['df']['data'])
+ #
+ # html = 'Type | Number | ' + \
+ # 'Size (height*width) |
'
+ # html += self.__built_html_table_row_3_columns('sample', nbr_sample, height_sample, width_sample)
+ # html += self.__built_html_table_row_3_columns('ob', nbr_ob, height_ob, width_ob)
+ # html += self.__built_html_table_row_3_columns('df', nbr_df, height_df, width_df)
+ # html += '
'
+ # display(HTML(html))
+
+ def integrate_images(self):
+ self.integrated_image = self.live_data
+ [_height, _width] = np.shape(self.integrated_image)
+ self.integrated_image_size['height'] = _height
+ self.integrated_image_size['width'] = _width
+
+ def _clean_image(self, image):
+ _result_inf = np.where(np.isinf(image))
+ image[_result_inf] = np.NaN
+ return image
+
+ def display_image(self):
+ _image = np.transpose(self.live_data)
+ _image = self._clean_image(_image)
+ self.ui.image_view.setImage(_image)
+
+ def remove_row_entry(self, row):
+ _roi_id = self.list_roi[row]['id']
+ self.ui.image_view.removeItem(_roi_id)
+ del self.list_roi[row]
+
+ #rename row
+ new_list_roi = {}
+ new_row_index = 0
+ for _previous_row_index in self.list_roi.keys():
+ new_list_roi[new_row_index] = self.list_roi[_previous_row_index]
+ new_row_index += 1
+ self.list_roi = new_list_roi
+
+ def remove_roi_button_clicked(self):
+
+ self.ui.table_roi.blockSignals(True)
+
+ _selection = self.ui.table_roi.selectedRanges()
+ row = _selection[0].topRow()
+ old_nbr_row = self.ui.table_roi.rowCount()
+
+ # remove entry from list of roi
+ self.remove_row_entry(row)
+
+ # update table of rois
+ self.update_table_roi_ui()
+ self.ui.table_roi.blockSignals(False)
+ self.check_add_remove_button_widgets_status()
+
+ # update selection
+ new_nbr_row = self.ui.table_roi.rowCount()
+ if new_nbr_row == 0:
+ return
+
+ if row == (old_nbr_row-1):
+ row = new_nbr_row - 1
+
+ _new_selection = QtGui.QTableWidgetSelectionRange(row, 0, row, 3)
+ self.ui.table_roi.setRangeSelected(_new_selection, True)
+
+ def clear_table(self):
+ nbr_row = self.ui.table_roi.rowCount()
+ for _row in np.arange(nbr_row):
+ self.ui.table_roi.removeRow(0)
+
+ def update_table_roi_ui(self):
+ """Using list_roi as reference, repopulate the table_roi_ui"""
+
+ self.ui.table_roi.blockSignals(True)
+ list_roi = self.list_roi
+
+ self.clear_table()
+
+ _index_row = 0
+ for _roi_key in list_roi.keys():
+ _roi = list_roi[_roi_key]
+
+ self.ui.table_roi.insertRow(_index_row)
+
+ self._set_item_value(_index_row, 0, _roi['x0'])
+ # _item = QtGui.QTableWidgetItem(str(_roi['x0']))
+ # self.ui.table_roi.setItem(_index_row, 0, _item)
+
+ self._set_item_value(_index_row, 1, _roi['y0'])
+ # _item = QtGui.QTableWidgetItem(str(_roi['y0']))
+ # self.ui.table_roi.setItem(_index_row, 1, _item)
+
+ self._set_item_value(_index_row, 2, _roi['x1'])
+ # _item = QtGui.QTableWidgetItem(str(_roi['x1']))
+ # self.ui.table_roi.setItem(_index_row, 2, _item)
+
+ self._set_item_value(_index_row, 3, _roi['y1'])
+ # _item = QtGui.QTableWidgetItem(str(_roi['y1']))
+ # self.ui.table_roi.setItem(_index_row, 3, _item)
+
+ _index_row += 1
+
+ self.ui.table_roi.blockSignals(False)
+ #self.ui.table_roi.itemChanged['QTableWidgetItem*'].connect(self.update_table_roi)
+
+ def _set_item_value(self, row=0, column=0, value=-1):
+ _item = QtGui.QTableWidgetItem(str(value))
+ self.ui.table_roi.setItem(row, column, _item)
+
+ def check_roi_validity(self, value, x_axis=True):
+ """Make sure the ROI selected or defined stays within the image size"""
+ min_value = 0
+
+ value = np.int(value)
+
+ if x_axis:
+ max_value = self.integrated_image_size['width']
+ else:
+ max_value = self.integrated_image_size['height']
+
+ if value < 0:
+ return min_value
+
+ if value > max_value:
+ return max_value
+
+ return value
+
+ def update_table_roi(self, item):
+ """Using the table_roi_ui as reference, will update the list_roi dictionary"""
+ self.ui.table_roi.blockSignals(True)
+
+ nbr_row = self.ui.table_roi.rowCount()
+ new_list_roi = OrderedDict()
+ old_list_roi = self.list_roi
+ for _row in np.arange(nbr_row):
+ _roi = {}
+
+ # checking that x0, y0, x1 and y1 stay within the range of the image
+ _x0 = self.check_roi_validity(self._get_item_value(_row, 0))
+ _y0 = self.check_roi_validity(self._get_item_value(_row, 1), x_axis=False)
+
+ _x1 = self.check_roi_validity(self._get_item_value(_row, 2))
+ _y1 = self.check_roi_validity(self._get_item_value(_row, 3), x_axis=False)
+
+ # updating table content (in case some of the roi were out of scope
+ self._set_item_value(_row, 0, _x0)
+ self._set_item_value(_row, 1, _y0)
+ self._set_item_value(_row, 2, _x1)
+ self._set_item_value(_row, 3, _y1)
+
+ _roi['x0'] = _x0
+ _roi['y0'] = _y0
+ _roi['x1'] = _x1
+ _roi['y1'] = _y1
+ _roi['id'] = old_list_roi[_row]['id']
+
+ new_list_roi[_row] = _roi
+
+ self.list_roi = new_list_roi
+ self.update_image_view_item()
+ self.ui.table_roi.blockSignals(False)
+
+ def update_image_view_item(self):
+ self.clear_roi_on_image_view()
+
+ list_roi = self.list_roi
+ for _row in list_roi.keys():
+ _roi = list_roi[_row]
+
+ _x0 = np.int(_roi['x0'])
+ _y0 = np.int(_roi['y0'])
+ _x1 = np.int(_roi['x1'])
+ _y1 = np.int(_roi['y1'])
+
+ _width = np.abs(_x1 - _x0)
+ _height = np.abs(_y1 - _y0)
+
+ _roi_id = self.init_roi(x0=_x0, y0=_y0,
+ width=_width, height=_height)
+ _roi['id'] = _roi_id
+
+ list_roi[_row] = _roi
+
+ self.list_roi = list_roi
+
+ def _get_item_value(self, row, column):
+ _item = self.ui.table_roi.item(row, column)
+ if _item:
+ return str(_item.text())
+ else:
+ return ''
+
+ def roi_manually_moved(self):
+ list_roi = self.list_roi
+
+ for _row in list_roi.keys():
+
+ _roi = list_roi[_row]
+
+ roi_id = _roi['id']
+ region = roi_id.getArraySlice(self.integrated_image, self.ui.image_view.imageItem)
+
+ x0 = region[0][0].start
+ x1 = region[0][0].stop
+ y0 = region[0][1].start
+ y1 = region[0][1].stop
+
+ _roi['x0'] = x0
+ _roi['x1'] = x1
+ _roi['y0'] = y0
+ _roi['y1'] = y1
+
+ list_roi[_row] = _roi
+
+ self.list_roi = list_roi
+ self.update_table_roi_ui()
+
+ def clear_roi_on_image_view(self):
+ list_roi = self.list_roi
+
+ for _row in list_roi.keys():
+
+ _roi = list_roi[_row]
+ roi_id = _roi['id']
+ self.ui.image_view.removeItem(roi_id)
+
+ def add_roi_button_clicked(self):
+ self.clear_roi_on_image_view()
+
+ self.ui.table_roi.blockSignals(True)
+ _selection = self.ui.table_roi.selectedRanges()
+ if _selection:
+ row = _selection[0].topRow()
+ else:
+ row = 0
+
+ # init new row with default value
+ self.ui.table_roi.insertRow(row)
+ _default_roi = self.default_roi
+
+ _item = QtGui.QTableWidgetItem(str(_default_roi['x0']))
+ self.ui.table_roi.setItem(row, 0, _item)
+
+ _item = QtGui.QTableWidgetItem(str(_default_roi['y0']))
+ self.ui.table_roi.setItem(row, 1, _item)
+
+ _item = QtGui.QTableWidgetItem(str(_default_roi['x1']))
+ self.ui.table_roi.setItem(row, 2, _item)
+
+ _item = QtGui.QTableWidgetItem(str(_default_roi['y1']))
+ self.ui.table_roi.setItem(row, 3, _item)
+
+ # save new list_roi dictionary
+ nbr_row = self.ui.table_roi.rowCount()
+ list_roi = OrderedDict()
+ for _row in np.arange(nbr_row):
+ _roi = {}
+
+ _x0 = self._get_item_value(_row, 0)
+ _roi['x0'] = np.int(_x0)
+
+ _y0 = self._get_item_value(_row, 1)
+ _roi['y0'] = np.int(_y0)
+
+ _x1 = self._get_item_value(_row, 2)
+ _roi['x1'] = np.int(_x1)
+
+ _y1 = self._get_item_value(_row, 3)
+ _roi['y1'] = np.int(_y1)
+
+ x0_int = int(_x0)
+ y0_int = int(_y0)
+ width_int = np.abs(x0_int - int(_x1))
+ height_int = np.abs(y0_int - int(_y1))
+
+ _roi_id = self.init_roi(x0=x0_int, y0=y0_int,
+ width=width_int, height=height_int)
+ _roi['id'] = _roi_id
+ list_roi[_row] = _roi
+
+ self.list_roi = list_roi
+
+ self.ui.table_roi.blockSignals(False)
+
+ self.check_add_remove_button_widgets_status()
+
+ if not _selection:
+ _new_selection = QtGui.QTableWidgetSelectionRange(0, 0, 0, 3)
+ self.ui.table_roi.setRangeSelected(_new_selection, True)
+
+ def init_roi(self, x0=0, y0=0, width=0, height=0):
+ _color = QtGui.QColor(62, 13, 244)
+ _pen = QtGui.QPen()
+ _pen.setColor(_color)
+ _pen.setWidthF(self.roi_width)
+ _roi_id = pg.ROI([x0, y0], [width, height], pen=_pen, scaleSnap=True)
+ _roi_id.addScaleHandle([1, 1], [0, 0])
+ _roi_id.addScaleHandle([0, 0], [1, 1])
+ self.ui.image_view.addItem(_roi_id)
+ # add connection to roi
+ _roi_id.sigRegionChanged.connect(self.roi_manually_moved)
+ return _roi_id
+
+ def check_add_remove_button_widgets_status(self):
+ nbr_row = self.ui.table_roi.rowCount()
+ if nbr_row > 0:
+ self.ui.remove_roi_button.setEnabled(True)
+ else:
+ self.ui.remove_roi_button.setEnabled(False)
+
+ def format_roi(self):
+ roi_selected = {}
+ for _key in self.list_roi.keys():
+ _roi = self.list_roi[_key]
+ x0 = _roi['x0']
+ y0 = _roi['y0']
+ x1 = _roi['x1']
+ y1 = _roi['y1']
+ new_entry = {'x0': x0, 'y0': y0, 'x1': x1, 'y1': y1}
+ roi_selected[_key] = new_entry
+
+ self.roi_selected = roi_selected
+
+ def apply_clicked(self):
+ self.update_table_roi(None) #check ROI before leaving application
+ self.format_roi()
+ self.close()
+
+ def cancel_clicked(self):
+ self.close()
+
+ def closeEvent(self, eventhere=None):
+ print("Leaving Parameters Selection UI")
diff --git a/notebooks/__code/bragg_edge_normalization.py b/notebooks/__code/bragg_edge_normalization.py
new file mode 100644
index 0000000..5091bf4
--- /dev/null
+++ b/notebooks/__code/bragg_edge_normalization.py
@@ -0,0 +1,367 @@
+import random
+import os
+import glob
+from pathlib import Path
+from IPython.core.display import HTML
+from IPython.display import display
+import numpy as np
+from plotly.offline import iplot
+import plotly.graph_objs as go
+from ipywidgets import widgets
+
+try:
+ from PyQt4.QtGui import QFileDialog
+ from PyQt4 import QtCore, QtGui
+ from PyQt4.QtGui import QMainWindow
+except ImportError:
+ from PyQt5.QtWidgets import QFileDialog
+ from PyQt5 import QtCore, QtGui
+ from PyQt5.QtWidgets import QApplication, QMainWindow
+
+from neutronbraggedge.experiment_handler import *
+from NeuNorm.normalization import Normalization
+from NeuNorm.roi import ROI
+
+from __code import file_handler
+from __code.bragg_edge.bragg_edge import BraggEdge as BraggEdgeParent
+from __code.file_folder_browser import FileFolderBrowser
+from __code import ipywe
+
+
+class BraggEdge(BraggEdgeParent):
+
+ def load_data(self, folder_selected):
+ self.o_norm = Normalization()
+ self.load_files(data_type='sample', folder=folder_selected)
+
+ # define time spectra file
+ folder = os.path.dirname(self.o_norm.data['sample']['file_name'][0])
+ self.list_files = self.o_norm.data['sample']['file_name']
+ self.data_folder_name = os.path.basename(folder)
+ spectra_file = glob.glob(os.path.join(folder, '*_Spectra.txt'))
+ if spectra_file:
+ self.spectra_file = spectra_file[0]
+ display(HTML(' Spectra File automatically located: ' + \
+ self.spectra_file + ''))
+
+ else:
+ #ask for spectra file
+ self.select_time_spectra_file()
+
+ def select_time_spectra_file(self):
+ self.working_dir = os.path.dirname(self.list_files[0])
+ self.time_spectra_ui = ipywe.fileselector.FileSelectorPanel(instruction='Select Time Spectra File ...',
+ start_dir=self.working_dir,
+ next=self.save_time_spectra,
+ filters={'spectra_file': "_Spectra.txt"},
+ multiple=False)
+
+ self.time_spectra_ui.show()
+ self.cancel_button = widgets.Button(description="or Do Not Select any Time Spectra",
+ button_style="info",
+ layout=widgets.Layout(width='100%'))
+ display(self.cancel_button)
+ self.cancel_button.on_click(self.cancel_time_spectra_selection)
+
+ def save_time_spectra(self, file):
+ BraggEdgeParent.save_time_spectra(self, file)
+ self.cancel_button.close()
+
+ def cancel_time_spectra_selection(self, value):
+ self.time_spectra_ui.remove()
+ self.cancel_button.close()
+ display(HTML('NO Spectra File loaded! '))
+
+ def load_files(self, data_type='sample', folder=None):
+
+ self.starting_dir = os.path.dirname(folder)
+ if data_type == 'sample':
+ self.data_folder_name = os.path.basename(folder)
+ list_files = glob.glob(os.path.join(folder, '*.fits'))
+
+ if list_files == []:
+ list_files = glob.glob(os.path.join(folder, '*.tif*'))
+
+ else: # fits
+ # keep only files of interest
+ list_files = [file for file in list_files if not "_SummedImg.fits" in file]
+ list_files = [file for file in list_files if ".fits" in file]
+
+ # sort list of files
+ list_files.sort()
+
+ self.o_norm.load(file=list_files, notebook=True, data_type=data_type)
+
+ display(HTML('' + str(len(list_files)) + \
+ ' files have been loaded as ' + data_type + ''))
+
+ def select_ob_folder(self):
+ select_data = ipywe.fileselector.FileSelectorPanel(instruction='Select OB Folder ...',
+ start_dir=self.starting_dir,
+ next=self.load_ob,
+ type='directory',
+ multiple=False)
+ select_data.show()
+
+ def load_ob(self, folder_selected):
+ self.load_files(data_type='ob', folder=folder_selected)
+ self.check_data_array_sizes()
+
+ def check_data_array_sizes(self):
+ len_ob = len(self.o_norm.data['ob']['file_name'])
+ len_sample = len(self.o_norm.data['sample']['file_name'])
+
+ if len_ob == len_sample:
+ display(HTML(' Sample and OB have the same size!'))
+ return
+
+ if len_ob < len_sample:
+ self.o_norm.data['sample']['data'] = self.o_norm.data['sample']['data'][0:len_ob]
+ self.o_norm.data['sample']['file_name'] = self.o_norm.data['sample']['file_name'][0:len_ob]
+ display(HTML(' Truncated Sample array to match OB!'))
+ else:
+ self.o_norm.data['ob']['data'] = self.o_norm.data['ob']['data'][0:len_sample]
+ self.o_norm.data['ob']['file_name'] = self.o_norm.data['ob']['file_name'][0:len_sample]
+ display(HTML(' Truncated OB array to match Sample!'))
+
+ def load_time_spectra(self):
+ _tof_handler = TOF(filename=self.spectra_file)
+ _exp = Experiment(tof=_tof_handler.tof_array,
+ distance_source_detector_m=np.float(self.dSD_ui.value),
+ detector_offset_micros=np.float(self.detector_offset_ui.value))
+
+ nbr_sample = len(self.o_norm.data['sample']['file_name'])
+
+ self.lambda_array = _exp.lambda_array[0: nbr_sample] * 1e10 # to be in Angstroms
+ self.tof_array = _tof_handler.tof_array[0: nbr_sample]
+
+ def how_many_data_to_use_to_select_sample_roi(self):
+ nbr_images = len(self.o_norm.data['sample']['data'])
+ init_value = np.int(nbr_images/10)
+ if init_value == 0:
+ init_value = 1
+ box1 = widgets.HBox([widgets.Label("Nbr of images to use:",
+ layout=widgets.Layout(width='15')),
+ widgets.IntSlider(value=init_value,
+ max=nbr_images,
+ min=1)])
+ # layout=widgets.Layout(width='50%'))])
+ box2 = widgets.Label("(The more you select, the longer it will take to display the preview!)")
+ vbox = widgets.VBox([box1, box2])
+ display(vbox)
+ self.number_of_data_to_use_ui = box1.children[1]
+
+ def get_image_to_use_for_display(self):
+ nbr_data_to_use = np.int(self.number_of_data_to_use_ui.value)
+ _data = self.o_norm.data['sample']['data']
+
+ nbr_images = len(_data)
+ list_of_indexes_to_keep = random.sample(list(range(nbr_images)), nbr_data_to_use)
+
+ final_array = []
+ for _index in list_of_indexes_to_keep:
+ final_array.append(_data[_index])
+ final_image = np.mean(final_array, axis=0)
+ self.final_image = final_image
+ return final_image
+
+ def normalization(self, list_rois=None):
+ if list_rois is None:
+ self.o_norm.normalization()
+ else:
+ list_o_roi = []
+ for key in list_rois.keys():
+ roi = list_rois[key]
+ _x0 = roi['x0']
+ _y0 = roi['y0']
+ _x1 = roi['x1']
+ _y1 = roi['y1']
+
+ list_o_roi.append(ROI(x0=_x0,
+ y0=_y0,
+ x1=_x1,
+ y1=_y1))
+
+ self.o_norm.normalization(roi=list_o_roi, notebook=True)
+ display(HTML(' Normalization DONE! '))
+
+ def export_normalized_data(self):
+ self.o_folder = FileFolderBrowser(working_dir=self.working_dir,
+ next_function=self.export_normalized_data_step2,
+ ipts_folder=self.ipts_folder)
+ self.o_folder.select_output_folder_with_new(instruction="Select where to create the normalized data ...")
+
+ def export_normalized_data_step2(self, output_folder):
+ output_folder = os.path.abspath(output_folder)
+ self.o_folder.list_output_folders_ui.shortcut_buttons.close()
+ normalized_export_folder = str(Path(output_folder) / (self.data_folder_name + '_normalized'))
+ file_handler.make_or_reset_folder(normalized_export_folder)
+
+ self.o_norm.export(folder=normalized_export_folder)
+ display(HTML(' Created the normalized data in the folder ' +
+ normalized_export_folder + ''))
+ if self.spectra_file:
+ file_handler.copy_files_to_folder(list_files=[self.spectra_file],
+ output_folder=normalized_export_folder)
+ display(HTML(' Copied time spectra file to same folder '))
+
+ def calculate_counts_vs_file_index_of_regions_selected(self, list_roi=None):
+
+ self.list_roi = list_roi
+ data = self.o_norm.get_sample_data()
+
+ nbr_data = len(data)
+ box_ui = widgets.HBox([widgets.Label("Calculate Counts vs lambda",
+ layout=widgets.Layout(width='20%')),
+ widgets.IntProgress(min=0,
+ max=nbr_data,
+ value=0,
+ layout=widgets.Layout(width='50%'))])
+ progress_bar = box_ui.children[1]
+ display(box_ui)
+
+ counts_vs_file_index = []
+ for _index, _data in enumerate(data):
+
+ if len(list_roi) == 0:
+ _array_data = _data
+
+ else:
+ _array_data = []
+ for _roi in list_roi.keys():
+
+ x0 = np.int(list_roi[_roi]['x0'])
+ y0 = np.int(list_roi[_roi]['y0'])
+ x1 = np.int(list_roi[_roi]['x1'])
+ y1 = np.int(list_roi[_roi]['y1'])
+
+ _array_data.append(np.nanmean(_data[y0:y1, x0:x1]))
+
+ counts_vs_file_index.append(np.nanmean(_array_data))
+
+ progress_bar.value = _index+1
+
+ self.counts_vs_file_index = counts_vs_file_index
+ box_ui.close()
+
+ def plot(self):
+
+ trace = go.Scatter(
+ x=self.lambda_array,
+ y=self.counts_vs_file_index,
+ mode='markers')
+
+ layout = go.Layout(
+ height=500,
+ title="Average transmission vs TOF (of entire images, or of selected region if any)",
+ xaxis=dict(
+ title="Lambda (Angstroms)"
+ ),
+ yaxis=dict(
+ title="Average Transmission"
+ ),
+ )
+
+ data = [trace]
+ figure = go.Figure(data=data, layout=layout)
+
+ iplot(figure)
+
+ def select_output_data_folder(self):
+ o_folder = FileFolderBrowser(working_dir=self.working_dir,
+ next_function=self.export_data)
+ o_folder.select_output_folder(instruction="Select where to create the ascii file...")
+ # self.select_folder(message='Select where to output the data',
+ # next_function=self.export_data)
+
+ def make_output_file_name(self, output_folder='', input_folder=''):
+ file_name = os.path.basename(input_folder) + "_counts_vs_lambda_tof.txt"
+ return os.path.join(os.path.abspath(output_folder), file_name)
+
+ def export_data(self, output_folder):
+ input_folder = os.path.dirname(self.o_norm.data['sample']['file_name'][0])
+ output_file_name = self.make_output_file_name(output_folder=output_folder,
+ input_folder=input_folder)
+
+ lambda_array = self.lambda_array
+ counts_vs_file_index = self.counts_vs_file_index
+ tof_array = self.tof_array
+
+ metadata = ["# input folder: {}".format(input_folder)]
+
+ list_roi = self.list_roi
+ if len(list_roi) == 0:
+ metadata.append("# Entire sample selected")
+ else:
+ for index, key in enumerate(list_roi.keys()):
+ roi = list_roi[key]
+ _x0 = roi['x0']
+ _y0 = roi['y0']
+ _x1 = roi['x1']
+ _y1 = roi['y1']
+ metadata.append("# ROI {}: x0={}, y0={}, x1={}, y1={}".format(index,
+ _x0,
+ _y0,
+ _x1,
+ _y1))
+ metadata.append("#")
+ metadata.append("# tof (micros), lambda (Angstroms), Average transmission")
+
+ data = []
+ for _t, _l, _c in zip(tof_array, lambda_array, counts_vs_file_index):
+ data.append("{}, {}, {}".format(_t, _l, _c))
+
+ file_handler.make_ascii_file(metadata=metadata,
+ data=data,
+ output_file_name=output_file_name,
+ dim='1d')
+
+ if os.path.exists(output_file_name):
+ display(HTML('Ascii file ' + output_file_name + ' has been ' +
+ 'created '))
+ else:
+ display(HTML('Error exporting Ascii file ' + output_file_name +
+ ''))
+
+ def select_output_table_folder(self):
+ o_folder = FileFolderBrowser(working_dir=self.working_dir,
+ next_function=self.export_table)
+ o_folder.select_output_folder()
+
+ def export_table(self, output_folder):
+ material = self.handler.material[0]
+ lattice = self.handler.lattice[material]
+ crystal_structure = self.handler.crystal_structure[material]
+ metadata = ["# material: {}".format(material),
+ "# crystal structure: {}".format(crystal_structure),
+ "# lattice: {} Angstroms".format(lattice),
+ "#",
+ "# hkl, d(angstroms), BraggEdge"]
+ data = []
+ bragg_edges = self.bragg_edges[material]
+ hkl = self.hkl[material]
+ for _index in np.arange(len(bragg_edges)):
+ _hkl_str = [str(i) for i in hkl[_index]]
+ _hkl = "".join(_hkl_str)
+ _bragg_edges = np.float(bragg_edges[_index])
+ _d = _bragg_edges/2.
+ _row = "{}, {}, {}".format(_hkl, _d, _bragg_edges)
+ data.append(_row)
+
+ output_file_name = os.path.join(output_folder, 'bragg_edges_of_{}.txt'.format(material))
+
+ file_handler.make_ascii_file(metadata=metadata,
+ data=data,
+ dim='1d',
+ output_file_name=output_file_name)
+
+ display(HTML('File created : ' + \
+ output_file_name + ''))
+
+ def select_folder(self, message="", next_function=None):
+ folder_widget = ipywe.fileselector.FileSelectorPanel(instruction='select {} folder'.format(message),
+ start_dir=self.working_dir,
+ next=next_function,
+ type='directory',
+ multiple=False)
+ folder_widget.show()
diff --git a/notebooks/__code/bragg_edge_peak_fitting.py b/notebooks/__code/bragg_edge_peak_fitting.py
new file mode 100644
index 0000000..20daad1
--- /dev/null
+++ b/notebooks/__code/bragg_edge_peak_fitting.py
@@ -0,0 +1,4 @@
+from __code.bragg_edge.bragg_edge_peak_fitting_evaluation import BraggEdge
+
+class BraggEdgePeakFitting(BraggEdge):
+ pass
diff --git a/notebooks/__code/bragg_edge_peak_fitting_gui_utility.py b/notebooks/__code/bragg_edge_peak_fitting_gui_utility.py
new file mode 100644
index 0000000..442fde6
--- /dev/null
+++ b/notebooks/__code/bragg_edge_peak_fitting_gui_utility.py
@@ -0,0 +1,186 @@
+import numpy as np
+from qtpy.QtWidgets import QHBoxLayout, QCheckBox, QLineEdit, QVBoxLayout, QWidget, QLabel
+
+from __code.table_handler import TableHandler
+
+
+class GuiUtility:
+
+ cell_str_format = "{:.3f}"
+ cell_str_format_2 = "{:f}"
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ def get_tab_selected(self, tab_ui=None):
+ tab_index = tab_ui.currentIndex()
+ return tab_ui.tabText(tab_index)
+
+ def get_rows_of_table_selected(self, table_ui=None):
+ o_table = TableHandler(table_ui=table_ui)
+ return o_table.get_rows_of_table_selected()
+
+ def select_rows_of_table(self, table_ui=None, list_of_rows=None):
+ if list_of_rows is None:
+ return
+ o_table = TableHandler(table_ui=table_ui)
+ o_table.select_rows(list_of_rows=list_of_rows)
+
+ def get_toolbox_selected(self, toolbox_ui=None):
+ toolbox_index = toolbox_ui.currentIndex()
+ return toolbox_ui.itemText(toolbox_index)
+
+ def update_kropff_high_lambda_table_ui(self, row=0, a0=None, b0=None, a0_error=None, b0_error=None):
+ table_ui = self.parent.ui.high_lda_tableWidget
+ table_ui.item(row, 1).setText(self.cell_str_format.format(a0))
+ table_ui.item(row, 2).setText(self.cell_str_format.format(b0))
+ table_ui.item(row, 3).setText(self.cell_str_format.format(a0_error))
+ table_ui.item(row, 4).setText(self.cell_str_format.format(b0_error))
+
+ def update_kropff_low_lambda_table_ui(self, row=0, ahkl=None, bhkl=None, ahkl_error=None, bhkl_error=None):
+ table_ui = self.parent.ui.low_lda_tableWidget
+ table_ui.item(row, 1).setText(self.cell_str_format.format(ahkl))
+ table_ui.item(row, 2).setText(self.cell_str_format.format(bhkl))
+ table_ui.item(row, 3).setText(self.cell_str_format.format(ahkl_error))
+ table_ui.item(row, 4).setText(self.cell_str_format.format(bhkl_error))
+
+ def update_kropff_bragg_edge_table_ui(self, row=0, ldahkl=None, ldahkl_error=None,
+ tau=None, tau_error=None,
+ sigma=None, sigma_error=None):
+
+ ldahkl_error = np.NaN if ldahkl_error is None else ldahkl_error
+ tau_error = np.NaN if tau_error is None else tau_error
+ sigma_error = np.NaN if sigma_error is None else sigma_error
+
+ table_ui = self.parent.ui.bragg_edge_tableWidget
+ table_ui.item(row, 1).setText(self.cell_str_format_2.format(ldahkl))
+ table_ui.item(row, 2).setText(self.cell_str_format_2.format(tau))
+ table_ui.item(row, 3).setText(self.cell_str_format_2.format(sigma))
+ table_ui.item(row, 4).setText(self.cell_str_format_2.format(ldahkl_error))
+ table_ui.item(row, 5).setText(self.cell_str_format_2.format(tau_error))
+ table_ui.item(row, 6).setText(self.cell_str_format_2.format(sigma_error))
+
+ def check_status_of_kropff_fitting_buttons(self):
+ pass
+ # enabled_low_lambda_button = False
+ # enabled_bragg_peak_button = False
+ #
+ # # can we enabled the low lambda button
+ # if self.parent.fitting_input_dictionary['rois'][0]['fitting']['kropff']['high']['a0']:
+ # enabled_low_lambda_button = True
+ #
+ # if self.parent.fitting_input_dictionary['rois'][0]['fitting']['kropff']['low']['ahkl']:
+ # enabled_bragg_peak_button = True
+
+ def get_kropff_fit_parameter_selected(self, fit_region='high'):
+ """
+ return the name of the button checked in the requested tab (kropff fit)
+ for example: a0 if high lambda and first radioButton checked
+ :param fit_region: name of the region ('high', 'low' or 'bragg_peak')
+ :return:
+ """
+ list_fit_parameters_radio_button = {'high': {'ui': [self.parent.ui.kropff_a0_radioButton,
+ self.parent.ui.kropff_b0_radioButton],
+ 'name': ['a0', 'b0']},
+ 'low': {'ui': [self.parent.ui.kropff_ahkl_radioButton,
+ self.parent.ui.kropff_bhkl_radioButton],
+ 'name': ['ahkl', 'bhkl']},
+ 'bragg_peak': {'ui': [self.parent.ui.kropff_lda_hkl_radioButton,
+ self.parent.ui.kropff_tau_radioButton,
+ self.parent.ui.kropff_sigma_radioButton],
+ 'name': ['ldahkl', 'tau', 'sigma'],
+ },
+ }
+
+ for _index, _ui in enumerate(list_fit_parameters_radio_button[fit_region]['ui']):
+ if _ui.isChecked():
+ return list_fit_parameters_radio_button[fit_region]['name'][_index]
+
+ return None
+
+ def get_kropff_fit_graph_ui(self, fit_region='high'):
+ list_ui = {'high': self.parent.kropff_high_plot,
+ 'low': self.parent.kropff_low_plot,
+ 'bragg_peak': self.parent.kropff_bragg_peak_plot}
+ return list_ui[fit_region]
+
+ def get_table_str_item(self, table_ui=None, row=0, column=0):
+ item = table_ui.item(row, column)
+ if item:
+ return str(item.text())
+ else:
+ return ""
+
+ def fill_march_dollase_table(self, list_state=None, initial_parameters=None):
+
+ table_ui = self.parent.ui.march_dollase_user_input_table
+ o_table = TableHandler(table_ui=table_ui)
+ o_table.remove_all_rows()
+
+ if not list_state:
+ return
+
+ march_dollase_row_height = {0: 110,
+ 'other': 60}
+
+ nbr_column = len(list_state[0])
+ for _row in np.arange(len(list_state)):
+ self.parent.ui.march_dollase_user_input_table.insertRow(_row)
+
+ row_height = march_dollase_row_height[0] if _row == 0 else march_dollase_row_height['other']
+ table_ui.setRowHeight(_row, row_height)
+
+ for _col in np.arange(nbr_column):
+ _state_col = list_state[_row][_col]
+ _widget = QWidget()
+ verti_layout = QVBoxLayout()
+
+ hori_layout = QHBoxLayout()
+ _checkbox = QCheckBox()
+ _checkbox.setChecked(_state_col)
+ _checkbox.stateChanged.connect(lambda state=0, row=_row, column=_col:
+ self.parent.march_dollase_table_state_changed(state=state,
+ row=row,
+ column=column))
+ hori_layout.addStretch()
+ hori_layout.addWidget(_checkbox)
+ hori_layout.addStretch()
+ new_widget = QWidget()
+ new_widget.setLayout(hori_layout)
+ verti_layout.addWidget(new_widget)
+
+ if _row == 0:
+ parameter_key = self.parent.march_dollase_list_columns[_col]
+
+ if (_col == 1) or (_col == 2):
+ _input = QLineEdit()
+ _input.returnPressed.connect(lambda column=_col:
+ self.parent.march_dollase_table_init_value_changed(column=column))
+ _input.setText(str(initial_parameters[parameter_key]))
+ verti_layout.addWidget(_input)
+ _input.setVisible(not _state_col)
+
+ elif (_col == 0):
+ _label = QLabel()
+ try:
+ str_format = "{:0.6f}".format(np.float(initial_parameters[parameter_key]))
+ except ValueError:
+ str_format = initial_parameters[parameter_key]
+
+ _label.setText(str_format)
+ verti_layout.addWidget(_label)
+ _label.setVisible(not _state_col)
+
+ else:
+ _label = QLabel()
+ _label.setText("Row dependent")
+ verti_layout.addWidget(_label)
+ _label.setVisible(not _state_col)
+
+
+ _widget.setLayout(verti_layout)
+ table_ui.setCellWidget(_row, _col, _widget)
+
+ def set_columns_hidden(self, table_ui=None, list_of_columns=None, state=True):
+ for _col in list_of_columns:
+ table_ui.setColumnHidden(_col, state)
diff --git a/notebooks/__code/bragg_edge_selection_tab.py b/notebooks/__code/bragg_edge_selection_tab.py
new file mode 100644
index 0000000..6737c60
--- /dev/null
+++ b/notebooks/__code/bragg_edge_selection_tab.py
@@ -0,0 +1,255 @@
+import numpy as np
+import pyqtgraph as pg
+from qtpy import QtGui
+from collections import OrderedDict
+
+from __code._utilities.array import check_size
+from __code.bragg_edge.get import Get
+
+
+class BraggEdgeSelectionTab:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ def update_all_size_widgets_infos(self):
+
+ if self.parent.ui.square_roi_radiobutton.isChecked():
+ return
+
+ roi_id = self.parent.roi_id
+ region = roi_id.getArraySlice(self.parent.final_image,
+ self.parent.ui.image_view.imageItem)
+ x0 = region[0][0].start
+ x1 = region[0][0].stop
+ y0 = region[0][1].start
+ y1 = region[0][1].stop
+
+ new_width = x1 - x0 - 1
+ new_height = y1 - y0 - 1
+
+ # if new width and height is the same as before, just skip that step
+ if self.parent.new_dimensions_within_error_range():
+ return
+
+ self.parent.ui.roi_width.setText(str(new_width))
+ self.parent.ui.roi_height.setText(str(new_height))
+ self.parent.ui.profile_of_bin_size_width.setText(str(new_width))
+ self.parent.ui.profile_of_bin_size_height.setText(str(new_height))
+
+ max_value = np.min([new_width, new_height])
+ self.parent.ui.profile_of_bin_size_slider.setValue(max_value)
+ self.parent.ui.profile_of_bin_size_slider.setMaximum(max_value)
+
+ def get_shrinking_roi_dimension(self):
+ coordinates = self.get_coordinates_of_new_inside_selection_box()
+ return [coordinates['x0'],
+ coordinates['y0'],
+ coordinates['x0'] + coordinates['width'],
+ coordinates['y0'] + coordinates['height']]
+
+ def get_coordinates_of_new_inside_selection_box(self):
+ # get width and height defined in fitting labels (top right)
+ width_requested = np.int(str(self.parent.ui.profile_of_bin_size_width.text()))
+ height_requested = np.int(str(self.parent.ui.profile_of_bin_size_height.text()))
+
+ # retrieve x0, y0, width and height of full selection
+ region = self.parent.roi_id.getArraySlice(self.parent.final_image, self.parent.ui.image_view.imageItem)
+ x0 = region[0][0].start
+ y0 = region[0][1].start
+ # [x0, y0] = self.parentselection_x0y0
+ width_full_selection = np.int(str(self.parent.ui.roi_width.text()))
+ height_full_selection = np.int(str(self.parent.ui.roi_height.text()))
+
+ delta_width = width_full_selection - width_requested
+ delta_height = height_full_selection - height_requested
+
+ new_x0 = x0 + np.int(delta_width / 2)
+ new_y0 = y0 + np.int(delta_height / 2)
+
+ return {'x0' : new_x0, 'y0': new_y0,
+ 'x1' : new_x0 + width_requested + 1, 'y1': new_y0 + height_requested + 1,
+ 'width': width_requested, 'height': height_requested}
+
+
+ def update_selection_profile_plot(self):
+
+ if self.parent.is_file_imported:
+ self.update_selection_plot()
+ self.parent.update_vertical_line_in_profile_plot()
+
+ else:
+ o_get = Get(parent=self.parent)
+ x_axis, x_axis_label = o_get.x_axis()
+ self.parent.ui.profile.clear()
+
+ # large selection region
+ [x0, y0, x1, y1, _, _] = o_get.selection_roi_dimension()
+ profile = o_get.profile_of_roi(x0, y0, x1, y1)
+ x_axis, y_axis = check_size(x_axis=x_axis,
+ y_axis=profile)
+ self.parent.ui.profile.plot(x_axis, y_axis, pen=(self.parent.selection_roi_rgb[0],
+ self.parent.selection_roi_rgb[1],
+ self.parent.selection_roi_rgb[2]))
+
+ # shrinkable region
+ shrinking_roi = self.get_coordinates_of_new_inside_selection_box()
+ x0 = shrinking_roi['x0']
+ y0 = shrinking_roi['y0']
+ x1 = shrinking_roi['x1']
+ y1 = shrinking_roi['y1']
+ profile = o_get.profile_of_roi(x0, y0, x1, y1)
+ x_axis, y_axis = check_size(x_axis=x_axis,
+ y_axis=profile)
+ self.parent.ui.profile.plot(x_axis, y_axis, pen=(self.parent.shrinking_roi_rgb[0],
+ self.parent.shrinking_roi_rgb[1],
+ self.parent.shrinking_roi_rgb[2]))
+ self.parent.ui.profile.setLabel("bottom", x_axis_label)
+ self.parent.ui.profile.setLabel("left", 'Mean transmission')
+
+ # vertical line showing peak to fit
+ bragg_edge_range = [x_axis[self.parent.bragg_edge_range[0]],
+ x_axis[self.parent.bragg_edge_range[1]]]
+
+ self.parent.bragg_edge_range_ui = pg.LinearRegionItem(values=bragg_edge_range,
+ orientation=None,
+ brush=None,
+ movable=True,
+ bounds=None)
+ self.parent.bragg_edge_range_ui.sigRegionChanged.connect(self.parent.bragg_edge_range_changed)
+ self.parent.bragg_edge_range_ui.setZValue(-10)
+ self.parent.ui.profile.addItem(self.parent.bragg_edge_range_ui)
+
+ def update_selection(self, new_value=None, mode='square'):
+ if self.parent.roi_id is None:
+ return
+
+ try:
+ region = self.parent.roi_id.getArraySlice(self.parent.final_image,
+ self.parent.ui.image_view.imageItem)
+ except TypeError:
+ return
+
+ x0 = region[0][0].start
+ y0 = region[0][1].start
+ self.parent.selection_x0y0 = [x0, y0]
+
+ # remove old one
+ self.parent.ui.image_view.removeItem(self.parent.roi_id)
+
+ _pen = QtGui.QPen()
+ _pen.setColor(self.parent.roi_settings['color'])
+ _pen.setWidth(self.parent.roi_settings['width'])
+ self.parent.roi_id = pg.ROI([x0, y0],
+ [new_value, new_value],
+ pen=_pen,
+ scaleSnap=True)
+
+ self.parent.ui.image_view.addItem(self.parent.roi_id)
+ self.parent.roi_id.sigRegionChanged.connect(self.parent.roi_moved)
+
+ if mode == 'square':
+ self.parent.ui.roi_width.setText(str(new_value))
+ self.parent.ui.roi_height.setText(str(new_value))
+ self.parent.reset_profile_of_bin_size_slider()
+ self.parent.update_profile_of_bin_size_infos()
+ else:
+ self.parent.roi_id.addScaleHandle([1, 1], [0, 0])
+
+ self.update_selection_profile_plot()
+ self.update_roi_defined_by_profile_of_bin_size_slider()
+
+ def update_selection_plot(self):
+ self.parent.ui.profile.clear()
+ o_get = Get(parent=self.parent)
+ x_axis, x_axis_label = o_get.x_axis()
+ max_value = self.parent.ui.profile_of_bin_size_slider.maximum()
+ roi_selected = max_value - self.parent.ui.profile_of_bin_size_slider.value()
+
+ y_axis = self.parent.fitting_input_dictionary['rois'][roi_selected]['profile']
+
+ self.parent.ui.profile.plot(x_axis, y_axis, pen=(self.parent.shrinking_roi_rgb[0],
+ self.parent.shrinking_roi_rgb[1],
+ self.parent.shrinking_roi_rgb[2]))
+ self.parent.ui.profile.setLabel("bottom", x_axis_label)
+ self.parent.ui.profile.setLabel("left", 'Mean transmission')
+
+ # full region
+ y_axis = self.parent.fitting_input_dictionary['rois'][0]['profile']
+ self.parent.ui.profile.plot(x_axis, y_axis, pen=(self.parent.selection_roi_rgb[0],
+ self.parent.selection_roi_rgb[1],
+ self.parent.selection_roi_rgb[2]))
+
+
+ def profile_of_bin_size_slider_changed(self, new_value):
+ try:
+ self.parent.update_dict_profile_to_fit()
+ if self.parent.ui.square_roi_radiobutton.isChecked():
+ new_width = new_value
+ new_height = new_value
+ else:
+ initial_roi_width = np.int(str(self.parent.ui.roi_width.text()))
+ initial_roi_height = np.int(str(self.parent.ui.roi_height.text()))
+ if initial_roi_width == initial_roi_height:
+ new_width = new_value
+ new_height = new_value
+ elif initial_roi_width < initial_roi_height:
+ new_width = new_value
+ delta = initial_roi_width - new_width
+ new_height = initial_roi_height - delta
+ else:
+ new_height = new_value
+ delta = initial_roi_height - new_height
+ new_width = initial_roi_width - delta
+
+ self.parent.ui.profile_of_bin_size_width.setText(str(new_width))
+ self.parent.ui.profile_of_bin_size_height.setText(str(new_height))
+ self.update_roi_defined_by_profile_of_bin_size_slider()
+ self.update_selection_profile_plot()
+ except AttributeError:
+ pass
+
+ def update_roi_defined_by_profile_of_bin_size_slider(self):
+ coordinates_new_selection = self.get_coordinates_of_new_inside_selection_box()
+ self.parent.shrinking_roi = coordinates_new_selection
+ x0 = coordinates_new_selection['x0']
+ y0 = coordinates_new_selection['y0']
+ width = coordinates_new_selection['width']
+ height = coordinates_new_selection['height']
+
+ # remove old selection
+ if self.parent.shrinking_roi_id:
+ self.parent.ui.image_view.removeItem(self.parent.shrinking_roi_id)
+
+ # plot new box
+ _pen = QtGui.QPen()
+ _pen.setDashPattern(self.parent.shrinking_roi_settings['dashes_pattern'])
+ _pen.setColor(self.parent.shrinking_roi_settings['color'])
+ _pen.setWidth(self.parent.shrinking_roi_settings['width'])
+
+ self.parent.shrinking_roi_id = pg.ROI([x0, y0],
+ [width, height],
+ pen=_pen,
+ scaleSnap=True,
+ movable=False)
+ self.parent.ui.image_view.addItem(self.parent.shrinking_roi_id)
+
+ def update_profile_of_bin_slider_widget(self):
+ self.parent.change_profile_of_bin_slider_signal()
+ fitting_input_dictionary = self.parent.fitting_input_dictionary
+ dict_rois_imported = OrderedDict()
+ nbr_key = len(fitting_input_dictionary['rois'].keys())
+ for _index, _key in enumerate(fitting_input_dictionary['rois'].keys()):
+ dict_rois_imported[nbr_key - 1 - _index] = {'width' : fitting_input_dictionary['rois'][_key]['width'],
+ 'height': fitting_input_dictionary['rois'][_key]['height']}
+ self.parent.dict_rois_imported = dict_rois_imported
+ self.parent.ui.profile_of_bin_size_slider.setRange(0, len(dict_rois_imported) - 1)
+ # self.parent.ui.profile_of_bin_size_slider.setMinimum(0)
+ # self.parent.ui.profile_of_bin_size_slider.setMaximum(len(dict_rois_imported)-1)
+ self.parent.ui.profile_of_bin_size_slider.setSingleStep(1)
+ self.parent.ui.profile_of_bin_size_slider.setValue(len(dict_rois_imported) - 1)
+ self.parent.update_profile_of_bin_slider_labels()
+
+ def update_selection_roi_slider_changed(self):
+ value = self.parent.ui.roi_size_slider.value()
+ self.parent.selection_roi_slider_changed(value)
diff --git a/notebooks/__code/export_handler.py b/notebooks/__code/export_handler.py
new file mode 100644
index 0000000..12c3840
--- /dev/null
+++ b/notebooks/__code/export_handler.py
@@ -0,0 +1,272 @@
+from pathlib import Path
+from qtpy.QtWidgets import QFileDialog
+import numpy as np
+from collections import OrderedDict
+
+from __code.bragg_edge.get import Get
+from __code.file_handler import make_ascii_file
+from __code.bragg_edge.bragg_edge_peak_fitting_gui_utility import GuiUtility
+
+
+class ExportHandler:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ def configuration(self):
+ # bring file dialog to locate where the file will be saved
+ base_folder = Path(self.parent.working_dir)
+ directory = str(base_folder.parent)
+ _export_folder = QFileDialog.getExistingDirectory(self.parent,
+ directory=directory,
+ caption="Select Output Folder",
+ options=QFileDialog.ShowDirsOnly)
+
+ if _export_folder:
+ data, metadata = self.get_data_metadata_from_selection_tab()
+
+ # collect initial selection size (x0, y0, width, height)
+ o_get = Get(parent=self.parent)
+ [x0, y0, x1, y1, width, height] = o_get.selection_roi_dimension()
+
+ name_of_ascii_file = ExportHandler.makeup_name_of_profile_ascii_file(base_name=str(base_folder.name),
+ export_folder=_export_folder,
+ x0=x0, y0=y0,
+ width=width,
+ height=height)
+
+ make_ascii_file(metadata=metadata,
+ data=data,
+ output_file_name=name_of_ascii_file,
+ dim='1d')
+
+ self.parent.ui.statusbar.showMessage("{} has been created!".format(name_of_ascii_file), 10000) # 10s
+ self.parent.ui.statusbar.setStyleSheet("color: green")
+
+ @staticmethod
+ def makeup_name_of_profile_ascii_file(base_name="default",
+ export_folder="./",
+ x0=None, y0=None, width=None, height=None):
+ """this will return the full path name of the ascii file to create that will contain all the profiles
+ starting with the selection box and all the way to the minimal size"""
+ full_base_name = "full_set_of_shrinkable_region_profiles_from_" + \
+ "x{}_y{}_w{}_h{}_for_folder_{}.txt".format(x0, y0, width, height, base_name)
+ return str(Path(export_folder) / full_base_name)
+
+ def get_data_metadata_from_selection_tab(self):
+ base_folder = Path(self.parent.working_dir)
+ o_get = Get(parent=self.parent)
+
+ index_axis, _ = o_get.specified_x_axis(xaxis='index')
+ tof_axis, _ = o_get.specified_x_axis(xaxis='tof')
+ lambda_axis, _ = o_get.specified_x_axis('lambda')
+ fitting_peak_range = self.parent.bragg_edge_range
+ distance_detector_sample = str(self.parent.ui.distance_detector_sample.text())
+ detector_offset = str(self.parent.ui.detector_offset.text())
+ kropff_fitting_values = self.collect_all_kropff_fitting_values()
+ march_dollase_fitting_values = self.collect_all_march_dollase_fitting_values()
+
+ dict_regions = o_get.all_russian_doll_region_full_infos()
+ metadata = ExportHandler.make_metadata(base_folder=base_folder,
+ fitting_peak_range=fitting_peak_range,
+ dict_regions=dict_regions,
+ distance_detector_sample=distance_detector_sample,
+ detector_offset=detector_offset,
+ kropff_fitting_values=kropff_fitting_values,
+ march_dollase_fitting_values=march_dollase_fitting_values)
+ self.add_fitting_infos_to_metadata(metadata)
+
+ metadata.append("#")
+ metadata.append("#File Index, TOF(micros), lambda(Angstroms), ROIs (see above)")
+ data = ExportHandler.format_data(col1=index_axis,
+ col2=tof_axis,
+ col3=lambda_axis,
+ dict_regions=dict_regions)
+
+ return data, metadata
+
+ def add_fitting_infos_to_metadata(self, metadata):
+ o_tab = GuiUtility(parent=self.parent)
+ fitting_algorithm_used = o_tab.get_tab_selected(tab_ui=self.parent.ui.tab_algorithm)
+ # fitting_rois = self.fitting_rois
+ # fitting_flag = True if self.parent.fitting_peak_ui else False
+ metadata.append("#fitting algorithm selected: {}".format(fitting_algorithm_used))
+ metadata.append("#kropff fitting procedure started: {}".format(
+ self.parent.fitting_procedure_started['kropff']))
+ metadata.append("#Bragg peak selection range: [{}, {}]".format(self.parent.kropff_fitting_range[
+ 'bragg_peak'][0],
+ self.parent.kropff_fitting_range['bragg_peak'][1]))
+ # kropff
+ for _key in self.parent.kropff_fitting_range.keys():
+ metadata.append("#kropff {} selection range: [{}, {}]".format(_key,
+ self.parent.kropff_fitting_range[_key][0],
+ self.parent.kropff_fitting_range[_key][1]))
+
+ # March-dollase
+ [left_peak, right_peak] = self.parent.march_dollase_fitting_range_selected
+ metadata.append("#march-dollase bragg peak selection range: [{}, {}]".format(left_peak, right_peak))
+ metadata.append("#march-dollase fitting procedure started: {}".format(
+ self.parent.fitting_procedure_started['march-dollase']))
+ for _row_index, _row_entry in enumerate(self.parent.march_dollase_fitting_history_table):
+ str_row_entry = [str(_value) for _value in _row_entry]
+ joined_str_row_entry = ", ".join(str_row_entry)
+ metadata.append("#march-dollase history table row {}: {}".format(_row_index, joined_str_row_entry))
+
+ sigma = self.parent.march_dollase_fitting_initial_parameters['sigma']
+ alpha = self.parent.march_dollase_fitting_initial_parameters['alpha']
+
+ metadata.append("#march-dollase history init sigma: {}".format(sigma))
+ metadata.append("#march-dollase history init alpha: {}".format(alpha))
+
+ def collect_all_march_dollase_fitting_values(self):
+ march_fitting_values = OrderedDict()
+ fitting_input_dictionary = self.parent.fitting_input_dictionary
+
+ for _row in fitting_input_dictionary['rois'].keys():
+ _entry = fitting_input_dictionary['rois'][_row]['fitting']['march_dollase']
+
+ march_fitting_values[_row] = {'d_spacing': _entry['d_spacing'],
+ 'sigma': _entry['sigma'],
+ 'alpha': _entry['alpha'],
+ 'a1': _entry['a1'],
+ 'a2': _entry['a2'],
+ 'a5': _entry['a5'],
+ 'a6': _entry['a6'],
+ 'd_spacing_error': _entry['d_spacing_error'],
+ 'sigma_error': _entry['sigma_error'],
+ 'alpha_error': _entry['alpha_error'],
+ 'a1_error': _entry['a1_error'],
+ 'a2_error': _entry['a2_error'],
+ 'a5_error': _entry['a5_error'],
+ 'a6_error': _entry['a6_error'],
+ }
+ return march_fitting_values
+
+ def collect_all_kropff_fitting_values(self):
+ kropff_fitting_values = OrderedDict()
+
+ fitting_input_dictionary = self.parent.fitting_input_dictionary
+
+ for _row in fitting_input_dictionary['rois'].keys():
+ _entry = fitting_input_dictionary['rois'][_row]['fitting']['kropff']
+
+ _entry_high = _entry['high']
+ _entry_low = _entry['low']
+ _entry_bragg_peak = _entry['bragg_peak']
+ kropff_fitting_values[_row] = {'a0': _entry_high['a0'],
+ 'b0': _entry_high['b0'],
+ 'a0_error': _entry_high['a0_error'],
+ 'b0_error': _entry_high['b0_error'],
+ 'ahkl': _entry_low['ahkl'],
+ 'bhkl': _entry_low['bhkl'],
+ 'ahkl_error': _entry_low['ahkl_error'],
+ 'bhkl_error': _entry_low['bhkl_error'],
+ 'ldahkl': _entry_bragg_peak['ldahkl'],
+ 'tau': _entry_bragg_peak['tau'],
+ 'sigma': _entry_bragg_peak['sigma'],
+ 'ldahkl_error': _entry_bragg_peak['ldahkl_error'],
+ 'tau_error': _entry_bragg_peak['tau_error'],
+ 'sigma_error': _entry_bragg_peak['sigma_error'],
+ }
+ return kropff_fitting_values
+
+ @staticmethod
+ def make_metadata(base_folder=None,
+ fitting_peak_range=None,
+ dict_regions=None,
+ distance_detector_sample="",
+ detector_offset="",
+ kropff_fitting_values=None,
+ march_dollase_fitting_values=None):
+
+ metadata = ["#base folder: {}".format(base_folder)]
+ metadata.append("#fitting peak range in file index: [{}, {}]".format(fitting_peak_range[0],
+ fitting_peak_range[1]))
+ metadata.append("#distance detector-sample: {}".format(distance_detector_sample))
+ metadata.append("#detector offset: {}".format(detector_offset))
+ for _row, _key in enumerate(dict_regions.keys()):
+ _entry = dict_regions[_key]
+ x0 = _entry['x0']
+ y0 = _entry['y0']
+ width = _entry['width']
+ height = _entry['height']
+
+ _entry_kropff = kropff_fitting_values[_row]
+ a0 = _entry_kropff['a0']
+ b0 = _entry_kropff['b0']
+ a0_error = _entry_kropff['a0_error']
+ b0_error = _entry_kropff['b0_error']
+ ahkl = _entry_kropff['ahkl']
+ bhkl = _entry_kropff['bhkl']
+ ahkl_error = _entry_kropff['ahkl_error']
+ bhkl_error = _entry_kropff['bhkl_error']
+ ldahkl = _entry_kropff['ldahkl']
+ tau = _entry_kropff['tau']
+ sigma = _entry_kropff['sigma']
+ ldahkl_error = _entry_kropff['ldahkl_error']
+ tau_error = _entry_kropff['tau_error']
+ sigma_error = _entry_kropff['sigma_error']
+
+ _entry_march = march_dollase_fitting_values[_row]
+ d_spacing = _entry_march['d_spacing']
+ sigma1 = _entry_march['sigma']
+ alpha = _entry_march['alpha']
+ a1 = _entry_march['a1']
+ a2 = _entry_march['a2']
+ a5 = _entry_march['a5']
+ a6 = _entry_march['a6']
+ d_spacing_error = _entry_march['d_spacing_error']
+ sigma1_error = _entry_march['sigma_error']
+ alpha_error = _entry_march['alpha_error']
+ a1_error = _entry_march['a1_error']
+ a2_error = _entry_march['a2_error']
+ a5_error = _entry_march['a5_error']
+ a6_error = _entry_march['a6_error']
+
+ metadata.append("#column {} -> x0:{}, y0:{}, width:{}, height:{},"
+ " kropff: a0:{}, b0:{}, a0_error:{}, b0_error:{},"
+ " ahkl:{}, bhkl:{}, ahkl_error:{}, bhkl_error:{},"
+ " ldahkl:{}, tau:{}, sigma:{},"
+ " ldahkl_error:{}, tau_error:{}, sigma_error:{},"
+ " march_dollase: d_spacing:{}, sigma:{}, alpha:{},"
+ " a1:{}, a2:{}, a5:{}, a6:{},"
+ " d_spacing_error:{}, sigma_error:{}, alpha_error:{},"
+ " a1_error:{}, a2_error:{}, a5_error:{}, a6_error:{}".format(_key + 3,
+ x0, y0,
+ width, height,
+ a0, b0, a0_error, b0_error,
+ ahkl, bhkl,
+ ahkl_error,
+ bhkl_error,
+ ldahkl, tau, sigma,
+ ldahkl_error,
+ tau_error,
+ sigma_error,
+ d_spacing,
+ sigma1, alpha,
+ a1, a2, a5, a6,
+ d_spacing_error,
+ sigma1_error, alpha_error,
+ a1_error, a2_error, a5_error,
+ a6_error))
+
+ return metadata
+
+ @staticmethod
+ def format_data(col1=None, col2=None, col3=None, dict_regions=None):
+ if col1 is None:
+ return []
+
+ data = []
+ profile_length = len(dict_regions[0]['profile'])
+ for _row_index in np.arange(profile_length):
+ list_profile_for_this_row = []
+ for _key in dict_regions.keys():
+ _profile = dict_regions[_key]['profile']
+ list_profile_for_this_row.append(str(_profile[_row_index]))
+ _col1 = col1[_row_index]
+ _col2 = col2[_row_index]
+ _col3 = col3[_row_index]
+ data.append("{}, {}, {}, ".format(_col1, _col2, _col3) + ", ".join(list_profile_for_this_row))
+ return data
+
diff --git a/notebooks/__code/get.py b/notebooks/__code/get.py
new file mode 100644
index 0000000..ccc40ea
--- /dev/null
+++ b/notebooks/__code/get.py
@@ -0,0 +1,167 @@
+import numpy as np
+
+from __code.bragg_edge.bragg_edge_peak_fitting_gui_utility import GuiUtility
+from __code.selection_region_utilities import SelectionRegionUtilities
+
+
+class Get:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ self.x_axis_choice_ui = {'selection': {'index' : self.parent.ui.selection_index_radiobutton,
+ 'tof' : self.parent.ui.selection_tof_radiobutton,
+ 'lambda': self.parent.ui.selection_lambda_radiobutton},
+ 'fitting' : {'index' : self.parent.ui.fitting_index_radiobutton,
+ 'tof' : self.parent.ui.fitting_tof_radiobutton,
+ 'lambda': self.parent.ui.fitting_lambda_radiobutton},
+ }
+
+ def specified_x_axis(self, xaxis='index'):
+ # if self.parent.is_file_imported:
+ # return self.parent.fitting_input_dictionary['xaxis'][xaxis]
+ # else:
+ label = self.parent.xaxis_label[xaxis]
+ if xaxis == 'index':
+ return self.parent.index_array, label
+ elif xaxis == 'tof':
+ return self.parent.tof_array_s * 1e6, label
+ elif xaxis == 'lambda':
+ return self.parent.lambda_array, label
+ else:
+ raise NotImplementedError
+
+ def x_axis_label(self, x_axis_selected='index'):
+ x_axis_dict = self.parent.fitting_input_dictionary['xaxis']
+ return x_axis_dict[x_axis_selected][1]
+
+ def x_axis_checked(self):
+ o_gui = GuiUtility(parent=self)
+ tab_selected = o_gui.get_tab_selected(tab_ui=self.parent.ui.tabWidget).lower()
+
+ list_ui = self.x_axis_choice_ui[tab_selected]
+
+ if list_ui['index'].isChecked():
+ return 'index'
+ elif list_ui['tof'].isChecked():
+ return 'tof'
+ else:
+ return 'lambda'
+
+ def x_axis(self):
+ o_gui = GuiUtility(parent=self.parent)
+ tab_selected = o_gui.get_tab_selected(self.parent.ui.tabWidget).lower()
+
+ list_ui = self.x_axis_choice_ui[tab_selected]
+ if list_ui['index'].isChecked():
+ return self.specified_x_axis(xaxis='index')
+ elif list_ui['tof'].isChecked():
+ return self.specified_x_axis(xaxis='tof')
+ else:
+ return self.specified_x_axis(xaxis='lambda')
+
+ def all_x_axis(self):
+ all_x_axis = {'index' : self.specified_x_axis(xaxis='index'),
+ 'tof' : self.specified_x_axis(xaxis='tof'),
+ 'lambda': self.specified_x_axis(xaxis='lambda')}
+ return all_x_axis
+
+ def all_russian_doll_region_full_infos(self):
+ if self.parent.is_file_imported:
+ dict_regions = self.parent.fitting_input_dictionary['rois']
+ else:
+ # collect initial selection size (x0, y0, width, height)
+ [x0, y0, x1, y1, width, height] = self.selection_roi_dimension()
+ # create profile for all the fitting region inside that first box
+ o_regions = SelectionRegionUtilities(x0=x0, y0=y0, width=width, height=height)
+ dict_regions = o_regions.get_all_russian_doll_regions()
+ self.parent.add_profile_to_dict_of_all_regions(dict_regions=dict_regions)
+ return dict_regions
+
+ def selection_roi_dimension(self):
+ roi_id = self.parent.roi_id
+
+ x0, y0, x1, y1, width, height = None, None, None, None, None, None
+
+ if roi_id:
+ region = roi_id.getArraySlice(self.parent.final_image,
+ self.parent.ui.image_view.imageItem)
+ x0 = region[0][0].start
+ x1 = region[0][0].stop
+ y0 = region[0][1].start
+ y1 = region[0][1].stop
+ width = np.int(x1 - x0)
+ height = np.int(y1 - y0)
+
+ else:
+ x0, y0, x1, y1, width, height = self.parent.roi_dimension_from_config_file
+
+ return [x0, y0, x1, y1, width, height]
+
+ def profile_of_roi(self, x0=None, y0=None, x1=None, y1=None, width=None, height=None):
+ profile_value = []
+
+ if width:
+ x1 = x0 + width
+ if height:
+ y1 = y0 + height
+
+ for _image in self.parent.o_norm.data['sample']['data']:
+ _value = np.mean(_image[y0:y1, x0:x1])
+ profile_value.append(_value)
+
+ return profile_value
+
+ def requested_xaxis(self, xaxis_label='index'):
+ if xaxis_label == 'index':
+ return self.parent.dict_profile_to_fit['xaxis']['index'], self.parent.xaxis_label['index']
+ elif xaxis_label == 'tof':
+ return self.parent.dict_profile_to_fit['xaxis']['tof'], self.parent.xaxis_label['tof']
+ elif xaxis_label == 'lambda':
+ return self.parent.dict_profile_to_fit['xaxis']['lambda'], self.parent.xaxis_label['lambda']
+
+ def fitting_profile_xaxis(self):
+ if self.parent.ui.fitting_tof_radiobutton.isChecked():
+ return self.requested_xaxis(xaxis_label='tof')
+ elif self.ui.fitting_index_radiobutton.isChecked():
+ return self.requested_xaxis(xaxis_label='index')
+ else:
+ return self.requested_xaxis(xaxis_label='lambda')
+
+ def part_of_fitting_selected(self):
+ """high, low or bragg_peak"""
+ list_pages = ["Bragg peak selection", "high", "low", "bragg_peak"]
+ list_table_ui = [None,
+ self.parent.ui.high_lda_tableWidget,
+ self.parent.ui.low_lda_tableWidget,
+ self.parent.ui.bragg_edge_tableWidget]
+
+ page_index = self.parent.ui.kropff_toolBox.currentIndex()
+
+ return {'name_of_page': list_pages[page_index],
+ 'table_ui' : list_table_ui[page_index]}
+
+ def y_axis_data_of_selected_row(self, row_selected):
+ selected_roi = self.parent.fitting_input_dictionary['rois'][row_selected]
+ yaxis = selected_roi['profile']
+ [left_xaxis_index, right_xaxis_index] = self.parent.bragg_edge_range
+ yaxis = yaxis[left_xaxis_index: right_xaxis_index]
+ return yaxis
+
+ def x_axis_data(self, x_axis_selected='index'):
+ xaxis_dict = self.parent.fitting_input_dictionary['xaxis']
+ xaxis_index, xaxis_label = xaxis_dict[x_axis_selected]
+ [left_xaxis_index, right_xaxis_index] = self.parent.bragg_edge_range
+ xaxis = xaxis_index[left_xaxis_index: right_xaxis_index]
+ return xaxis
+
+ @staticmethod
+ def units(name='index'):
+ if name == 'index':
+ return 'file index'
+ elif name == 'tof':
+ return u"\u03BCs"
+ elif name == 'lambda':
+ return u"\u212B"
+ else:
+ return ""
diff --git a/notebooks/__code/import_handler.py b/notebooks/__code/import_handler.py
new file mode 100644
index 0000000..144b23e
--- /dev/null
+++ b/notebooks/__code/import_handler.py
@@ -0,0 +1,298 @@
+from pathlib import Path
+from qtpy.QtWidgets import QFileDialog
+import numpy as np
+from collections import OrderedDict
+
+from __code.file_handler import read_bragg_edge_fitting_ascii_format
+from __code.bragg_edge.peak_fitting_initialization import PeakFittingInitialization
+from __code.bragg_edge.fitting_functions import kropff_high_lambda, kropff_low_lambda, kropff_bragg_peak_tof
+from __code.bragg_edge.bragg_edge_peak_fitting_gui_utility import GuiUtility
+from __code.bragg_edge.bragg_edge_selection_tab import BraggEdgeSelectionTab
+from __code.bragg_edge.kropff import Kropff
+from __code.bragg_edge.march_dollase import MarchDollase
+
+
+class ImportHandler:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ def run(self):
+ working_dir = str(Path(self.parent.working_dir).parent)
+ ascii_file = QFileDialog.getOpenFileName(self.parent,
+ caption="Select ASCII file",
+ directory=working_dir,
+ filter="ASCII (*.txt)")
+
+ if ascii_file[0]:
+
+ self.parent.full_reset_of_ui()
+ self.parent.block_table_ui(True)
+ self.parent.is_file_imported = True
+ result_of_import = read_bragg_edge_fitting_ascii_format(full_file_name=str(ascii_file[0]))
+ self.save_initial_roi_dimension_from_config_file(result_of_import['metadata']['columns']['3'])
+ self.save_march_dollase_parameters(result_of_import['metadata'])
+ self.parent.bragg_edge_range = result_of_import['metadata']['bragg_edge_range']
+ self.parent.bragg_peak_selection_range = result_of_import['metadata']['bragg_peak_selection_range']
+
+ self.update_selection_tab(result_of_import=result_of_import)
+ self.update_interface(result_of_import=result_of_import)
+
+ self.parent.ui.statusbar.showMessage("{} has been imported!".format(ascii_file[0]), 10000) # 10s
+ self.parent.ui.statusbar.setStyleSheet("color: green")
+
+ o_selection = BraggEdgeSelectionTab(parent=self.parent)
+ o_selection.update_profile_of_bin_slider_widget()
+ o_selection.update_selection_plot()
+
+ self.parent.ui.tabWidget.setTabEnabled(1, self.parent.is_fit_infos_loaded())
+ self.parent.ui.tabWidget.setEnabled(True)
+ self.parent.ui.actionExport.setEnabled(True)
+
+ self.parent.fitting_procedure_started['kropff'] = result_of_import.get('metadata').get('kropff fitting '
+ 'procedure '
+ 'started', False)
+ self.parent.fitting_procedure_started['march-dollase'] = result_of_import.get('metadata').get(
+ 'march-dollase fitting procedure started', False)
+
+ o_kropff = Kropff(parent=self.parent)
+ o_kropff.reset_all_table()
+
+ o_march = MarchDollase(parent=self.parent)
+ o_march.reset_table()
+
+ if result_of_import.get('metadata').get('kropff fitting procedure started', False):
+ # fill tables with minimum contains
+ o_kropff.fill_table_with_fitting_information()
+
+ if result_of_import.get('metadata').get('march-dollase fitting procedure started', False):
+ # fill tables with minimum contains
+ o_march.fill_tables_with_fitting_information()
+ o_march.fill_history_table_with_fitting_information()
+
+ self.parent.select_first_row_of_all_fitting_table()
+
+ # self.parent.initialize_default_peak_regions()
+
+ self.parent.block_table_ui(False)
+ self.parent.update_vertical_line_in_profile_plot()
+ self.parent.update_fitting_plot()
+ self.parent.kropff_fitting_range_changed()
+
+ o_gui = GuiUtility(parent=self.parent)
+ o_gui.check_status_of_kropff_fitting_buttons()
+
+ def update_interface(self, result_of_import=None):
+ self.create_fitting_input_dictionary_from_imported_ascii_file(result_of_import=result_of_import)
+ self.parent.tof_array_s = self.parent.fitting_input_dictionary['xaxis']['tof'][0] * 1e-6
+ self.parent.lambda_array = self.parent.fitting_input_dictionary['xaxis']['lambda'][0]
+ self.parent.index_array = self.parent.fitting_input_dictionary['xaxis']['index'][0]
+
+ def update_selection_tab(self, result_of_import=None):
+ self.parent.ui.distance_detector_sample.setText(result_of_import['metadata']['distance_detector_sample'])
+ self.parent.ui.detector_offset.setText(result_of_import['metadata']['detector_offset'])
+ self.parent.disable_left_part_of_selection_tab()
+ self.parent.ui.info_message_about_cyan.setVisible(False)
+
+ def save_march_dollase_parameters(self, metadata_dict):
+ march_dollase_history_table = metadata_dict['march-dollase history table']
+ march_dollase_history_init = metadata_dict['march-dollase history init']
+
+ march_dollase_fitting_history_table = []
+ for _row_index in march_dollase_history_table.keys():
+ str_flag = march_dollase_history_table[_row_index]
+ list_flag = str_flag.split(",")
+ list_flag = [_value.strip() for _value in list_flag]
+
+ _row_flag = []
+ for _value in list_flag:
+ _flag = True if _value == "True" else False
+ _row_flag.append(_flag)
+ march_dollase_fitting_history_table.append(_row_flag)
+
+ march_dollase_fitting_initial_parameters = {'sigma': march_dollase_history_init['sigma'],
+ 'alpha': march_dollase_history_init['alpha'],
+ 'd_spacing': np.NaN,
+ 'a1': np.NaN,
+ 'a2': np.NaN,
+ 'a5': np.NaN,
+ 'a6': np.NaN}
+
+ self.parent.march_dollase_fitting_history_table = march_dollase_fitting_history_table
+ self.parent.march_dollase_fitting_initial_parameters = march_dollase_fitting_initial_parameters
+ self.parent.march_dollase_fitting_range_selected = metadata_dict['march-dollase bragg peak selection range']
+
+ def save_initial_roi_dimension_from_config_file(self, column_3_dict):
+ """column_3_dict = {'x0': value, 'y0': value, 'width': value, 'height': value}"""
+ self.parent.roi_dimension_from_config_file = [column_3_dict['x0'],
+ column_3_dict['y0'],
+ None, None,
+ column_3_dict['width'],
+ column_3_dict['height']]
+
+ def create_fitting_input_dictionary_from_imported_ascii_file(self, result_of_import):
+ metadata = result_of_import['metadata']
+ self.parent.kropff_fitting_range['high'] = metadata['kropff_high']
+ self.parent.kropff_fitting_range['low'] = metadata['kropff_low']
+ self.parent.kropff_fitting_range['bragg_peak'] = metadata['kropff_bragg_peak']
+
+ self.parent.working_dir = metadata['base_folder']
+ self.parent.bragg_edge_range = metadata['bragg_edge_range']
+
+ columns_roi = metadata['columns']
+
+ o_init = PeakFittingInitialization(parent=self.parent)
+ self.parent.fitting_input_dictionary = o_init.fitting_input_dictionary(nbr_rois=len(columns_roi))
+ self.parent.fitting_input_dictionary['bragg_edge_range'] = metadata['bragg_edge_range']
+
+ data = result_of_import['data']
+ tof_array = np.array(data['tof'])
+ index_array = np.array(data['index'])
+ lambda_array = np.array(data['lambda'])
+ rois_dictionary = OrderedDict()
+
+ lda_array_of_peak_selected = lambda_array[self.parent.bragg_edge_range[0]:
+ self.parent.bragg_edge_range[1]]
+
+ for col in np.arange(3, len(columns_roi) + 3):
+ str_col = str(col)
+ col_index = col-3
+
+ # high lambda
+ self.parent.fitting_input_dictionary['rois'][col_index]['profile'] = np.array(data[str_col])
+ self.parent.fitting_input_dictionary['rois'][col_index]['x0'] = columns_roi[str_col]['x0']
+ self.parent.fitting_input_dictionary['rois'][col_index]['y0'] = columns_roi[str_col]['y0']
+ self.parent.fitting_input_dictionary['rois'][col_index]['width'] = columns_roi[str_col]['width']
+ self.parent.fitting_input_dictionary['rois'][col_index]['height'] = columns_roi[str_col]['height']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['high']['a0'] = \
+ columns_roi[str_col]['kropff']['a0']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['high']['b0'] = \
+ columns_roi[str_col]['kropff']['b0']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['high']['a0_error'] = \
+ columns_roi[str_col]['kropff']['a0_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['high']['b0_error'] = \
+ columns_roi[str_col]['kropff']['b0_error']
+
+ xaxis_to_fit = lda_array_of_peak_selected[self.parent.kropff_fitting_range['high'][0]:
+ self.parent.kropff_fitting_range['high'][1]]
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['high']['xaxis_to_fit'] = \
+ xaxis_to_fit
+
+ kropff_a0 = np.NaN if columns_roi[str_col]['kropff']['a0'] == 'None' else np.float(columns_roi[str_col][
+ 'kropff']['a0'])
+ kropff_b0 = np.NaN if columns_roi[str_col]['kropff']['b0'] == 'None' else np.float(columns_roi[str_col][
+ 'kropff']['b0'])
+ yaxis_fitted = kropff_high_lambda(xaxis_to_fit,
+ kropff_a0,
+ kropff_b0)
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['high']['yaxis_fitted'] = \
+ yaxis_fitted
+
+ # low lambda
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['low']['ahkl'] = \
+ columns_roi[str_col]['kropff']['ahkl']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['low']['bhkl'] = \
+ columns_roi[str_col]['kropff']['bhkl']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['low']['ahkl_error'] = \
+ columns_roi[str_col]['kropff']['ahkl_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['low']['bhkl_error'] = \
+ columns_roi[str_col]['kropff']['bhkl_error']
+
+ xaxis_to_fit = lda_array_of_peak_selected[self.parent.kropff_fitting_range['low'][0]:
+ self.parent.kropff_fitting_range['low'][1]]
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['low']['xaxis_to_fit'] = \
+ xaxis_to_fit
+
+ kropff_ahkl = np.NaN if columns_roi[str_col]['kropff']['ahkl'] == 'None' else np.float(columns_roi[str_col][
+ 'kropff']['ahkl'])
+ kropff_bhkl = np.NaN if columns_roi[str_col]['kropff']['bhkl'] == 'None' else np.float(columns_roi[str_col][
+ 'kropff']['bhkl'])
+
+ yaxis_fitted = kropff_low_lambda(xaxis_to_fit,
+ kropff_a0,
+ kropff_b0,
+ kropff_ahkl,
+ kropff_bhkl)
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['low']['yaxis_fitted'] = \
+ yaxis_fitted
+
+ # Bragg peak
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['ldahkl'] = \
+ columns_roi[str_col]['kropff']['ldahkl']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['tau'] = \
+ columns_roi[str_col]['kropff']['tau']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['sigma'] = \
+ columns_roi[str_col]['kropff']['sigma']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['ldahkl_error']\
+ = columns_roi[str_col]['kropff']['ldahkl_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['tau_error'] = \
+ columns_roi[str_col]['kropff']['tau_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['sigma_error']\
+ = \
+ columns_roi[str_col]['kropff']['sigma_error']
+
+ xaxis_to_fit = lda_array_of_peak_selected[self.parent.kropff_fitting_range['bragg_peak'][0]:
+ self.parent.kropff_fitting_range['bragg_peak'][1]]
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['xaxis_to_fit']\
+ = \
+ xaxis_to_fit
+
+ kropff_tau = np.NaN if columns_roi[str_col]['kropff']['tau'] == 'None' else np.float(columns_roi[
+ str_col][
+ 'kropff']['tau'])
+ kropff_ldahkl = np.NaN if columns_roi[str_col]['kropff']['ldahkl'] == 'None' else np.float(columns_roi[
+ str_col][
+ 'kropff'][
+ 'ldahkl'])
+ kropff_sigma = np.NaN if columns_roi[str_col]['kropff']['sigma'] == 'None' else np.float(columns_roi[
+ str_col][
+ 'kropff'][
+ 'sigma'])
+
+ yaxis_fitted = kropff_bragg_peak_tof(xaxis_to_fit,
+ kropff_a0,
+ kropff_b0,
+ kropff_ahkl,
+ kropff_bhkl,
+ kropff_ldahkl,
+ kropff_sigma,
+ kropff_tau)
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['kropff']['bragg_peak']['yaxis_fitted']\
+ = \
+ yaxis_fitted
+
+ # March_dollase
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['d_spacing'] = \
+ columns_roi[str_col]['march_dollase']['d_spacing']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['sigma'] = \
+ columns_roi[str_col]['march_dollase']['sigma']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['alpha'] = \
+ columns_roi[str_col]['march_dollase']['alpha']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a1'] = \
+ columns_roi[str_col]['march_dollase']['a1']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a2'] = \
+ columns_roi[str_col]['march_dollase']['a2']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a5'] = \
+ columns_roi[str_col]['march_dollase']['a5']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a6'] = \
+ columns_roi[str_col]['march_dollase']['a6']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['d_spacing_error'] = \
+ columns_roi[str_col]['march_dollase']['d_spacing_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['sigma_error'] = \
+ columns_roi[str_col]['march_dollase']['sigma_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['alpha_error'] = \
+ columns_roi[str_col]['march_dollase']['alpha_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a1_error'] = \
+ columns_roi[str_col]['march_dollase']['a1_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a2_error'] = \
+ columns_roi[str_col]['march_dollase']['a2_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a5_error'] = \
+ columns_roi[str_col]['march_dollase']['a5_error']
+ self.parent.fitting_input_dictionary['rois'][col_index]['fitting']['march_dollase']['a6_error'] = \
+ columns_roi[str_col]['march_dollase']['a6_error']
+
+ xaxis_dictionary = {'index': (index_array, self.parent.xaxis_label['index']),
+ 'lambda': (lambda_array, self.parent.xaxis_label['lambda']),
+ 'tof': (tof_array, self.parent.xaxis_label['tof'])}
+ self.parent.fitting_input_dictionary['xaxis'] = xaxis_dictionary
+ self.parent.fitting_input_dictionary['bragg_edge_range_selected'] = result_of_import['metadata']['bragg_edge_range']
diff --git a/notebooks/__code/kropff.py b/notebooks/__code/kropff.py
new file mode 100644
index 0000000..cb0321d
--- /dev/null
+++ b/notebooks/__code/kropff.py
@@ -0,0 +1,344 @@
+import numpy as np
+from qtpy import QtGui
+from qtpy.QtWidgets import QFileDialog
+from pathlib import Path
+import pyqtgraph as pg
+
+from __code.table_handler import TableHandler
+from __code.bragg_edge.bragg_edge_peak_fitting_gui_utility import GuiUtility
+from __code.bragg_edge.kropff_fitting_job_handler import KropffFittingJobHandler
+from __code.file_handler import make_ascii_file_from_2dim_array
+from __code.bragg_edge.get import Get
+from __code._utilities.dictionary import key_path_exists_in_dictionary
+from __code.utilities import find_nearest_index
+
+
+class Kropff:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ self.table_ui = {'high_lda': self.parent.ui.high_lda_tableWidget,
+ 'low_lda' : self.parent.ui.low_lda_tableWidget,
+ 'bragg_peak' : self.parent.ui.bragg_edge_tableWidget}
+
+ def reset_all_table(self):
+ self.reset_high_lambda_table()
+ self.reset_low_lambda_table()
+ self.reset_bragg_peak_table()
+
+ def reset_high_lambda_table(self):
+ self.clear_table(table_name='high_lda')
+ self.fill_table_with_minimum_contain(table_ui=self.table_ui['high_lda'])
+
+ def reset_low_lambda_table(self):
+ self.clear_table(table_name='low_lda')
+ self.fill_table_with_minimum_contain(table_ui=self.table_ui['low_lda'])
+
+ def reset_bragg_peak_table(self):
+ self.clear_table(table_name='bragg_peak')
+ self.fill_table_with_minimum_contain(table_ui=self.parent.ui.bragg_edge_tableWidget)
+
+ def clear_table(self, table_name='high_lambda', is_all=False):
+ """remove all the rows of the table name specified, or all if is_all is True"""
+ if is_all:
+ for _key in self.table_ui.keys():
+ self.clear_table(table_name=_key)
+ else:
+ o_table = TableHandler(table_ui=self.table_ui[table_name])
+ o_table.remove_all_rows()
+
+ def fill_table_with_minimum_contain(self, table_ui=None):
+ fitting_input_dictionary = self.parent.fitting_input_dictionary
+ rois = fitting_input_dictionary['rois']
+
+ o_table = TableHandler(table_ui=table_ui)
+ nbr_column = o_table.table_ui.columnCount()
+ other_column_name = ["N/A" for _ in np.arange(nbr_column)]
+ for _row, _roi in enumerate(rois.keys()):
+ _roi_key = rois[_roi]
+ list_col_name = "{}; {}; {}; {}".format(_roi_key['x0'],
+ _roi_key['y0'],
+ _roi_key['width'],
+ _roi_key['height'])
+ col_name = [list_col_name] + other_column_name
+ o_table.insert_row(_row, col_name)
+
+ def fill_table_with_fitting_information(self):
+ fitting_input_dictionary = self.parent.fitting_input_dictionary
+
+ o_table = TableHandler(table_ui=self.table_ui['high_lda'])
+ _col = 1
+ for _row in fitting_input_dictionary['rois'].keys():
+ _entry = fitting_input_dictionary['rois'][_row]['fitting']['kropff']['high']
+ o_table.set_item_with_float(_row, _col, _entry['a0'])
+ o_table.set_item_with_float(_row, _col+1, _entry['b0'])
+ o_table.set_item_with_float(_row, _col+2, _entry['a0_error'])
+ o_table.set_item_with_float(_row, _col+3, _entry['b0_error'])
+
+ o_table = TableHandler(table_ui=self.table_ui['low_lda'])
+ _col = 1
+ for _row in fitting_input_dictionary['rois'].keys():
+ _entry = fitting_input_dictionary['rois'][_row]['fitting']['kropff']['low']
+ o_table.set_item_with_float(_row, _col, _entry['ahkl'])
+ o_table.set_item_with_float(_row, _col+1, _entry['bhkl'])
+ o_table.set_item_with_float(_row, _col+2, _entry['ahkl_error'])
+ o_table.set_item_with_float(_row, _col+3, _entry['bhkl_error'])
+
+ o_table = TableHandler(table_ui=self.table_ui['bragg_peak'])
+ _col = 1
+ for _row in fitting_input_dictionary['rois'].keys():
+ _entry = fitting_input_dictionary['rois'][_row]['fitting']['kropff']['bragg_peak']
+ o_table.set_item_with_float(_row, _col, _entry['ldahkl'])
+ o_table.set_item_with_float(_row, _col+1, _entry['tau'])
+ o_table.set_item_with_float(_row, _col+2, _entry['sigma'])
+ o_table.set_item_with_float(_row, _col+3, _entry['ldahkl_error'])
+ o_table.set_item_with_float(_row, _col+4, _entry['tau_error'])
+ o_table.set_item_with_float(_row, _col+5, _entry['sigma_error'])
+
+ def bragg_peak_right_click(self, position=None):
+ menu = QtGui.QMenu(self.parent)
+
+ selected_rows_submenu = QtGui.QMenu("Selected Rows")
+ menu.addMenu(selected_rows_submenu)
+ _fit = selected_rows_submenu.addAction("Fit")
+ _export = selected_rows_submenu.addAction("Export ...")
+
+ advanced_selection_submenu = QtGui.QMenu("Advanced Rows Selection")
+ menu.addMenu(advanced_selection_submenu)
+ _negative_thkl = advanced_selection_submenu.addAction("Where t_hkl < 0")
+
+ action = menu.exec_(QtGui.QCursor.pos())
+
+ if action == _fit:
+ self.fit_bragg_peak_selected_rows()
+ elif action == _export:
+ self.export_bragg_peak_profile()
+ elif action == _negative_thkl:
+ self.select_all_rows_with_negative_thkl()
+
+ QtGui.QGuiApplication.processEvents() # to close QFileDialog
+
+ def fit_bragg_peak_selected_rows(self):
+ o_gui = GuiUtility(parent=self.parent)
+ list_rows_selected = o_gui.get_rows_of_table_selected(table_ui=self.parent.ui.bragg_edge_tableWidget)
+ self.parent.kropff_fit_bragg_peak_region_of_selected_rows(list_row_to_fit=list_rows_selected)
+
+ def export_bragg_peak_profile(self):
+ working_dir = str(Path(self.parent.working_dir).parent)
+ _export_folder = QFileDialog.getExistingDirectory(self.parent,
+ directory=working_dir,
+ caption="Select Output Folder")
+
+ QtGui.QGuiApplication.processEvents() # to close QFileDialog
+
+ if _export_folder:
+
+ o_gui = GuiUtility(parent=self.parent)
+ list_row_selected = o_gui.get_rows_of_table_selected(table_ui=self.parent.ui.bragg_edge_tableWidget)
+
+ for row_selected in list_row_selected:
+
+ # make up output file name
+ name_of_row = o_gui.get_table_str_item(table_ui=self.parent.ui.bragg_edge_tableWidget,
+ row=row_selected,
+ column=0)
+ [x0, y0, width, height] = name_of_row.split("; ")
+ name_of_row_formatted = "x0{}_y0{}_width{}_height{}".format(x0,y0, width, height)
+ file_name = "kropff_bragg_peak_profile_{}.txt".format(name_of_row_formatted)
+ full_file_name = str(Path(_export_folder) / Path(file_name))
+
+ o_fit = KropffFittingJobHandler(parent=self.parent)
+ o_fit.prepare(kropff_tooldbox='bragg_peak')
+
+ x_axis = o_fit.xaxis_to_fit
+ y_axis = o_fit.list_yaxis_to_fit[row_selected]
+
+ a0 = self.parent.fitting_input_dictionary['rois'][row_selected]['fitting']['kropff']['high']['a0']
+ b0 = self.parent.fitting_input_dictionary['rois'][row_selected]['fitting']['kropff']['high']['b0']
+ ahkl = self.parent.fitting_input_dictionary['rois'][row_selected]['fitting']['kropff']['low']['ahkl']
+ bhkl = self.parent.fitting_input_dictionary['rois'][row_selected]['fitting']['kropff']['low']['bhkl']
+
+ metadata = ["# Bragg peak fitting of row {}".format(row_selected+1)]
+ metadata.append("# x0: {}".format(x0))
+ metadata.append("# y0: {}".format(y0))
+ metadata.append("# width: {}".format(width))
+ metadata.append("# height: {}".format(height))
+ metadata.append("# a0: {}".format(a0))
+ metadata.append("# b0: {}".format(b0))
+ metadata.append("# ahkl: {}".format(ahkl))
+ metadata.append("# bhkl: {}".format(bhkl))
+ metadata.append("#")
+ metadata.append("# lambda (Angstroms), average transmission")
+
+ make_ascii_file_from_2dim_array(metadata=metadata,
+ col1=x_axis,
+ col2=y_axis,
+ output_file_name=full_file_name)
+
+ message = "Exported {} file(s) in {}".format(len(list_row_selected), _export_folder)
+ self.parent.ui.statusbar.showMessage(message, 15000) # 15s
+ self.parent.ui.statusbar.setStyleSheet("color: green")
+
+ def select_all_rows_with_negative_thkl(self):
+ # activate table
+ self.parent.ui.bragg_edge_tableWidget.setFocus()
+
+ # switch to multi selection mode
+ self.parent.ui.kropff_bragg_peak_multi_selection.setChecked(True)
+ self.parent.ui.bragg_edge_tableWidget.setSelectionMode(2)
+
+ list_of_rows_to_select = []
+ fitting_input_dictionary_rois = self.parent.fitting_input_dictionary['rois']
+ for _row in fitting_input_dictionary_rois.keys():
+ _thkl = np.float(fitting_input_dictionary_rois[_row]['fitting']['kropff']['bragg_peak']['ldahkl'])
+ if _thkl < 0:
+ list_of_rows_to_select.append(_row)
+
+ o_gui = GuiUtility(parent=self.parent)
+ o_gui.select_rows_of_table(table_ui=self.parent.ui.bragg_edge_tableWidget,
+ list_of_rows=list_of_rows_to_select)
+
+ def update_fitting_plot(self):
+ self.parent.ui.fitting.clear()
+ o_get = Get(parent=self.parent)
+ part_of_fitting_dict = o_get.part_of_fitting_selected()
+ name_of_page = part_of_fitting_dict['name_of_page']
+ table_ui = part_of_fitting_dict['table_ui']
+
+ o_table = TableHandler(table_ui=table_ui)
+ list_row_selected = o_table.get_rows_of_table_selected()
+ x_axis_selected = o_get.x_axis_checked()
+
+ if list_row_selected is None:
+ # first fitting tab where we only display the full data with bragg peak selection
+ if self.parent.fitting_peak_ui:
+ self.parent.ui.fitting.removeItem(self.parent.fitting_peak_ui)
+ xaxis_dict = self.parent.fitting_input_dictionary['xaxis']
+ xaxis_index, xaxis_label = xaxis_dict[x_axis_selected]
+ [left_xaxis_index, right_xaxis_index] = self.parent.bragg_edge_range
+ xaxis = xaxis_index[left_xaxis_index: right_xaxis_index]
+ selected_roi = self.parent.fitting_input_dictionary['rois'][0]
+ yaxis = selected_roi['profile']
+ yaxis = yaxis[left_xaxis_index: right_xaxis_index]
+ yaxis = -np.log(yaxis)
+ self.parent.ui.fitting.plot(xaxis, yaxis,
+ pen=(self.parent.selection_roi_rgb[0],
+ self.parent.selection_roi_rgb[1],
+ self.parent.selection_roi_rgb[2]),
+ symbol='o')
+ self.parent.ui.fitting.setLabel("bottom", xaxis_label)
+ peak_range_index = self.parent.kropff_fitting_range['bragg_peak']
+ if peak_range_index[0] is None:
+ peak_range = self.parent.bragg_edge_range
+ else:
+ peak_range = [xaxis[peak_range_index[0]], xaxis[peak_range_index[1]]]
+
+ if self.parent.fitting_peak_ui:
+ self.parent.ui.fitting.removeItem(self.parent.fitting_peak_ui)
+ self.parent.fitting_peak_ui = pg.LinearRegionItem(values=peak_range,
+ orientation=None,
+ brush=None,
+ movable=True,
+ bounds=None)
+ self.parent.fitting_peak_ui.sigRegionChanged.connect(self.parent.fitting_range_changed)
+ self.parent.fitting_peak_ui.setZValue(-10)
+ self.parent.ui.fitting.addItem(self.parent.fitting_peak_ui)
+
+ else:
+
+ for row_selected in list_row_selected:
+
+ selected_roi = self.parent.fitting_input_dictionary['rois'][row_selected]
+
+ xaxis_dict = self.parent.fitting_input_dictionary['xaxis']
+ [left_xaxis_index, right_xaxis_index] = self.parent.bragg_edge_range
+
+ yaxis = selected_roi['profile']
+ xaxis_index, xaxis_label = xaxis_dict[x_axis_selected]
+
+ xaxis = xaxis_index[left_xaxis_index: right_xaxis_index]
+ yaxis = yaxis[left_xaxis_index: right_xaxis_index]
+
+ self.parent.ui.fitting.setLabel("bottom", xaxis_label)
+ self.parent.ui.fitting.setLabel("left", 'Cross Section (arbitrary units)')
+ yaxis = -np.log(yaxis)
+ self.parent.ui.fitting.plot(xaxis, yaxis,
+ pen=(self.parent.selection_roi_rgb[0],
+ self.parent.selection_roi_rgb[1],
+ self.parent.selection_roi_rgb[2]),
+ symbol='o')
+
+ peak_range_index = self.parent.kropff_fitting_range[name_of_page]
+ if peak_range_index[0] is None:
+ peak_range = self.parent.bragg_edge_range
+ else:
+ peak_range = [xaxis[peak_range_index[0]], xaxis[peak_range_index[1]]]
+
+ if self.parent.fitting_peak_ui:
+ self.parent.ui.fitting.removeItem(self.parent.fitting_peak_ui)
+ self.parent.fitting_peak_ui = pg.LinearRegionItem(values=peak_range,
+ orientation=None,
+ brush=None,
+ movable=False,
+ bounds=None)
+ self.parent.fitting_peak_ui.sigRegionChanged.connect(self.parent.fitting_range_changed)
+ self.parent.fitting_peak_ui.setZValue(-10)
+ self.parent.ui.fitting.addItem(self.parent.fitting_peak_ui)
+
+ o_gui = GuiUtility(parent=self.parent)
+ algo_name = o_gui.get_tab_selected(self.parent.ui.tab_algorithm).lower()
+
+ if key_path_exists_in_dictionary(dictionary=self.parent.fitting_input_dictionary,
+ tree_key=['rois', row_selected, 'fitting', algo_name,
+ name_of_page, 'xaxis_to_fit']):
+
+ # show fit only if tof scale selected
+ if x_axis_selected == 'lambda':
+ _entry = self.parent.fitting_input_dictionary['rois'][row_selected]['fitting'][algo_name][name_of_page]
+ xaxis = _entry['xaxis_to_fit']
+ yaxis = _entry['yaxis_fitted']
+ yaxis = -np.log(yaxis)
+ self.parent.ui.fitting.plot(xaxis, yaxis,
+ pen=(self.parent.fit_rgb[0],
+ self.parent.fit_rgb[1],
+ self.parent.fit_rgb[2]))
+
+ if peak_range_index[0] is None:
+ self.parent.fitting_range_changed()
+
+ self.parent.ui.fitting.setLabel("left", "Cross Section (arbitrary Units)")
+
+ def update_roi_labels(self):
+ [global_left_range, global_right_range] = self.parent.bragg_edge_range
+ [left_range, right_range] = list(self.parent.fitting_peak_ui.getRegion())
+
+ o_get = Get(parent=self.parent)
+ x_axis_selected = o_get.x_axis_checked()
+ xaxis_dict = self.parent.fitting_input_dictionary['xaxis']
+ xaxis_index, _ = xaxis_dict[x_axis_selected]
+ [left_xaxis_index, right_xaxis_index] = [global_left_range, global_right_range]
+
+ xaxis = xaxis_index[left_xaxis_index: right_xaxis_index]
+
+ left_index = find_nearest_index(array=xaxis, value=left_range)
+ right_index = find_nearest_index(array=xaxis, value=right_range)
+
+ xaxis_in_selected_axis = self.parent.fitting_input_dictionary['xaxis'][x_axis_selected][0][
+ global_left_range: global_right_range]
+ real_left_value = xaxis_in_selected_axis[left_index]
+ real_right_value = xaxis_in_selected_axis[right_index]
+ if x_axis_selected == 'lambda':
+ str_format = "{:02f}"
+ elif x_axis_selected == 'tof':
+ str_format = "{:04.2f}"
+ else:
+ str_format = "{}"
+ real_left_value = str_format.format(real_left_value)
+ real_right_value = str_format.format(real_right_value)
+
+ units = Get.units(name=x_axis_selected)
+ self.parent.ui.bragg_peak_range_from_value.setText(str(real_left_value))
+ self.parent.ui.bragg_peak_range_to_value.setText(str(real_right_value))
+ self.parent.ui.from_bragg_peak_range_units.setText(units)
+ self.parent.ui.to_bragg_peak_range_units.setText(units)
\ No newline at end of file
diff --git a/notebooks/__code/kropff_fitting_job_handler.py b/notebooks/__code/kropff_fitting_job_handler.py
new file mode 100644
index 0000000..925b6b1
--- /dev/null
+++ b/notebooks/__code/kropff_fitting_job_handler.py
@@ -0,0 +1,188 @@
+from lmfit import Model, Parameter
+from copy import deepcopy
+import numpy as np
+
+from __code.bragg_edge.fitting_functions import kropff_high_lambda, kropff_low_lambda, kropff_bragg_peak_tof
+from __code.bragg_edge.bragg_edge_peak_fitting_gui_utility import GuiUtility
+
+
+class KropffFittingJobHandler:
+ """https://lmfit.github.io/lmfit-py/examples/example_Model_interface.html"""
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ self.xaxis_to_fit = None
+ self.list_yaxis_to_fit = None
+
+ def prepare(self, kropff_tooldbox='high'):
+ """
+ :param kropff_tooldbox: 'high', 'low', 'bragg_peak'
+ """
+ if kropff_tooldbox == 'bragg_peak':
+ fitting_range = [self.parent.kropff_fitting_range['low'][0],
+ self.parent.kropff_fitting_range['high'][1]]
+ else:
+ fitting_range = self.parent.kropff_fitting_range[kropff_tooldbox]
+
+ xaxis = self.parent.fitting_input_dictionary['xaxis']['lambda'][0]
+ [left_xaxis_index, right_xaxis_index] = self.parent.bragg_edge_range
+ full_fitting_xaxis = xaxis[left_xaxis_index: right_xaxis_index]
+ # self.xaxis_to_fit = full_fitting_xaxis[fitting_range[0]: fitting_range[1] + 1] * 1e-6 # to convert in s
+ self.xaxis_to_fit = full_fitting_xaxis[fitting_range[0]: fitting_range[1] + 1]
+
+ list_yaxis_to_fit = []
+ for _key in self.parent.fitting_input_dictionary['rois'].keys():
+ _yaxis = self.parent.fitting_input_dictionary['rois'][_key]['profile']
+ full_fitting_yaxis = _yaxis[left_xaxis_index: right_xaxis_index]
+ list_yaxis_to_fit.append(full_fitting_yaxis[fitting_range[0]: fitting_range[1] + 1])
+ self.list_yaxis_to_fit = list_yaxis_to_fit
+
+ def run_kropff_high_lambda(self, update_table_ui=False):
+ gmodel = Model(kropff_high_lambda, missing='drop', independent_vars=['lda'])
+
+ lda = self.xaxis_to_fit
+ o_gui = GuiUtility(parent=self.parent)
+
+ a0_init = np.float(str(self.parent.kropff_high_lda_a0_init.text()))
+ b0_init = np.float(str(self.parent.kropff_high_lda_b0_init.text()))
+ for _index, yaxis in enumerate(self.list_yaxis_to_fit):
+
+ yaxis = -np.log(yaxis)
+ _result = gmodel.fit(yaxis, lda=lda, a0=a0_init, b0=b0_init)
+ a0 = _result.params['a0'].value
+ a0_error = _result.params['a0'].stderr
+ b0 = _result.params['b0'].value
+ b0_error = _result.params['b0'].stderr
+
+ yaxis_fitted = kropff_high_lambda(self.xaxis_to_fit, a0, b0)
+
+ result_dict = {'a0': a0,
+ 'b0': b0,
+ 'a0_error': a0_error,
+ 'b0_error': b0_error,
+ 'xaxis_to_fit': lda,
+ 'yaxis_fitted': yaxis_fitted}
+
+ self.parent.fitting_input_dictionary['rois'][_index]['fitting']['kropff']['high'] = deepcopy(result_dict)
+
+ if update_table_ui:
+ o_gui.update_kropff_high_lambda_table_ui(row=_index,
+ a0=a0,
+ b0=b0,
+ a0_error=a0_error,
+ b0_error=b0_error)
+
+ def run_kropff_low_lambda(self, update_table_ui=False):
+ gmodel = Model(kropff_low_lambda, missing='drop', independent_vars=['lda'])
+
+ lda = self.xaxis_to_fit
+ o_gui = GuiUtility(parent=self.parent)
+
+ ahkl_init = np.float(str(self.parent.kropff_low_lda_ahkl_init.text()))
+ bhkl_init = np.float(str(self.parent.kropff_low_lda_bhkl_init.text()))
+
+ for _row, yaxis in enumerate(self.list_yaxis_to_fit):
+
+ _entry = self.parent.fitting_input_dictionary['rois'][_row]['fitting']['kropff']['high']
+ a0 = np.float(_entry['a0'])
+ b0 = np.float(_entry['b0'])
+
+ yaxis = -np.log(yaxis)
+ _result = gmodel.fit(yaxis, lda=lda,
+ a0=Parameter('a0', value=a0, vary=False),
+ b0=Parameter('b0', value=b0, vary=False),
+ ahkl=ahkl_init,
+ bhkl=bhkl_init)
+
+ ahkl = _result.params['ahkl'].value
+ ahkl_error = _result.params['ahkl'].stderr
+ bhkl = _result.params['bhkl'].value
+ bhkl_error = _result.params['bhkl'].stderr
+
+ yaxis_fitted = kropff_low_lambda(lda,
+ a0, b0, ahkl, bhkl)
+
+ result_dict = {'ahkl': ahkl,
+ 'bhkl': bhkl,
+ 'ahkl_error': ahkl_error,
+ 'bhkl_error': bhkl_error,
+ 'xaxis_to_fit': lda,
+ 'yaxis_fitted': yaxis_fitted}
+
+ self.parent.fitting_input_dictionary['rois'][_row]['fitting']['kropff']['low'] = deepcopy(result_dict)
+
+ if update_table_ui:
+ o_gui.update_kropff_low_lambda_table_ui(row=_row,
+ ahkl=ahkl,
+ bhkl=bhkl,
+ ahkl_error=ahkl_error,
+ bhkl_error=bhkl_error)
+
+ def run_bragg_peak(self, update_table_ui=False, list_row_to_fit=None):
+ gmodel = Model(kropff_bragg_peak_tof, nan_policy='propagate', independent_vars=['lda'])
+
+ lda = self.xaxis_to_fit
+ o_gui = GuiUtility(parent=self.parent)
+
+ ldahkl_init = np.float(str(self.parent.ui.kropff_bragg_peak_ldahkl_init.text()))
+ tau_init = np.float(str(self.parent.kropff_bragg_peak_tau_init.text()))
+ sigma_init = np.float(self.parent.kropff_bragg_peak_sigma_comboBox.currentText())
+
+ for _row, yaxis in enumerate(self.list_yaxis_to_fit):
+
+ if not list_row_to_fit is None:
+ if _row not in list_row_to_fit:
+ continue
+
+ _entry_high = self.parent.fitting_input_dictionary['rois'][_row]['fitting']['kropff']['high']
+ a0 = np.float(_entry_high['a0'])
+ b0 = np.float(_entry_high['b0'])
+
+ _entry_low = self.parent.fitting_input_dictionary['rois'][_row]['fitting']['kropff']['low']
+ ahkl = np.float(_entry_low['ahkl'])
+ bhkl = np.float(_entry_low['bhkl'])
+
+ yaxis = -np.log(yaxis)
+
+ _result = gmodel.fit(yaxis,
+ lda=lda,
+ a0=Parameter('a0', value=a0, vary=False),
+ b0=Parameter('b0', value=b0, vary=False),
+ ahkl=Parameter('ahkl', value=ahkl, vary=False),
+ bhkl=Parameter('bhkl', value=bhkl, vary=False),
+ ldahkl=ldahkl_init,
+ sigma=sigma_init,
+ tau=tau_init)
+
+ ldahkl = _result.params['ldahkl'].value
+ ldahkl_error = _result.params['ldahkl'].stderr
+ sigma = _result.params['sigma'].value
+ sigma_error = _result.params['sigma'].stderr
+ tau = _result.params['tau'].value
+ tau_error = _result.params['tau'].stderr
+
+ yaxis_fitted = kropff_bragg_peak_tof(self.xaxis_to_fit,
+ a0, b0, ahkl, bhkl,
+ ldahkl, sigma, tau)
+
+ result_dict = {'ldahkl': ldahkl,
+ 'ldahkl_error': ldahkl_error,
+ 'sigma': sigma,
+ 'sigma_error': sigma_error,
+ 'tau': tau,
+ 'tau_error': tau_error,
+ 'xaxis_to_fit': lda,
+ 'yaxis_fitted': yaxis_fitted}
+
+ self.parent.fitting_input_dictionary['rois'][_row]['fitting']['kropff']['bragg_peak'] = deepcopy(
+ result_dict)
+
+ if update_table_ui:
+ o_gui.update_kropff_bragg_edge_table_ui(row=_row,
+ ldahkl=ldahkl,
+ ldahkl_error=ldahkl_error,
+ tau=tau,
+ tau_error=tau_error,
+ sigma=sigma,
+ sigma_error=sigma_error)
diff --git a/notebooks/__code/peak_fitting_initialization.py b/notebooks/__code/peak_fitting_initialization.py
new file mode 100644
index 0000000..3876664
--- /dev/null
+++ b/notebooks/__code/peak_fitting_initialization.py
@@ -0,0 +1,65 @@
+import numpy as np
+from copy import deepcopy
+
+KROPFF_HIGH = {'a0': None, 'b0': None,
+ 'a0_error': None, 'b0_error': None,
+ 'xaxis_to_fit': None,
+ 'yaxis_fitted': None}
+KROPFF_LOW = {'ahkl': None, 'bhkl': None,
+ 'ahkl_error': None, 'bhkl_error': None,
+ 'xaxis_to_fit': None,
+ 'yaxis_fitted': None}
+KROPFF_BRAGG_PEAK = {'ldahkl': None,
+ 'ldahkl_error': None,
+ 'tau': None,
+ 'tau_error': None,
+ 'sigma': None,
+ 'sigma_error': None}
+MARCHE_DOLLASE = {'d_spacing': None,
+ 'd_spacing_error': None,
+ 'alpha': None,
+ 'alpha_error': None,
+ 'sigma': None,
+ 'sigma_error': None,
+ 'a1': None,
+ 'a1_error': None,
+ 'a2': None,
+ 'a2_error': None,
+ 'a5': None,
+ 'a5_error': None,
+ 'a6': None,
+ 'a6_error': None,
+ }
+
+
+class PeakFittingInitialization:
+
+ def __init__(self, parent=None):
+ self.parent = parent
+
+ def fitting_input_dictionary(self, nbr_rois=0):
+
+ fitting_input_dictionary = {'xaxis': {},
+ 'rois': {},
+ 'fit_infos': {}}
+
+ for _roi_index in np.arange(nbr_rois):
+ _roi_dict = {'x0': None, 'y0': None,
+ 'width': None, 'height': None,
+ 'profile': None,
+ 'bragg_edge_range': None, # bragg peak range selected in first tab
+ 'fitting': {'kropff': {'high': deepcopy(KROPFF_HIGH),
+ 'low': deepcopy(KROPFF_LOW),
+ 'bragg_peak': deepcopy(KROPFF_BRAGG_PEAK),
+ },
+ 'march_dollase': deepcopy(MARCHE_DOLLASE),
+ },
+ }
+ fitting_input_dictionary['rois'][_roi_index] = deepcopy(_roi_dict)
+
+ return fitting_input_dictionary
+
+ def set_top_keys_values(self, dictionary=None, new_keys_values=None):
+ for _key in new_keys_values.keys():
+ _value = new_keys_values[_key]
+ dictionary[_key] = _value
diff --git a/notebooks/__code/peak_fitting_interface_initialization.py b/notebooks/__code/peak_fitting_interface_initialization.py
new file mode 100644
index 0000000..99167bc
--- /dev/null
+++ b/notebooks/__code/peak_fitting_interface_initialization.py
@@ -0,0 +1,274 @@
+import numpy as np
+import matplotlib
+import os
+import copy
+matplotlib.use('Qt5Agg')
+
+from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
+
+from qtpy.QtWidgets import QProgressBar, QVBoxLayout
+from qtpy import QtGui
+import pyqtgraph as pg
+
+from __code.table_handler import TableHandler
+from __code.bragg_edge.mplcanvas import MplCanvas
+from __code.bragg_edge.bragg_edge_peak_fitting_gui_utility import GuiUtility
+
+
+class Initialization:
+
+ distance_detector_sample = 1300 # m
+ detector_offset = 6500 # micros
+
+ march_dollase_history_state = list()
+ march_dollase_history_init = [np.NaN, np.NaN]
+ march_dollase_history_state.append([False, False, False, True, False, False, True])
+ march_dollase_history_state.append([False, False, False, False, True, True, False])
+ march_dollase_history_state.append([True, True, True, False, False, False, False])
+ march_dollase_history_state.append([False, False, False, True, True, True, True])
+ march_dollase_history_state.append([True, True, True, False, False, False, False])
+ march_dollase_history_state.append([True, True, True, True, True, True, True])
+
+ def __init__(self, parent=None, tab='all'):
+ self.parent = parent
+
+ self.block_signals(True)
+ self.pyqtgraph_image_view()
+ self.pyqtgraph_profile()
+ self.matplotlib()
+
+ if tab == 'all':
+ self.normalize_images_by_white_beam()
+ self.save_image_size()
+ self.roi_setup()
+ self.widgets()
+
+ self.labels()
+ self.text_fields()
+ self.statusbar()
+ self.pyqtgraph_fitting()
+ self.kropff_fitting_table()
+ self.march_dollase()
+
+ self.block_signals(False)
+
+ def normalize_images_by_white_beam(self):
+ white_beam_ob = self.parent.o_bragg.white_beam_ob
+ list_data = self.parent.o_norm.data['sample']['data']
+ for _index_data, _data in enumerate(list_data):
+ normalized_data = _data / white_beam_ob
+ self.parent.o_norm.data['sample']['data'][_index_data] = normalized_data
+
+ def block_signals(self, flag):
+ list_ui = [self.parent.ui.profile_of_bin_size_slider]
+ for _ui in list_ui:
+ _ui.blockSignals(flag)
+
+ def save_image_size(self):
+ _image = self.parent.get_live_image()
+ [height, width] = np.shape(_image)
+ self.parent.image_size['width'] = width
+ self.parent.image_size['height'] = height
+
+ def statusbar(self):
+ self.parent.eventProgress = QProgressBar(self.parent.ui.statusbar)
+ self.parent.eventProgress.setMinimumSize(20, 14)
+ self.parent.eventProgress.setMaximumSize(540, 100)
+ self.parent.eventProgress.setVisible(False)
+ self.parent.ui.statusbar.addPermanentWidget(self.parent.eventProgress)
+
+ def pyqtgraph_image_view(self):
+ # image view
+ self.parent.ui.image_view = pg.ImageView()
+ self.parent.ui.image_view.ui.roiBtn.hide()
+ self.parent.ui.image_view.ui.menuBtn.hide()
+ image_layout = QVBoxLayout()
+ image_layout.addWidget(self.parent.ui.image_view)
+ self.parent.ui.image_widget.setLayout(image_layout)
+
+ def pyqtgraph_profile(self):
+ # profile view
+ self.parent.ui.profile = pg.PlotWidget(title="Profile of ROI selected")
+ profile_layout = QVBoxLayout()
+ profile_layout.addWidget(self.parent.ui.profile)
+ self.parent.ui.profile_widget.setLayout(profile_layout)
+
+ def matplotlib(self):
+
+ def _matplotlib(parent=None, widget=None):
+ sc = MplCanvas(parent, width=5, height=4, dpi=100)
+ # sc.axes.plot([0,1,2,3,4,5], [10, 1, 20 ,3, 40, 50])
+ toolbar = NavigationToolbar(sc, parent)
+ layout = QVBoxLayout()
+ layout.addWidget(toolbar)
+ layout.addWidget(sc)
+ widget.setLayout(layout)
+ return sc
+
+ self.parent.kropff_high_plot = _matplotlib(parent=self.parent,
+ widget=self.parent.ui.high_widget)
+ self.parent.kropff_low_plot = _matplotlib(parent=self.parent,
+ widget=self.parent.ui.low_widget)
+ self.parent.kropff_bragg_peak_plot = _matplotlib(parent=self.parent,
+ widget=self.parent.ui.bragg_peak_widget)
+
+ self.parent.march_dollase_plot = _matplotlib(parent=self.parent,
+ widget=self.parent.ui.march_dollase_graph_widget)
+
+ def pyqtgraph_fitting(self):
+ # fitting view
+ self.parent.ui.fitting = pg.PlotWidget(title="Fitting")
+ fitting_layout = QVBoxLayout()
+ fitting_layout.addWidget(self.parent.ui.fitting)
+ self.parent.ui.fitting_widget.setLayout(fitting_layout)
+
+ def kropff_fitting_table(self):
+ ## Kropff
+ # high lambda
+ column_names = [u'x\u2080; y\u2080; width; height', u'a\u2080', u'b\u2080', u'a\u2080_error',
+ u'b\u2080_error']
+ column_sizes = [150, 100, 100, 100, 100]
+ o_high = TableHandler(table_ui=self.parent.ui.high_lda_tableWidget)
+ for _col_index, _col_name in enumerate(column_names):
+ o_high.insert_column(_col_index)
+ o_high.set_column_names(column_names=column_names)
+ o_high.set_column_sizes(column_sizes=column_sizes)
+
+ # low lambda
+ column_names = [u'x\u2080; y\u2080; width; height',
+ u'a_hkl', u'b_hkl',
+ u'a_hkl_error',
+ u'b_hkl_error']
+ column_sizes = [150, 100, 100, 100, 100]
+ o_low = TableHandler(table_ui=self.parent.ui.low_lda_tableWidget)
+ for _col_index, _col_name in enumerate(column_names):
+ o_low.insert_column(_col_index)
+ o_low.set_column_names(column_names=column_names)
+ o_low.set_column_sizes(column_sizes=column_sizes)
+
+ # bragg edge
+ column_names = ['x0; y0; width; height', 't_hkl', 'tau', 'sigma',
+ 't_hkl_error', 'tau_error', 'sigma_error']
+ column_sizes = [150, 100, 100, 100, 100, 100, 100]
+ o_bragg = TableHandler(table_ui=self.parent.ui.bragg_edge_tableWidget)
+ for _col_index, _col_name in enumerate(column_names):
+ o_bragg.insert_column(_col_index)
+ o_bragg.set_column_names(column_names=column_names)
+ o_bragg.set_column_sizes(column_sizes=column_sizes)
+
+ def march_dollase(self):
+
+ self.parent.march_dollase_history_state_full_reset = copy.deepcopy(self.march_dollase_history_state)
+
+ # init widgets
+ _file_path = os.path.dirname(__file__)
+ up_arrow_file = os.path.abspath(os.path.join(_file_path, '../static/up_arrow_black.png'))
+ self.parent.ui.march_dollase_user_input_up.setIcon(QtGui.QIcon(up_arrow_file))
+
+ down_arrow_file = os.path.abspath(os.path.join(_file_path, '../static/down_arrow_black.png'))
+ self.parent.ui.march_dollase_user_input_down.setIcon(QtGui.QIcon(down_arrow_file))
+
+ o_gui = GuiUtility(parent=self.parent)
+ o_gui.fill_march_dollase_table(list_state=self.march_dollase_history_state,
+ initial_parameters=self.parent.march_dollase_fitting_initial_parameters)
+
+ self.parent.march_dollase_fitting_history_table = self.march_dollase_history_state
+ self.parent.march_dollase_fitting_history_table_default_new_row = copy.deepcopy(
+ self.march_dollase_history_state[0])
+
+ column_names = [u'x\u2080; y\u2080; width; height',
+ u'd_spacing', u'sigma', u'alpha',
+ u'A\u2081', u'A\u2082',
+ u'A\u2085', u'A\u2086',
+ u'd_spacing_error', u'sigma_error', u'alpha_error',
+ u'A\u2081_error',
+ u'A\u2082_error',
+ u'A\u2085_error', u'A\u2086_error',
+ ]
+ column_sizes = [150, 100, 100, 100, 100, 100, 100, 100,
+ 100, 100, 100, 100, 100, 100, 100]
+ o_march = TableHandler(table_ui=self.parent.ui.march_dollase_result_table)
+ for _col_index, _col_name in enumerate(column_names):
+ o_march.insert_column(_col_index)
+ o_march.set_column_names(column_names=column_names)
+ o_march.set_column_sizes(column_sizes=column_sizes)
+
+ state_advanced_columns = not self.parent.ui.march_dollase_advanced_mode_checkBox.isChecked()
+ o_gui.set_columns_hidden(table_ui=self.parent.ui.march_dollase_user_input_table,
+ list_of_columns=[5, 6],
+ state=state_advanced_columns)
+
+ # table
+ self.parent.ui.march_dollase_user_input_table.verticalHeader().setVisible(True)
+ self.parent.ui.march_dollase_result_table.verticalHeader().setVisible(True)
+ self.parent.ui.march_dollase_result_table.horizontalHeader().setVisible(True)
+
+ def labels(self):
+ # labels
+ self.parent.ui.detector_offset_units.setText(u"\u03BCs")
+ self.parent.ui.selection_tof_radiobutton.setText(u"TOF (\u03BCs)")
+ self.parent.ui.fitting_tof_radiobutton.setText(u"TOF (\u03BCs)")
+ self.parent.ui.selection_lambda_radiobutton.setText(u"\u03BB (\u212B)")
+ self.parent.ui.fitting_lambda_radiobutton.setText(u"\u03BB (\u212B)")
+
+ def text_fields(self):
+ self.parent.ui.distance_detector_sample.setText(str(self.distance_detector_sample))
+ self.parent.ui.detector_offset.setText(str(self.detector_offset))
+
+ self.parent.ui.kropff_high_lda_a0_init.setText(str(self.parent.fitting_parameters_init['kropff']['a0']))
+ self.parent.ui.kropff_high_lda_b0_init.setText(str(self.parent.fitting_parameters_init['kropff']['b0']))
+ self.parent.ui.kropff_low_lda_ahkl_init.setText(str(self.parent.fitting_parameters_init['kropff']['ahkl']))
+ self.parent.ui.kropff_low_lda_bhkl_init.setText(str(self.parent.fitting_parameters_init['kropff']['bhkl']))
+ self.parent.ui.kropff_bragg_peak_ldahkl_init.setText(str(self.parent.fitting_parameters_init['kropff'][
+ 'ldahkl']))
+ self.parent.ui.kropff_bragg_peak_tau_init.setText(str(self.parent.fitting_parameters_init['kropff']['tau']))
+ # list_sigma = self.parent.fitting_parameters_init['kropff']['sigma']
+ # list_sigma = [str(_value) for _value in list_sigma]
+ # str_list_sigma = ", ".join(list_sigma)
+ # self.parent.ui.kropff_bragg_peak_sigma_init.setText(str_list_sigma)
+
+ kropff_list_sigma = self.parent.fitting_parameters_init['kropff']['sigma']
+ str_kropff_list_sigma = [str(value) for value in kropff_list_sigma]
+ self.parent.ui.kropff_bragg_peak_sigma_comboBox.addItems(str_kropff_list_sigma)
+
+ def widgets(self):
+ self.parent.ui.splitter.setSizes([500, 400])
+
+ self.parent.ui.roi_size_slider.setMinimum(1)
+ max_value = np.min([self.parent.image_size['width'], self.parent.image_size['height']])
+ self.parent.ui.roi_size_slider.setMaximum(max_value)
+ default_roi_size = np.int(max_value/3)
+ self.parent.ui.roi_size_slider.setValue(default_roi_size)
+ self.parent.ui.roi_width.setText(str(default_roi_size))
+ self.parent.ui.roi_height.setText(str(default_roi_size))
+ self.parent.ui.profile_of_bin_size_width.setText(str(default_roi_size))
+ self.parent.ui.profile_of_bin_size_height.setText(str(default_roi_size))
+ self.parent.ui.profile_of_bin_size_slider.setMaximum(default_roi_size)
+ self.parent.ui.profile_of_bin_size_slider.setValue(default_roi_size)
+
+ def roi_setup(self):
+ [x0, y0] = self.parent.roi_settings['position']
+ self.parent.selection_x0y0 = [x0, y0]
+ width = self.parent.ui.roi_size_slider.value()
+ self.parent.previous_roi_selection['width'] = width
+ self.parent.previous_roi_selection['height'] = width
+ _pen = QtGui.QPen()
+ _pen.setColor(self.parent.roi_settings['color'])
+ _pen.setWidth(self.parent.roi_settings['width'])
+ self.parent.roi_id = pg.ROI([x0, y0],
+ [width, width],
+ pen=_pen,
+ scaleSnap=True)
+ self.parent.ui.image_view.addItem(self.parent.roi_id)
+ self.parent.roi_id.sigRegionChanged.connect(self.parent.roi_moved)
+
+ def display(self, image=None):
+ self.parent.live_image = image
+ _image = np.transpose(image)
+ _image = self._clean_image(_image)
+ self.parent.ui.image_view.setImage(_image)
+
+ def _clean_image(self, image):
+ _result_inf = np.where(np.isinf(image))
+ image[_result_inf] = np.NaN
+ return image
diff --git a/notebooks/__code/table_handler.py b/notebooks/__code/table_handler.py
new file mode 100644
index 0000000..ef5b67c
--- /dev/null
+++ b/notebooks/__code/table_handler.py
@@ -0,0 +1,138 @@
+import numpy as np
+from qtpy import QtGui
+
+class TableHandler:
+
+ cell_str_format = "{:.3f}"
+ cell_str_format = "{}"
+
+ def __init__(self, table_ui=None):
+ self.table_ui = table_ui
+
+ def select_everything(self, state):
+ nbr_row = self.table_ui.rowCount()
+ nbr_column = self.table_ui.columnCount()
+ selection_range = QtGui.QTableWidgetSelectionRange(0, 0, nbr_row-1, nbr_column-1)
+ self.table_ui.setRangeSelected(selection_range, state)
+
+ def select_rows(self, list_of_rows=None):
+ self.select_everything(False)
+ nbr_row = self.table_ui.rowCount()
+ nbr_column = self.table_ui.columnCount()
+
+ for _row in list_of_rows:
+ selection_range = QtGui.QTableWidgetSelectionRange(_row, 0, _row, nbr_column - 1)
+ self.table_ui.setRangeSelected(selection_range, True)
+
+ def remove_all_rows(self):
+ nbr_row = self.table_ui.rowCount()
+ for _ in np.arange(nbr_row):
+ self.table_ui.removeRow(0)
+
+ def remove_all_columns(self):
+ nbr_column = self.table_ui.columnCount()
+ for _ in np.arange(nbr_column):
+ self.table_ui.removeColumn(0)
+
+ def full_reset(self):
+ self.remove_all_rows()
+ self.remove_all_columns()
+
+ def get_rows_of_table_selected(self):
+ if self.table_ui is None:
+ return None
+
+ selected_ranges = self.table_ui.selectedRanges()
+ if selected_ranges == []:
+ return None
+
+ list_row_selected = []
+ for _selection in selected_ranges:
+ top_row = _selection.topRow()
+ bottom_row = _selection.bottomRow()
+ if top_row == bottom_row:
+ list_row_selected.append(top_row)
+ else:
+ _range = np.arange(top_row, bottom_row + 1)
+ for _row in _range:
+ list_row_selected.append(_row)
+
+ return list_row_selected
+
+ def get_row_selected(self):
+ if self.table_ui is None:
+ return -1
+ list_selection = self.table_ui.selectedRanges()
+ try:
+ first_selection = list_selection[0]
+ except IndexError:
+ return -1
+ return first_selection.topRow()
+
+ def get_cell_selected(self):
+ list_selection = self.table_ui.selectedRanges()
+ first_selection = list_selection[0]
+ row = first_selection.topRow()
+ col = first_selection.leftColumn()
+ return (row, col)
+
+ def select_cell(self, row=0, column=0):
+ self.select_everything(False)
+ range_selected = QtGui.QTableWidgetSelectionRange(row, column, row, column)
+ self.table_ui.setRangeSelected(range_selected, True)
+
+ def select_row(self, row=0):
+ if row < 0:
+ row = 0
+ self.table_ui.selectRow(row)
+
+ def set_column_names(self, column_names=None):
+ self.table_ui.setHorizontalHeaderLabels(column_names)
+
+ def set_row_names(self, row_names=None):
+ self.table_ui.setVerticalHeaderLabels(row_names)
+
+ def set_column_sizes(self, column_sizes=None):
+ for _col, _size in enumerate(column_sizes):
+ self.table_ui.setColumnWidth(_col, _size)
+
+ def insert_empty_row(self, row=0):
+ self.table_ui.insertRow(row)
+
+ def insert_row(self, row=0, list_col_name=None):
+ """row is the row number
+ """
+ self.table_ui.insertRow(row)
+ for column, _text in enumerate(list_col_name):
+ _item = QtGui.QTableWidgetItem(_text)
+ self.table_ui.setItem(row, column, _item)
+
+ def insert_column(self, column):
+ self.table_ui.insertColumn(column)
+
+ def insert_empty_column(self, column):
+ self.table_ui.insertColumn(column)
+
+ def set_item_with_float(self, row=0, column=0, float_value=""):
+ if (str(float_value) == 'None') or (str(float_value) == 'N/A'):
+ _str_value = "N/A"
+ else:
+ _str_value = self.cell_str_format.format(np.float(float_value))
+ self.table_ui.item(row, column).setText(_str_value)
+
+ def insert_item_with_float(self, row=0, column=0, float_value="", format_str="{}"):
+ if (str(float_value) == 'None') or (str(float_value) == 'N/A'):
+ _str_value = "N/A"
+ else:
+ _str_value = format_str.format(np.float(float_value))
+ _item = QtGui.QTableWidgetItem(_str_value)
+ self.table_ui.setItem(row, column, _item)
+
+ def insert_item(self, row=0, column=0, value="", format_str="{}"):
+ _str_value = format_str.format(value)
+ _item = QtGui.QTableWidgetItem(_str_value)
+ self.table_ui.setItem(row, column, _item)
+
+ def set_background_color(self, row=0, column=0, qcolor=QtGui.QColor(0, 255, 255)):
+ _item = self.table_ui.item(row, column)
+ _item.setBackground(qcolor)
diff --git a/notebooks/__code/utilities.py b/notebooks/__code/utilities.py
new file mode 100644
index 0000000..ac2be54
--- /dev/null
+++ b/notebooks/__code/utilities.py
@@ -0,0 +1,387 @@
+import numpy as np
+import os
+import re
+import shutil
+from configparser import RawConfigParser
+#import glob
+import itertools
+from shutil import copyfile
+
+#from ipywidgets.widgets import interact
+from ipywidgets import widgets
+from IPython.core.display import display, HTML
+
+
+def calculate_file_temperature(left_T=-1, right_T=-1, left_time=-1, right_time=-1, file_time = -1):
+ coeff = (float(right_T) - float(left_T)) / (float(right_time) - float(left_time))
+ part1 = coeff * (float(file_time) - float(left_time))
+ return part1 + float(left_T)
+
+
+def get_first_temperature_and_index_value(index=-1, data_array=[], direction='left'):
+ if direction == 'left':
+ coeff = -1
+ else:
+ coeff = 1
+
+ while (np.isnan(data_array[index])):
+ index += coeff
+ return [data_array[index], index]
+
+
+def extract_temperature(index=-1, temperature_array=[], time_stamp_array=[]):
+
+ [left_T, left_index] = get_first_temperature_and_index_value(index=index, data_array=temperature_array, direction='left')
+ [right_T, right_index] = get_first_temperature_and_index_value(index=index, data_array=temperature_array, direction='right')
+
+ left_time = time_stamp_array[left_index]
+ right_time = time_stamp_array[right_index]
+
+ file_time = time_stamp_array[index]
+
+ file_temperature = calculate_file_temperature(left_T = left_T, right_T = right_T,
+ left_time = left_time, right_time = right_time,
+ file_time = file_time)
+
+ return file_temperature
+
+
+def retrieve_T_from_file_vs_temperature_array(file_name='', file_array=[], temperature_array=[]):
+ index = file_array.index(file_name)
+ return temperature_array[index]
+
+
+def make_output_file_name(bin_number=-1, index=-1, algorithm='mean'):
+ '''
+ takes the bin number and the algorithm name to create the output file name
+
+ Paramters:
+ * bin_number: index of bin
+ * index: index of file in folder
+ * algorithm: (optional) default value 'mean'. Name of algorithm used to bin data
+ will be used in the new output file name
+
+ Return:
+ * string file name of the output file
+
+ Example:
+ bin_number = 3
+ index = 2
+ algorithm = "mean"
+
+ will return 'bin#3_0002_mean.fits
+
+ '''
+
+ ext = '.fits'
+ list_output_file_name = []
+ _output_file_name = "bin#{:03d}_{:04d}_{}.fits".format(bin_number, index, algorithm)
+ return _output_file_name
+
+
+def keep_folder_name(image):
+ image_array = image.split('_')
+ return image_array[0]
+
+
+def is_extension(filename='', ext='.fits'):
+ _ext = os.path.splitext(filename)[1]
+ if _ext == ext:
+ return True
+ else:
+ return False
+
+
+def index_first_boolean(result, boolean=True):
+ for _index, _value in enumerate(result):
+ if _value == boolean:
+ return _index
+
+
+def index_last_boolean(result, boolean=True):
+ for _index, _value in reversed(list(enumerate(result))):
+ if _value == boolean:
+ return _index
+
+
+def find_index_of_value_in_array(array=[], value=-1, index_type='le'):
+ '''
+ index_type is either 'le' or 'ge'
+ '''
+ if index_type == 'le':
+ result = x_axis < value
+ return index_first_boolean(result, False)
+ else:
+ result = x_axis > value
+ return index_last_boolean(result, False)
+
+
+def make_user_friendly_list_of_bins(full_list_of_bins):
+ return [os.path.basename(_file) for _file in full_list_of_bins]
+
+
+def get_ipts():
+ current_folder = os.getcwd()
+ parent_folder = os.path.basename(current_folder)
+
+ result = re.search('IPTS_(\d+)', parent_folder)
+ if result:
+ ipts = result.group(1)
+ else:
+ ipts = ''
+
+ return ipts
+
+
+def get_working_dir(ipts='', debugging=False):
+ '''
+ if there is an ipts argument passed in, the working dir will be '/HFIR/CG1DImaging/IPTS-{}'.format(ipts)
+ if ipts is empty: program will look if there is a 'working_dir' argument in the 'main_session' of the config file
+ '~/.notebooks_config.cfg', otherwise will return the current folder location
+ '''
+ if ipts:
+ if debugging:
+ _path = '/Volumes/my_book_thunderbolt_duo/IPTS/IPTS_{}'.format(ipts)
+ else:
+ _path = '/HFIR/CG1DImaging/IPTS-{}/'.format(ipts)
+ print(_path)
+ if os.path.exists(_path):
+ return _path
+
+ config_path = os.path.join(os.path.expanduser('~/'), '.notebooks_config.cfg')
+ if os.path.exists(config_path):
+ parser = RawConfigParser()
+ parser.read(config_path)
+ try:
+ working_dir = parser.get('main_session', 'working_dir')
+ except:
+ working_dir = './'
+ else:
+ working_dir = './'
+
+ return working_dir
+
+
+def make_dir(dir='', overwrite=True):
+ if dir== '':
+ return
+
+ if overwrite:
+ if os.path.exists(dir):
+ shutil.rmtree(dir)
+ os.mkdir(dir)
+ else:
+ if not (os.path.exists(dir)):
+ os.mkdir(dir)
+
+
+def format_file_index(filename='', number_of_digits=4):
+ '''
+ This function take a file name that may look like this /Users/my_user/folder/description_1.tif
+ and will format it to make sure the prefix has a fix number of digit. If number of digit is 4,
+ the file name will be now /Users/my_user/folder/description_0001.tif
+
+ Parameters:
+ ===========
+ filename: string. name of file
+ number_of_digits: default is 4. int. number of digit to add to number at the end
+
+ Returns:
+ ========
+ new file name formatted
+ '''
+ _basename = os.path.basename(filename)
+ [_base, _ext] = os.path.splitext(_basename)
+ _base_slitted = _base.split('_')
+ _number = np.int(_base_slitted[-1])
+
+ return ''
+
+
+def get_n_random_element(input_list=[], n=1):
+ '''
+ will return a list of n element taken from the input array called input_list
+ '''
+ n_random = np.random.randint(0, len(input_list)-1, n)
+ new_list = [input_list[_index] for _index in n_random]
+ return new_list
+
+
+def rename_files(dict_old_new_names={}, new_output_folder=''):
+ make_dir(dir=new_output_folder)
+
+ nbr_files = len(dict_old_new_names.keys())
+ w1 = widgets.IntProgress()
+ w1.max = nbr_files
+ display(w1)
+
+ # create new images
+ for _index, _old_name in enumerate(dict_old_new_names.keys()):
+ _new_name = os.path.join(new_output_folder, dict_old_new_names[_old_name])
+ os.rename(_old_name, _new_name)
+ w1.value = _index + 1
+
+
+def copy_files(dict_old_new_names={}, new_output_folder='', overwrite=True):
+ make_dir(dir=new_output_folder, overwrite=overwrite)
+
+ nbr_files = len(dict_old_new_names.keys())
+ w1 = widgets.IntProgress()
+ w1.max = nbr_files
+ display(w1)
+
+ # create new images
+ for _index, _old_name in enumerate(dict_old_new_names.keys()):
+ _new_name = os.path.join(new_output_folder, dict_old_new_names[_old_name])
+ copyfile(_old_name, _new_name)
+ w1.value = _index + 1
+
+
+def display_html_message(*, title_message='', message='', message_type='info'):
+
+ if message_type == 'info':
+ line_color = 'blue'
+ message_color = 'black'
+
+ elif message_type == 'error':
+ line_color = 'red'
+ message_color = 'red'
+
+ elif message_type == 'ok':
+ line_color = 'green'
+ message_color = 'black'
+
+ else:
+ line_color = 'black'
+ message_color = 'black'
+
+ display(HTML('{} '.format(line_color,
+ title_message) +
+ ' '.format(message_color) +
+ message + ''))
+
+def find_nearest_index(array, value):
+ idx = (np.abs(np.array(array) - value)).argmin()
+ return idx
+
+
+class ListRunsParser(object):
+ """
+ will clean up the current_list_of_runs with the new added runs
+ ex: [1,2,3,4,7] -> 1:4,7
+ if a new run is already in the list of runs, it will then be removed from the list
+ ex: [1,2,3,4] with new run [1] -> 2:4
+ """
+
+ list_current_runs = [] # ['1','10','2','30','4']
+ int_list_current_runs = [] # [1, 2, 4, 10, 30]
+
+ def __init__(self, current_runs=''):
+ if current_runs:
+ self.make_discrete_list_of_runs(str_current_runs=current_runs)
+
+ def make_discrete_list_of_runs(self, str_current_runs=''):
+ spans = (el.partition(':')[::2] for el in str_current_runs.split(','))
+ ranges = (np.arange(int(s), int(e) + 1 if e else int(s) + 1)
+ for s, e in spans)
+ try:
+ all_nums = itertools.chain.from_iterable(ranges)
+ _all_nums = set(all_nums)
+ except ValueError:
+ raise ValueError("Check format of input")
+ self.list_current_runs = [str(_run) for _run in _all_nums]
+
+ def new_runs(self, list_runs=[]):
+ """add new runs, remove already existing ones"""
+
+ # find list of runs to remove
+ list_runs = set(list_runs)
+ _list_runs_to_remove = set(list_runs.intersection(self.list_current_runs))
+
+ # remove the runs from list_runs and list_current_runs
+ clean_list_runs = list(list_runs - _list_runs_to_remove)
+ clean_list_current_runs = list(set(self.list_current_runs) - _list_runs_to_remove)
+
+ new_list_current_runs = clean_list_runs + clean_list_current_runs
+ self.list_current_runs = new_list_current_runs
+
+ # go from string to int
+ int_new_list_current_runs = [np.int(_run) for _run in new_list_current_runs]
+
+ # sort them to prepare them for output format
+ int_new_list_current_runs.sort()
+ self.int_list_current_runs = int_new_list_current_runs
+
+ if int_new_list_current_runs == []:
+ self.str_list_current_runs = ""
+ return
+
+ # create output string format
+
+ # only 1 run
+ if len(int_new_list_current_runs) == 1:
+ self.str_list_current_runs = str(int_new_list_current_runs[0])
+ return str(int_new_list_current_runs[0])
+
+ # more than 1 run
+
+ # create full matching list
+ def match_list(reference_list=[], our_list=[]):
+ _index = 0
+ _ref_list_and_our_list = zip(our_list, reference_list)
+ for _ref_run, _our_run in _ref_list_and_our_list:
+ if _ref_run == _our_run:
+ _index += 1
+ continue
+ break
+
+ return _index
+
+ _index = 0
+ _groups = []
+ _our_list = self.int_list_current_runs[_index: ]
+ _list_full_reference = np.arange(_our_list[0], _our_list[-1]+1)
+
+ # print("new list: {}".format(_our_list))
+
+ while _our_list:
+
+ _ref_index = match_list(reference_list=_list_full_reference,
+ our_list=_our_list)
+
+ _group = [_our_list[0], _our_list[_ref_index-1]]
+ # print("_group: {}".format(_group))
+ _groups.append(_group)
+
+ _our_list = _our_list[_ref_index:]
+ if len(_our_list) == 1:
+ _groups.append(_our_list)
+ break
+
+ if len(_our_list) == 0:
+ break
+
+ _list_full_reference = np.arange(_our_list[0], _our_list[-1]+1)
+
+ # print("_groups: {}".format(_groups))
+
+ list_runs = []
+ for _group in _groups:
+
+ if len(_group) == 2:
+ [_left_value, _right_value] = _group
+
+ if _left_value == _right_value:
+ list_runs.append(str(_left_value))
+ elif _right_value == (_left_value + 1):
+ list_runs.append(str(_left_value))
+ list_runs.append(str(_right_value))
+ else:
+ list_runs.append("{}:{}".format(_left_value, _right_value))
+
+ else:
+ list_runs.append(str(_group[0]))
+
+ str_runs = ",".join(list_runs)
+ # print(str_runs)
+ return str_runs
diff --git a/notebooks/bragg_edge_peak_fitting.ipynb b/notebooks/bragg_edge_peak_fitting.ipynb
new file mode 100644
index 0000000..862a303
--- /dev/null
+++ b/notebooks/bragg_edge_peak_fitting.ipynb
@@ -0,0 +1,288 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "run_control": {
+ "frozen": false,
+ "read_only": false
+ }
+ },
+ "source": [
+ "[![Notebook Tutorial](__code/__all/notebook_tutorial.png)](https://neutronimaging.pages.ornl.gov/tutorial/notebooks/bragg_edge_peak_fitting/#activate-search)\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "run_control": {
+ "frozen": false,
+ "read_only": false
+ }
+ },
+ "source": [
+ "# Select Your IPTS "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "run_control": {
+ "frozen": false,
+ "read_only": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "from __code import system\n",
+ "from __code.bragg_edge.bragg_edge_peak_fitting import BraggEdge, Interface\n",
+ "\n",
+ "system.System.select_working_dir(facility='SNS', instrument='VENUS')\n",
+ "from __code.__all import custom_style\n",
+ "custom_style.style()\n",
+ "\n",
+ "from plotly.offline import plot, init_notebook_mode, iplot\n",
+ "init_notebook_mode()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Prepare UI engine "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "run_control": {
+ "frozen": false,
+ "read_only": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "run_control": {
+ "frozen": false,
+ "read_only": false
+ }
+ },
+ "source": [
+ "# Select Normalized Data Input Folder\n",
+ "\n",
+ "Data and time spectra files will be loaded"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "run_control": {
+ "frozen": false,
+ "read_only": false
+ }
+ },
+ "outputs": [],
+ "source": [
+ "o_bragg = BraggEdge(working_dir=system.System.get_working_dir())\n",
+ "o_bragg.select_working_folder()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Select Open Beam Data Input folder "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "jupyter": {
+ "outputs_hidden": true
+ }
+ },
+ "outputs": [],
+ "source": [
+ "o_bragg.select_ob_folder()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Select sample region and peak to fit"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Select how many random files to use to select region to fit"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "o_bragg.how_many_data_to_use_to_select_sample_roi()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### fit ui "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "o_interface = Interface(o_bragg=o_bragg, spectra_file=o_bragg.spectra_file)\n",
+ "o_interface.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# DEBUGGING"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from __code import system\n",
+ "from __code.bragg_edge.bragg_edge_peak_fitting import BraggEdge, Interface"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = \"/Users/j35/IPTS/VENUS/shared/testing_normalized/\"\n",
+ "import glob\n",
+ "import os\n",
+ "list_data = glob.glob(data_path + \"*.tif\")\n",
+ "spectra_file = os.path.join(data_path, \"Image019_Spectra.txt\")\n",
+ "assert os.path.exists(spectra_file)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "o_bragg = BraggEdge(working_dir=data_path)\n",
+ "o_bragg.load_data(data_path)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "o_interface = Interface(o_bragg=o_bragg,\n",
+ " working_dir=data_path,\n",
+ " spectra_file=spectra_file)\n",
+ "o_interface.show()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# DEBUGGING using import straight "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from __code import system\n",
+ "from __code.bragg_edge.bragg_edge_peak_fitting import BraggEdge, Interface"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%gui qt"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data_path = \"/Users/j35/IPTS/SNAP/Si_normalized\"\n",
+ "o_interface = Interface(working_dir=data_path)\n",
+ "o_interface.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}