Commit 29ac5666 authored by Fang Yuedong's avatar Fang Yuedong
Browse files

Baseline

parents
"""
Pythonic utilities ported to C [Cython] for speedup.
"""
import numpy as np
cimport numpy as np
DTYPE = np.double
ctypedef np.double_t DTYPE_t
ctypedef np.int_t ITYPE_t
ctypedef np.uint_t UINT_t
import cython
cdef extern from "math.h":
double fabs(double)
cdef extern from"stdio.h":
extern int printf(const char *format, ...)
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
@cython.embedsignature(True)
def interp_c(np.ndarray[DTYPE_t, ndim=1] x, np.ndarray[DTYPE_t, ndim=1] xp, np.ndarray[DTYPE_t, ndim=1] fp, double extrapolate=0., short int assume_sorted=1):
"""
interp_c(x, xp, fp, extrapolate=0., assume_sorted=0)
Fast interpolation: [`xp`, `fp`] interpolated at `x`.
Extrapolated values are set to `extrapolate`.
The default `assume_sorted`=1 assumes that the `x` array is sorted and single-
valued, providing a significant gain in speed. (xp is always assumed to be sorted)
"""
cdef unsigned long i, j, N, Np
cdef DTYPE_t x1,x2,y1,y2,out
cdef DTYPE_t fout, xval, xmin
N, Np = len(x), len(xp)
cdef np.ndarray[DTYPE_t, ndim=1] f = np.zeros(N)
i=0
j=0
### Handle left extrapolation
xmin = xp[0]
if assume_sorted == 1:
while x[j] < xmin:
f[j] = extrapolate
j+=1
if j>=N:
break
while j < N:
xval = x[j]
if assume_sorted == 0:
if x[j] < xmin:
f[j] = extrapolate
j+=1
continue
else:
i=0
while (xp[i] <= xval) & (i < Np-1): i+=1;
if i == (Np-1):
if x[j] != xp[i]:
f[j] = extrapolate
else:
f[j] = fp[i]
j+=1
continue
#### x[i] is now greater than xval because the
#### expression (x[i]<xval) is false, assuming
#### that xval < max(x).
# x1 = xp[i];
# x2 = xp[i+1];
# y1 = fp[i];
# y2 = fp[i+1];
x1 = xp[i-1];
x2 = xp[i];
y1 = fp[i-1];
y2 = fp[i];
out = ((y2-y1)/(x2-x1))*(xval-x1)+y1;
f[j] = out
j+=1
return f
@cython.boundscheck(False)
def interp_conserve_c(np.ndarray[DTYPE_t, ndim=1] x, np.ndarray[DTYPE_t, ndim=1] tlam, np.ndarray[DTYPE_t, ndim=1] tf, double left=0, double right=0, double integrate=0):
"""
interp_conserve_c(x, xp, fp, left=0, right=0, integrate=0)
Interpolate `xp`,`yp` array to the output x array, conserving flux.
`xp` can be irregularly spaced.
"""
cdef np.ndarray[DTYPE_t, ndim=1] templmid
cdef np.ndarray[DTYPE_t, ndim=1] tempfmid
cdef np.ndarray[DTYPE_t, ndim=1] outy
cdef unsigned long i,k,istart,ntlam,NTEMPL
cdef DTYPE_t h, numsum
# templmid = (x[1:]+x[:-1])/2. #2.+x[:-1]
# templmid = np.append(templmid, np.array([x[0], x[-1]]))
# templmid = templmid[np.argsort(templmid)]
NTEMPL = len(x)
ntlam = len(tlam)
templmid = midpoint_c(x, NTEMPL)
#tempfmid = np.interp(templmid, tlam, tf, left=left, right=right)
tempfmid = interp_c(templmid, tlam, tf, extrapolate=0.)
outy = np.zeros(NTEMPL, dtype=DTYPE)
###### Rebin template grid to master wavelength grid, conserving template flux
i=0
k=0
while templmid[k] < tlam[0]:
outy[k] = left
k+=1
if k >NTEMPL-1:
break
if(k>0) & (templmid[k-1] < tlam[0]) & (templmid[k] > tlam[0]):
m = 1;
numsum=0.;
while (tlam[m] < templmid[k]):
h = tlam[m]-tlam[m-1];
numsum+=h*(tf[m]+tf[m-1]);
m+=1;
if m >= ntlam:
break;
#print 'test #%d, %d' %(m, ntlam)
if m == 1:
h = templmid[k]-tlam[0];
numsum+=h*(tempfmid[k]+tf[0]);
else:
##### Last point
if m < ntlam:
if (templmid[k] == tlam[m]):
h = tlam[m]-tlam[m-1];
numsum+=h*(tf[m]+tf[m-1]);
else:
m-=1;
h = templmid[k]-tlam[m];
numsum+=h*(tempfmid[k]+tf[m]);
outy[k-1] = numsum*0.5;#/(templmid[k+1]-templmid[k]);
if integrate == 0.:
outy[k-1] /= (templmid[k]-templmid[k-1]);
for k in range(k, NTEMPL):
if templmid[k] > tlam[ntlam-1]:
break
numsum=0.;
#### Go to where tlam is greater than the first midpoint
while (tlam[i] < templmid[k]) & (i < ntlam): i+=1;
istart=i;
####### First point
if tlam[i] < templmid[k+1]:
h = tlam[i]-templmid[k];
numsum+=h*(tf[i]+tempfmid[k]);
i+=1;
if i==0: i+=1;
####### Template points between master grid points
while (tlam[i] < templmid[k+1]) & (i < ntlam):
h = tlam[i]-tlam[i-1];
numsum+=h*(tf[i]+tf[i-1]);
i+=1;
#### If no template points between master grid points, then just use interpolated midpoints
if i == istart:
h = templmid[k+1]-templmid[k];
numsum=h*(tempfmid[k+1]+tempfmid[k]);
else:
##### Last point
if (templmid[k+1] == tlam[i]) & (i < ntlam):
h = tlam[i]-tlam[i-1];
numsum+=h*(tf[i]+tf[i-1]);
else:
i-=1;
h = templmid[k+1]-tlam[i];
numsum+=h*(tempfmid[k+1]+tf[i]);
outy[k] = numsum*0.5;#/(templmid[k+1]-templmid[k]);
if integrate == 0.:
outy[k] /= (templmid[k+1]-templmid[k]);
return outy
def midpoint(x):
mp = (x[1:]+x[:-1])/2.
mp = np.append(mp, np.array([x[0],x[-1]]))
mp = mp[np.argsort(mp)]
return mp
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
@cython.embedsignature(True)
def midpoint_c(np.ndarray[DTYPE_t, ndim=1] x, long N):
cdef long i
cdef DTYPE_t xi,xi1
# N = len(x)
cdef np.ndarray[DTYPE_t, ndim=1] midpoint = np.zeros(N+1, dtype=DTYPE)
midpoint[0] = x[0]
midpoint[N] = x[N-1]
xi1 = x[0]
for i in range(1, N):
xi = x[i]
midpoint[i] = 0.5*xi+0.5*xi1
xi1 = xi
midpoint[0] = 2*x[0]-midpoint[1]
midpoint[N] = 2*x[N-1]-midpoint[N-1]
return midpoint
from setuptools import setup
from setuptools.extension import Extension
from setuptools.config import read_configuration
from Cython.Build import cythonize
import numpy
extensions = [
Extension("disperse_c.interp", ["disperse_c/interp.pyx"],
include_dirs = [numpy.get_include()],
libraries=["m"]),
Extension("disperse_c.disperse", ["disperse_c/disperse.pyx"],
include_dirs = [numpy.get_include()],
libraries=["m"]),
]
setup(
name = "slssim_disperse",
ext_modules = cythonize(extensions),
)
import galsim
import os, sys
import numpy as np
import astropy.constants as cons
from astropy.table import Table
from ._util import integrate_sed_bandpass, getNormFactorForSpecWithABMAG, getObservedSED, getABMAG, tag_sed
from .SpecDisperser import SpecDisperser
from .MockObject import MockObject
from scipy import interpolate
class Star(MockObject):
def __init__(self, param):
super().__init__(param)
def unload_SED(self):
"""(Test) free up SED memory
"""
del self.sed
def load_SED(self, survey_type, normFilter=None, target_filt=None, sed_lib=None, sed_path=None):
if survey_type == "photometric":
norm_thr_rang_ids = normFilter['SENSITIVITY'] > 0.001
# spec_lambda = Table.read(sed_path, path=f"/SED/wave_{self.model_tag}")
# spec_flux = Table.read(sed_path, path=f"/SED/{self.sed_type}")
# wave, flux = spec_lambda['col0'].data, spec_flux['col0'].data
_, wave, flux = tag_sed(
h5file=sed_lib,
model_tag=self.param['model_tag'],
teff=self.param['teff'],
logg=self.param['logg'],
feh=self.param['feh'])
flux_photon = flux * (wave / (cons.h.value * cons.c.value)) * 1e-13
sed_photon = Table(np.array([wave, flux_photon]).T, names=('WAVELENGTH', 'FLUX'))
# Get scaling factor for SED
sedNormFactor = getNormFactorForSpecWithABMAG(ABMag=self.param['mag_use_normal'],
spectrum=sed_photon,
norm_thr=normFilter,
sWave=np.floor(normFilter[norm_thr_rang_ids][0][0]),
eWave=np.ceil(normFilter[norm_thr_rang_ids][-1][0]))
sed_photon = np.array([sed_photon['WAVELENGTH'], sed_photon['FLUX']*sedNormFactor]).T
# Convert to galsim.SED object
spec = galsim.LookupTable(x=np.array(sed_photon[:, 0]), f=np.array(sed_photon[:, 1]), interpolant='nearest')
self.sed = galsim.SED(spec, wave_type='A', flux_type='1', fast=False)
# Get magnitude
interFlux = integrate_sed_bandpass(sed=self.sed, bandpass=target_filt.bandpass_full)
self.param['mag_%s'%target_filt.filter_type] = getABMAG(
interFlux=interFlux,
bandpass=target_filt.bandpass_full)
# print('mag_use_normal = ', self.param['mag_use_normal'])
# print('mag_%s = '%target_filt.filter_type, self.param['mag_%s'%target_filt.filter_type])
elif survey_type == "spectroscopic":
# self.sedPhotons(sed_path=sed_path)
self.sedPhotons(sed_lib=sed_lib)
def sedPhotons(self, sed_path=None, sed_lib=None):
# spec_lambda = Table.read(sed_path, path=f"/SED/wave_{self.model_tag}")
# spec_flux = Table.read(sed_path, path=f"/SED/{self.sed_type}")
_, w_orig, f_orig = tag_sed(
h5file=sed_lib,
model_tag=self.param['model_tag'],
teff=self.param['teff'],
logg=self.param['logg'],
feh=self.param['feh'])
# spec_data = {}
# f_orig = spec_flux["col0"].data
# w_orig = spec_lambda["col0"].data
speci = interpolate.interp1d(w_orig, f_orig)
lamb = np.arange(2500, 10001 + 0.5, 0.5)
y = speci(lamb)
# erg/s/cm2/A --> photo/s/m2/A
all_sed = y * lamb / (cons.h.value * cons.c.value) * 1e-13
self.sed = Table(np.array([lamb, all_sed]).T, names=('WAVELENGTH', 'FLUX'))
def getGSObj(self, psf, g1=0, g2=0, flux=None, filt=None, tel=None, exptime=150.):
if flux == None:
flux = self.getElectronFluxFilt(filt, tel, exptime)
# star = galsim.Gaussian(sigma=1.e-8, flux=1.)
star = galsim.DeltaFunction()
star = star.withFlux(flux)
final = galsim.Convolve(psf, star)
return final
def getGSObj_multiband(self, tel, psf_list, bandpass_list, filt, nphotons_tot=None, g1=0, g2=0, exptime=150.):
if len(psf_list) != len(bandpass_list):
raise ValueError("!!!The number of PSF profiles and the number of bandpasses must be equal.")
objs = []
if nphotons_tot == None:
nphotons_tot = self.getElectronFluxFilt(filt, tel, exptime)
try:
full = integrate_sed_bandpass(sed=self.sed, bandpass=filt.bandpass_full)
except Exception as e:
print(e)
return -1
for i in range(len(bandpass_list)):
bandpass = bandpass_list[i]
try:
sub = integrate_sed_bandpass(sed=self.sed, bandpass=bandpass)
except Exception as e:
print(e)
return -1
ratio = sub/full
if not (ratio == -1 or (ratio != ratio)):
nphotons = ratio * nphotons_tot
else:
return -1
star = galsim.DeltaFunction()
star = star.withFlux(nphotons)
star = galsim.Convolve(psf, star)
objs.append(star)
final = galsim.Sum(objs)
return final
\ No newline at end of file
from .MockObject import MockObject
from .Galaxy import Galaxy
from .Quasar import Quasar
from .Star import Star
from .Catalog import Catalog
from .SkybackgroundMap import *
# from .CosmicRay import CosmicRay
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment