Skip to content

Commit

Permalink
Merge pull request #718 from brnovasco/extend-shift-spectra
Browse files Browse the repository at this point in the history
Extend shift spectra
  • Loading branch information
markotoplak committed Jul 24, 2024
2 parents 17b239e + b192971 commit 78a85e3
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 28 deletions.
32 changes: 22 additions & 10 deletions orangecontrib/spectroscopy/preprocess/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,28 +730,40 @@ def __call__(self, data):
return data.transform(domain)


class CurveShiftFeature(SelectColumn):
class ShiftAndScaleFeature(SelectColumn):
InheritEq = True


class _CurveShiftCommon(CommonDomain):
class _ShiftAndScaleCommon(CommonDomain):

def __init__(self, amount, domain):
def __init__(self, offset, scale, domain):
super().__init__(domain)
self.amount = amount
self.offset = offset
self.scale = scale


def transformed(self, data):
return data.X + self.amount
return self.scale * data.X + self.offset


class CurveShift(Preprocess):
class ShiftAndScale(Preprocess):
"""
Shift and scale of the data into the form:
y = scale * x + offset
def __init__(self, amount=0.):
self.amount = amount
Parameters
----------
offset : float
scale : float
"""

def __init__(self, offset=0., scale=1.):
self.offset = offset
self.scale = scale

def __call__(self, data):
common = _CurveShiftCommon(self.amount, data.domain)
atts = [a.copy(compute_value=CurveShiftFeature(i, common))
common = _ShiftAndScaleCommon(self.offset, self.scale, data.domain)
atts = [a.copy(compute_value=ShiftAndScaleFeature(i, common))
for i, a in enumerate(data.domain.attributes)]
domain = Orange.data.Domain(atts, data.domain.class_vars,
data.domain.metas)
Expand Down
10 changes: 5 additions & 5 deletions orangecontrib/spectroscopy/tests/test_preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from orangecontrib.spectroscopy.preprocess import Absorbance, Transmittance, \
Integrate, Interpolate, Cut, SavitzkyGolayFiltering, \
GaussianSmoothing, PCADenoising, RubberbandBaseline, \
Normalize, LinearBaseline, CurveShift, EMSC, MissingReferenceException, \
Normalize, LinearBaseline, ShiftAndScale, EMSC, MissingReferenceException, \
WrongReferenceException, NormalizeReference, XASnormalization, ExtractEXAFS, \
PreprocessException, NormalizePhaseReference, Despike, SpSubtract
from orangecontrib.spectroscopy.preprocess.als import ALSP, ARPLS, AIRPLS
Expand Down Expand Up @@ -58,7 +58,7 @@ def preprocessor_data(preproc):
Normalize(method=Normalize.Vector),
Normalize(method=Normalize.Area, int_method=Integrate.PeakMax, lower=0, upper=10000),
Normalize(method=Normalize.MinMax),
CurveShift(1),
ShiftAndScale(1, 2),
Despike(threshold=5, cutoff=60, dis=5),
ALSP(lam=100E+6, itermax=5, p=0.5),
ARPLS(lam=100E+5, itermax=5, ratio=0.5),
Expand Down Expand Up @@ -588,14 +588,14 @@ def test_iris(self):
[4.75015528, 3.15366444, 1.46254138, 0.23693223]])


class TestCurveShift(unittest.TestCase):
class TestShiftAndScale(unittest.TestCase):

def test_simple(self):
data = Table.from_numpy(None, [[1.0, 2.0, 3.0, 4.0]])
f = CurveShift(amount=1.1)
f = ShiftAndScale(offset=1.1, scale=2.)
fdata = f(data)
np.testing.assert_almost_equal(fdata.X,
[[2.1, 3.1, 4.1, 5.1]])
[[3.1, 5.1, 7.1, 9.1]])


class TestUtils(unittest.TestCase):
Expand Down
6 changes: 5 additions & 1 deletion orangecontrib/spectroscopy/widgets/owpreprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from Orange.widgets.data.utils.preprocess import SequenceFlow, Controller, \
StandardItemModel
from Orange.widgets.data.owpreprocess import (
PreprocessAction, Description, icon_path, DescriptionRole, ParametersRole, blocked
PreprocessAction, Description, icon_path, DescriptionRole, ParametersRole
)
from Orange.widgets.utils.sql import check_sql_input
from Orange.widgets.utils.overlay import OverlayWidget
Expand Down Expand Up @@ -988,6 +988,10 @@ def migrate_preprocessor(cls, preprocessor, version):
if name == "orangecontrib.infrared.cutinverse":
name = "orangecontrib.spectroscopy.cut"
settings["inverse"] = True
if name == "orangecontrib.infrared.curveshift":
name = "orangecontrib.spectroscopy.shiftandscale"
settings["offset"] = settings.get("amount", 0.)
settings["scale"] = 1.
return [((name, settings), version)]

@classmethod
Expand Down
30 changes: 18 additions & 12 deletions orangecontrib/spectroscopy/widgets/preprocessors/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from orangecontrib.spectroscopy.preprocess import (
PCADenoising, GaussianSmoothing, Cut, SavitzkyGolayFiltering,
Absorbance, Transmittance,
CurveShift, SpSubtract
ShiftAndScale, SpSubtract
)
from orangecontrib.spectroscopy.preprocess.transform import SpecTypes
from orangecontrib.spectroscopy.widgets.gui import lineEditFloatRange, MovableVline, \
Expand Down Expand Up @@ -294,34 +294,40 @@ def createinstance(cls, params):
return SavitzkyGolayFiltering(window=window, polyorder=polyorder, deriv=deriv)


class CurveShiftEditor(BaseEditorOrange):
class ShiftAndScaleEditor(BaseEditorOrange):
"""
Editor for CurveShift
Editor for ShiftAndScale
"""
# TODO: the layout changes when I click the area of the preprocessor
# EFFECT: the sidebar snaps in

name = "Shift Spectra"
qualname = "orangecontrib.infrared.curveshift"
name = "Shift and scale"
qualname = "orangecontrib.spectroscopy.shiftandscale"
replaces = ["orangecontrib.infrared.curveshift"]

def __init__(self, parent=None, **kwargs):
super().__init__(parent, **kwargs)

self.amount = 0.
self.offset = 0.
self.scale = 1.

form = QFormLayout()
amounte = lineEditFloatRange(self, self, "amount", callback=self.edited.emit)
form.addRow("Shift Amount", amounte)
offset_input = lineEditFloatRange(self, self, "offset", callback=self.edited.emit)
form.addRow("Vertical offset", offset_input)
scale_input = lineEditFloatRange(self, self, "scale", callback=self.edited.emit)
form.addRow("Vertical scaling", scale_input)
self.controlArea.setLayout(form)

def setParameters(self, params):
self.amount = params.get("amount", 0.)
self.amount = params.get("offset", 0.)
self.scale = params.get("scale", 1.)

@staticmethod
def createinstance(params):
params = dict(params)
amount = float(params.get("amount", 0.))
return CurveShift(amount=amount)
offset = float(params.get("offset", 0.))
scale = float(params.get("scale", 1.))
return ShiftAndScale(offset=offset, scale=scale)


class PCADenoisingEditor(BaseEditorOrange):
Expand Down Expand Up @@ -453,5 +459,5 @@ def update_reference_info(self):
preprocess_editors.register(SavitzkyGolayFilteringEditor, 100)
preprocess_editors.register(PCADenoisingEditor, 200)
preprocess_editors.register(SpectralTransformEditor, 225)
preprocess_editors.register(CurveShiftEditor, 250)
preprocess_editors.register(ShiftAndScaleEditor, 250)
preprocess_editors.register(SpSubtractEditor, 275)

0 comments on commit 78a85e3

Please sign in to comment.