Source code for padre_meddea.io.amptek

"""
Provides io support for reading files created by the amptek detector.
"""

from datetime import datetime
from pathlib import Path

import astropy.units as u
import numpy as np
from astropy.io.fits import Header
from astropy.nddata import StdDevUncertainty
from numpy.polynomial.polynomial import Polynomial
from specutils import Spectrum1D
from specutils.spectra import SpectralRegion

from padre_meddea.util.util import str_to_fits_keyword


[docs] def read_mca(filename: Path, count_rate=False): """ Read an amptek mca file. Parameters ---------- filename: Path A file to read. count_rate: bool If True, then return data in count rate rather than counts. Returns ------- spectrum: Spectrum1D All meta data with all capitals are direct from the mca file. Lower case metadata is added. Examples -------- """ with open(filename, "r", encoding="unicode_escape") as fp: in_data_section = False in_calib_section = False in_roi_section = False in_dp5config_section = False in_status_section = False in_spectrum_meta_section = False calib_data = {} roi_data = {} data = [] line_number = 0 hdr = Header() meta = {} for line in fp: # figure out what section of the file we are in # the order used here is the order expected in the file # once in new section you are done with the previous section if line.count("PMCA SPECTRUM"): in_spectrum_meta_section = True continue if line.count("CALIBRATION"): in_calib_section = True in_spectrum_meta_section = False continue if line.count("ROI"): in_roi_section = True in_calib_section = False in_spectrum_meta_section = False continue if line.count("DATA"): in_data_section = True in_roi_section = False continue if line.count("END"): in_data_section = False if line.count("DP5 CONFIGURATION"): in_dp5config_section = True in_data_section = False continue if line.count("DPP STATUS"): in_dp5config_section = False in_status_section = True continue # now gather information if in_spectrum_meta_section: # this is a measurement metadata tag keyword = line.split("-")[0] value = line.split("-")[1].strip() try: value = float(value) except ValueError: pass hdr.append((str_to_fits_keyword(keyword), value)) if in_calib_section: if line.count("-"): continue else: channel = float(line.split(" ")[0]) energy = float(line.split(" ")[1]) calib_data.update({channel: energy}) if in_roi_section: roi_data.update({int(line.split(" ")[0]): int(line.split(" ")[1])}) if in_data_section and not (line.count("<<") == 1): data.append(int(line)) if in_dp5config_section and not (line.count("<<") == 1): keyword = line.split("=")[0].upper() value = line.split("=")[1].split(";")[0].strip() description = line.split("=")[1].split(";")[1].strip() try: value = float(value) except ValueError: pass hdr.append((str_to_fits_keyword(keyword), value, description)) if in_status_section and not (line.count("<<") == 1): keyword = line.split(":")[0] value = line.split(":")[1].strip() try: value = float(value) except ValueError: pass hdr.append((str_to_fits_keyword(keyword), value)) line_number += 1 if count_rate: y = u.Quantity(np.array(data) / hdr["REALTIME"], "ct/s") uncertainty = StdDevUncertainty( u.Quantity(np.sqrt(data) / hdr["REALTIME"], "ct/s") ) else: y = data * u.ct uncertainty = StdDevUncertainty(np.sqrt(data) * u.ct) if roi_data: rois = SpectralRegion( [[x1 * u.pix, x2 * u.pix] for x1, x2 in roi_data.items()] ) meta.update({"header": hdr}) meta.update({"roi": rois}) meta.update({"livetime": hdr["LIVETIME"] * u.s}) meta.update({"realtime": hdr["REALTIME"] * u.s}) meta.update( {"obs_time": datetime.strptime(hdr["starttim"], "%m/%d/%Y %H:%M:%S")} ) meta.update({"filename": filename}) meta.update({"dtimfrac": 1 - hdr["livetime"] / hdr["realtime"]}) meta.update({"rate": np.sum(data) * u.ct / meta["realtime"]}) if len(calib_data) > 0: channels = list(calib_data.keys()) energies = list(calib_data.values()) meta.update({"calib": Polynomial.fit(channels, energies, deg=1)}) spectrum = Spectrum1D( flux=y, spectral_axis=np.arange(len(data)) * u.pix, uncertainty=uncertainty, # TODO add uncertainty, problem with ct/s as unit meta=meta, ) return spectrum