Commit a535a5b5 authored by payno's avatar payno
Browse files

[operation] add GradientRemoval operation

create a sub class _MappingBase to get the same interface between IntensityMapping and GradientRemoval.
This also allow to use the PlotMapping class for both.
parent d719ad15
......@@ -216,6 +216,12 @@ class Experiment(object):
if isinstance(operation, DataReduction):
self._data_reduction_operations.append(operation)
def getOperation(self, id):
if id in self.operations:
return self.operations[id]
else:
return None
def _getRoiOperations(self):
"""
......
......@@ -35,7 +35,24 @@ import logging
_logger = logging.getLogger(__file__)
class IntensityMapping(AdditiveOperation):
class _MappingBase(AdditiveOperation):
"""
Base class used for mapping
"""
@property
def dim(self):
raise NotImplementedError('Base class')
@property
def intensity_map(self):
raise NotImplementedError('Base class')
@property
def ndim(self):
raise NotImplementedError('Base class')
class IntensityMapping(_MappingBase):
"""
for each detector pixel (x,y), each data dimension (motors scanned/rocked)
are evaluated: 1) intensity is summed along all other dimensions than the
......@@ -45,9 +62,10 @@ class IntensityMapping(AdditiveOperation):
:param float or None threshold: if the threshold is None then the mean
value of the current data will be take
"""
KEY = 'intensity mapping'
def __init__(self, experiment, threshold=None):
AdditiveOperation.__init__(self, experiment=experiment,
name='intensity mapping')
_MappingBase.__init__(self, experiment=experiment, name=self.KEY)
self._dim = []
if threshold is None:
self._threshold = numpy.median(self.data)
......@@ -58,7 +76,7 @@ class IntensityMapping(AdditiveOperation):
self.__dim = []
def key(self):
return self._name
return self.KEY
def compute(self):
_logger.info('start computing the dx2d map')
......@@ -126,3 +144,83 @@ class IntensityMapping(AdditiveOperation):
@property
def dim(self):
return self.__dim
@property
def ndim(self):
return len(self.__dim)
class GradientRemoval(_MappingBase):
"""
Compute gradient for the current intensity and remove it from the initial
intensity calculation
"""
def __init__(self, experiment):
_MappingBase.__init__(self, experiment=experiment,
name='gradient removal')
self._gradients = None
self.__dim = []
self.__intensity_map = None
def dry_run(self, cache_data=None):
raise ValueError('Not available for Gradient removal yet')
def compute(self):
# TODO: why delta = 0.567
delta = 0.567
# TODO: for now we ask experiment for the intensity mapping if computed
mapping = self._experiment.getOperation(IntensityMapping.KEY)
if mapping is None:
_logger.error('unable to process gradient correction, mapping '
'needs to be proceed before.')
return
self.__dim = self.apply_gradient_correction(self.data, delta=delta, mapping=mapping)
self.__intensity_map = mapping.intensity_map[...]
self.registerOperation()
@staticmethod
def apply_gradient_correction(data, delta, mapping):
assert isinstance(mapping, IntensityMapping)
# TODO: number of element: for now only square matrices but if evolve ?
corr2, corr1 = numpy.meshgrid(
numpy.linspace(-delta, delta, data.shape[2]),
numpy.linspace(0, 0, data.shape[1]))
_gradients = []
# TODO: if necessary compute mean...
for iDim in range(mapping.ndim):
gradient = mapping.dim[iDim][...]
# TODO: for now gradient corrcetion is only apply on mean, why ?
# TODO: this should be in enumerate(Mode) but intensity is stored
# in an other struct, why ?
_gradient = numpy.asarray((
gradient[:, :, 0] + corr2,
gradient[:, :, 1] + corr2,
gradient[:, :, 2] + corr2,
gradient[:, :, 3] + corr2)
)
_gradients.append(_gradient)
return _gradients
def gradients(self):
return self._gradients
def key(self):
return self._name
@property
def dim(self):
return self.__dim
@property
def intensity_map(self):
return self.__intensity_map
@property
def ndim(self):
return len(self.__dim)
......@@ -31,61 +31,12 @@ __date__ = "15/10/2018"
import logging
from . import AdditiveOperation, OverwritingOperation
from .mapping import IntensityMapping
import numpy
_logger = logging.getLogger(__file__)
class GradientCalculation(AdditiveOperation):
"""
Compute gradient for the current intensity
"""
def __init__(self, experiment):
AdditiveOperation.__init__(self, experiment=experiment,
name='gradient removal')
self._gradients = None
def compute(self):
try:
# TODO: in the future create the operation if not existing
intensityOperation = self._experiment.getOperation('intensity')
except Exception as e:
_logger.error(e)
return
# TODO: how to get delta ?
delta = 0.567
corr2, corr1 = numpy.meshgrid(
numpy.linspace(-delta, delta, self.data.shape[0]),
numpy.linspace(0, 0,
self.data.shape[0]))
self._gradients = []
# TODO: if necessary compute mean...
for iDim in self._experiment.ndim:
gradient = intensityOperation.dim[iDim][...]
gradient = gradient + corr2
self._gradients.append(gradient)
self.registerOperation()
return self._gradients
def gradients(self):
return self._gradients
def key(self):
return self._name
class GradientRemoval(OverwritingOperation):
"""Apply a gradient removal to the data"""
pass
def key(self):
return self._name
class ThresholdRemoval(OverwritingOperation):
"""
Apply a simple threshold filtering on data
......
......@@ -204,7 +204,6 @@ class FileList(qt.QTableWidget):
itemIndex = self.row(item)
self.takeItem(itemIndex, 0)
self._selection.remove(item.text())
# ScanList.remove(self, item.text())
self.removeRow(item.row())
self.setRowCount(self.rowCount() - 1)
self._update()
......
......@@ -32,7 +32,7 @@ from silx.gui import qt
from silx.gui.plot import Plot2D
from id06workflow.gui import icons
from id06workflow.core.mapping import MEAN, VARIANCE, SKENESS, KURTOSIS, MODES, INTENSITY
from id06workflow.core.experiment.operation.mapping import IntensityMapping
from id06workflow.core.experiment.operation.mapping import _MappingBase
from id06workflow.gui.settings import DEFAULT_COLORMAP
from collections import OrderedDict
import functools
......@@ -124,7 +124,7 @@ class MappingPlot(qt.QMainWindow):
self._data[SKENESS] = self._data[KURTOSIS] = None
if operation is not None:
assert isinstance(operation, IntensityMapping)
assert isinstance(operation, _MappingBase)
self._data[INTENSITY] = operation.intensity_map
self._data[MEAN] = operation.dim[0][:, :, 0]
self._data[VARIANCE] = operation.dim[0][:, :, 1]
......
......@@ -99,6 +99,7 @@ class NoiseReductionWidget(qt.QWidget):
threshold = self._paramsWidget.getUpperThreshold()
if threshold is not None:
self._upperThreshold.threshold = threshold
self._upperThreshold.replacement_value = 0.0
self._cache_data = self._upperThreshold.dry_run(self._cache_data)
threshold = self._paramsWidget.getLowerThreshold()
if threshold is not None:
......
# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/
__authors__ = ["H. Payno"]
__license__ = "MIT"
__date__ = "16/10/2018"
from Orange.widgets import gui
from Orange.widgets.widget import OWWidget
from Orange.canvas.registry.description import InputSignal, OutputSignal
from id06workflow.gui.mapping import MappingPlot
from id06workflow.core.experiment import Experiment
from id06workflow.core.experiment.operation.mapping import GradientRemoval
from id06workflow.core.types import _Image
class GradientRemovalOW(OWWidget):
"""
Widget used to define the calibration of the experimentation (select motor
positions...)
"""
name = "Gradient removal"
id = "orange.widgets.id06workflow.gradientremoval"
description = "Remove gradient artifact"
icon = "icons/gradientremoval.svg"
priority = 4
category = "esrfWidgets"
keywords = ["dataset", "gradient", "removal"]
inputs = [InputSignal(name="data", type=Experiment, handler='_process')]
outputs = [OutputSignal(name="data", type=Experiment),
OutputSignal(name="image", type=_Image)]
want_main_area = True
resizing_enabled = True
compress_signal = False
def __init__(self):
super().__init__()
layout = gui.vBox(self.mainArea, 'noise removal').layout()
self._plot = MappingPlot(parent=self)
layout.addWidget(self._plot)
def _process(self, experiment):
if experiment is None:
return
operation = GradientRemoval(experiment=experiment)
operation.compute()
self.send("image",
_Image(img=operation.dim[0][:, :, 0], name='mean'))
self._plot.setOperation(operation)
self.send("data", experiment)
OWWidget.accept(self)
This diff is collapsed.
......@@ -69,7 +69,7 @@ class MappingOW(OWWidget):
def _process(self, experiment):
if experiment is None:
return
# try:
operation = IntensityMapping(experiment=experiment)
operation.compute()
self.send("image",
......@@ -77,15 +77,12 @@ class MappingOW(OWWidget):
self.send("image",
_Image(img=operation.dim[0][:, :, 0], name='mean'))
self.send("image",
_Image(img=operation.dim[0][:, :, 1], name='varaiance'))
_Image(img=operation.dim[0][:, :, 1], name='variance'))
self.send("image",
_Image(img=operation.dim[0][:, :, 2], name='skeness'))
self.send("image",
_Image(img=operation.dim[0][:, :, 3], name='kurtosis'))
self._plot.setOperation(operation)
#
# except Exception as e:
# _logger.error(e)
self.send("data", experiment)
......
......@@ -86,7 +86,7 @@ class NoiseReductionOW(OWWidget):
if experiment is None:
return
assert isinstance(experiment, Experiment)
if experiment.getRawData() is None:
if experiment.data is None:
_logger.warning('dataset is empty, won\'t apply noise removal')
else:
self._widget.reset(experiment)
......
......@@ -86,7 +86,7 @@ class RoiSelectionOW(OWWidget):
else:
assert experiment is not None
self._editedExperiment = experiment
self._widget.setStack(self._editedExperiment.getRawData())
self._widget.setStack(self._editedExperiment.data)
self._buttons.show()
self.show()
......
Supports Markdown
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