fits.py 5.04 KB
Newer Older
Wei Shoulin's avatar
Wei Shoulin committed
1
2
3
from astropy_healpix import HEALPix
from astropy.coordinates import ICRS
from astropy import units as u
Wei Shoulin's avatar
C9    
Wei Shoulin committed
4
from astropy.coordinates import SkyCoord
Wei Shoulin's avatar
Wei Shoulin committed
5
from astropy.io import fits
Wei Shoulin's avatar
Wei Shoulin committed
6
from astropy import wcs
Wei Shoulin's avatar
C9    
Wei Shoulin committed
7

Wei Shoulin's avatar
Wei Shoulin committed
8
from csst_dfs_commons.models.constants import PI, DEFAULT_NSIDE
Wei Shoulin's avatar
add hp    
Wei Shoulin committed
9

Wei Shoulin's avatar
Wei Shoulin committed
10
def get_header_value(key: str, headers, default_value = None):
Wei Shoulin's avatar
Wei Shoulin committed
11
    try:
Wei Shoulin's avatar
Wei Shoulin committed
12
13
14
15
16
17
18
19
        ret_value = None
        if not isinstance(headers, list):
            headers = [headers]
        for header in headers:
            if key in header:
                ret_value = header[key]
                if type(ret_value) == str:
                    return ret_value.strip()
Wei Shoulin's avatar
Wei Shoulin committed
20
                return ret_value
Wei Shoulin's avatar
Wei Shoulin committed
21
22
        if ret_value is None:
            return default_value
Wei Shoulin's avatar
Wei Shoulin committed
23
    except Exception as e:
Wei Shoulin's avatar
Wei Shoulin committed
24
25
        return default_value

Wei Shoulin's avatar
Wei Shoulin committed
26
def get_healpix_id(ra, dec, nside=256):
Wei Shoulin's avatar
Wei Shoulin committed
27
28
29
30
31
32
    try:
        hp = HEALPix(nside=nside, order='nested', frame=ICRS())
        coord = SkyCoord(ra = ra * u.deg, dec = dec * u.deg, frame='icrs')
        return hp.skycoord_to_healpix(coord)
    except:
        return -1
Wei Shoulin's avatar
h    
Wei Shoulin committed
33

Wei Shoulin's avatar
Wei Shoulin committed
34
def get_healpix_ids(ra, dec, radius, nside=256):
Wei Shoulin's avatar
h    
Wei Shoulin committed
35
36
    hp = HEALPix(nside=nside, order='nested', frame=ICRS())
    coord = SkyCoord(ra = ra * u.deg, dec = dec * u.deg, frame='icrs')
Wei Shoulin's avatar
Wei Shoulin committed
37
38
39
40
41
42
43
44
45
46
47
48
49
50
    return hp.cone_search_skycoord(coord, radius = radius * u.deg)

def get_raw_header(filepath, **keys):
    union = {}
    with fits.open(filepath, **keys) as hdulist:
        for hdu in hdulist:
            for card in hdu.header.cards:
                card.verify('fix')
                key, value = card.keyword, card.value
                if not key:
                    continue
                union[key]= value
    return union

Wei Shoulin's avatar
Wei Shoulin committed
51
def heapix_sql_condition(ra, dec, radius, ra_col = 'ra', dec_col = 'dec', nside = DEFAULT_NSIDE):
Wei Shoulin's avatar
C9    
Wei Shoulin committed
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    """
    生成用于筛选特定天区范围内数据的SQL条件语句(大圆公式)。
    
    Args:
        ra (float): 天区中心的赤经值,单位为度。
        dec (float): 天区中心的赤纬值,单位为度。
        radius (float): 天区的半径,单位为度。
        ra_col (str, optional): 数据表中赤经值的列名,默认为'ra'。
        dec_col (str, optional): 数据表中赤纬值的列名,默认为'dec'。
        nside (int, optional): Healpix像素化的nside参数,默认为DEFAULT_NSIDE。
    
    Returns:
        str: 用于筛选特定天区范围内数据的SQL条件语句。
    
    """
Wei Shoulin's avatar
Wei Shoulin committed
67
    arcDec = (PI / 180) * dec
Wei Shoulin's avatar
C9    
Wei Shoulin committed
68
    whereSql = f"abs((180./pi()) * ACOS(SIN(pi() * {dec_col}/180) * SIN({arcDec}) + COS(pi() * {dec_col}/180) * COS({arcDec}) * COS(pi()* ({ra_col} - {ra})/180))) < {radius}"
Wei Shoulin's avatar
Wei Shoulin committed
69
70
71
72
73
74

    heapix_ids = get_healpix_ids(ra, dec, radius, nside)
    nside_column = "NS%dHIdx" % (nside,)
    whereZoneSql = "%s in (%s)" % \
                (nside_column, ','.join([str(i) for i in heapix_ids]))
    
Wei Shoulin's avatar
C9    
Wei Shoulin committed
75
    return f"{whereSql} and {whereZoneSql}"
Wei Shoulin's avatar
C9    
Wei Shoulin committed
76
77

def catalog_heapix_sql_condition(ra, dec, radius, ra_col = 'ra', dec_col = 'dec', nside = DEFAULT_NSIDE):
Wei Shoulin's avatar
C9    
Wei Shoulin committed
78
79
80
    x2 = f"cos(pi()*{dec_col}/180.0)*cos(pi()*{ra_col}/180.0)"
    y2 = f"cos(pi()*{dec_col}/180.0)*sin(pi()*{ra_col}/180.0)"
    z2 = f"sin(pi()*{dec_col}/180.0)"
Wei Shoulin's avatar
C9    
Wei Shoulin committed
81

Wei Shoulin's avatar
C9    
Wei Shoulin committed
82
83
84
    x1 = f"cos(pi()*{dec}/180.0)*cos(pi()*{ra}/180.0)"
    y1 = f"cos(pi()*{dec}/180.0)*sin(pi()*{ra}/180.0)"
    z1 = f"sin(pi()*{dec}/180.0)"
Wei Shoulin's avatar
C9    
Wei Shoulin committed
85
86
87
88
89
90
91

    distance = f"pow(({x2}-{x1}),2)+pow(({y2}-{y1}),2)+pow(({z2}-{z1}),2)"

    heapix_ids = get_healpix_ids(ra, dec, radius, nside)
    nside_column = "NS%dHIdx" % (nside,)
    whereZoneSql = "%s in (%s)" % \
                (nside_column, ','.join([str(i) for i in heapix_ids]))
Wei Shoulin's avatar
C9    
Wei Shoulin committed
92
    whereSql = f"{distance} <= 4*pow(pi()*{radius}/180.0/2, 2) and {whereZoneSql}"
Wei Shoulin's avatar
Wei Shoulin committed
93
    
Wei Shoulin's avatar
C9    
Wei Shoulin committed
94
95
    return whereSql

Wei Shoulin's avatar
Wei Shoulin committed
96
def dfs_heapix_sql_condition(ra, dec, radius, ra_col = 'ra', dec_col = 'dec', brick_col = "brick_id", nside = DEFAULT_NSIDE):
Wei Shoulin's avatar
C9    
Wei Shoulin committed
97
98
99
    x2 = f"cos(pi()*{dec_col}/180.0)*cos(pi()*{ra_col}/180.0)"
    y2 = f"cos(pi()*{dec_col}/180.0)*sin(pi()*{ra_col}/180.0)"
    z2 = f"sin(pi()*{dec_col}/180.0)"
Wei Shoulin's avatar
Wei Shoulin committed
100

Wei Shoulin's avatar
C9    
Wei Shoulin committed
101
102
103
    x1 = f"cos(pi()*{dec}/180.0)*cos(pi()*{ra}/180.0)"
    y1 = f"cos(pi()*{dec}/180.0)*sin(pi()*{ra}/180.0)"
    z1 = f"sin(pi()*{dec}/180.0)"
Wei Shoulin's avatar
Wei Shoulin committed
104
105
106
107
108

    distance = f"pow(({x2}-{x1}),2)+pow(({y2}-{y1}),2)+pow(({z2}-{z1}),2)"

    heapix_ids = get_healpix_ids(ra, dec, radius, nside)
    whereZoneSql = "%s in (%s)" % \
Wei Shoulin's avatar
Wei Shoulin committed
109
                (brick_col, ','.join([str(i) for i in heapix_ids]))
Wei Shoulin's avatar
Wei Shoulin committed
110
    
Wei Shoulin's avatar
C9    
Wei Shoulin committed
111
    whereSql = f"{distance} <= 4*pow(pi()*{radius}/180.0/2, 2) and {whereZoneSql}"
Wei Shoulin's avatar
Wei Shoulin committed
112

Wei Shoulin's avatar
Wei Shoulin committed
113
    return whereSql
Wei Shoulin's avatar
Wei Shoulin committed
114

Wei Shoulin's avatar
Wei Shoulin committed
115
def compute_ra_dec_range(header):
Wei Shoulin's avatar
Wei Shoulin committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
    fits_wcs = wcs.WCS(header)

    # Get the shape of the data
    naxis1 = header['NAXIS1']
    naxis2 = header['NAXIS2']

    # Get the pixel coordinates of all corners
    corners = [(0, 0), (naxis1, 0), (naxis1, naxis2), (0, naxis2)]

    # Convert pixel coordinates of corners to RA and Dec
    corners_coords = fits_wcs.all_pix2world(corners, 0)

    # Extract RA and Dec values
    ras = [coord[0] for coord in corners_coords]
    decs = [coord[1] for coord in corners_coords]

    # Compute the min and max of RA and Dec
    min_ra, max_ra = min(ras), max(ras)
    min_dec, max_dec = min(decs), max(decs)

    return min_ra, max_ra, min_dec, max_dec