Source code for spectrochempy.core.writers.exporter

# ======================================================================================
# Copyright (©) 2015-2025 LCS - Laboratoire Catalyse et Spectrochimie, Caen, France.
# CeCILL-B FREE SOFTWARE LICENSE AGREEMENT
# See full LICENSE agreement in the root directory.
# ======================================================================================
"""Define a generic class to import files and contents."""

__all__ = ["write"]
__dataset_methods__ = __all__

from traitlets import Any
from traitlets import HasTraits

from spectrochempy.utils.file import check_filename_to_save
from spectrochempy.utils.file import pathclean
from spectrochempy.utils.file import patterns


# --------------------------------------------------------------------------------------
class Exporter(HasTraits):
    # Exporter class

    object = Any()

    def __init__(self):
        FILETYPES = [
            ("scp", "SpectroChemPy files (*.scp)"),
            ("labspec", "LABSPEC exported files (*.txt)"),
            ("matlab", "MATLAB files (*.mat)"),
            ("dso", "Data Set Object files (*.dso)"),
            ("jcamp", "JCAMP-DX files (*.jdx *dx)"),
            ("csv", "CSV files (*.csv)"),
            ("excel", "Microsoft Excel files (*.xls)"),
        ]

        self.filetypes = dict(FILETYPES)
        self.protocols = {}
        for protocol, filter in self.filetypes.items():
            for s in patterns(filter, allcase=False):
                self.protocols[s[1:]] = protocol

    def __call__(self, *args, **kwargs):
        args = self._setup_object(*args)

        try:
            if "filetypes" not in kwargs:
                kwargs["filetypes"] = list(self.filetypes.values())
                if args and args[0] is not None:  # filename
                    protocol = self.protocols[pathclean(args[0]).suffix]
                    kwargs["filetypes"] = [self.filetypes[protocol]]
            filename = check_filename_to_save(self.object, *args, **kwargs)
            if filename is None:
                return None
            if kwargs.get("suffix", ""):
                filename = filename.with_suffix(kwargs.get("suffix", ""))
            protocol = self.protocols[filename.suffix]
            write_ = getattr(self, f"_write_{protocol}")
            write_(self.object, filename, **kwargs)
            return filename

        except Exception as e:
            raise e

    def _setup_object(self, *args):
        # check if the first argument is an instance of NDDataset or Project
        args = list(args)

        if (
            args
            and hasattr(args[0], "_implements")
            and args[0]._implements() in ["NDDataset"]
        ):
            # the first arg is an instance of NDDataset
            self.object = args.pop(0)

        else:
            raise TypeError(
                "the API write method needs a NDDataset object as the first argument",
            )

        return args


def exportermethod(func):
    # Decorator
    setattr(Exporter, func.__name__, staticmethod(func))
    return func


# --------------------------------------------------------------------------------------
# Generic Read function
# --------------------------------------------------------------------------------------
[docs] def write(dataset, filename=None, **kwargs): """ Write the current dataset. Parameters ---------- dataset : `NDDataset` Dataset to write. filename : str or pathlib object, optional If not provided, a dialog is opened to select a file for writing. **kwargs Optional keyword parameters (see Other Parameters). Returns ------- output_path Path of the output file. Other Parameters ---------------- protocol : {'scp', 'matlab', 'jcamp', 'csv', 'excel'}, optional Protocol used for writing. If not provided, the correct protocol is inferred (whnever it is possible) from the file name extension. directory : str, optional Where to write the specified `filename` . If not specified, write in the current directory. description: str, optional A Custom description. csv_delimiter : str, optional Set the column delimiter in CSV file. By default it is the one set in SpectroChemPy `Preferences` . See Also -------- save : Generic function for saving a NDDataset in SpectroChemPy format. Examples -------- write a dataset (providing a windows type filename relative to the default `Datadir` ) >>> nd = scp.read_opus('irdata/OPUS') >>> f = nd.write('opus.scp') # doctest: +SKIP >>> f.name # doctest: +SKIP 'opus.scp' # doctest: +SKIP """ exporter = Exporter() return exporter(dataset, filename, **kwargs)
@exportermethod def _write_scp(*args, **kwargs): dataset, filename = args dataset.filename = filename return dataset.dump(filename, **kwargs)