_util.py 4.73 KB
Newer Older
Fang Yuedong's avatar
Fang Yuedong committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import numpy as np
import os
import math
from pylab import *
from scipy import interpolate

try:
    import importlib.resources as pkg_resources
except ImportError:
    # Try backported to PY<37 'importlib_resources'
    import importlib_resources as pkg_resources

VC_A = 2.99792458e+18  # speed of light: A/s
VC_M = 2.99792458e+8   # speed of light: m/s
H_PLANK = 6.626196e-27  # Plank constant: erg s

ALL_FILTERS = ["NUV", "u", "g", "r", "i", "z", "y", "GU", "GV", "GI", "FGS"]
PHOT_FILTERS = ["NUV", "u", "g", 'r', 'i', 'z', 'y', 'FGS']
SPEC_FILTERS = ["GI", "GV", "GU"]


def rotate_conterclockwise(x0, y0, x, y, angle):
    """
Rotate a point counterclockwise by a given angle around a given origin.

The angle should be given in radians.
"""
    angle = np.deg2rad(angle)
    qx = x0 + np.cos(angle)*(x - x0) - np.sin(angle) * (y - y0)
    qy = y0 + np.sin(angle)*(x - x0) + np.cos(angle) * (y - y0)
    return qx, qy


def photonEnergy(lambd):
    """ The energy of photon at a given wavelength

    Parameter:
            lambd: the wavelength in unit of Angstrom
    Return:
            eph: energy of photon in unit of erg
    """
    nu = VC_A / lambd
    eph = H_PLANK * nu
    return eph


def calculateLimitMag(aperture=2.0, psf_fwhm=0.1969, pixelSize=0.074, pmRation=0.8, throughputFn='i_throughput.txt', readout=5.0, skyFn='sky_emiss_hubble_50_50_A.dat', darknoise=0.02, exTime=150, exNum=1, fw=90000):
    '''
Wei Chengliang's avatar
Wei Chengliang committed
49
    description:
Fang Yuedong's avatar
Fang Yuedong committed
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
    param {*} aperture: unit m, default 2 m
    param {*} psf_fwhm: psf fwhm, default 0.1969"
    param {*} pixelSize: pixel size, default 0.074"
    param {*} pmRation: the ratio of souce flux in the limit mag calculation
    param {*} throughputFn: throuput file name
    param {*} readout: unit, e-/pixel
    param {*} skyFn: sky sed file name, average of hst, 'sky_emiss_hubble_50_50_A.dat'
    param {*} darknoise: unit, e-/pixel/s
    param {*} exTime: exposure time one time, default 150s
    param {*} exNum: exposure number, defautl 1
    param {*} fw, full well value( or saturation value),default 90000e-/pixel
    return {*} limit mag and saturation mag
    '''
    try:
        with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(throughputFn) as data_file:
            throughput_f = np.loadtxt(data_file)
    except AttributeError:
        with pkg_resources.path('observation_sim.instruments.data.throughputs', throughputFn) as data_file:
            throughput_f = np.loadtxt(data_file)
    thr_i = interpolate.interp1d(
        throughput_f[:, 0]/10, throughput_f[:, 1])  # wavelength in anstrom
    f_s = 200
    f_e = 1100
    delt_f = 0.5

    data_num = int((f_e-f_s)/delt_f+1)

    eff = np.zeros([data_num, 2])
    eff[:, 0] = np.arange(f_s, f_e+delt_f, delt_f)
    eff[:, 1] = thr_i(eff[:, 0])

    wave = np.arange(f_s, f_e+delt_f, delt_f)
    wavey = np.ones(wave.shape[0])

    try:
        with pkg_resources.files('observation_sim.instruments.data.throughputs').joinpath(skyFn) as data_file:
            skydata = np.loadtxt(data_file)
    except AttributeError:
        with pkg_resources.path('observation_sim.instruments.data.throughputs', skyFn) as data_file:
            skydata = np.loadtxt(data_file)
    skydatai = interpolate.interp1d(skydata[:, 0]/10, skydata[:, 1]*10)

    sky_data = np.zeros([data_num, 2])
    sky_data[:, 0] = np.arange(f_s, f_e+delt_f, delt_f)
    sky_data[:, 1] = skydatai(sky_data[:, 0])

    flux_sky = trapz((sky_data[:, 1])*eff[:, 1], sky_data[:, 0])
    skyPix = flux_sky*pixelSize*pixelSize*pi*(aperture*aperture/4)

    # limit mag

    r_pix = psf_fwhm*0.7618080243778568/pixelSize  # radius RE80, pixel
    cnum = math.pi * r_pix * r_pix
    sn = 5

    d = skyPix*exTime*exNum*cnum + darknoise * \
        exTime*exNum*cnum+readout*readout*cnum*exNum
    a = 1
    b = -sn*sn
    c = -sn*sn*d

    flux = (-b+sqrt(b*b-4*a*c))/(2*a)/pmRation
    limitMag = -2.5*log10(flux/(54799275581.04437 * trapz(wavey *
                          eff[:, 1]/wave, wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2)))

    # saturation mag

    from astropy.modeling.models import Gaussian2D
    m_size = int(20 * psf_fwhm/pixelSize)
    if m_size % 2 == 0:
        m_size + 1
    m_cen = m_size//2
    psf_sigma = psf_fwhm/2.355/pixelSize

    gaussShape = Gaussian2D(1, m_cen, m_cen, psf_sigma, psf_sigma)
    yp, xp = np.mgrid[0:m_size, 0:m_size]
    psfMap = gaussShape(xp, yp)
    maxRatio = np.amax(psfMap)/np.sum(psfMap)
    # print(maxRatio)

    flux_sat = fw/maxRatio*exNum
    satMag = -2.5*log10(flux_sat/(54799275581.04437 * trapz(wavey *
                        eff[:, 1]/wave, wave, 0.1)*exTime*exNum*pi*(aperture/2)*(aperture/2)))

    return limitMag, satMag