diff --git a/MANIFEST.in b/MANIFEST.in index 890b8fb22..67c856d56 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -7,6 +7,7 @@ recursive-include orangecontrib/spectroscopy/datasets emsc/* recursive-include orangecontrib/spectroscopy/datasets NeaReaderGSF_test/* recursive-include orangecontrib/spectroscopy/datasets renishaw_test_files/* recursive-include orangecontrib/spectroscopy/datasets photothermal/* +recursive-include orangecontrib/spectroscopy/datasets perkinelmer/* global-exclude __pycache__ diff --git a/orangecontrib/spectroscopy/datasets/perkinelmer/4x4_pixel_PE_image.fsm b/orangecontrib/spectroscopy/datasets/perkinelmer/4x4_pixel_PE_image.fsm new file mode 100644 index 000000000..00886b434 Binary files /dev/null and b/orangecontrib/spectroscopy/datasets/perkinelmer/4x4_pixel_PE_image.fsm differ diff --git a/orangecontrib/spectroscopy/datasets/perkinelmer/single_PE_spectrum.sp b/orangecontrib/spectroscopy/datasets/perkinelmer/single_PE_spectrum.sp new file mode 100644 index 000000000..5c0c45b30 Binary files /dev/null and b/orangecontrib/spectroscopy/datasets/perkinelmer/single_PE_spectrum.sp differ diff --git a/orangecontrib/spectroscopy/io/__init__.py b/orangecontrib/spectroscopy/io/__init__.py index ddceab36f..9f33338d6 100644 --- a/orangecontrib/spectroscopy/io/__init__.py +++ b/orangecontrib/spectroscopy/io/__init__.py @@ -17,6 +17,7 @@ from .opus import OPUSReader from .ptir import PTIRFileReader from .wire import WiREReaders +from .perkinelmer import PerkinElmerReader # Facility-specific readers from .diamond import NXS_STXM_Diamond_I08 diff --git a/orangecontrib/spectroscopy/io/perkinelmer.py b/orangecontrib/spectroscopy/io/perkinelmer.py new file mode 100644 index 000000000..e4d730d79 --- /dev/null +++ b/orangecontrib/spectroscopy/io/perkinelmer.py @@ -0,0 +1,165 @@ +import os + +import numpy as np + +from Orange.data import Table, Domain, FileFormat + +from orangecontrib.spectroscopy.io.util import SpectralFileFormat, _spectra_from_image_2d +from orangecontrib.spectroscopy.utils.specio.specio import BlockReader, PerkinElmer + +# This code is partially based on software developed in the Diamond synchrotron. + + +class PerkinElmerReader(FileFormat, SpectralFileFormat): + EXTENSIONS = (".sp", ".fsm",) + DESCRIPTION = "Perkin Elmer" + + def read_sp(self): + with open(self.filename, "rb") as f: + data = f.read() + + reader = BlockReader(data) + + info = { + "signature": reader.read(4, format="utf-8"), + "description": reader.read(40, format="utf-8"), + } + + decoders = { + 25739: PerkinElmer.decode25739, + 35698: PerkinElmer.decode35698, + 35699: PerkinElmer.decode35699, + 35700: PerkinElmer.decode35700, + 35701: PerkinElmer.decode35701, + 35708: PerkinElmer.decode35708, + } + + stops = [] + spectrum = [] + + block_id, block_size = reader.read(6, + format="= stops[-1]: + stops = stops[:-1] + + else: + block_id, block_size = reader.read(6, + format="= self.size - step + + @property + def size(self): + return len(self.data) + + @staticmethod + def readData(data, start, step, format=None, expect_tuple=False): + block = data[start: start + step] + return BlockReader.format(block, + format, + expect_tuple=expect_tuple) + + @staticmethod + def format(data, format, expect_tuple=False): + DECODE_FORMATS = [ + "utf-8", + ] + + if format == None: + return data + + if format in DECODE_FORMATS: + assert (not expect_tuple) + + return BlockReader._decode(data, format) + + unpacked = BlockReader._unpack(data, format) + + if expect_tuple: + return unpacked + + return BlockReader._asSingular(unpacked) + + @staticmethod + def _decode(data, format): + return data.decode(format) + + @staticmethod + def _unpack(data, format): + return struct.unpack(format, data) + + @staticmethod + def _asSingular(unpacked): + assert (len(unpacked) == 1) + + return unpacked[0] + + +class PerkinElmer: + @staticmethod + def varIdDecode(data, var_id, format, step, expect_tuple=False): + _var_id = BlockReader.readData(data, 0, 2, "