Source code for firescipy.instruments.reader

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

# Import the individual instrument parsers from the same package.
# Each parser knows how to read one specific file format.
from .base import InstrumentFile
from .netzsch_sta import read_netzsch_sta_file
from .deatak_mcc import read_deatak_mcc_file
from .netzsch_cone import read_netzsch_cone_file

# Central registry: maps a human-readable instrument name to its parser function.
# To add support for a new instrument, add a new entry here and provide
# a corresponding parser module in this package.
FILE_TYPE_PARSERS = {
    "Netzsch STA": read_netzsch_sta_file,
    "Deatak MCC": read_deatak_mcc_file,
    "Netzsch Cone": read_netzsch_cone_file,
}

# Convenience list of all supported instrument names, derived from the registry.
SUPPORTED_TYPES = list(FILE_TYPE_PARSERS.keys())


[docs]def detect_file_type(file_path): """ Detect instrument file type by inspecting file content. Returns a key from FILE_TYPE_PARSERS, or None if the type is unknown. """ # Read the file using the generic loader (handles encoding automatically). f = InstrumentFile(file_path).read() # An empty file cannot be identified. if not f.lines: return None # Look at the very first line — each format has a unique marker there. first_line = f.lines[0].strip() # Netzsch STA / DSC / TGA exports always start with "#EXPORTTYPE". if first_line.startswith("#EXPORTTYPE"): return "Netzsch STA" # Netzsch Cone Calorimeter exports always start with "General information". if first_line.startswith("General information"): return "Netzsch Cone" # DEATAK MCC exports do not have a fixed first line, but always contain # a line with only "@" that separates metadata from measurement data. for line in f.lines: if line.strip() == "@": return "Deatak MCC" # None of the known markers were found — file type is unknown. return None
[docs]def read_instrument_file(file_path, file_type=None): """ Load an instrument export file, optionally with a manually specified type. Auto-detection is attempted when file_type is None. If detection fails and no file_type is provided, a ValueError is raised with the list of supported types. Parameters ---------- file_path : str or Path Path to the instrument export file. file_type : str, optional Force a specific parser. Must be one of SUPPORTED_TYPES. If None, the file type is detected automatically. Returns ------- file_type : str The detected or provided file type. meta : dict Parsed metadata. df : pandas.DataFrame Parsed measurement table. Raises ------ ValueError If the file type cannot be detected and no file_type is given, or if the provided file_type is not in SUPPORTED_TYPES. """ # If no file type was provided by the caller, try to detect it automatically. if file_type is None: file_type = detect_file_type(file_path) # If detection also failed, stop and tell the user what went wrong. if file_type is None: raise ValueError( f"Could not detect instrument type for '{file_path}'. " f"Specify manually via file_type. Supported: {SUPPORTED_TYPES}" ) # Guard against a typo or unsupported type passed in manually. if file_type not in FILE_TYPE_PARSERS: raise ValueError( f"Unknown file_type '{file_type}'. Supported: {SUPPORTED_TYPES}" ) # Look up the correct parser from the registry and run it. meta, df = FILE_TYPE_PARSERS[file_type](file_path) # Return the file type alongside the data so the caller knows what was loaded. return file_type, meta, df