def test_Q(): assert_raises(ValueError, rft.Q, -1) assert_raises(ValueError, rft.Q, 0) x = np.arange(-9, 10) for dim in range(1, 4): res = rft.Q(dim) assert_almost_equal(res(x), hermitenorm(dim - 1)(x))
def test_polynomial2(): # EC density of chi^2(1) is 2 * EC density of Gaussian so polynomial part is # a factor of 2 as well. for dim in range(1,10): q = rft.ChiSquared(dfn=1).quasi(dim) h = hermitenorm(dim-1) yield assert_almost_equal, q.c, 2*h.c
def Q(dim, dfd=np.inf): """ Q polynomial If dfd == inf (the default), then Q(dim) is the (dim-1)-st Hermite polynomial H_j(x) = (-1)^j * e^{x^2/2} * (d^j/dx^j e^{-x^2/2}) If dfd != inf, then it is the polynomial Q defined in Worsley, K.J. (1994). 'Local maxima and the expected Euler characteristic of excursion sets of \chi^2, F and t fields.' Advances in Applied Probability, 26:13-42. """ m = dfd j = dim if j > 0: poly = hermitenorm(j - 1) poly = np.poly1d(np.around(poly.c)) if np.isfinite(m): for l in range((j - 1) / 2 + 1): f = np.exp( gammaln((m + 1) / 2.0) - gammaln((m + 2 - j + 2 * l) / 2.0) - 0.5 * (j - 1 - 2 * l) * (np.log(m / 2.0)) ) poly.c[2 * l] *= f return np.poly1d(poly.c) else: raise ValueError, "Q defined only for dim > 0"
def gaussflux(pixbound, cen, sig, h_order=0): """ For monotonically increasing pixel boundaries specified by 'pixbound' in some abscissa units, consider a Gaussian with unit integrated amplitude that expresses a density per those same abscissa units, centered on 'cen' and with sigma parameter 'sig', and return the average value of that Gaussian between the boundaries (i.e., its pixel-averaged value for possibly non-uniform pixels.) Can specify a Gauss-Hermite order (a la scipy.special.hermitenorm) via the 'h_order' argument, which defaults to zero. (bolton@utah@iac 2014mayo) (Added Hermite orders: bolton@utah@iac 2014junio) """ # Calculate the pixel widths and test for monotonicity: pixdiff = pixbound[1:] - pixbound[:-1] if (pixdiff.min <= 0): print 'pixbound must be monotonically increasing!' return 0 # Make sure scalar arguments are scalars: if (n.asarray(cen).size != 1): print 'cen argument must be scalar!' return 0 if (n.asarray(sig).size != 1): print 'sig argument must be scalar!' return 0 # Compute and return: if h_order > 0: u = (pixbound - cen) / sig int_term = - spc.hermitenorm(h_order-1)(u) * n.exp(-0.5 * u**2) / \ n.sqrt(2. * n.pi) else: int_term = 0.5 * spc.erf((pixbound - cen) / (n.sqrt(2.) * sig)) return (int_term[1:] - int_term[:-1]) / pixdiff
def test_polynomial2(): # EC density of chi^2(1) is 2 * EC density of Gaussian so polynomial part is # a factor of 2 as well. for dim in range(1, 10): q = rft.ChiSquared(dfn=1).quasi(dim) h = hermitenorm(dim - 1) yield assert_almost_equal, q.c, 2 * h.c
def gen_grad_dict_dot_f(self, Xdot, X): """ compute the gradient of phi dot product with f :type Xdot: np.ndarray :param Xdot: time derivative of state :return: generated_gradPhi_dot_f_array :rtype: np.ndarray """ num_sample, num_components = Xdot.shape if self.dict == 'hermite': # normalized hermite polynomial ## compute [ [d[H0(x1).. H0(xn)]/dx1,...,d[HN(x1).. HN(xn)]/dx1 ], # ... # [d[H0(x1).. H0(xn)]/dxn,...,d[HN(x1).. HN(xn)]/dxn ] ] generated_feature_array_list = [] feature_list_ddx_list = [] for i_component in range(num_components): feature_list = [] for order in range(self.hermite_order + 1): phi_i = hermitenorm(order) phi_i_dx = np.poly1d.deriv(phi_i) phi_i_X = np.polyval(phi_i, X) # update i_component with the derivative one phi_i_X[:, i_component] = np.polyval(phi_i_dx, X[:, i_component]) feature_list.append(phi_i_X) feature_list_ddx_list.append(feature_list) # generate feature array from feature list for each i_component generated_feature_array = self.gen_cross_component_features( feature_list=feature_list, num_sample=num_sample, num_components=num_components) # dot product f with the gradient Xdot_i_component = Xdot[:, i_component] Xdot_i_matrix = np.diag(Xdot_i_component) generated_feature_array_list.append( np.matmul(Xdot_i_matrix, generated_feature_array)) # summing up the dot product for each component generated_gradPhi_dot_f_array = np.sum( generated_feature_array_list, axis=0) elif self.dict == 'rff_gaussian': generated_gradPhi_dot_f_array = self.gen_rff_features_dot(Xdot, X) elif self.dict == 'nystrom': pass else: raise NotImplementedError("the type of " + self.dict + " is not implemented yet!") return generated_gradPhi_dot_f_array
def gaussflux(pixbound, cen, sig, h_order=0): """ For monotonically increasing pixel boundaries specified by 'pixbound' in some abscissa units, consider a Gaussian with unit integrated amplitude that expresses a density per those same abscissa units, centered on 'cen' and with sigma parameter 'sig', and return the average value of that Gaussian between the boundaries (i.e., its pixel-averaged value for possibly non-uniform pixels.) Can specify a Gauss-Hermite order (a la scipy.special.hermitenorm) via the 'h_order' argument, which defaults to zero. (bolton@utah@iac 2014mayo) (Added Hermite orders: bolton@utah@iac 2014junio) """ # Calculate the pixel widths and test for monotonicity: pixdiff = pixbound[1:] - pixbound[:-1] if (pixdiff.min <= 0): print('pixbound must be monotonically increasing!') return 0 # Make sure scalar arguments are scalars: if (n.asarray(cen).size != 1): print('cen argument must be scalar!') return 0 if (n.asarray(sig).size != 1): print('sig argument must be scalar!') return 0 # Compute and return: if h_order > 0: u = (pixbound - cen) / sig int_term = - spc.hermitenorm(h_order-1)(u) * n.exp(-0.5 * u**2) / \ n.sqrt(2. * n.pi) else: int_term = 0.5 * spc.erf((pixbound - cen) / (n.sqrt(2.) * sig)) return (int_term[1:] - int_term[:-1]) / pixdiff
def get_polys(self, x): """ Calculates the normalized Hermite polynomials evaluated at sample points. **Inputs:** * **x** (`ndarray`): `ndarray` containing the samples. **Outputs:** (`list`): Returns a list of 'ndarrays' with the design matrix and the normalized polynomials. """ a, b = -np.inf, np.inf mean_ = Polynomials.get_mean(self) std_ = Polynomials.get_std(self) x_ = Polynomials.standardize_normal(x, mean_, std_) norm = Normal(0, 1) pdf_st = norm.pdf p = [] for i in range(self.degree): p.append(special.hermitenorm(i, monic=False)) return Polynomials.normalized(self.degree, x_, a, b, pdf_st, p)
def __init__(self, filename): """ Initialize GaussHermitePSF from input file """ #- Check that this file is a current generation Gauss Hermite PSF fx = fits.open(filename, memmap=False) self._polyparams = hdr = fx[1].header if 'PSFTYPE' not in hdr: raise ValueError, 'Missing PSFTYPE keyword' if hdr['PSFTYPE'] != 'GAUSS-HERMITE2': raise ValueError, 'PSFTYPE %s is not GAUSS-HERMITE' % hdr['PSFTYPE'] if 'PSFVER' not in hdr: raise ValueError, "PSFVER missing; this version not supported" if hdr['PSFVER'] < '1': raise ValueError, "Only GAUSS-HERMITE versions 1.0 and greater are supported" #- Calculate number of spectra from FIBERMIN and FIBERMAX (inclusive) self.nspec = hdr['FIBERMAX'] - hdr['FIBERMIN'] + 1 #- Other necessary keywords self.npix_x = hdr['NPIX_X'] self.npix_y = hdr['NPIX_Y'] #- Load the parameters into self.coeff dictionary keyed by PARAM #- with values as TraceSets for evaluating the Legendre coefficients data = fx[1].data self.coeff = dict() for p in data: domain = (p['WAVEMIN'], p['WAVEMAX']) for p in data: name = p['PARAM'].strip() self.coeff[name] = TraceSet(p['COEFF'], domain=domain) #- Pull out x and y as special tracesets self._x = self.coeff['X'] self._y = self.coeff['Y'] #- Create inverse y -> wavelength mapping self._w = self._y.invert() self._wmin = np.min(self.wavelength(None, 0)) self._wmin_all = np.max(self.wavelength(None, 0)) self._wmax = np.max(self.wavelength(None, self.npix_y-1)) self._wmax_all = np.min(self.wavelength(None, self.npix_y-1)) #- Filled only if needed self._xsigma = None self._ysigma = None #- Cache hermitenorm polynomials so we don't have to create them #- every time xypix is called self._hermitenorm = list() maxdeg = max(hdr['GHDEGX'], hdr['GHDEGY'], hdr['GHDEGX2'], hdr['GHDEGY2']) for i in range(maxdeg+1): self._hermitenorm.append( sp.hermitenorm(i) ) fx.close()
def test_polynomial1(): # Polynomial part of Gaussian densities are Hermite polynomials. for dim in range(1,10): q = rft.Gaussian().quasi(dim) h = hermitenorm(dim-1) yield assert_almost_equal, q.c, h.c
def get_psi_sq(self): """ Calculate the term <psii,psij> Returns ------- psi_sq : array the term <psii,psij> """ dim = self.my_experiment.dimension multindices = self.basis['multi-indices'] n_terms = len(multindices) psi_sq = np.ones(n_terms, ) for i in range(n_terms): for j in range(dim): deg = multindices[i][j] if self.my_experiment.polytypes[j] == 'Legendre': x_i, w_i = special.p_roots(deg + 1) ''' Integrate exactly the SQUARE of the Legendre polynomial. For example, if the Legendre polynomial is of order (deg), the numerical integration must be exact till order (deg**2). Thus, we need at least (deg+1) abscissas' and weights. ''' poly = special.legendre(deg)**2 psi_sq[i] *= 1.0 / 2 * sum(w_i * poly(x_i)) elif self.my_experiment.polytypes[j] == 'Hermite': x_i, w_i = special.he_roots(deg + 1) ''' special.he_roots(deg) and np.polynomial.hermite_e.hermegauss(deg) returns the same abscissas' but different weights (!). There is a factor 2 between the two. Given the fact that the integral of the standard Gaussian must be 1, np.polynomial.hermite_e.hermegauss(deg) provides the right weights. ''' poly = special.hermitenorm(deg)**2 # 2*w_i*poly(x_i) psi_sq[i] *= 1.0 / np.sqrt(2 * np.pi) * sum( w_i * poly(x_i)) return psi_sq
def shapelet1d(n, x0=0, s=1): def sqfac(k): fac = 1. for i in xrange(k): fac *= np.sqrt(i + 1) return fac u = lambda x: (x - x0) / s fn = lambda x: (1. / (2 * np.pi)**0.25) * (1. / sqfac(n)) * hermitenorm(n)( u(x)) * np.exp(-0.25 * u(x)**2) return fn
def test_custom_hermitenorm(self): #need to compare our custom hermite norm function to the scipy one m = 3 #degree of the polynomial u = np.random.uniform(0,10,size=10) #generate scipy polynomial scipy_poly = sp.hermitenorm(m) #evalulate at point u scipy_out = scipy_poly(u) #now try our custom fuction custom_out = custom_hermitenorm(m,u) #check if they're the same self.assertTrue(np.all(scipy_out == custom_out))
def gen_dict_feature(self, X): """ generate nonlinear feature given data + nonlinear transformation given X = | x_1,.....,x_n @ time_step = 1| | x_1,.....,x_n @ time_step = M| X.shape = (num_samples, num_components) .. note:: Computational time: * The computational time scales with the number of features mainly, which is determined by number of components and polynomial order :type X: np.ndarray :param X: input data with shape = (num_samples, num_components) :return: generated_feature_array with shape (num_samples, num_features) :rtype: np.ndarray """ num_sample, num_components = X.shape generated_feature_array = None if self.dict == 'hermite': # normalized hermite polynomial ## compute feature list = [[H0(x1).. H0(xn)],...,[HN(x1).. HN(xn)] ] feature_list = [] for order in range(self.hermite_order + 1): phi_i = hermitenorm(order) phi_i_X = np.polyval(phi_i, X) feature_list.append(phi_i_X) # create feature array from feature list generated_feature_array = self.gen_cross_component_features( feature_list=feature_list, num_sample=num_sample, num_components=num_components) elif self.dict == 'rff_gaussian': # isotropic gaussian kernel exp(-||x||^2/2\sigma) generated_feature_array = self.gen_rff_features(X=X) elif self.dict == 'rff_gaussian_state': generated_feature_array = self.gen_rff_features_include_state(X=X) elif self.dict == 'nystrom': pass else: raise NotImplementedError("we haven't implemented that!") return generated_feature_array
def shapelet1d(n,x0=0,s=1): """Make a 1D shapelet template to be used in the construction of 2D shapelets n : Integer representing energy quantum number x0 : Integer defining the centroid s : Float which is the same as beta parameter in refregier """ def sqfac(k): fac = 1. for i in xrange(k): fac *= np.sqrt(i+1) return fac u = lambda x: (x-x0)/s fn = lambda x: (1./(2*np.pi)**0.25)*(1./sqfac(n))*hermitenorm(n)(u(x))*np.exp(-0.25*u(x)**2) return fn
def __init__(self,dim = 1, dist_type = None, var = None, order = None): self.dim = dim self.order = order self.nbpoly = order + 1 self.var = var self.dist_type = dist_type #self.coef = np.zeros(self.nbpoly, self.order + 1) if dist_type =='norm': self.funcs = np.array([sp.hermitenorm(i)for i in range (0, self.order+1)]) for i in range(0, self.order+1): normalized_const = np.sqrt(sp.factorial(i)) self.funcs[i] = poly1d(self.funcs[i].c/normalized_const) if dist_type =='uniform': #The polynomials are orthogonal over [0,1] with weight function 1. self.funcs = np.array([sp.sh_legendre(i)for i in range (0, self.order+1)]) for i in range(0, self.order+1): normalized_const = np.sqrt(1./(2.*i+1.)) self.funcs[i] = poly1d(self.funcs[i].c/normalized_const) self.modelcoef = np.zeros((self.nbpoly,))
def basis(index, eps): """ BASIS is the multivariate basis Parameters ---------- index (int) : index of the basis (from 0 to nt) eps (int) : evaluation points: * from -1 to +1 for a uniform distribution, * from -inf to onf for a normal distribution. Return ------ y (float) : value of the basis in eps --> y = psi(eps) AUTHOR: Luca Giaccone ([email protected]) DATE: 17.12.2018 HISTORY: """ # check input if index > (nt - 1): raise ValueError(f'max index possible is nt-1={self.nt-1}') if isinstance(eps, (list, tuple)): eps = np.array(eps) # get multi-index i = self.multi_index[index] # initialize output y = np.ones(eps.shape[0]) # cycle on distrubutions (nt element) for k, dist in enumerate(distrib): if dist.upper() == 'U': y = y * np.polyval(legendre(i[k]), eps[..., k]) elif dist.upper() == 'N': y = y * np.polyval(hermitenorm(i[k]), eps[..., k]) return y
def Q(dim, dfd=np.inf): """ Q polynomial If `dfd` == inf (the default), then Q(dim) is the (dim-1)-st Hermite polynomial: .. math:: H_j(x) = (-1)^j * e^{x^2/2} * (d^j/dx^j e^{-x^2/2}) If `dfd` != inf, then it is the polynomial Q defined in [Worsley1994]_ Parameters ---------- dim : int dimension of polynomial dfd : scalar Returns ------- q_poly : np.poly1d instance References ---------- .. [Worsley1994] Worsley, K.J. (1994). 'Local maxima and the expected Euler characteristic of excursion sets of \chi^2, F and t fields.' Advances in Applied Probability, 26:13-42. """ m = dfd j = dim if j <= 0: raise ValueError('Q defined only for dim > 0') poly = hermitenorm(j - 1) poly = np.poly1d(np.around(poly.c)) if np.isfinite(m): for l in range((j - 1) // 2 + 1): f = np.exp( gammaln((m + 1) / 2.) - gammaln((m + 2 - j + 2 * l) / 2.) - 0.5 * (j - 1 - 2 * l) * (np.log(m / 2.))) poly.c[2 * l] *= f return np.poly1d(poly.c)
def get_polys(self, x): """ Calculates the normalized Hermite polynomials evaluated at sample points. :param x: :class:`numpy.ndarray` containing the samples. :return: Α list of :class:`numpy.ndarray` with the design matrix and the normalized polynomials. """ a, b = -np.inf, np.inf mean_ = Polynomials.get_mean(self) std_ = Polynomials.get_std(self) x_ = Polynomials.standardize_normal(x, mean_, std_) norm = Normal(0, 1) pdf_st = norm.pdf p = [] for i in range(self.degree): p.append(special.hermitenorm(i, monic=False)) return Polynomials.normalized(self.degree, x_, a, b, pdf_st, p)
def Q(dim, dfd=np.inf): r""" Q polynomial If `dfd` == inf (the default), then Q(dim) is the (dim-1)-st Hermite polynomial: .. math:: H_j(x) = (-1)^j * e^{x^2/2} * (d^j/dx^j e^{-x^2/2}) If `dfd` != inf, then it is the polynomial Q defined in [Worsley1994]_ Parameters ---------- dim : int dimension of polynomial dfd : scalar Returns ------- q_poly : np.poly1d instance References ---------- .. [Worsley1994] Worsley, K.J. (1994). 'Local maxima and the expected Euler characteristic of excursion sets of \chi^2, F and t fields.' Advances in Applied Probability, 26:13-42. """ m = dfd j = dim if j <= 0: raise ValueError('Q defined only for dim > 0') coeffs = np.around(hermitenorm(j - 1).c) if np.isfinite(m): for L in range((j - 1) // 2 + 1): f = np.exp(gammaln((m + 1) / 2.) - gammaln((m + 2 - j + 2 * L) / 2.) - 0.5 * (j - 1 - 2 * L) * (np.log(m / 2.))) coeffs[2 * L] *= f return np.poly1d(coeffs)
def gen_dict_feature(self, X): """ generate nonlinear feature given data + nonlinear transformation given X = | x_1,.....,x_n @ time_step = 1| | x_1,.....,x_n @ time_step = M| X.shape = (num_samples, num_components) .. note:: Computational time: * The computational time scales with the number of features mainly, which is determined by number of components and polynomial order :type X: np.ndarray :param X: input data with shape = (num_samples, num_components) :return: generated_feature_array with shape (num_samples, num_features) :rtype: np.ndarray """ num_sample, num_components = X.shape generated_feature_array = None if self.dict == 'hermite': # normalized hermite polynomial ## compute feature list = [[H0(x1).. H0(xn)],...,[HN(x1).. HN(xn)] ] feature_list = [] for order in range(self.hermite_order + 1): phi_i = hermitenorm(order) phi_i_X = np.polyval(phi_i, X) feature_list.append(phi_i_X) # create feature array from feature list generated_feature_array = self.gen_cross_component_features( feature_list=feature_list, num_sample=num_sample, num_components=num_components ) return generated_feature_array
def __init__(self, filename): """ Initialize GaussHermitePSF from input file """ #- Check that this file is a current generation Gauss Hermite PSF fx = fits.open(filename, memmap=False) #- Read primary header phdr = fx[0].header if 'PSFTYPE' not in phdr: raise ValueError('Missing PSFTYPE keyword') if phdr['PSFTYPE'] != 'GAUSS-HERMITE': raise ValueError('PSFTYPE {} is not GAUSS-HERMITE'.format(phdr['PSFTYPE'])) if 'PSFVER' not in phdr: raise ValueError("PSFVER missing; this version not supported") PSFVER = float(phdr["PSFVER"]) if PSFVER<3 : psf_hdu = 1 else : psf_hdu = "PSF" self._polyparams = hdr = dict(fx[psf_hdu].header) if 'PSFTYPE' not in hdr: raise ValueError('Missing PSFTYPE keyword') if hdr['PSFTYPE'] != 'GAUSS-HERMITE': raise ValueError('PSFTYPE {} is not GAUSS-HERMITE'.format(hdr['PSFTYPE'])) if 'PSFVER' not in hdr: raise ValueError("PSFVER missing; this version not supported") if hdr['PSFVER'] < '1': raise ValueError("Only GAUSS-HERMITE versions 1.0 and greater are supported") #- Calculate number of spectra from FIBERMIN and FIBERMAX (inclusive) self.nspec = hdr['FIBERMAX'] - hdr['FIBERMIN'] + 1 #- Other necessary keywords self.npix_x = hdr['NPIX_X'] self.npix_y = hdr['NPIX_Y'] #- PSF model error if 'PSFERR' in hdr: self.psferr = hdr['PSFERR'] else: self.psferr = 0.01 #- Load the parameters into self.coeff dictionary keyed by PARAM #- with values as TraceSets for evaluating the Legendre coefficients data = fx[psf_hdu].data self.coeff = dict() if PSFVER<3 : # old format for p in data: domain = (p['WAVEMIN'], p['WAVEMAX']) for p in data: name = p['PARAM'].strip() self.coeff[name] = TraceSet(p['COEFF'], domain=domain) #- Pull out x and y as special tracesets self._x = self.coeff['X'] self._y = self.coeff['Y'] else : # new format domain = (hdr['WAVEMIN'], hdr['WAVEMAX']) for p in data: name = p['PARAM'].strip() self.coeff[name] = TraceSet(p['COEFF'], domain=domain) self._x = TraceSet(fx["XTRACE"].data, domain=(fx['XTRACE'].header["WAVEMIN"], fx['XTRACE'].header['WAVEMAX'])) self._y = TraceSet(fx["YTRACE"].data, domain=(fx['YTRACE'].header["WAVEMIN"], fx['YTRACE'].header['WAVEMAX'])) #- Create inverse y -> wavelength mapping self._w = self._y.invert() #- Cache min/max wavelength per fiber at pixel edges self._wmin_spec = self.wavelength(None, -0.5) self._wmax_spec = self.wavelength(None, self.npix_y-0.5) self._wmin = np.min(self._wmin_spec) self._wmin_all = np.max(self._wmin_spec) self._wmax = np.max(self._wmax_spec) self._wmax_all = np.min(self._wmax_spec) #- Filled only if needed self._xsigma = None self._ysigma = None #create dict to hold legval cached data self.legval_dict = None #- Cache hermitenorm polynomials so we don't have to create them #- every time xypix is called self._hermitenorm = list() maxdeg = max(hdr['GHDEGX'], hdr['GHDEGY']) for i in range(maxdeg+1): self._hermitenorm.append( sp.hermitenorm(i) ) fx.close()
import numpy as np import matplotlib.pyplot as plt from scipy.special import chebyt, hermitenorm x = np.linspace(-1, 1, 100) xx = np.linspace(-5, 5, 100) t1 = np.polyval(chebyt(1), x) t2 = np.polyval(chebyt(2), x) t3 = np.polyval(chebyt(3), x) t4 = np.polyval(chebyt(4), x) h1 = np.polyval(hermitenorm(1), x) h2 = np.polyval(hermitenorm(2), x) h3 = np.polyval(hermitenorm(3), x) h4 = np.polyval(hermitenorm(4), x) plt.rc('mathtext', fontset='stix') fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(9, 6)) ax1.plot(x, t1, label=r'$T_{1}(x)$') ax1.plot(x, t2, label=r'$T_{2}(x)$') ax1.plot(x, t3, label=r'$T_{3}(x)$') ax1.plot(x, t4, label=r'$T_{4}(x)$') ax1.legend(loc='best') ax1.set_xlabel(r'$x$') ax1.set_title('First four Chebyshev polynomials of the first kind') ax1.grid() ax2.plot(xx, h1, label=r'$H_{1}(x)$') ax2.plot(xx, h2, label=r'$H_{2}(x)$') ax2.plot(xx, h3, label=r'$H_{3}(x)$')
def __init__(self, filename): """ Initialize GaussHermitePSF from input file """ #- Check that this file is a current generation Gauss Hermite PSF fx = fits.open(filename, memmap=False) self._polyparams = hdr = fx[1].header if 'PSFTYPE' not in hdr: raise ValueError('Missing PSFTYPE keyword') if hdr['PSFTYPE'] != 'GAUSS-HERMITE2': raise ValueError('PSFTYPE {} is not GAUSS-HERMITE'.format(hdr['PSFTYPE'])) if 'PSFVER' not in hdr: raise ValueError("PSFVER missing; this version not supported") if hdr['PSFVER'] < '1': raise ValueError("Only GAUSS-HERMITE versions 1.0 and greater are supported") #- Calculate number of spectra from FIBERMIN and FIBERMAX (inclusive) self.nspec = hdr['FIBERMAX'] - hdr['FIBERMIN'] + 1 #- Other necessary keywords self.npix_x = hdr['NPIX_X'] self.npix_y = hdr['NPIX_Y'] #- PSF model error if 'PSFERR' in hdr: self.psferr = hdr['PSFERR'] else: self.psferr = 0.01 #- Load the parameters into self.coeff dictionary keyed by PARAM #- with values as TraceSets for evaluating the Legendre coefficients data = fx[1].data self.coeff = dict() for p in data: domain = (p['WAVEMIN'], p['WAVEMAX']) for p in data: name = p['PARAM'].strip() self.coeff[name] = TraceSet(p['COEFF'], domain=domain) #- Pull out x and y as special tracesets self._x = self.coeff['X'] self._y = self.coeff['Y'] #- Create inverse y -> wavelength mapping self._w = self._y.invert() #- Cache min/max wavelength per fiber at pixel edges self._wmin_spec = self.wavelength(None, -0.5) self._wmax_spec = self.wavelength(None, self.npix_y-0.5) self._wmin = np.min(self._wmin_spec) self._wmin_all = np.max(self._wmin_spec) self._wmax = np.max(self._wmax_spec) self._wmax_all = np.min(self._wmax_spec) #- Filled only if needed self._xsigma = None self._ysigma = None #- Cache hermitenorm polynomials so we don't have to create them #- every time xypix is called self._hermitenorm = list() maxdeg = max(hdr['GHDEGX'], hdr['GHDEGY'], hdr['GHDEGX2'], hdr['GHDEGY2']) for i in range(maxdeg+1): self._hermitenorm.append( sp.hermitenorm(i) ) fx.close()
def test_polynomial1(): # Polynomial part of Gaussian densities are Hermite polynomials. for dim in range(1, 10): q = rft.Gaussian().quasi(dim) h = hermitenorm(dim - 1) yield assert_almost_equal, q.c, h.c