Skip to content

Commit

Permalink
added polefigure export #355
Browse files Browse the repository at this point in the history
  • Loading branch information
Fancher committed Jan 4, 2023
1 parent 02f9afd commit cb924fc
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 92 deletions.
77 changes: 36 additions & 41 deletions pyrs/core/polefigurecalculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ def get_polefigure_array(self, peak_id):
self.calculate_pole_figure()
return self._pole_figure_dict[peak_id]

def export_pole_figure(self, detector_id_list, file_name, file_type, file_header=''):
def export_pole_figure(self, output_folder: str = '', peak_id_list: list = [], peak_name_list: list = [],
run_number: int = 0, file_type: str = 'mtex', file_header: str = ''):
"""
exported the calculated pole figure
:param detector_id_list: list of detector IDs to write the pole figure file
Expand All @@ -126,22 +127,24 @@ def export_pole_figure(self, detector_id_list, file_name, file_type, file_heade
# TESTME - 20180711 - Clean this method and allow user to specifiy header

# process detector ID list
if detector_id_list is None:
detector_id_list = self.get_detector_ids()
if peak_id_list is None:
peak_id_list = self.get_detector_ids()
else:
checkdatatypes.check_list('Detector IDs', detector_id_list)

# check inputs
checkdatatypes.check_file_name(file_name, check_exist=False, check_writable=True)
checkdatatypes.check_string_variable('Output pole figure file type/format', file_type)

# it is a dictionary now
if file_type.lower() == 'ascii':
# export pole figure arrays as ascii column file
export_arrays_to_ascii(self._pole_figure_dict, detector_id_list, file_name)
elif file_type.lower() == 'mtex':
# export to MTEX format
export_to_mtex(self._pole_figure_dict, detector_id_list, file_name, header=file_header)
checkdatatypes.check_list('Detector IDs', peak_id_list)

for i_peak in range(len(peak_id_list)):
file_name = '{}/HB2B_{}_{}'.format(output_folder, run_number, peak_name_list[i_peak])
# check inputs
checkdatatypes.check_file_name(file_name, check_exist=False, check_writable=True)
checkdatatypes.check_string_variable('Output pole figure file type/format', file_type)

# it is a dictionary now
if file_type.lower() == 'ascii':
# export pole figure arrays as ascii column file
export_arrays_to_ascii(self._pole_figure_dict, peak_id_list, file_name)
elif file_type.lower() == 'mtex':
# export to MTEX format
export_to_mtex(self._pole_figure_dict, [peak_id_list[i_peak]], file_name, header=file_header)

return

Expand All @@ -162,11 +165,7 @@ def get_pole_figure_1_pt(self, det_id: int, log_index: int) -> Tuple[float, floa
log_index = to_int('Sample log index', log_index)

# get raw parameters' fitted value
log_index_vec, pole_figure_vec = self._pole_figure_dict[det_id]

# check
if log_index != int(log_index_vec[log_index]):
raise RuntimeError('Log index {0} does not match the value in log index vector')
pole_figure_vec = self._pole_figure_dict[det_id]

pf_tuple = pole_figure_vec[log_index]
alpha = pf_tuple[0]
Expand Down Expand Up @@ -224,27 +223,28 @@ def reset_calculator(self):
self._pole_figure_dict = dict()


def export_arrays_to_ascii(pole_figure_array_dict, detector_id_list, file_name):
def export_arrays_to_ascii(pole_figure_array_dict: dict, peak_id_list: list, file_name: str):
"""
export a dictionary of arrays to an ASCII file
:param file_name:
:param detector_id_list: selected the detector IDs for pole figure
:param pole_figure_array_dict:
:return:
"""
# check input types
checkdatatypes.check_dict('Pole figure array dictionary', pole_figure_array_dict)
checkdatatypes.check_list('Detector ID list', detector_id_list)

print('[INFO] Export Pole Figure Arrays To ASCII:\nKeys: {0}\nValues[0]: {1}'
''.format(pole_figure_array_dict.keys(), pole_figure_array_dict.values()[0]))

# check for correct file extension
if '.txt' not in file_name:
file_name = '{}.txt'.format(file_name.replace('.jul', ''))

# combine
pole_figure_array_list = list()
for pf_key in pole_figure_array_dict.keys():
index_vec, pole_figure_vec = pole_figure_array_dict[pf_key]
pole_figure_array_list = []
for pf_key in peak_id_list:
pole_figure_vec = pole_figure_array_dict[pf_key]

if pf_key not in detector_id_list:
if pf_key not in peak_id_list:
raise NotImplementedError('The data structure of pole figure array is not clear. '
'Find out how detector IDs are involved.')

Expand All @@ -260,7 +260,7 @@ def export_arrays_to_ascii(pole_figure_array_dict, detector_id_list, file_name):
return


def export_to_mtex(pole_figure_array_dict, detector_id_list, file_name, header):
def export_to_mtex(pole_figure_array_dict: dict, peak_id_list: list, file_name: str, header: str):
"""
export to mtex format, which includes
line 1: NRSF2
Expand All @@ -273,9 +273,10 @@ def export_to_mtex(pole_figure_array_dict, detector_id_list, file_name, header):
:param header
:return:
"""
# check input types
checkdatatypes.check_dict('Pole figure array dictionary', pole_figure_array_dict)
checkdatatypes.check_list('Detector ID list', detector_id_list)

# check for correct file extension
if '.jul' not in file_name:
file_name = '{}.jul'.format(file_name.replace('.jul', ''))

# initialize output string: MTEX HEAD
mtex = 'NRSF2\n'
Expand All @@ -285,15 +286,9 @@ def export_to_mtex(pole_figure_array_dict, detector_id_list, file_name, header):
mtex += '{0}\n'.format(header)

# writing data
pf_keys = sorted(pole_figure_array_dict.keys())
for pf_key in pf_keys:
print('[STUDY ]Pole figure key = {}. It is in detector ID list {} = {}'
''.format(pf_key, detector_id_list, pf_key in detector_id_list))
if pf_key not in detector_id_list:
raise NotImplementedError('The data structure of pole figure array is not clear. '
'Find out how detector IDs are involved.')
for pf_key in peak_id_list:

sample_log_index, pole_figure_array = pole_figure_array_dict[pf_key]
pole_figure_array = pole_figure_array_dict[pf_key]
for i_pt in range(pole_figure_array.shape[0]):
mtex += '{0:5.5f}\t{1:5.5f}\t{2:5.5f}\n' \
''.format(pole_figure_array[i_pt, 0], pole_figure_array[i_pt, 1], pole_figure_array[i_pt, 2])
Expand Down
4 changes: 2 additions & 2 deletions pyrs/interface/peak_fitting/fit_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def set_item(value='', fitting_worked=True):
if np.isnan(_microstrain):
str_strain_value = "nan"
else:
str_strain_value = str(np.int(_microstrain))
str_strain_value = str(np.int32(_microstrain))
_item = set_item(value=str_strain_value, fitting_worked=_fitting_worked)
self.parent.ui.tableView_fitSummary.setItem(_row, _global_col_index, _item)
_global_col_index += 1
Expand All @@ -78,7 +78,7 @@ def set_item(value='', fitting_worked=True):
_global_col_index += 1

def _get_d_spacing_to_display(self, peak_selected=1, peak_collection=None):
_d_reference = np.float(str(self.parent.ui.peak_range_table.item(peak_selected-1, 3).text()))
_d_reference = np.float32(str(self.parent.ui.peak_range_table.item(peak_selected-1, 3).text()))
peak_collection.set_d_reference(values=_d_reference)
values, error = peak_collection.get_dspacing_center()
if self.parent.ui.radioButton_fit_value.isChecked():
Expand Down
9 changes: 9 additions & 0 deletions pyrs/interface/texture_fitting/texture_fitting_crtl.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,12 @@ def extract_polar_projection(self, peak_number):

else:
return None

def export_polar_projection(self, output_folder, peak_id_list, peak_label_list):

if self._model._polefigureinterface is not None:
self._model._polefigureinterface.calculate_pole_figure()
self._model._polefigureinterface.export_pole_figure(output_folder=output_folder,
peak_id_list=peak_id_list,
peak_name_list=peak_label_list,
run_number=self._model.runnumber)
24 changes: 13 additions & 11 deletions pyrs/interface/texture_fitting/texture_fitting_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,29 @@ def __init__(self, peak_fit_core):
self.ws = None
self.peak_fit_engine = None
self._polefigureinterface = None
self._run_number = None

@property
def runnumber(self):
return self._run_number

def set_workspaces(self, name, filenames):
setattr(self, name, filenames)

def get_default_csv_filename(self):
runs = [[peak_collection.runnumber for peak_collection in getattr(self._stress, f'strain{d}').peak_collections]
for d in ('11', '22', '33')]
runnumbers = []
for runs in runs:
for runnumber in runs:
if runnumber != -1:
runnumbers.append(str(runnumber))
return "HB2B_{}_stress_grid_{}.csv".format('_'.join(runnumbers),
self.selectedPeak)

def load_hidra_project_file(self, filename):

try:
source_project = HidraProjectFile(filename, mode=HidraProjectFileMode.READONLY)
self.ws = HidraWorkspace(filename)
self.ws.load_hidra_project(source_project, False, True)
self.sub_runs = np.array(self.ws.get_sub_runs())

for part in filename.split('/')[-1].replace('.h5', '').split('_'):
try:
self._run_number = int(part)
except ValueError:
pass

except Exception as e:
self.failureMsg.emit(f"Failed to load {filename}. Check that this is a Hidra Project File",
str(e),
Expand Down
80 changes: 42 additions & 38 deletions pyrs/interface/texture_fitting/texture_fitting_viewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ def __init__(self, parent=None):
self.fit_range = QGroupBox()
self.fit_range_layout = QVBoxLayout()
self.fit_range.setTitle("Peak Ranges")
self.fit_range.setFlat(True)

self.save_load_fit = QGroupBox()
self.save_load_fit_layout = QHBoxLayout()
Expand All @@ -553,6 +554,7 @@ def __init__(self, parent=None):
self.save_load_fit_layout.addWidget(self.load_fit_info)
self.save_load_fit_layout.addWidget(self.save_fit_info)
self.save_load_fit.setLayout(self.save_load_fit_layout)
self.save_load_fit.setFlat(True)

self.fit_range_table = QTableWidget(self)
self.fit_range_table.setColumnCount(4)
Expand Down Expand Up @@ -592,6 +594,7 @@ def __init__(self, parent=None):
sub_runs_select_layout.addWidget(self.lineEdit, 1, 0)
sub_runs_select_layout.addWidget(example_label, 1, 1)
self.sub_runs_select.setLayout(sub_runs_select_layout)
self.sub_runs_select.setFlat(True)

self.fit_setup = QGroupBox()
self.fit_setup.setTitle("Fitting Functions")
Expand All @@ -610,13 +613,23 @@ def __init__(self, parent=None):
self.fit_setup_layout.addWidget(self.peak_back)
self.fit_setup_layout.addWidget(self.fit_peaks)
self.fit_setup.setLayout(self.fit_setup_layout)
self.fit_setup.setFlat(True)

self.export = QPushButton("Export Peak Information")
self.export.clicked.connect(self.save_CSV)
self.export_setup = QGroupBox()
self.export_setup_layout = QHBoxLayout()
self.export_peak_info = QPushButton("Export Peak Information")
self.export_peak_info.clicked.connect(self.save_peak_CSV)
self.export_pole_figs = QPushButton("Export Polefigures")
self.export_pole_figs.clicked.connect(self.save_pole_fig)

self.export_setup_layout.addWidget(self.export_peak_info)
self.export_setup_layout.addWidget(self.export_pole_figs)
self.export_setup.setLayout(self.export_setup_layout)
self.export_setup.setFlat(True)

self.peak_setup_layout.addWidget(self.sub_runs_select)
self.peak_setup_layout.addWidget(self.fit_setup)
self.peak_setup_layout.addWidget(self.export)
self.peak_setup_layout.addWidget(self.export_setup)

self.peak_setup.setLayout(self.peak_setup_layout)

Expand Down Expand Up @@ -653,7 +666,7 @@ def update_peak_tabel_entry(self, x1):

return

def save_CSV(self):
def save_peak_CSV(self):
filename, _ = QFileDialog.getSaveFileName(self,
"Export Peak Information",
self._parent.model.get_default_csv_filename(),
Expand All @@ -663,10 +676,31 @@ def save_CSV(self):

self._parent.controller.export_peak_data(filename, self._parent.fit_summary.fit_table_operator.fits)

def save_pole_fig(self):

peak_label_list = []
peaks_id_list = []
for peak_row in range(self.fit_range_table.rowCount()):
if (self.fit_range_table.item(peak_row, 0) is not None and
self.fit_range_table.item(peak_row, 1) is not None):
peaks_id_list.append(peak_row + 1)
if self.fit_range_table.item(peak_row, 2) is None:
peak_label_list.append('peak_{}'.format(peak_row + 1))
else:
peak_label_list.append(self.fit_range_table.item(peak_row, 2).text())

output_folder = QFileDialog.getExistingDirectory(self,
"Export Experimental Polefigure Information")

if not output_folder:
return

self._parent.controller.export_polar_projection(output_folder, peaks_id_list, peak_label_list)

def save_json(self):
filename, _ = QFileDialog.getSaveFileName(self,
"Export Peak Fit Information",
self._parent.model.get_default_csv_filename(),
self._parent.model.runnumber,
"JSON (*.json);;All Files (*)")
if not filename:
return
Expand All @@ -675,7 +709,7 @@ def save_json(self):
def load_json(self):
filename, _ = QFileDialog.getSaveFileName(self,
"Export Peak Fit Information",
self._parent.model.get_default_csv_filename(),
self._parent.model.runnumber,
"JSON (*.json);;All Files (*)")
if not filename:
return
Expand Down Expand Up @@ -891,7 +925,7 @@ def set_item(value='', fitting_worked=True):
if np.isnan(_microstrain):
str_strain_value = "nan"
else:
str_strain_value = str(np.int(_microstrain))
str_strain_value = str(np.int32(_microstrain))
_item = set_item(value=str_strain_value, fitting_worked=_fitting_worked)
self._parent.tableView_fitSummary.setItem(_row, _global_col_index, _item)
_global_col_index += 1
Expand All @@ -902,7 +936,7 @@ def set_item(value='', fitting_worked=True):
_global_col_index += 1

def _get_d_spacing_to_display(self, peak_selected=1, peak_collection=None):
_d_reference = np.float(str(self._parent._parent.fit_setup.fit_range_table.item(peak_selected-1, 3).text()))
_d_reference = np.float32(str(self._parent._parent.fit_setup.fit_range_table.item(peak_selected-1, 3).text()))

peak_collection.set_d_reference(values=_d_reference)
values, error = peak_collection.get_dspacing_center()
Expand Down Expand Up @@ -1003,36 +1037,6 @@ def select_first_row(self):
self._parent.tableView_fitSummary.setRangeSelected(selection_first_row, True)


class CSVExport(QGroupBox):
def __init__(self, parent=None):
self._parent = parent
super().__init__(parent=parent)
self.setTitle("CSV Export")
layout = QHBoxLayout()
self.export = QPushButton("Export Grid Information")
self.export.clicked.connect(self.save_CSV)
self.detailed = QCheckBox("Detailed")
layout.addWidget(self.export)
layout.addWidget(self.detailed)
self.setLayout(layout)

self.setEnabled(False)

def setEnabled(self, enabled):
self.export.setEnabled(enabled)
self.detailed.setEnabled(enabled)

def save_CSV(self):
self._parent.calculate_stress()
filename, _ = QFileDialog.getSaveFileName(self,
"Export Grid Information",
self._parent.model.get_default_csv_filename(),
"CSV (*.csv);;All Files (*)")
if not filename:
return
self._parent.controller.write_stress_to_csv(filename, self.detailed.isChecked())


class TextureFittingViewer(QMainWindow):
def __init__(self, fit_peak_model, fit_peak_ctrl, parent=None):

Expand Down

0 comments on commit cb924fc

Please sign in to comment.