Skip to content
Snippets Groups Projects
Commit 4a68f0d6 authored by Henri Payno's avatar Henri Payno
Browse files

Helical: add a dedicated widget for `nabu-helical-prepare-weights-double`

parent 2190c533
Branches add_helical
No related tags found
No related merge requests found
Showing
with 509 additions and 11 deletions
import logging
from orangewidget import gui
from orangewidget.settings import Setting
from orangewidget.widget import Input, Output
from orangecontrib.tomwer.orange.managedprocess import TomwerWithStackStack
from silx.gui import qt
from typing import Optional
from tomwer.core.futureobject import FutureTomwerObject
from tomwer.core.scan.scanbase import TomwerScanBase
from tomwer.gui.reconstruction.nabu.helical import HelicalPrepareWeightsDouble
from tomwer.core.process.reconstruction.nabu.helical import (
NabuHelicalPrepareWeightsDouble,
)
from tomwer.core.scan.hdf5scan import HDF5TomoScan
_logger = logging.getLogger(__name__)
class NabuHelicalPrepareWeightsDoubleOW(
TomwerWithStackStack,
ewokstaskclass=NabuHelicalPrepareWeightsDouble,
):
"""
widget used to call the `nabu-helical-prepare-weights-double` application on a dedicated thread
:param parent: the parent widget
"""
# note of this widget should be the one registered on the documentation
name = "helical prepate weights double"
id = "orange.widgets.tomwer.reconstruction.NabuHelicalPrepareWeightsDoubleOW.NabuHelicalPrepareWeightsDoubleOW"
description = "compute map of weights requested for nabu helical reconstruction"
icon = "icons/nabu_prepare_weights_double.svg"
priority = 199
keywords = [
"tomography",
"nabu",
"reconstruction",
"nabu-helical",
"helical",
"weights",
"prepare",
]
want_main_area = True
resizing_enabled = True
compress_signal = False
allows_cycle = True
_ewoks_default_inputs = Setting(
{
"data": None,
"transition_width": 50,
"processes_file": "",
}
)
sigScanReady = qt.Signal(TomwerScanBase)
"Signal emitted when a scan is ended"
TIMEOUT = 30
class Inputs:
data = Input(
name="data",
type=TomwerScanBase,
doc="one scan to be process",
default=True,
multiple=False,
)
class Outputs:
data = Output(name="data", type=TomwerScanBase, doc="one scan to be process")
future_tomo_obj = Output(
name="future_tomo_obj",
type=FutureTomwerObject,
doc="future object (process remotely)",
)
LOGGER = _logger
def __init__(self, parent=None):
super().__init__(parent)
self.__scan = None
# gui definition
_layout = gui.vBox(self.mainArea, self.name).layout()
self.widget = HelicalPrepareWeightsDouble(parent=self)
_layout.addWidget(self.widget)
## connect signal / slot
self.widget.sigConfigChanged.connect(self._updateSettings)
self.task_output_changed_callbacks.add(self._notify_state)
## handle settings
self._loadSettings()
self.task_executor_queue.sigComputationStarted.connect(self._newTaskStarted)
def _updateSettings(self):
config = self.widget.getConfiguration()
for key in ("transition_width", "processes_file"):
self._ewoks_default_inputs[key] = config[key]
@property
def request_input(self):
return self.__request_input
@request_input.setter
def request_input(self, request):
self.__request_input = request
def get_task_inputs(self):
assert self.__scan is not None
return {
"data": self.__scan,
"transition_width": self.widget.getConfiguration()["transition_width"],
"processes_file": self.widget.getConfiguration()["processes_file"],
}
def handleNewSignals(self) -> None:
"""Invoked by the workflow signal propagation manager after all
signals handlers have been called.
"""
# for now we want to avoid propagation any processing.
# task will be executed only when the user validates the dialog
data = super().get_task_inputs().get("data", None)
if data is not None:
if not isinstance(data, HDF5TomoScan):
raise TypeError(
f"data is expected to be an instance of HDF5TomoScan. {type(data)} are not handled"
)
self.add(data.path)
def _loadSettings(self):
self.widget.setConfiguration(self._ewoks_default_inputs)
def _newTaskStarted(self):
try:
task_executor = self.sender()
scan = task_executor.current_task.inputs.data
self.notify_on_going(scan)
except Exception:
pass
def _notify_state(self):
try:
task_executor = self.sender()
task_suceeded = task_executor.succeeded
scan = task_executor.current_task.outputs.data
if task_suceeded:
self.notify_succeed(scan=scan)
else:
self.notify_failed(scan=scan)
except Exception as e:
_logger.error(f"failed to handle task finished callback. Raiseon is {e}")
@Inputs.data
def process_data(self, scan: Optional[TomwerScanBase]):
if scan is None:
return
else:
self.__scan = scan
self.notify_pending(scan=scan)
self.execute_ewoks_task()
def sizeHint(self) -> qt.QSize:
return qt.QSize(400, 60)
orangecontrib/tomwer/widgets/reconstruction/icons/nabu_prepare_weights_double.png

163 B

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48"
height="48"
viewBox="0 0 12.7 12.7"
version="1.1"
id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="nabu_prepare_weights_double.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="41.132491"
inkscape:cy="25.54345"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1848"
inkscape:window-height="1136"
inkscape:window-x="72"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-284.3)">
<rect
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.32017678;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect815"
width="10.951561"
height="2.7875743"
x="0.86019582"
y="289.58221" />
<rect
style="opacity:1;fill:#949494;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect817"
width="1.6063988"
height="6.3074775"
x="3.1986237"
y="287.88132" />
<g
transform="matrix(0.00788463,0,0,0.00739488,0.77385056,283.73387)"
id="id9">
<path
style="fill:none;stroke:#000000;stroke-width:40;stroke-linejoin:round"
inkscape:connector-curvature="0"
d="m 1001.3586,1089.2304 c 51,3 92,8 138,15 106,17 183,41 245,78 63,36 93,74 95,120 3,45 -22,86 -80,129 -58,44 -132,76 -235,105 -103,29 -204.99998,46 -324.99998,53 -121,7 -224,2 -330,-15 -78,-13 -137,-29 -193,-52"
id="path105" />
<g
transform="matrix(1.2682905,0,0,1.3522871,-266.83951,-443.90403)"
class="com.sun.star.drawing.EllipseShape"
id="g115">
<g
id="id10">
<rect
style="fill:none;stroke:none"
class="BoundingBox"
x="180"
y="531"
width="1229"
height="290"
id="rect110" />
<path
style="fill:none;stroke:#000000;stroke-width:40;stroke-linejoin:round"
inkscape:connector-curvature="0"
d="M 433.97152,785.52867 C 340.97152,773.52867 350,774 294,755 c -65,-22 -94,-43 -94,-68 0,-25 29,-46 94,-68 64,-22 144,-37 256,-50 112,-12 221,-18 350,-18 129,0 238,6 350,18 53,6 94,12 137,20"
id="path112"
sodipodi:nodetypes="ccsccscc" />
</g>
</g>
<rect
style="fill:none;stroke:none"
class="BoundingBox"
x="414"
y="884"
width="1206"
height="544"
id="rect103" />
</g>
<rect
style="opacity:1;fill:#cfcfcf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.38202855;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect817-3-6"
width="1.3574991"
height="4.3573365"
x="9.8455238"
y="288.85657" />
<rect
style="opacity:1;fill:#cfcfcf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.38202855;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect817-3-6-7"
width="1.3574991"
height="4.3573365"
x="1.5891073"
y="288.96268" />
<rect
style="opacity:1;fill:#949494;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke markers fill"
id="rect817-3"
width="1.6063988"
height="6.3074775"
x="8.0319939"
y="287.97815" />
</g>
</svg>
import pickle
from orangecanvas.scheme.readwrite import literal_dumps
from tomwer.tests.conftest import qtapp # noqa F401
from orangecontrib.tomwer.widgets.reconstruction.NabuHelicalPrepareWeightsDoubleOW import (
NabuHelicalPrepareWeightsDoubleOW,
)
def test_NabuHelicalPrepareWeightsDoubleOW(
qtapp, # noqa F811
):
"""simple test of the _DeltaBetaSelectorDialog"""
widget = NabuHelicalPrepareWeightsDoubleOW()
widget._loadSettings()
# test settings serialization
pickle.dumps(widget._ewoks_default_inputs)
literal_dumps(widget._ewoks_default_inputs)
import logging
from nabu.resources.nxflatfield import update_dataset_info_flats_darks
from nabu.resources.dataset_analyzer import HDF5DatasetAnalyzer
from nabu.io.reader import load_images_from_dataurl_dict
from nabu.app.prepare_weights_double import create_heli_maps
from tomwer.core.process.task import TaskWithProgress
from tomwer.core.scan.hdf5scan import HDF5TomoScan
from tomwer.core.utils.scanutils import format_output_location
_logger = logging.getLogger(__name__)
class NabuHelicalPrepareWeightsDouble(
TaskWithProgress,
input_names=(
"data",
"transition_width",
"processes_file",
),
optional_input_names=("progress"),
output_names=("data",),
):
def run(self):
# TODO: handle future /cluster config ???
scan = self.inputs.data
if not isinstance(scan, HDF5TomoScan):
raise TypeError(f"data is expected to be an instance of {HDF5TomoScan}")
dataset_info = HDF5DatasetAnalyzer(
scan.master_file,
extra_options={"h5_entry": scan.entry},
)
update_dataset_info_flats_darks(dataset_info, flatfield_mode=1)
mappe = 0
my_flats = load_images_from_dataurl_dict(dataset_info.flats)
for _, flat in my_flats.items():
mappe += flat
mappe = mappe / len(list(dataset_info.flats.keys()))
scan.helical.processes_files = format_output_location(
location=self.inputs.processes_file, scan=scan
)
create_heli_maps(
profile=mappe,
process_file_name=scan.helical.processes_files,
entry_name=scan.entry,
transition_width=self.inputs.transition_width,
)
self.outputs.data = scan
...@@ -252,6 +252,7 @@ def get_recons_volume_identifier( ...@@ -252,6 +252,7 @@ def get_recons_volume_identifier(
class _NabuMode(_Enum): class _NabuMode(_Enum):
FULL_FIELD = "standard acquisition" FULL_FIELD = "standard acquisition"
HALF_ACQ = "half acquisition" HALF_ACQ = "half acquisition"
HELICAL = "helical acquisition"
class _NabuStages(_Enum): class _NabuStages(_Enum):
......
...@@ -47,6 +47,7 @@ from tomoscan.esrf.scan.hdf5scan import ImageKey ...@@ -47,6 +47,7 @@ from tomoscan.esrf.scan.hdf5scan import ImageKey
from tomoscan.io import HDF5File from tomoscan.io import HDF5File
from tomwer.utils import docstring from tomwer.utils import docstring
from tomwer.core.scan.helicalmetadata import HelicalMetadata
from .scanbase import TomwerScanBase from .scanbase import TomwerScanBase
...@@ -110,6 +111,7 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase): ...@@ -110,6 +111,7 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
_tsHDF5TomoScan.__init__(self, scan=scan, entry=entry, index=index) _tsHDF5TomoScan.__init__(self, scan=scan, entry=entry, index=index)
# register at least the 'default' working directory as a possible reconstruction path # register at least the 'default' working directory as a possible reconstruction path
self.add_reconstruction_path(self.path) self.add_reconstruction_path(self.path)
self._helical = HelicalMetadata()
self._reconstruction_urls = None self._reconstruction_urls = None
self._projections_with_angles = None self._projections_with_angles = None
...@@ -137,6 +139,10 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase): ...@@ -137,6 +139,10 @@ class HDF5TomoScan(_tsHDF5TomoScan, TomwerScanBase):
else: else:
return os.path.realpath(os.path.dirname(self.master_file)) return os.path.realpath(os.path.dirname(self.master_file))
@property
def helical(self):
return self._helical
@staticmethod @staticmethod
def from_identifier(identifier): def from_identifier(identifier):
"""Return the Dataset from a identifier""" """Return the Dataset from a identifier"""
......
class HelicalMetadata:
def __init__(self) -> None:
self._processes_files = (
"{scan_parent_dir_basename}/{scan_dir_name}/map_and_doubleff.hdf5"
)
@property
def processes_files(self) -> str:
return self._processes_files
@processes_files.setter
def processes_files(self, path: str):
if not isinstance(path, str):
raise TypeError(f"expects a str. Get {path}")
self._processes_files = path
...@@ -2,6 +2,10 @@ from silx.gui import qt ...@@ -2,6 +2,10 @@ from silx.gui import qt
class QLFileSystem(qt.QLineEdit): class QLFileSystem(qt.QLineEdit):
"""
QLineEdit with a completer using a QDirModel
"""
def __init__(self, text, parent, filters=None, **kwargs): def __init__(self, text, parent, filters=None, **kwargs):
super().__init__(parent=parent, **kwargs) super().__init__(parent=parent, **kwargs)
self.completer = qt.QCompleter() self.completer = qt.QCompleter()
...@@ -10,3 +14,5 @@ class QLFileSystem(qt.QLineEdit): ...@@ -10,3 +14,5 @@ class QLFileSystem(qt.QLineEdit):
model.setFilter(filters) model.setFilter(filters)
self.completer.setModel(model) self.completer.setModel(model)
self.setCompleter(self.completer) self.setCompleter(self.completer)
if text is not None:
self.setText(text)
from silx.gui import qt
from tomwer.gui.qlefilesystem import QLFileSystem
class HelicalPrepareWeightsDouble(qt.QWidget):
sigConfigChanged = qt.Signal()
"""emit when the configuration has changed"""
def __init__(self, parent=None, *args, **kwargs) -> None:
super().__init__(parent, *args, **kwargs)
self.setLayout(qt.QGridLayout())
# TODO: optional outptu file path. Default or set by the user
self._outputFilePathLabel = qt.QLabel("output file", self)
self.layout().addWidget(self._outputFilePathLabel, 0, 0, 1, 1)
self._outputFilePathQLE = QLFileSystem(
text="{scan_parent_dir_basename}/{scan_dir_name}/map_and_doubleff.hdf5",
parent=self,
)
self._outputFilePathQLE.setToolTip(
"location of the output file. Which will contain the weight map."
)
self.layout().addWidget(self._outputFilePathQLE, 0, 2, 1, 1)
# transition_width
self._transitionWidthQDSP = qt.QLabel("transition width", self)
self.layout().addWidget(self._transitionWidthQDSP, 1, 0, 1, 1)
self._transitionWidthQDSP = qt.QDoubleSpinBox(self)
self._transitionWidthQDSP.setRange(0.0, 99999999)
self._transitionWidthQDSP.setValue(50.0)
self._transitionWidthQDSP.setToolTip(
"the transition width is used to determine the vertical borders"
)
# TODO: improve tooltip of this
self.layout().addWidget(self._transitionWidthQDSP, 1, 1, 1, 2)
spacer = qt.QWidget(parent=self)
spacer.setSizePolicy(qt.QSizePolicy.Expanding, qt.QSizePolicy.Expanding)
self.layout().addWidget(spacer, 100, 0, 1, 3)
# connect signal / slot
self._outputFilePathQLE.editingFinished.connect(self._changed)
self._transitionWidthQDSP.valueChanged.connect(self._changed)
def _changed(self, *args, **kwargs):
self.sigConfigChanged.emit()
def getConfiguration(self) -> dict:
return {
"processes_file": self._outputFilePathQLE.text(),
"transition_width": self._transitionWidthQDSP.value(),
}
def setConfiguration(self, config: dict):
processes_file = config.get("processes_file", None)
if processes_file is not None:
self._outputFilePathQLE.setText(processes_file)
transition_width = config.get("transition_width", None)
if transition_width is not None:
self._transitionWidthQDSP.setValue(float(transition_width))
...@@ -60,13 +60,14 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -60,13 +60,14 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
qt.QWidget.__init__(self, parent) qt.QWidget.__init__(self, parent)
self.setLayout(qt.QGridLayout()) self.setLayout(qt.QGridLayout())
# flat field # default options
## flat field
self._flatFieldCB = qt.QCheckBox("flat field correction", self) self._flatFieldCB = qt.QCheckBox("flat field correction", self)
self._flatFieldCB.setToolTip("Whether to enable flat-field " "normalization") self._flatFieldCB.setToolTip("Whether to enable flat-field " "normalization")
self.layout().addWidget(self._flatFieldCB, 0, 0, 1, 2) self.layout().addWidget(self._flatFieldCB, 0, 0, 1, 2)
self.registerWidget(self._flatFieldCB, "optional") self.registerWidget(self._flatFieldCB, "optional")
# double flat field ## double flat field
self._dffCB = qt.QCheckBox("double flat field correction", self) self._dffCB = qt.QCheckBox("double flat field correction", self)
self._dffCB.setToolTip("Whether to enable double flat field " "normalization") self._dffCB.setToolTip("Whether to enable double flat field " "normalization")
self.layout().addWidget(self._dffCB, 1, 0, 1, 2) self.layout().addWidget(self._dffCB, 1, 0, 1, 2)
...@@ -84,7 +85,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -84,7 +85,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
self.registerWidget(self._dffSigmaQDSB, "required"), self.registerWidget(self._dffSigmaQDSB, "required"),
] ]
# sino ring corrcetion ## sino ring corrcetion
self._sinoRingCorrectionCB = qt.QLabel("rings removal method", self) self._sinoRingCorrectionCB = qt.QLabel("rings removal method", self)
self._sinoRingCorrectionCB.setToolTip("Sinogram rings removal method") self._sinoRingCorrectionCB.setToolTip("Sinogram rings removal method")
self.layout().addWidget(self._sinoRingCorrectionCB, 2, 0, 1, 2) self.layout().addWidget(self._sinoRingCorrectionCB, 2, 0, 1, 2)
...@@ -93,7 +94,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -93,7 +94,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
self._sinoRingCorrectionMthd = QComboBox(parent=self, scrollArea=scrollArea) self._sinoRingCorrectionMthd = QComboBox(parent=self, scrollArea=scrollArea)
for method in _RingCorrectionMethod: for method in _RingCorrectionMethod:
self._sinoRingCorrectionMthd.addItem(method.value) self._sinoRingCorrectionMthd.addItem(method.value)
# force method to be None by default ## force method to be None by default
idx = self._sinoRingCorrectionMthd.findText(_RingCorrectionMethod.NONE.value) idx = self._sinoRingCorrectionMthd.findText(_RingCorrectionMethod.NONE.value)
self._sinoRingCorrectionMthd.setCurrentIndex(idx) self._sinoRingCorrectionMthd.setCurrentIndex(idx)
...@@ -103,13 +104,13 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -103,13 +104,13 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
self._sinoRingsOpts = SinoRingsOptions(parent=self) self._sinoRingsOpts = SinoRingsOptions(parent=self)
self.layout().addWidget(self._sinoRingsOpts, 3, 1, 1, 3) self.layout().addWidget(self._sinoRingsOpts, 3, 1, 1, 3)
# ccd filter ## ccd filter
self._ccdFilterCB = qt.QCheckBox("CCD hot spot correction", self) self._ccdFilterCB = qt.QCheckBox("CCD hot spot correction", self)
self._ccdFilterCB.setToolTip("Whether to enable the CCD hotspots " "correction") self._ccdFilterCB.setToolTip("Whether to enable the CCD hotspots " "correction")
self.layout().addWidget(self._ccdFilterCB, 4, 0, 1, 2) self.layout().addWidget(self._ccdFilterCB, 4, 0, 1, 2)
self.registerWidget(self._ccdFilterCB, "optional") self.registerWidget(self._ccdFilterCB, "optional")
# ccd filter threshold ## ccd filter threshold
self._ccdHotspotLabel = qt.QLabel("threshold:", self) self._ccdHotspotLabel = qt.QLabel("threshold:", self)
self._ccdHotspotLabel.setAlignment(qt.Qt.AlignRight) self._ccdHotspotLabel.setAlignment(qt.Qt.AlignRight)
self.layout().addWidget(self._ccdHotspotLabel, 5, 2, 1, 1) self.layout().addWidget(self._ccdHotspotLabel, 5, 2, 1, 1)
...@@ -131,7 +132,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -131,7 +132,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
self.registerWidget(self._ccdThreshold, "optional"), self.registerWidget(self._ccdThreshold, "optional"),
] ]
# sr current normalization ## sr current normalization
self._normalizeCurrent = qt.QCheckBox("normalize with current", self) self._normalizeCurrent = qt.QCheckBox("normalize with current", self)
self._normalizeCurrent.setToolTip( self._normalizeCurrent.setToolTip(
"Whether to normalize frames with Synchrotron Current. This can correct the effect of a beam refill not taken into account by flats." "Whether to normalize frames with Synchrotron Current. This can correct the effect of a beam refill not taken into account by flats."
...@@ -139,12 +140,12 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -139,12 +140,12 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
self.layout().addWidget(self._normalizeCurrent, 6, 0, 1, 2) self.layout().addWidget(self._normalizeCurrent, 6, 0, 1, 2)
self.registerWidget(self._normalizeCurrent, "required") self.registerWidget(self._normalizeCurrent, "required")
# take logarithm ## take logarithm
self._takeLogarithmCB = qt.QCheckBox("take logarithm", self) self._takeLogarithmCB = qt.QCheckBox("take logarithm", self)
self.layout().addWidget(self._takeLogarithmCB, 7, 0, 1, 2) self.layout().addWidget(self._takeLogarithmCB, 7, 0, 1, 2)
self.registerWidget(self._takeLogarithmCB, "advanced") self.registerWidget(self._takeLogarithmCB, "advanced")
# log min clip value ## log min clip value
self._clipMinLogValueLabel = qt.QLabel("log min clip value:", self) self._clipMinLogValueLabel = qt.QLabel("log min clip value:", self)
self._clipMinLogValueLabel.setAlignment(qt.Qt.AlignRight) self._clipMinLogValueLabel.setAlignment(qt.Qt.AlignRight)
self.layout().addWidget(self._clipMinLogValueLabel, 8, 2, 1, 1) self.layout().addWidget(self._clipMinLogValueLabel, 8, 2, 1, 1)
...@@ -159,7 +160,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -159,7 +160,7 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
self.registerWidget(self._clipMinLogValue, "optional"), self.registerWidget(self._clipMinLogValue, "optional"),
] ]
# log max clip value ## log max clip value
self._clipMaxLogValueLabel = qt.QLabel("log max clip value:", self) self._clipMaxLogValueLabel = qt.QLabel("log max clip value:", self)
self._clipMaxLogValueLabel.setAlignment(qt.Qt.AlignRight) self._clipMaxLogValueLabel.setAlignment(qt.Qt.AlignRight)
self.layout().addWidget(self._clipMaxLogValueLabel, 9, 2, 1, 1) self.layout().addWidget(self._clipMaxLogValueLabel, 9, 2, 1, 1)
...@@ -176,11 +177,24 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget): ...@@ -176,11 +177,24 @@ class _NabuPreProcessingConfig(_NabuStageConfigBase, qt.QWidget):
] ]
) )
# tilt correction ## tilt correction
self._tiltCorrection = TiltCorrection("tilt correction", self) self._tiltCorrection = TiltCorrection("tilt correction", self)
self.registerWidget(self._tiltCorrection, "advanced") self.registerWidget(self._tiltCorrection, "advanced")
self.layout().addWidget(self._tiltCorrection, 10, 0, 1, 4) self.layout().addWidget(self._tiltCorrection, 10, 0, 1, 4)
# option dedicated to Helical
## process file
self._processFileQLE = qt.QLabel("file containing weights maps", self)
self._processFileQLE.setToolTip(
"also know as 'process_file'. If you don't have this file it can be created from the 'helical-prepare-weights' widget"
)
self.layout().addWidget(self._processFileQLE, 20, 0, 1, 1)
self._processFileQLE = qt.QLineEdit("", self)
self.registerWidget(self._processFileQLE, "advanced")
self.layout().addWidget(self._processFileQLE, 20, 1, 1, 3)
# style
# spacer for style # spacer for style
spacer = qt.QWidget(self) spacer = qt.QWidget(self)
spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding) spacer.setSizePolicy(qt.QSizePolicy.Minimum, qt.QSizePolicy.Expanding)
......
from tomwer.tests.conftest import qtapp # noqa F401
from tomwer.gui.reconstruction.nabu.helical import HelicalPrepareWeightsDouble
def test_DeltaBetaSelector(
qtapp, # noqa F811
):
"""simple test of the _DeltaBetaSelectorDialog"""
widget = HelicalPrepareWeightsDouble()
assert widget.getConfiguration() == {
"processes_file": "{scan_dir_name}/map_and_doubleff.hdf5",
"transition_width": 50.0,
}
config = {
"processes_file": "test.hdf5",
"transition_width": 12.5,
}
widget.setConfiguration(config=config)
assert widget.getConfiguration() == config
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment