FocalPlane.py 3.83 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
49
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
import galsim
import numpy as np


class FocalPlane(object):
    def __init__(self, chip_list=None, survey_type='Photometric', bad_chips=None):
        """Get the focal plane layout
        """
        self.nchips = 42
        self.ignore_chips = []

        if bad_chips == None:
            self.bad_chips = []
        else:
            self.bad_chips = bad_chips
            for chip_id in bad_chips:
                self.ignore_chips.append(chip_id)

        if chip_list is not None:
            for i in range(42):
                if not (i+1 in chip_list):
                    self.ignore_chips.append(i+1)
        elif survey_type == 'Photometric':
            for i in range(5):
                self.ignore_chips.append(i+1)
                self.ignore_chips.append(i+26)
            self.ignore_chips.append(10)
            self.ignore_chips.append(21)
            for i in range(31, 43):
                self.ignore_chips.append(i)
        elif survey_type == 'Spectroscopic':
            for i in range(6, 26):
                if i == 10 or i == 21:
                    continue
                else:
                    self.ignore_chips.append(i)
            for i in range(31, 43):
                self.ignore_chips.append(i)
        elif survey_type == 'FGS':
            for i in range(1, 31):
                self.ignore_chips.append(i)

        self.nchip_x = 6
        self.nchip_y = 5
        self.npix_tot_x = 59516
        self.npix_tot_y = 49752
        self.npix_gap_x = (534, 1309)
        self.npix_gap_y = 898

        self._getCenter()

    def _getCenter(self):
        self.cen_pix_x = 0
        self.cen_pix_y = 0

    def getChipLabel(self, chipID):
        return str("0%d" % chipID)[-2:]

    def isBadChip(self, chipID):
        """Check if chip #(chipID) on the focal plane is bad or not
        """
        return (chipID in self.bad_chips)

    def isIgnored(self, chipID):
        return (chipID in self.ignore_chips)

    def getTanWCS(self, ra, dec, img_rot, pix_scale, xcen=None, ycen=None, logger=None):
        """ Get the WCS of the image mosaic using Gnomonic/TAN projection

        Parameter:
            ra, dec:    float
                        (RA, Dec) of pointing of optical axis
            img_rot:    galsim Angle object
                        Rotation of image
            pix_scale:  float
                        Pixel size in unit of as/pix
        Returns:
            WCS of the focal plane
        """
        if logger is not None:
            logger.info(
                "    Construct the wcs of the entire image mosaic using Gnomonic/TAN projection")
        if (xcen == None) or (ycen == None):
            xcen = self.cen_pix_x
            ycen = self.cen_pix_y

        dudx = -np.cos(img_rot.rad) * pix_scale
        dudy = +np.sin(img_rot.rad) * pix_scale
        dvdx = -np.sin(img_rot.rad) * pix_scale
        dvdy = -np.cos(img_rot.rad) * pix_scale

        moscen = galsim.PositionD(x=xcen, y=ycen)
        sky_center = galsim.CelestialCoord(
            ra=ra*galsim.degrees, dec=dec*galsim.degrees)
        affine = galsim.AffineTransform(dudx, dudy, dvdx, dvdy, origin=moscen)
        WCS = galsim.TanWCS(affine, sky_center, units=galsim.arcsec)

        return WCS

    def getSkyCoverage(self, wcs, x0, x1, y0, y1):
        """
        The sky coverage of an area
        """
        r2d = 180.0/np.pi
        s1 = wcs.toWorld(galsim.PositionD(x0, y0))
        s2 = wcs.toWorld(galsim.PositionD(x0, y1))
        s3 = wcs.toWorld(galsim.PositionD(x1, y0))
        s4 = wcs.toWorld(galsim.PositionD(x1, y1))
        ra = [s1.ra.rad*r2d, s2.ra.rad*r2d, s3.ra.rad*r2d, s4.ra.rad*r2d]
        dec = [s1.dec.rad*r2d, s2.dec.rad*r2d, s3.dec.rad*r2d, s4.dec.rad*r2d]

        return galsim.BoundsD(min(ra), max(ra), min(dec), max(dec))