Source code for shapelets

import numpy as np
from ctypes import c_float, c_double
from numpy.polynomial.hermite import Hermite
from typing import Union

[docs] def numpy_eval_hermite(n : int, x : Union[float, np.ndarray]) -> Union[float, np.ndarray]: """This function duplicates what scipy.special.eval_hermite does: Evaluate physicist's Hermite polynomial at a point. Have found that installing `scipy` on some clusters can be problematic (looking at you Pawsey) so implement a numpy version to sidestep needed scipy. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.eval_hermite.html#scipy-special-eval-hermite for more detail Parameters ---------- n : int Order of hermite polynomial x : Union[float, np.ndarray] Coordinate(s) to evaluate the polynomial at Returns ------- Union[float, np.ndarray] The evaulated polynomial values """ ##`Hermite` below will sum all orders of polynomials, with given ##coefficients. We just want herm_coeffs = np.zeros(n + 1) herm_coeffs[n] = 1 herm_func = Hermite(herm_coeffs) return herm_func(x)
[docs] def calc_basis_func_1D_numpy(n : int, x : Union[float, np.ndarray], beta=1) -> np.ndarray: """Calculate shapelet basis function values to use in WODEN. These values work with models fitted using SHAMFI https://github.com/JLBLine/SHAMFI See Line et al. 2020 https://doi.org/10.1017/pasa.2020.18 for more information on shapelet fitting Parameters ---------- n : int Order of shapelet basis function to calculate x : Union[float, np.ndarray] Coordinate(s) to evaluate the basis function at beta : int, optional The x-coord scaling factor, should be 1 when used with WODEN, by default 1 Returns ------- np.ndarray The basis function values """ ##this is the fourier transform of image-based basis functions written into ##Line et al. 2020, so there is a factor of pi difference. Something ##something fourier transform convention something something norm = np.sqrt(beta)*np.sqrt((2**n*float(np.math.factorial(n)))) hermite = numpy_eval_hermite(n, x) gauss = np.exp(-0.5*((x*beta)**2)) return (hermite*gauss) / norm
[docs] def create_sbf(precision = "double", sbf_N = 101, sbf_c = 5000, sbf_dx = 0.01): """Creates a ctypes array of float or doubles, containing shapelet basis functions to feed into `run_woden`. All settings default to settings hard-coded into `libwoden_double.so`, so only mess with them if you know what you're doing. A future iteration of WODEN could have `sbf_N`, `sbf_c`, `sbf_dx` put into `woden_settings` to allow for on-the-fly basis function adjustment. With the defaults listed below, each basis function will be calculate over a range of x = -50 to x = 50, with a resolution of x = 0.01 (for a total of 10001 x values per basis function). The final array is 1D, populated by basis function n = 0 for all x values, up to basis function n = (sbf_N - 1). Parameters ---------- precision : str, optional Precision to return. If set to 'float', uses `c_float`, if set to `double` uses `c_double`. By default set to "double". sbf_N : int, optional Sets what order of basis function to generate up to, by default 101 sbf_c : int, optional Sets the central array value, where x = 0 will be, by default 5000 sbf_dx : float, optional The `x` resolution of each array element, by default 0.01 Returns ------- c_float_Array or c_double_Array All of the basis functions stored in a 1D array of len = 2*sbf_c + 1 """ x_range = np.arange(-sbf_c*sbf_dx, sbf_c*sbf_dx + sbf_dx, sbf_dx) sbf_L = len(x_range) if precision == 'float': sbf = (c_float*(sbf_L*sbf_N))() else: sbf = (c_double*(sbf_L*sbf_N))() for n in range(sbf_N): low_ind = n*sbf_L basis = calc_basis_func_1D_numpy(n, x_range) for basis_ind, sbf_ind in enumerate(range(low_ind, low_ind + sbf_L)): sbf[sbf_ind] = basis[basis_ind] return sbf