Commit dc9fe0a1 authored by Damien Naudet's avatar Damien Naudet

Renamed rect_roi to roi.

Docstrings.
parent 9993d40f
......@@ -195,7 +195,7 @@ class XsocsGui(Qt.QMainWindow):
outQSpaceH5=output_f,
qspaceDims=None,
imageBinning=None,
rectRoi=event,
roi=event,
parent=self.sender())
widget.exec_()
if widget.status == QSpaceWidget.StatusCompleted:
......
......@@ -41,6 +41,11 @@ _DEFAULT_IMG_BIN = [1, 1]
class ConversionParamsWidget(Qt.QWidget):
"""
Widget for conversion parameters input :
- qspace dimensions
- image binning size
"""
def __init__(self, **kwargs):
super(ConversionParamsWidget, self).__init__(**kwargs)
layout = Qt.QGridLayout(self)
......@@ -108,6 +113,10 @@ class ConversionParamsWidget(Qt.QWidget):
@property
def image_binning(self):
"""
Returns the image binning, a 2 integers array.
:return:
"""
h_bin = self.__imgbin_h_edit.text()
if len(h_bin) == 0:
h_bin = None
......@@ -122,11 +131,21 @@ class ConversionParamsWidget(Qt.QWidget):
@image_binning.setter
def image_binning(self, image_binning):
"""
Sets the image binning.
:param image_binning: a 2 integers array.
:return:
"""
self.__imgbin_h_edit.setText(str(image_binning[0]))
self.__imgbin_v_edit.setText(str(image_binning[1]))
@property
def qspace_size(self):
"""
Returns the qspace dimensions, a 3 integers (> 1) array if set,
or [None, None, None].
:return:
"""
qsize_x = self.__qsize_x_edit.text()
if len(qsize_x) == 0:
qsize_x = None
......@@ -146,6 +165,11 @@ class ConversionParamsWidget(Qt.QWidget):
@qspace_size.setter
def qspace_size(self, qspace_size):
"""
Sets the qspace dimensions.
:param qspace_size: A three integers array.
:return:
"""
self.__qsize_x_edit.setText(str(int(qspace_size[0])))
self.__qsize_y_edit.setText(str(int(qspace_size[1])))
self.__qsize_z_edit.setText(str(int(qspace_size[2])))
......@@ -165,13 +189,23 @@ class QSpaceWidget(Qt.QDialog):
outQSpaceH5,
qspaceDims=None,
imageBinning=None,
rectRoi=None,
roi=None,
**kwargs):
"""
Widgets displaying informations about data to be converted to QSpace,
and allowing the user to input some parameters.
:param xsocH5File:
:param outQSpaceH5:
:param qspaceDims:
:param imageBinning:
:param roi:
:param kwargs:
"""
super(QSpaceWidget, self).__init__(**kwargs)
self.__status = QSpaceWidget.StatusInit
self.__params = {'rect_roi': rectRoi,
self.__params = {'roi': roi,
'xsocsH5_f': xsocH5File,
'qspaceH5_f': outQSpaceH5}
......@@ -298,7 +332,7 @@ class QSpaceWidget(Qt.QDialog):
output_f=outQSpaceH5,
qspace_dims=qspaceDims,
img_binning=imageBinning,
rect_roi=rectRoi)
roi=roi)
cancelBn.clicked.connect(self.close)
convertBn.clicked.connect(self.__slotConvertBnClicked)
......@@ -306,6 +340,11 @@ class QSpaceWidget(Qt.QDialog):
self.__fillScansInfos()
def __slotConvertBnClicked(self):
"""
Slot called when the convert button is clicked. Does some checks
then starts the conversion if all is OK.
:return:
"""
converter = self.__converter
if converter is None:
# shouldn't be here
......@@ -364,6 +403,10 @@ class QSpaceWidget(Qt.QDialog):
procDialog.deleteLater()
def __slotConvertDone(self):
"""
Method called when the conversion has been completed succesfuly.
:return:
"""
converter = self.__converter
if not converter:
return
......@@ -382,25 +425,22 @@ class QSpaceWidget(Qt.QDialog):
self._setStatus(self.StatusUnknown)
qspaceH5 = property(lambda self: self.__qspaceH5)
""" Written file (set when the conversion was succesful, None otherwise. """
status = property(lambda self: self.__status)
""" Status of the widget. """
def _setStatus(self, status):
"""
Sets the status of the widget.
:param status:
:return:
"""
if status not in QSpaceWidget.StatusList:
raise ValueError('Unknown status value : {0}.'
''.format(status))
self.__status = status
def __resetState(self):
widgets = self.__widgets
widgets.scans_table.clear()
widgets.scans_table.setHorizontalHeaderLabels(['scan', 'eta'])
self.__nImgLabel.setText('')
self.__nAnglesLabel.setText('')
self._setStatus(QSpaceWidget.StatusInit)
def __fillScansInfos(self):
"""
Fills the QTableWidget with info found in the input file
......@@ -435,11 +475,11 @@ class QSpaceWidget(Qt.QDialog):
# TODO : warning if the ROI is empty (too small to contain images)
params = converter.scan_params(scans[0])
rect_roi = converter.rect_roi
if rect_roi is None:
roi = converter.roi
if roi is None:
xMin = xMax = yMin = yMax = 'ns'
else:
xMin, xMax, yMin, yMax = rect_roi
xMin, xMax, yMin, yMax = roi
self.__roiXMinEdit.setText(str(xMin))
self.__roiXMaxEdit.setText(str(xMax))
......@@ -459,6 +499,13 @@ class _ConversionProcessDialog(Qt.QDialog):
def __init__(self, converter,
parent=None,
**kwargs):
"""
Simple widget displaying a progress bar and a info label during the
conversion process.
:param converter:
:param parent:
:param kwargs:
"""
super(_ConversionProcessDialog, self).__init__(parent)
layout = Qt.QVBoxLayout(self)
......@@ -493,16 +540,29 @@ class _ConversionProcessDialog(Qt.QDialog):
self.__qtimer.start(1000)
def __onAbort(self):
"""
Slot called when the abort button is clicked.
:return:
"""
self.__status_lab.setText('<font color="orange">Cancelling...</font>')
self.__bn_box.button(Qt.QDialogButtonBox.Abort).setEnabled(False)
self.__converter.abort(wait=False)
self.__aborted = True
def __onProgress(self):
"""
Slot called when the progress timer timeouts.
:return:
"""
progress = self.__converter.progress()
self.__progress_bar.setValue(progress)
def __convertDone(self):
"""
Callback called when the conversion is done (whether its successful or
not).
:return:
"""
self.__qtimer.stop()
self.__qtimer = None
self.__onProgress()
......@@ -522,6 +582,7 @@ class _ConversionProcessDialog(Qt.QDialog):
okBn.setText('Close')
status = property(lambda self: 0 if self.__aborted else 1)
""" Status of the process. """
if __name__ == '__main__':
......
......@@ -35,9 +35,6 @@ from threading import Thread
import multiprocessing as mp
import multiprocessing.sharedctypes as mp_sharedctypes
from functools import partial
import h5py
import numpy as np
import xrayutilities as xu
......@@ -83,8 +80,8 @@ class QSpaceConverter(object):
n_proc = property(lambda self: self.__n_proc)
""" Number of processes to use. Will use cpu_count() if None or 0. """
roi = property(lambda self: self.__rect_roi)
""" Selected ROI (in sample coordinates) """
roi = property(lambda self: self.__params['roi'])
""" Selected ROI in sample coordinates : [xmin, xmax, ymin, ymax] """
def __init__(self,
xsocsH5_f,
......@@ -92,7 +89,7 @@ class QSpaceConverter(object):
sample_indices=None,
img_binning=None,
output_f=None,
rect_roi=None,
roi=None,
callback=None):
"""
Merger for the Kmap SPEC and EDF files. This loads a spech5 file,
......@@ -114,7 +111,7 @@ class QSpaceConverter(object):
self.__params = {'qspace_dims': None,
'image_binning': None,
'sample_indices': None,
'rect_roi': None}
'roi': None}
self.__callback = callback
self.__n_proc = None
......@@ -129,7 +126,7 @@ class QSpaceConverter(object):
self.image_binning = img_binning
self.qspace_dims = qspace_dims
self.sample_indices = sample_indices
self.rect_roi = rect_roi
self.roi = roi
self.__set_status(self.READY)
......@@ -292,14 +289,19 @@ class QSpaceConverter(object):
self.__params['sample_indices'] = np.array(sample_indices,
dtype=np.int32)
rect_roi = property(lambda self: self.__params['rect_roi'])
@rect_roi.setter
def rect_roi(self, rect_roi):
if self.rect_roi is False:
@roi.setter
def roi(self, roi):
"""
Sets the roi. Set to None to unset it. To change an already set roi
the previous one has to be unset first.
:param roi: roi coordinates in sample coordinates.
Four elements array : (xmin, xmax, ymin, ymax)
:return:
"""
if self.roi is False:
raise ValueError('Cannot set a rectangular ROI, pos_indices are '
'already set, remove them first.')
self.__params['rect_roi'] = rect_roi
self.__params['roi'] = roi
self.__params['sample_indices'] = self.__indices_from_roi()
def __indices_from_roi(self):
......@@ -310,16 +312,15 @@ class QSpaceConverter(object):
positions = xsocsH5.scan_positions(entries[0])
x_pos = positions.pos_0
y_pos = positions.pos_1
scan_params = xsocsH5.scan_params(entries[0])
rect_roi = self.rect_roi
if self.rect_roi is None:
roi = self.roi
if self.roi is None:
return np.arange(len(x_pos))
x_min = rect_roi[0]
x_max = rect_roi[1]
y_min = rect_roi[2]
y_max = rect_roi[3]
x_min = roi[0]
x_max = roi[1]
y_min = roi[2]
y_max = roi[3]
# we cant do this because the points arent perfectly aligned!
# we could end up with non rectangular rois
......@@ -426,10 +427,12 @@ class QSpaceConverter(object):
return errors
def scan_params(self, scan):
""" Returns the scan parameters (filled during acquisition). """
params = _get_all_params(self.__xsocsH5_f)
return params[scan]
def __get_scans(self):
""" Returns the scan names. """
params = _get_all_params(self.__xsocsH5_f)
return sorted(params.keys())
......@@ -750,7 +753,8 @@ class QSpaceConverter(object):
for result_idx, pos_idx in enumerate(sample_indices):
idx_queue.put((result_idx, pos_idx))
# sending the None value to let the threads know that they should return
# sending the None value to let the threads know that they
# should return
for th_idx in range(n_proc):
idx_queue.put(None)
......@@ -771,10 +775,6 @@ class QSpaceConverter(object):
print('Write {0}'.format(res_times.t_write))
print('(lock : {0})'.format(res_times.t_w_lock))
# for res in proc_result = []:
# res_val = res.get()
# if res_val[0] != self.DONE
proc_results = [result.get() for result in results]
proc_codes = np.array([proc_result[0]
for proc_result in proc_results])
......@@ -817,16 +817,19 @@ class QSpaceConverter(object):
self.__thread.join()
def __running_exception(self):
""" Raises an exception if a conversion is in progress. """
if self.is_running():
raise RuntimeError('Operation not permitted while '
'a parse or merge in running.')
def is_running(self):
""" Returns True if a conversion is in progress. """
return self.status == QSpaceConverter.RUNNING
#self.__thread and self.__thread.is_alive()
@output_f.setter
def output_f(self, output_f):
""" Sets the output file. """
if not isinstance(output_f, str):
raise TypeError('output_f must be a string. Received {0}'
''.format(type(output_f)))
......@@ -834,6 +837,10 @@ class QSpaceConverter(object):
@n_proc.setter
def n_proc(self, n_proc):
""" Sets the number of processes to use. If None or 0 the number of
processes used will be the number returned by
multiprocessing.cpu_count.
"""
if n_proc is None:
self.__n_proc = None
return
......@@ -845,6 +852,12 @@ class QSpaceConverter(object):
self.__n_proc = n_proc
def abort(self, wait=True):
"""
Aborts the current conversion, if any.
:param wait: set to False to return immediatly without waiting for the
processes to return.
:return:
"""
if self.is_running():
self.__term_evt.set()
if wait:
......@@ -939,6 +952,17 @@ def _to_qspace(th_idx,
output_fn,
image_binning,
img_dtype):
"""
Fonction running in a process. Performs the conversion.
:param th_idx:
:param entry_files:
:param entries:
:param img_size:
:param output_fn:
:param image_binning:
:param img_dtype:
:return:
"""
print('Thread {0} started.'.format(th_idx))
t_histo = 0.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment