Source code for mcalf.utils.misc

import os

import numpy as np
from astropy.io import fits
from scipy.io import readsav


__all__ = ['make_iter', 'load_parameter']


[docs]def make_iter(*args): """Returns each inputted argument, wrapping in a list if not already iterable Parameters ---------- *args Arguments to make iterable. Returns ------- iterables `*args` converted to iterables. Examples -------- >>> make_iter(1) [[1]] >>> make_iter(1, 2, 3) [[1], [2], [3]] >>> make_iter(1, [2], 3) [[1], [2], [3]] It is intended that a list of arguments be passed to the function for conversion: >>> make_iter(*[1, [2], 3]) [[1], [2], [3]] Remember that strings are already iterable! >>> make_iter(*[[1, 2, 3], (4, 5, 6), "a"]) [[1, 2, 3], (4, 5, 6), 'a'] """ iterables = [] # Holder to return for parameter in args: try: # Will work if iterable _ = (i for i in parameter) except TypeError: # Not iterable parameter = [parameter] # Wrap in a list iterables = iterables + [parameter] # Append to list to return return iterables
[docs]def load_parameter(parameter, wl=None): """Load parameters from file, optionally evaluating variables from strings Loads the parameter from string or file. Parameters ---------- parameter : str Parameter to load, either string of Python list/number or filename string. Supported filename extensions are '.fits', '.fit', '.fts', '.csv', '.txt', '.npy', '.npz', and '.sav'. If the file does not exist, it will assume the string is a Python expression. wl : float, optional, default = None Central line core wavelength to replace 'wl' in strings. Will only replace occurrences in the `parameter` variable itself or in files with extension ".csv" or ".txt". When using `wl`, also use 'inf' and 'nan' as required. Returns ------- value : ndarray or list of floats Value of parameter in easily computable format (not string) Examples -------- >>> load_parameter("wl + 4.2", wl=7.1) 11.3 >>> load_parameter("[wl + 4.2, 5.2 - inf, 5 > 3]", wl=7.1) [11.3, -inf, 1.0] Filenames are given as follows: >>> x = load_parameter("datafile.csv", wl=12.4) >>> x = load_parameter("datafile.fits") If the file does not exist, the function will assume that the string is a Python expression, possibly leading to an error: >>> load_parameter("nonexistant.csv") TypeError: 'NoneType' object is not subscriptable """ if os.path.exists(parameter): # If the parameter is a real file ext = os.path.splitext(parameter)[1] # File extension if ext.lower() in ['.fits', '.fit', '.fts']: # Extension suggests FITS file # Read data from the primary HDU of the FITS file hdul = fits.open(parameter) # Open with mmap value = hdul[0].data.copy() # Copy out of mmap hdul.close() # Close the file elif ext.lower() in ['.csv', '.txt']: # Extension suggests CSV file # Read CSV file (assumes a ',' delimiter) if wl is not None: # If `wl` is specified, try a replacement value = str(list(np.loadtxt(parameter, delimiter=',', dtype=object))).replace('\'', '') try: value = eval(str(value), {'__builtins__': None}, {'wl': wl, 'inf': float('inf'), 'nan': float('nan')}) except TypeError: # Only allowed to process `wl` and `inf` variables for security reasons raise SyntaxError("parameter string contains illegal variables") except SyntaxError: raise SyntaxError("parameter string '{}' contains a syntax error".format(parameter)) else: value = np.loadtxt(parameter, delimiter=',', dtype=float) elif ext.lower() in ['.npy', '.npz']: # Extension suggests NumPy array value = np.load(parameter) elif ext.lower() in ['.sav']: # Extension suggests IDL SAVE file (assumes relevant data in first variable) value = list(readsav(parameter).values())[0] else: # Extension not matched raise ValueError("loaded parameters can only have file extensions: '.fits', '.fit', '.fts', '.csv', " "'.txt', '.npy', '.npz', '.sav', got '%s'" % ext.lower()) else: # Must not be a file (or the filename is incorrect!) # Convert to list, calculate relative to central line core (`wl`) value = eval(str(parameter), {'__builtins__': None}, {'wl': wl, 'inf': float('inf')}) try: value = [float(val) for val in value] # Make sure all values are floats except TypeError: value = float(value) return value