예제 #1
0
파일: imSim.py 프로젝트: LSSTDESC/imSim
def _chip_downselect(mag_norm, x_pupil, y_pupil, logger, target_chips=None):
    """
    Down-select objects based on focalplane location relative to chip
    boundaries.  If target_chips is None, then the down-selection will
    be made for all of the science sensors in the focalplane.

    Returns
    -------
    dict: Dictionary of np.where indexes keyed by chip name
    """
    if target_chips is None:
        target_chips = [det.getName() for det in lsst_camera()]

    # how close to the edge of the detector a source has
    # to be before we will just simulate it anyway
    pix_tol = 50.0

    # any source brighter than this will be considered
    # so bright that it should be simulated for all
    # detectors, just in case light scatters onto them.
    max_mag = 16.0

    # Down-select by object location in focalplane relative to chip
    # boundaries.
    logger.debug('down-selecting by chip, %s GB', uss_mem())
    on_chip_dict = {}
    for chip_name in target_chips:
        pixel_corners = getCornerPixels(chip_name, lsst_camera())
        x_min = pixel_corners[0][0]
        x_max = pixel_corners[2][0]
        y_min = pixel_corners[0][1]
        y_max = pixel_corners[3][1]
        xpix, ypix = pixelCoordsFromPupilCoords(x_pupil,
                                                y_pupil,
                                                chipName=chip_name,
                                                camera=lsst_camera())

        on_chip = np.where(
            np.logical_or(
                mag_norm < max_mag,
                np.logical_and(
                    xpix > x_min - pix_tol,
                    np.logical_and(
                        xpix < x_max + pix_tol,
                        np.logical_and(ypix > y_min - pix_tol,
                                       ypix < y_max + pix_tol)))))

        on_chip_dict[chip_name] = on_chip
    return on_chip_dict
예제 #2
0
    def test_camPixFromDMpix(self):
        """
        test that trasformation between Camera Team and DM pixels works
        """
        camera_wrapper = DMtoCameraPixelTransformer()
        rng = np.random.RandomState()
        camera = lsst_camera()
        npts = 200
        for det in camera:
            det_name = det.getName()
            cam_x_in = rng.random_sample(npts)*4000.0
            cam_y_in = rng.random_sample(npts)*4000.0
            dm_x, dm_y = camera_wrapper.dmPixFromCameraPix(cam_x_in, cam_y_in, det_name)
            cam_x, cam_y = camera_wrapper.cameraPixFromDMPix(dm_x, dm_y, det_name)
            np.testing.assert_array_almost_equal(cam_x_in, cam_x, decimal=10)
            np.testing.assert_array_almost_equal(cam_y_in, cam_y, decimal=10)


            center_point = camera[det_name].getCenter(FOCAL_PLANE)
            pixel_system = camera[det_name].makeCameraSys(PIXELS)
            center_pix = camera.transform(center_point, FOCAL_PLANE, pixel_system)

            # test that DM and Camera Team pixels are correctly rotated
            # with respect to each other

            np.testing.assert_allclose(dm_x-center_pix.getX(),
                                       cam_y-center_pix.getX(),
                                       atol=1.0e-10, rtol=0.0)
            np.testing.assert_allclose(dm_y-center_pix.getY(),
                                       center_pix.getY()-cam_x,
                                       atol=1.0e-10, rtol=0.0)

        del camera_wrapper
        del lsst_camera._lsst_camera
예제 #3
0
    def __init__(self):
        self._camera = lsst_camera()
        self._pixel_transformer = DMtoCameraPixelTransformer()
        self._z_gen = ZernikePolynomialGenerator()

        self._rr = 500.0  # radius in mm of circle containing LSST focal plane;
        # make it a little bigger to accommodate any slop in
        # the conversion from focal plane coordinates back to
        # pupil coordinates (in case the optical distortions
        # cause points to cross over the actual boundary of
        # the focal plane)

        self._band_to_int = {}
        self._band_to_int['u'] = 0
        self._band_to_int['g'] = 1
        self._band_to_int['r'] = 2
        self._band_to_int['i'] = 3
        self._band_to_int['z'] = 4
        self._band_to_int['y'] = 5

        self._int_to_band = 'ugrizy'

        self._n_grid = []
        self._m_grid = []

        # 2018 May 8
        # During development, I found that there was negligible
        # improvement in the fit when allowing n>4, so I am
        # hard-coding the limit of n=4 here.
        for n in range(4):
            for m in range(-n, n + 1, 2):
                self._n_grid.append(n)
                self._m_grid.append(m)

        self._build_transformations()
예제 #4
0
    def __init__(self):
        self._camera = lsst_camera()
        self._pixel_transformer = DMtoCameraPixelTransformer()
        self._z_gen = ZernikePolynomialGenerator()

        self._rr = 500.0  # radius in mm of circle containing LSST focal plane;
                          # make it a little bigger to accommodate any slop in
                          # the conversion from focal plane coordinates back to
                          # pupil coordinates (in case the optical distortions
                          # cause points to cross over the actual boundary of
                          # the focal plane)

        self._band_to_int = {}
        self._band_to_int['u'] = 0
        self._band_to_int['g'] = 1
        self._band_to_int['r'] = 2
        self._band_to_int['i'] = 3
        self._band_to_int['z'] = 4
        self._band_to_int['y'] = 5

        self._int_to_band = 'ugrizy'

        self._n_grid = []
        self._m_grid = []

        # 2018 May 8
        # During development, I found that there was negligible
        # improvement in the fit when allowing n>4, so I am
        # hard-coding the limit of n=4 here.
        for n in range(4):
            for m in range(-n, n+1, 2):
                self._n_grid.append(n)
                self._m_grid.append(m)

        self._build_transformations()
예제 #5
0
 def _setupCamera(self):
     self.camera = lsst_camera()
     self.ccd_type_dict = {
         SCIENCE: 'science',
         WAVEFRONT: 'wavefront',
         GUIDER: 'guider',
         FOCUS: 'focus'
     }
예제 #6
0
파일: imSim.py 프로젝트: LSSTDESC/imSim
def get_obs_lsstSim_camera(log_level=lsstLog.WARN):
    """
    Get the obs_lsstSim CameraMapper object, setting the default
    log-level at WARN in order to silence the INFO message about
    "Loading Posix exposure registry from .". Note that this only
    affects the 'CameraMapper' logging level.  The logging level set
    by any calling code (e.g., imsim.py) will still apply to other log
    messages made by imSim code.
    """
    lsstLog.setLevel('CameraMapper', log_level)
    return lsst_camera()
예제 #7
0
    def pupilCoordsFromPixelCoords(self,
                                   xPix,
                                   yPix,
                                   chipName,
                                   includeDistortion=True):
        """
        Convert pixel coordinates into pupil coordinates

        Parameters
        ----------
        xPix is the x pixel coordinate of the point.
        Can be either a float or a numpy array.
        Defined in the Camera team system (not the DM system).

        yPix is the y pixel coordinate of the point.
        Can be either a float or a numpy array.
        Defined in the Camera team system (not the DM system).

        chipName is the name of the chip(s) on which the pixel coordinates
        are defined.  This can be a list (in which case there should be one chip name
        for each (xPix, yPix) coordinate pair), or a single value (in which case, all
        of the (xPix, yPix) points will be reckoned on that chip).

        includeDistortion is a boolean.  If True (default), then this method will
        expect the true pixel coordinates with optical distortion included.  If False, this
        method will expect TAN_PIXEL coordinates, which are the pixel coordinates with
        estimated optical distortion removed.  See the documentation in afw.cameraGeom for more
        details.

        Returns
        -------
        a 2-D numpy array in which the first row is the x pupil coordinate
        and the second row is the y pupil coordinate (both in radians)
        """
        dm_xPix = yPix
        if isinstance(chipName, list) or isinstance(chipName, np.ndarray):
            dm_yPix = np.zeros(len(xPix))
            for ix, (det_name, xx) in enumerate(zip(chipName, xPix)):
                came_center_pix = self.getCenterPixel(det_name)
                dm_yPix[ix] = 2.0 * cam_center_pix.getX() - xPix[ix]
        else:
            cam_center_pix = self.getCenterPixel(chipName)
            dm_yPix = 2.0 * cam_center_pix.getX() - xPix
        return coordUtils.pupilCoordsFromPixelCoords(
            dm_xPix,
            dm_yPix,
            chipName,
            camera=coordUtils.lsst_camera(),
            includeDistortion=includeDistortion)
예제 #8
0
def sources_from_list(lines, obs_md, phot_params, file_name):
    """Return a two-item tuple containing
       * a list of GalSimCelestialObjects for each object entry in `lines`
       * a dictionary of these objects disaggregated by chip_name.
    """
    target_chips = [det.getName() for det in lsst_camera()]
    gs_object_dict = dict()
    out_obj_dict = dict()
    for chip_name in target_chips:
        out_obj_dict[chip_name] \
            = [_ for _ in desc.imsim.GsObjectList(lines, obs_md, phot_params,
                                                  file_name, chip_name)]
        for gsobj in out_obj_dict[chip_name]:
            gs_object_dict[gsobj.uniqueId] = gsobj
    return list(gs_object_dict.values()), out_obj_dict
예제 #9
0
    def setUpClass(cls):
        cls.camera = lsst_camera()
        cls.data_dir = os.path.join(getPackageDir('sims_coordUtils'),
                                   'tests', 'lsstCameraData')

        pix_dtype = np.dtype([('ra', float), ('dec', float),
                              ('name', str, 15),
                              ('focal_x', float), ('focal_y', float),
                              ('pixel_x', float), ('pixel_y', float)])

        cls.pix_data = np.genfromtxt(os.path.join(cls.data_dir,
                                                  'lsst_pixel_data.txt'),
                                     delimiter=';', dtype=pix_dtype)

        ra = 25.0
        dec = -62.0
        cls.obs = ObservationMetaData(pointingRA=ra, pointingDec=dec,
                                      rotSkyPos=57.2, mjd=59586.2)
    def setUpClass(cls):
        cls.camera = lsst_camera()
        cls.data_dir = os.path.join(getPackageDir('sims_coordUtils'), 'tests',
                                    'lsstCameraData')

        pix_dtype = np.dtype([('ra', float), ('dec', float), ('name', str, 15),
                              ('focal_x', float), ('focal_y', float),
                              ('pixel_x', float), ('pixel_y', float)])

        cls.pix_data = np.genfromtxt(os.path.join(cls.data_dir,
                                                  'lsst_pixel_data.txt'),
                                     delimiter=';',
                                     dtype=pix_dtype)

        ra = 25.0
        dec = -62.0
        cls.obs = ObservationMetaData(pointingRA=ra,
                                      pointingDec=dec,
                                      rotSkyPos=57.2,
                                      mjd=59586.2)
예제 #11
0
def pupilCoordsFromFocalPlaneCoordsLSST(xmm, ymm, band='r'):
    """
    Convert mm on the focal plane to radians on the pupil.

    Note: round-tripping through focalPlaneCoordsFromPupilCoordsLSST
    and pupilCoordsFromFocalPlaneCoordsLSST introduces a residual
    of up to 2.18e-6 mm that accumulates with each round trip.

    Parameters
    ----------
    xmm -- x coordinate in millimeters on the focal plane

    ymm -- y coordinate in millimeters on the focal plane

    band -- the filter we are simulating (default='r')

    Returns
    -------
    a 2-D numpy array in which the first row is the x
    pupil coordinate and the second row is the y pupil
    coordinate (both in radians)
    """
    if not hasattr(pupilCoordsFromFocalPlaneCoordsLSST, '_z_fitter'):
        pupilCoordsFromFocalPlaneCoordsLSST._z_fitter = LsstZernikeFitter()

    if isinstance(xmm, numbers.Number):
        if np.isnan(xmm) or np.isnan(ymm):
            return np.array([np.NaN, np.NaN])

    z_fitter = pupilCoordsFromFocalPlaneCoordsLSST._z_fitter
    dx, dy = z_fitter.dxdy_inverse(xmm, ymm, band)
    x_f1 = xmm + dx
    y_f1 = ymm + dy
    xp, yp = pupilCoordsFromFocalPlaneCoords(x_f1, y_f1, camera=lsst_camera())

    if not isinstance(xmm, numbers.Number):
        nan_dex = np.where(np.logical_or(np.isnan(xmm), np.isnan(ymm)))
        xp[nan_dex] = np.NaN
        yp[nan_dex] = np.NaN

    return np.array([xp, yp])
예제 #12
0
def focalPlaneCoordsFromPupilCoordsLSST(xPupil, yPupil, band='r'):
    """
    Get the focal plane coordinates for all objects in the catalog.

    Parameters
    ----------
    xPupil -- the x pupil coordinates in radians.
    Can be a float or a numpy array.

    yPupil -- the y pupil coordinates in radians.
    Can be a float or a numpy array.

    band -- the filter being simulated (default='r')

    Returns
    --------
    a 2-D numpy array in which the first row is the x
    focal plane coordinate and the second row is the y focal plane
    coordinate (both in millimeters)
    """

    if not hasattr(focalPlaneCoordsFromPupilCoordsLSST, '_z_fitter'):
        focalPlaneCoordsFromPupilCoordsLSST._z_fitter = LsstZernikeFitter()

    if isinstance(xPupil, numbers.Number):
        if np.isnan(xPupil) or np.isnan(yPupil):
            return np.array([np.NaN, np.NaN])

    z_fitter = focalPlaneCoordsFromPupilCoordsLSST._z_fitter
    x_f0, y_f0 = focalPlaneCoordsFromPupilCoords(xPupil,
                                                 yPupil,
                                                 camera=lsst_camera())
    dx, dy = z_fitter.dxdy(x_f0, y_f0, band)

    if not isinstance(xPupil, numbers.Number):
        nan_dex = np.where(np.logical_or(np.isnan(xPupil), np.isnan(yPupil)))
        x_f0[nan_dex] = np.NaN
        y_f0[nan_dex] = np.NaN

    return np.array([x_f0 + dx, y_f0 + dy])
    def test_camPixFromDMpix(self):
        """
        test that trasformation between Camera Team and DM pixels works
        """
        camera_wrapper = DMtoCameraPixelTransformer()
        rng = np.random.RandomState()
        camera = lsst_camera()
        npts = 200
        for det in camera:
            det_name = det.getName()
            cam_x_in = rng.random_sample(npts) * 4000.0
            cam_y_in = rng.random_sample(npts) * 4000.0
            dm_x, dm_y = camera_wrapper.dmPixFromCameraPix(
                cam_x_in, cam_y_in, det_name)
            cam_x, cam_y = camera_wrapper.cameraPixFromDMPix(
                dm_x, dm_y, det_name)
            np.testing.assert_array_almost_equal(cam_x_in, cam_x, decimal=10)
            np.testing.assert_array_almost_equal(cam_y_in, cam_y, decimal=10)

            center_point = camera[det_name].getCenter(FOCAL_PLANE)
            pixel_system = camera[det_name].makeCameraSys(PIXELS)
            center_pix = camera.transform(center_point, FOCAL_PLANE,
                                          pixel_system)

            # test that DM and Camera Team pixels are correctly rotated
            # with respect to each other

            np.testing.assert_allclose(dm_x - center_pix.getX(),
                                       cam_y - center_pix.getX(),
                                       atol=1.0e-10,
                                       rtol=0.0)
            np.testing.assert_allclose(dm_y - center_pix.getY(),
                                       center_pix.getY() - cam_x,
                                       atol=1.0e-10,
                                       rtol=0.0)

        del camera_wrapper
        del lsst_camera._lsst_camera
예제 #14
0
def _findDetectorsListLSST(focalPointList,
                           detectorList,
                           possible_points,
                           allow_multiple_chips=False):
    """!Find the detectors that cover a list of points specified by x and y coordinates in any system

    This is based one afw.camerGeom.camera.findDetectorsList.  It has been optimized for the LSST
    camera in the following way:

        - it accepts a limited list of detectors to check in advance (this list should be
          constructed by comparing the pupil coordinates in question and comparing to the
          pupil coordinates of the center of each detector)

       - it will stop looping through detectors one it has found one that is correct (the LSST
         camera does not allow an object to fall on more than one detector)

    @param[in] focalPointList  a list of points in FOCAL_PLANE coordinates

    @param[in] detectorList is a list of the afwCameraGeom detector objects being considered

    @param[in] possible_points is a list of lists.  possible_points[ii] is a list of integers
    corresponding to the indices in focalPointList of the pupilPoints that may be on detectorList[ii].

    @param [in] allow_multiple_chips is a boolean (default False) indicating whether or not
    this method will allow objects to be visible on more than one chip.  If it is 'False'
    and an object appears on more than one chip, only the first chip will appear in the list of
    chipNames but NO WARNING WILL BE EMITTED.  If it is 'True' and an object falls on more than one
    chip, a list of chipNames will appear for that object.

    @return outputNameList is a numpy array of the names of the detectors
    """
    # transform the points to the native coordinate system
    #
    # The conversion to a numpy array looks a little clunky.
    # The problem, if you do the naive thing (nativePointList = np.array(lsst_camera().....),
    # the conversion to a numpy array gets passed down to the contents of nativePointList
    # and they end up in a form that the afwCameraGeom code does not know how to handle
    nativePointList = np.zeros(len(focalPointList), dtype=object)
    for ii in range(len(focalPointList)):
        nativePointList[ii] = focalPointList[ii]

    # initialize output and some caching lists
    outputNameList = [None] * len(focalPointList)
    chip_has_found = np.array([-1] * len(focalPointList))
    unfound_pts = len(chip_has_found)

    # Figure out if any of these (RA, Dec) pairs could be
    # on more than one chip.  This is possible on the
    # wavefront sensors, since adjoining wavefront sensors
    # are kept one in focus, one out of focus.
    # See figure 2 of arXiv:1506.04839v2
    # (This might actually be a bug in obs_lsstSim
    # I opened DM-8075 on 25 October 2016 to investigate)
    could_be_multiple = [False] * len(focalPointList)
    if allow_multiple_chips:
        for ipt in range(len(focalPointList)):
            for det in detectorList[ipt]:
                if det.getType() == WAVEFRONT:
                    could_be_multiple[ipt] = True

    # t_assemble_list = 0.0
    # loop over detectors
    for i_detector, detector in enumerate(detectorList):
        if len(possible_points[i_detector]) == 0:
            continue

        if unfound_pts <= 0:
            if unfound_pts < 0:
                raise RuntimeError(
                    "Somehow, unfound_pts = %d in _findDetectorsListLSST" %
                    unfound_pts)
            # we have already found all of the (RA, Dec) pairs
            for ix, name in enumerate(outputNameList):
                if isinstance(name, list):
                    outputNameList[ix] = str(name)
            return np.array(outputNameList)

        # find all of the pupil points that could be on this detector
        valid_pt_dexes = possible_points[i_detector][np.where(
            chip_has_found[possible_points[i_detector]] < 0)]

        if len(valid_pt_dexes) > 0:
            valid_pt_list = nativePointList[valid_pt_dexes]
            transform = detector.getTransform(lsst_camera()._nativeCameraSys,
                                              PIXELS)
            detectorPointList = transform.applyForward(valid_pt_list)

            box = geom.Box2D(detector.getBBox())
            for ix, pt in zip(valid_pt_dexes, detectorPointList):
                if box.contains(pt):
                    if not could_be_multiple[ix]:
                        # because this (RA, Dec) pair is not marked as could_be_multiple,
                        # the fact that this (RA, Dec) pair is on the current chip
                        # means this (RA, Dec) pair no longer needs to be considered.
                        # You can set chip_has_found[ix] to unity.
                        outputNameList[ix] = detector.getName()
                        chip_has_found[ix] = 1
                        unfound_pts -= 1
                    else:
                        # Since this (RA, Dec) pair has been makred could_be_multiple,
                        # finding this (RA, Dec) pair on the chip does not remove the
                        # (RA, Dec) pair from contention.
                        if outputNameList[ix] is None:
                            outputNameList[ix] = detector.getName()
                        elif isinstance(outputNameList[ix], list):
                            outputNameList[ix].append(detector.getName())
                        else:
                            outputNameList[ix] = [
                                outputNameList[ix],
                                detector.getName()
                            ]

    # convert entries corresponding to multiple chips into strings
    # (i.e. [R:2,2 S:0,0, R:2,2 S:0,1] becomes `[R:2,2 S:0,0, R:2,2 S:0,1]`)
    for ix, name in enumerate(outputNameList):
        if isinstance(name, list):
            outputNameList[ix] = str(name)

    # print('t_assemble %.2e' % t_assemble_list)

    return np.array(outputNameList)
예제 #15
0
def _build_lsst_focal_coord_map():
    """
    Build a map of focal plane coordinates on the LSST focal plane.
    Returns _lsst_focal_coord_map, which is a dict.
    _lsst_focal_coord_map['name'] contains a list of the names of each chip in the lsst camera
    _lsst_focal_coord_map['xx'] contains the x focal plane coordinate of the center of each chip (mm)
    _lsst_focal_coord_map['yy'] contains the y focal plane coordinate of the center of each chip (mm)
    _lsst_focal_coord_map['dp'] contains the radius (in mm) of the circle containing each chip
    """

    camera = lsst_camera()

    name_list = []
    x_pix_list = []
    y_pix_list = []
    x_mm_list = []
    y_mm_list = []
    n_chips = 0
    for chip in camera:
        chip_name = chip.getName()
        pixels_to_focal = chip.getTransform(PIXELS, FOCAL_PLANE)
        n_chips += 1
        corner_list = getCornerPixels(chip_name, lsst_camera())
        for corner in corner_list:
            x_pix_list.append(corner[0])
            y_pix_list.append(corner[1])
            pixel_pt = geom.Point2D(corner[0], corner[1])
            focal_pt = pixels_to_focal.applyForward(pixel_pt)
            x_mm_list.append(focal_pt.getX())
            y_mm_list.append(focal_pt.getY())
            name_list.append(chip_name)

    x_pix_list = np.array(x_pix_list)
    y_pix_list = np.array(y_pix_list)
    x_mm_list = np.array(x_mm_list)
    y_mm_list = np.array(y_mm_list)

    center_x = np.zeros(n_chips, dtype=float)
    center_y = np.zeros(n_chips, dtype=float)
    extent = np.zeros(n_chips, dtype=float)
    final_name = []
    for ix_ct in range(n_chips):
        ix = ix_ct * 4
        chip_name = name_list[ix]
        xx = 0.25 * (x_mm_list[ix] + x_mm_list[ix + 1] + x_mm_list[ix + 2] +
                     x_mm_list[ix + 3])

        yy = 0.25 * (y_mm_list[ix] + y_mm_list[ix + 1] + y_mm_list[ix + 2] +
                     y_mm_list[ix + 3])

        dx = 0.25 * np.array([
            np.sqrt(
                np.power(xx - x_mm_list[ix + ii], 2) +
                np.power(yy - y_mm_list[ix + ii], 2)) for ii in range(4)
        ]).sum()

        center_x[ix_ct] = xx
        center_y[ix_ct] = yy
        extent[ix_ct] = dx
        final_name.append(chip_name)

    final_name = np.array(final_name)

    lsst_focal_coord_map = {}
    lsst_focal_coord_map['name'] = final_name
    lsst_focal_coord_map['xx'] = center_x
    lsst_focal_coord_map['yy'] = center_y
    lsst_focal_coord_map['dp'] = extent
    return lsst_focal_coord_map
예제 #16
0
    def test_naive_focal_plane_position(self):
        """
        Test deprecession of PhoSim coordinates by comparing
        the focal plane position predicted by CatSim from ICRS
        with the focal plane position predicted by CatSim from deprecessed
        coordinates.
        """

        phosim_mixin = PhoSimAstrometryBase()

        mjd = 59587.2

        # create site with no atmosphere so that we can avoid
        # refraction
        site = Site(name="LSST", pressure=0.0, humidity=0.0)

        obs = ObservationMetaData(mjd=mjd, site=site)
        ra, dec = raDecFromAltAz(31.0, 112.0, obs)

        d_sun = distanceToSun(ra, dec, obs.mjd)
        self.assertGreater(d_sun, 45.0)

        obs = ObservationMetaData(pointingRA=ra,
                                  pointingDec=dec,
                                  rotSkyPos=27.3,
                                  mjd=mjd,
                                  site=site)
        ra_icrs = np.arange(obs.pointingRA - 2.0, obs.pointingRA + 2.0, 0.05)
        dec_icrs = np.arange(obs.pointingDec - 2.0, obs.pointingDec + 2.0,
                             0.05)

        coord_grid = np.meshgrid(ra_icrs, dec_icrs)
        ra_icrs = coord_grid[0].flatten()
        dec_icrs = coord_grid[1].flatten()

        (xpup_icrs, ypup_icrs) = pupilCoordsFromRaDec(ra_icrs,
                                                      dec_icrs,
                                                      obs_metadata=obs,
                                                      epoch=2000.0,
                                                      includeRefraction=False)

        (x_focal_icrs,
         y_focal_icrs) = focalPlaneCoordsFromPupilCoords(xpup_icrs,
                                                         ypup_icrs,
                                                         camera=lsst_camera())

        ra_obs, dec_obs = observedFromICRS(ra_icrs,
                                           dec_icrs,
                                           obs_metadata=obs,
                                           epoch=2000.0,
                                           includeRefraction=False)

        ra_obs_rad = np.radians(ra_obs)
        dec_obs_rad = np.radians(dec_obs)

        (ra_deprecessed_rad, dec_deprecessed_rad) = phosim_mixin._dePrecess(
            ra_obs_rad, dec_obs_rad, obs)

        (xpup_deprecessed, ypup_deprecessed) = _naivePupilCoordsFromObserved(
            ra_deprecessed_rad, dec_deprecessed_rad, obs._pointingRA,
            obs._pointingDec, obs._rotSkyPos)

        (x_focal_deprecessed,
         y_focal_deprecessed) = focalPlaneCoordsFromPupilCoords(
             xpup_deprecessed, ypup_deprecessed, camera=lsst_camera())

        dd = np.sqrt((x_focal_icrs - x_focal_deprecessed)**2 +
                     (y_focal_icrs - y_focal_deprecessed)**2)

        self.assertLess(dd.max(), 1.0e-8)
    def test_pixel_positions(self):
        """
        Test that CatSim pixel positions are close to PhoSim pixel positions.

        This is complicated by the fact that PhoSim uses the camera team definition
        of pixel space, which differs from the DM definition of pixel space as follows:

        Camera +y = DM +x
        Camera +x = DM -y
        Camera +z = DM +z

        This has been verified both by consulting documentation -- the documentation for
        afwCameraGeom says that +x is along the serial readout direction; LCA-13381
        indicates that, in the Camera team's definition, the serial readout is along +y --
        and phenomenologically by comparing the relationship between
        pixelCoordsFromPupilCoords() to visual inspection of PhoSim-generated FITS images.
        """
        self.assertGreater(len(self.data), 10)
        for ix in range(len(self.data)):

            in_name = self.data['chipName'][ix]
            chip_name = in_name[0] + ':' + in_name[1] + ',' + in_name[2]
            chip_name += ' ' + in_name[3] + ':' + in_name[4] + ',' + in_name[5]
            corner_pixels = getCornerPixels(chip_name, lsst_camera())

            x_center_dm = 0.25 * (corner_pixels[0][0] + corner_pixels[1][0] +
                                  corner_pixels[2][0] + corner_pixels[3][0])

            y_center_dm = 0.25 * (corner_pixels[0][1] + corner_pixels[1][1] +
                                  corner_pixels[2][1] + corner_pixels[3][1])

            obs = ObservationMetaData(pointingRA=self.data['pointingRA'][ix],
                                      pointingDec=self.data['pointingDec'][ix],
                                      rotSkyPos=self.data['rotSkyPos'][ix],
                                      mjd=59580.0)

            xpix, ypix = pixelCoordsFromRaDecLSST(self.data['objRA'][ix],
                                                  self.data['objDec'][ix],
                                                  obs_metadata=obs)

            raObs, decObs = observedFromICRS(self.data['objRA'][ix],
                                             self.data['objDec'][ix],
                                             obs_metadata=obs,
                                             epoch=2000.0)

            # find displacement from center of DM coordinates of the
            # objects as placed by PhoSim
            d_y_phosim = y_center_dm - self.data['xpix'][ix]
            d_x_phosim = self.data['ypix'][ix] - x_center_dm

            # displacement from center of DM coordinates as calculated
            # by DM
            d_x_dm = xpix - x_center_dm
            d_y_dm = ypix - y_center_dm

            d_pix = np.sqrt((d_x_dm - d_x_phosim)**2 +
                            (d_y_dm - d_y_phosim)**2)

            # demand that the difference between the two displacements is less
            # than 0.05 of the total displacement from the center of the object
            # as calculated by DM
            msg = 'dx %e; dy %e' % (d_x_dm, d_y_dm)
            self.assertLess(d_pix,
                            0.05 * np.sqrt(d_x_dm**2 + d_y_dm**2),
                            msg=msg)
예제 #18
0
import numpy as np
from PhoSimTransform import PhoSimPixelTransformer
from lsst.afw.cameraGeom import SCIENCE
from lsst.sims.coordUtils import lsst_camera


if __name__ == "__main__":

    coord_converter = PhoSimPixelTransformer()
    camera = lsst_camera()
    rng = np.random.RandomState(213)
    det_name_list = []
    for det in camera:
        if det.getType() != SCIENCE:
            continue
        det_name_list.append(det.getName())

    n_test = 20
    test_name_list = rng.choice(det_name_list, size=n_test, replace=True)
    xpix_list = rng.random_sample(n_test)*4000.0
    ypix_list = rng.random_sample(n_test)*4000.0
    for xpix, ypix, test_name in zip(xpix_list, ypix_list, test_name_list):

        xmm, ymm = coord_converter.mmFromPix(xpix, ypix, test_name)
        xpix1, ypix1 = coord_converter.pixFromMM(xmm, ymm, test_name)
        dd = np.sqrt((xpix-xpix1)**2+(ypix-ypix1)**2)
        assert dd<1.0e-10
theta = rng.random_sample(n_sources)*2.0*np.pi

from lsst.sims.coordUtils import pupilCoordsFromPixelCoordsLSST
from lsst.sims.coordUtils import lsst_camera
from lsst.afw.cameraGeom import SCIENCE

xpix = np.arange(200.0, 3801.0, 200.0)
ypix = np.arange(200.0, 3801.0, 200.0)
mesh = np.meshgrid(xpix, ypix)
xpix_mesh =mesh[0].flatten()
ypix_mesh = mesh[1].flatten()

xpix = []
ypix = []
chip = []
for det in lsst_camera():
    if det.getType()!=SCIENCE:
        continue
    for xx, yy in zip(xpix_mesh, ypix_mesh):
        xpix.append(xx)
        ypix.append(yy)
        chip.append(det.getName())

xpix = np.array(xpix)
ypix = np.array(ypix)
chip = np.array(chip)
xp, yp = pupilCoordsFromPixelCoordsLSST(xpix, ypix, chipName=chip, band='r')
ra, dec = raDecFromPupilCoords(xp, yp, obs_metadata=obs_root,
                               includeRefraction=False)

out_dir = 'ratio_test/catalogs'
예제 #20
0
    def test_pixel_positions(self):
        """
        Test that CatSim pixel positions are close to PhoSim pixel positions.

        This is complicated by the fact that PhoSim uses the camera team definition
        of pixel space, which differs from the DM definition of pixel space as follows:

        Camera +y = DM +x
        Camera +x = DM -y
        Camera +z = DM +z

        This has been verified both by consulting documentation -- the documentation for
        afwCameraGeom says that +x is along the serial readout direction; LCA-13381
        indicates that, in the Camera team's definition, the serial readout is along +y --
        and phenomenologically by comparing the relationship between
        pixelCoordsFromPupilCoords() to visual inspection of PhoSim-generated FITS images.
        """
        self.assertGreater(len(self.data), 10)
        for ix in range(len(self.data)):

            in_name = self.data['chipName'][ix]
            chip_name = in_name[0]+':'+in_name[1]+','+in_name[2]
            chip_name += ' '+in_name[3]+':'+in_name[4]+','+in_name[5]
            corner_pixels = getCornerPixels(chip_name, lsst_camera())

            x_center_dm = 0.25*(corner_pixels[0][0] + corner_pixels[1][0] +
                                corner_pixels[2][0] + corner_pixels[3][0])

            y_center_dm = 0.25*(corner_pixels[0][1] + corner_pixels[1][1] +
                                corner_pixels[2][1] + corner_pixels[3][1])

            obs = ObservationMetaData(pointingRA=self.data['pointingRA'][ix],
                                      pointingDec=self.data['pointingDec'][ix],
                                      rotSkyPos=self.data['rotSkyPos'][ix],
                                      mjd=59580.0)

            xpix, ypix = pixelCoordsFromRaDecLSST(self.data['objRA'][ix],
                                                  self.data['objDec'][ix],
                                                  obs_metadata=obs)

            raObs, decObs = observedFromICRS(self.data['objRA'][ix],
                                             self.data['objDec'][ix],
                                             obs_metadata=obs,
                                             epoch=2000.0)

            # find displacement from center of DM coordinates of the
            # objects as placed by PhoSim
            d_y_phosim = y_center_dm - self.data['xpix'][ix]
            d_x_phosim = self.data['ypix'][ix] - x_center_dm

            # displacement from center of DM coordinates as calculated
            # by DM
            d_x_dm = xpix - x_center_dm
            d_y_dm = ypix - y_center_dm

            d_pix = np.sqrt((d_x_dm - d_x_phosim)**2 +
                            (d_y_dm - d_y_phosim)**2)

            # demand that the difference between the two displacements is less
            # than 0.05 of the total displacement from the center of the object
            # as calculated by DM
            msg = 'dx %e; dy %e' % (d_x_dm, d_y_dm)
            self.assertLess(d_pix, 0.05*np.sqrt(d_x_dm**2+d_y_dm**2), msg=msg)
    def test_avro_alert_generation_diff_dmag(self):
        """
        Make sure everything works properly when the AlertDataGenerator
        and the AvroAlertGenerator have different dmag thresholds
        """
        dmag_cutoff_sqlite = 0.005
        dmag_cutoff_avro = 0.2
        mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z': 4, 'y': 5}

        star_db = StarAlertTestDBObj_avro(database=self.star_db_name,
                                          driver='sqlite')

        # assemble a dict of all of the alerts that need to be generated

        obshistid_list = []
        for obs in self.obs_list:
            obshistid_list.append(obs.OpsimMetaData['obsHistID'])
        obshistid_max = max(obshistid_list)
        obshistid_bits = int(np.ceil(np.log(obshistid_max) / np.log(2.0)))

        true_alert_dict = {}
        obs_dict = {}
        ignored_sqlite = 0  # count number of alerts written to sqlite, but not avro
        for obs in self.obs_list:
            obs_dict[obs.OpsimMetaData['obsHistID']] = obs
            obshistid = obs.OpsimMetaData['obsHistID']
            cat = TestAlertsTruthCat_avro(star_db, obs_metadata=obs)
            cat.camera = lsst_camera()

            for line in cat.iter_catalog():
                if line[1] is None:
                    continue

                dmag = line[2]
                mag = line[3]
                if (np.abs(dmag) > dmag_cutoff_avro and mag <=
                        self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]):

                    alertId = (line[0] << obshistid_bits) + obshistid
                    self.assertNotIn(alertId, true_alert_dict)
                    true_alert_dict[alertId] = {}
                    true_alert_dict[alertId]['chipName'] = line[1]
                    true_alert_dict[alertId]['dmag'] = dmag
                    true_alert_dict[alertId]['mag'] = mag
                    true_alert_dict[alertId]['ra'] = np.degrees(line[4])
                    true_alert_dict[alertId]['decl'] = np.degrees(line[5])
                    true_alert_dict[alertId]['xPix'] = line[6]
                    true_alert_dict[alertId]['yPix'] = line[7]
                elif np.abs(dmag) > dmag_cutoff_sqlite:
                    ignored_sqlite += 1

        self.assertGreater(len(true_alert_dict), 10)

        self.assertGreater(ignored_sqlite,
                           50)  # just make sure that some sqlite
        # alerts were ignored by the more
        # stringent avro cut

        log_file_name = tempfile.mktemp(dir=self.alert_data_output_dir,
                                        suffix='log.txt')
        alert_gen = AlertDataGenerator(testing=True)

        alert_gen.subdivide_obs(self.obs_list, htmid_level=6)

        for htmid in alert_gen.htmid_list:
            alert_gen.alert_data_from_htmid(
                htmid,
                star_db,
                photometry_class=TestAlertsVarCat_avro,
                output_prefix='alert_test',
                output_dir=self.alert_data_output_dir,
                dmag_cutoff=dmag_cutoff_sqlite,
                log_file_name=log_file_name)

        obshistid_to_htmid = {}
        for htmid in alert_gen.htmid_list:
            for obs in alert_gen.obs_from_htmid(htmid):
                obshistid = obs.OpsimMetaData['obsHistID']
                if obshistid not in obshistid_to_htmid:
                    obshistid_to_htmid[obshistid] = []
                obshistid_to_htmid[obshistid].append(htmid)

        avro_gen = AvroAlertGenerator()
        avro_gen.load_schema(
            os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData',
                         'avroSchema'))
        sql_prefix_list = ['alert_test']
        out_prefix = 'test_avro'
        log_file_name = tempfile.mktemp(dir=self.avro_out_dir,
                                        prefix='test_avro',
                                        suffix='log.txt')
        for obshistid in obshistid_list:
            avro_gen.write_alerts(obshistid,
                                  self.alert_data_output_dir,
                                  sql_prefix_list,
                                  obshistid_to_htmid[obshistid],
                                  self.avro_out_dir,
                                  out_prefix,
                                  dmag_cutoff_avro,
                                  lock=None,
                                  log_file_name=log_file_name)

        list_of_avro_files = os.listdir(self.avro_out_dir)
        self.assertGreater(len(list_of_avro_files), 2)
        alert_ct = 0
        dummy_sed = Sed()
        bp_dict = BandpassDict.loadTotalBandpassesFromFiles()
        photParams = PhotometricParameters()
        diasourceId_set = set()
        for avro_file_name in list_of_avro_files:
            if avro_file_name.endswith('log.txt'):
                continue
            full_name = os.path.join(self.avro_out_dir, avro_file_name)
            with DataFileReader(open(full_name, 'rb'),
                                DatumReader()) as data_reader:
                for alert in data_reader:
                    alert_ct += 1
                    obshistid = alert['alertId'] >> 20
                    obs = obs_dict[obshistid]
                    uniqueId = alert['diaObject']['diaObjectId']
                    true_alert_id = (uniqueId << obshistid_bits) + obshistid
                    self.assertIn(true_alert_id, true_alert_dict)
                    self.assertEqual(alert['l1dbId'], uniqueId)

                    true_alert = true_alert_dict[true_alert_id]

                    diaSource = alert['diaSource']
                    self.assertAlmostEqual(diaSource['ra'], true_alert['ra'],
                                           10)
                    self.assertAlmostEqual(diaSource['decl'],
                                           true_alert['decl'], 10)
                    self.assertAlmostEqual(diaSource['x'], true_alert['xPix'],
                                           3)
                    self.assertAlmostEqual(diaSource['y'], true_alert['yPix'],
                                           3)
                    self.assertAlmostEqual(diaSource['midPointTai'],
                                           obs.mjd.TAI, 4)

                    true_tot_flux = dummy_sed.fluxFromMag(true_alert['mag'])
                    true_q_mag = true_alert['mag'] - true_alert['dmag']
                    true_q_flux = dummy_sed.fluxFromMag(true_q_mag)
                    true_dflux = true_tot_flux - true_q_flux
                    self.assertAlmostEqual(diaSource['psFlux'] / true_dflux,
                                           1.0, 6)
                    self.assertAlmostEqual(
                        diaSource['totFlux'] / true_tot_flux, 1.0, 6)
                    self.assertAlmostEqual(diaSource['diffFlux'] / true_dflux,
                                           1.0, 6)

                    true_tot_snr, gamma = calcSNR_m5(true_alert['mag'],
                                                     bp_dict[obs.bandpass],
                                                     obs.m5[obs.bandpass],
                                                     photParams)

                    true_q_snr, gamma = calcSNR_m5(
                        true_q_mag, bp_dict[obs.bandpass],
                        self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]],
                        photParams)

                    true_tot_err = true_tot_flux / true_tot_snr
                    true_q_err = true_q_flux / true_q_snr
                    true_diff_err = np.sqrt(true_tot_err**2 + true_q_err**2)

                    self.assertAlmostEqual(
                        diaSource['snr'] / np.abs(true_dflux / true_diff_err),
                        1.0, 6)

                    self.assertAlmostEqual(
                        diaSource['totFluxErr'] / true_tot_err, 1.0, 6)
                    self.assertAlmostEqual(
                        diaSource['diffFluxErr'] / true_diff_err, 1.0, 6)

                    chipnum = int(true_alert['chipName'].replace(
                        'R', '').replace('S', '').replace(',', '').replace(
                            ':', '').replace(' ', ''))

                    true_ccdid = (chipnum * 10**7) + obshistid
                    self.assertEqual(true_ccdid, diaSource['ccdVisitId'])
                    self.assertEqual(uniqueId, diaSource['diaObjectId'])

                    self.assertNotIn(diaSource['diaSourceId'], diasourceId_set)
                    diasourceId_set.add(diaSource['diaSourceId'])

                    diaObject = alert['diaObject']
                    obj_dex = (uniqueId // 1024) - 1
                    self.assertAlmostEqual(
                        0.001 * diaObject['pmRa'] / self.pmra_truth[obj_dex],
                        1.0, 5)
                    self.assertAlmostEqual(
                        0.001 * diaObject['pmDecl'] /
                        self.pmdec_truth[obj_dex], 1.0, 5)
                    self.assertAlmostEqual(
                        0.001 * diaObject['parallax'] / self.px_truth[obj_dex],
                        1.0, 5)

                    (true_ra_base, true_dec_base) = applyProperMotion(
                        self.ra_truth[obj_dex],
                        self.dec_truth[obj_dex],
                        self.pmra_truth[obj_dex],
                        self.pmdec_truth[obj_dex],
                        self.px_truth[obj_dex],
                        self.vrad_truth[obj_dex],
                        mjd=ModifiedJulianDate(TAI=diaObject['radecTai']))

                    self.assertAlmostEqual(true_ra_base, diaObject['ra'], 7)
                    self.assertAlmostEqual(true_dec_base, diaObject['decl'], 7)

        self.assertEqual(alert_ct, len(true_alert_dict))
예제 #22
0
def sources_from_file(file_name, obs_md, phot_params, numRows=None):
    """
    Read in an InstanceCatalog and extract all of the astrophysical
    sources from it

    Parameters
    ----------
    file_name: str
        The name of the InstanceCatalog

    obs_md: ObservationMetaData
        The ObservationMetaData characterizing the pointing

    phot_params: PhotometricParameters
        The PhotometricParameters characterizing this telescope

    numRows: int (optional)
        The number of rows of the InstanceCatalog to read in (including the
        header)

    Returns
    -------
    gs_obj_arr: numpy array
        Contains the GalSimCelestialObjects for all of the
        astrophysical sources in this InstanceCatalog

    out_obj_dict: dict
        Keyed on the names of the detectors in the LSST camera.
        The values are numpy arrays of GalSimCelestialObjects
        that should be simulated for that detector, including
        objects that are near the edge of the chip or
        just bright (in which case, they might still illuminate
        the detector).
    """

    camera = get_obs_lsstSim_camera()

    num_objects = 0
    ct_rows = 0
    with fopen(file_name, mode='rt') as input_file:
        for line in input_file:
            ct_rows += 1
            params = line.strip().split()
            if params[0] == 'object':
                num_objects += 1
            if numRows is not None and ct_rows >= numRows:
                break

    # RA, Dec in the coordinate system expected by PhoSim
    ra_phosim = np.zeros(num_objects, dtype=float)
    dec_phosim = np.zeros(num_objects, dtype=float)

    sed_name = [None] * num_objects
    mag_norm = 55.0 * np.ones(num_objects, dtype=float)
    gamma1 = np.zeros(num_objects, dtype=float)
    gamma2 = np.zeros(num_objects, dtype=float)
    kappa = np.zeros(num_objects, dtype=float)

    internal_av = np.zeros(num_objects, dtype=float)
    internal_rv = np.zeros(num_objects, dtype=float)
    galactic_av = np.zeros(num_objects, dtype=float)
    galactic_rv = np.zeros(num_objects, dtype=float)
    semi_major_arcsec = np.zeros(num_objects, dtype=float)
    semi_minor_arcsec = np.zeros(num_objects, dtype=float)
    position_angle_degrees = np.zeros(num_objects, dtype=float)
    sersic_index = np.zeros(num_objects, dtype=float)
    npoints = np.zeros(num_objects, dtype=int)
    redshift = np.zeros(num_objects, dtype=float)

    unique_id = np.zeros(num_objects, dtype=int)
    object_type = np.zeros(num_objects, dtype=int)

    i_obj = -1
    with fopen(file_name, mode='rt') as input_file:
        for line in input_file:
            params = line.strip().split()
            if params[0] != 'object':
                continue
            i_obj += 1
            if numRows is not None and i_obj >= num_objects:
                break
            unique_id[i_obj] = int(params[1])
            ra_phosim[i_obj] = float(params[2])
            dec_phosim[i_obj] = float(params[3])
            mag_norm[i_obj] = float(params[4])
            sed_name[i_obj] = params[5]
            redshift[i_obj] = float(params[6])
            gamma1[i_obj] = float(params[7])
            gamma2[i_obj] = float(params[8])
            kappa[i_obj] = float(params[9])
            if params[12].lower() == 'point':
                object_type[i_obj] = _POINT_SOURCE
                i_gal_dust_model = 14
                if params[13].lower() != 'none':
                    i_gal_dust_model = 16
                    internal_av[i_obj] = float(params[14])
                    internal_rv[i_obj] = float(params[15])
                if params[i_gal_dust_model].lower() != 'none':
                    galactic_av[i_obj] = float(params[i_gal_dust_model + 1])
                    galactic_rv[i_obj] = float(params[i_gal_dust_model + 2])
            elif params[12].lower() == 'sersic2d':
                object_type[i_obj] = _SERSIC_2D
                semi_major_arcsec[i_obj] = float(params[13])
                semi_minor_arcsec[i_obj] = float(params[14])
                position_angle_degrees[i_obj] = float(params[15])
                sersic_index[i_obj] = float(params[16])
                i_gal_dust_model = 18
                if params[17].lower() != 'none':
                    i_gal_dust_model = 20
                    internal_av[i_obj] = float(params[18])
                    internal_rv[i_obj] = float(params[19])
                if params[i_gal_dust_model].lower() != 'none':
                    galactic_av[i_obj] = float(params[i_gal_dust_model + 1])
                    galactic_rv[i_obj] = float(params[i_gal_dust_model + 2])
            elif params[12].lower() == 'knots':
                object_type[i_obj] = _RANDOM_WALK
                semi_major_arcsec[i_obj] = float(params[13])
                semi_minor_arcsec[i_obj] = float(params[14])
                position_angle_degrees[i_obj] = float(params[15])
                npoints[i_obj] = int(params[16])
                i_gal_dust_model = 18
                if params[17].lower() != 'none':
                    i_gal_dust_model = 20
                    internal_av[i_obj] = float(params[18])
                    internal_rv[i_obj] = float(params[19])
                if params[i_gal_dust_model].lower() != 'none':
                    galactic_av[i_obj] = float(params[i_gal_dust_model + 1])
                    galactic_rv[i_obj] = float(params[i_gal_dust_model + 2])
            else:
                raise RuntimeError("Do not know how to handle "
                                   "object type: %s" % params[12])

    ra_appGeo, dec_appGeo = PhoSimAstrometryBase._appGeoFromPhoSim(
        np.radians(ra_phosim), np.radians(dec_phosim), obs_md)

    (ra_obs_rad, dec_obs_rad) = _observedFromAppGeo(ra_appGeo,
                                                    dec_appGeo,
                                                    obs_metadata=obs_md,
                                                    includeRefraction=True)

    semi_major_radians = radiansFromArcsec(semi_major_arcsec)
    semi_minor_radians = radiansFromArcsec(semi_minor_arcsec)
    position_angle_radians = np.radians(position_angle_degrees)

    x_pupil, y_pupil = _pupilCoordsFromObserved(ra_obs_rad, dec_obs_rad,
                                                obs_md)

    bp_dict = BandpassDict.loadTotalBandpassesFromFiles()

    sed_dir = lsstUtils.getPackageDir('sims_sed_library')

    object_is_valid = np.array([True] * num_objects)

    invalid_objects = np.where(
        np.logical_or(
            np.logical_or(
                mag_norm > 50.0,
                np.logical_and(galactic_av == 0.0, galactic_rv == 0.0)),
            np.logical_or(
                np.logical_and(object_type == _SERSIC_2D,
                               semi_major_arcsec < semi_minor_arcsec),
                np.logical_and(object_type == _RANDOM_WALK, npoints <= 0))))

    object_is_valid[invalid_objects] = False

    if len(invalid_objects[0]) > 0:
        message = "\nOmitted %d suspicious objects from " % len(
            invalid_objects[0])
        message += "the instance catalog:\n"
        n_bad_mag_norm = len(np.where(mag_norm > 50.0)[0])
        message += "    %d had mag_norm > 50.0\n" % n_bad_mag_norm
        n_bad_av = len(
            np.where(np.logical_and(galactic_av == 0.0,
                                    galactic_rv == 0.0))[0])
        message += "    %d had galactic_Av == galactic_Rv == 0\n" % n_bad_av
        n_bad_axes = len(
            np.where(
                np.logical_and(object_type == _SERSIC_2D,
                               semi_major_arcsec < semi_minor_arcsec))[0])
        message += "    %d had semi_major_axis < semi_minor_axis\n" % n_bad_axes
        n_bad_knots = len(
            np.where(np.logical_and(object_type == _RANDOM_WALK,
                                    npoints <= 0))[0])
        message += "    %d had n_points <= 0 \n" % n_bad_knots
        warnings.warn(message)

    wav_int = None
    wav_gal = None

    gs_object_arr = []
    for i_obj in range(num_objects):
        if not object_is_valid[i_obj]:
            continue

        if object_type[i_obj] == _POINT_SOURCE:
            gs_type = 'pointSource'
        elif object_type[i_obj] == _SERSIC_2D:
            gs_type = 'sersic'
        elif object_type[i_obj] == _RANDOM_WALK:
            gs_type = 'RandomWalk'

        # load the SED
        sed_obj = Sed()
        sed_obj.readSED_flambda(os.path.join(sed_dir, sed_name[i_obj]))
        fnorm = getImsimFluxNorm(sed_obj, mag_norm[i_obj])
        sed_obj.multiplyFluxNorm(fnorm)
        if internal_av[i_obj] != 0.0:
            if wav_int is None or not np.array_equal(sed_obj.wavelen, wav_int):
                a_int, b_int = sed_obj.setupCCMab()
                wav_int = copy.deepcopy(sed_obj.wavelen)

            sed_obj.addCCMDust(a_int,
                               b_int,
                               A_v=internal_av[i_obj],
                               R_v=internal_rv[i_obj])

        if redshift[i_obj] != 0.0:
            sed_obj.redshiftSED(redshift[i_obj], dimming=True)

        sed_obj.resampleSED(wavelen_match=bp_dict.wavelenMatch)

        if galactic_av[i_obj] != 0.0:
            if wav_gal is None or not np.array_equal(sed_obj.wavelen, wav_gal):
                a_g, b_g = sed_obj.setupCCMab()
                wav_gal = copy.deepcopy(sed_obj.wavelen)

            sed_obj.addCCMDust(a_g,
                               b_g,
                               A_v=galactic_av[i_obj],
                               R_v=galactic_rv[i_obj])

        gs_object = GalSimCelestialObject(gs_type,
                                          x_pupil[i_obj],
                                          y_pupil[i_obj],
                                          semi_major_radians[i_obj],
                                          semi_minor_radians[i_obj],
                                          semi_major_radians[i_obj],
                                          position_angle_radians[i_obj],
                                          sersic_index[i_obj],
                                          sed_obj,
                                          bp_dict,
                                          phot_params,
                                          npoints[i_obj],
                                          gamma1=gamma1[i_obj],
                                          gamma2=gamma2[i_obj],
                                          kappa=kappa[i_obj],
                                          uniqueId=unique_id[i_obj])

        gs_object_arr.append(gs_object)

    gs_object_arr = np.array(gs_object_arr)

    # how close to the edge of the detector a source has
    # to be before we will just simulate it anyway
    pix_tol = 50.0

    # any source brighter than this will be considered
    # so bright that it should be simulated for all
    # detectors, just in case light scatters onto them.
    max_mag = 16.0

    # down-select mag_norm, x_pupil, and y_pupil
    # to only contain those objects that were
    # deemed to be valid above
    valid = np.where(object_is_valid)
    mag_norm = mag_norm[valid]
    x_pupil = x_pupil[valid]
    y_pupil = y_pupil[valid]

    assert len(mag_norm) == len(gs_object_arr)
    assert len(x_pupil) == len(gs_object_arr)
    assert len(y_pupil) == len(gs_object_arr)

    out_obj_dict = {}
    for det in lsst_camera():
        chip_name = det.getName()
        pixel_corners = getCornerPixels(chip_name, lsst_camera())
        x_min = pixel_corners[0][0]
        x_max = pixel_corners[2][0]
        y_min = pixel_corners[0][1]
        y_max = pixel_corners[3][1]
        xpix, ypix = pixelCoordsFromPupilCoords(x_pupil,
                                                y_pupil,
                                                chipName=chip_name,
                                                camera=lsst_camera())

        on_chip = np.where(
            np.logical_or(
                mag_norm < max_mag,
                np.logical_and(
                    xpix > x_min - pix_tol,
                    np.logical_and(
                        xpix < x_max + pix_tol,
                        np.logical_and(ypix > y_min - pix_tol,
                                       ypix < y_max + pix_tol)))))

        out_obj_dict[chip_name] = gs_object_arr[on_chip]

    return gs_object_arr, out_obj_dict
예제 #23
0
 def __init__(self):
     self._camera = lsst_camera()
예제 #24
0
    obs.site = site_no_atm
    assert np.abs(obs.site.pressure) < 1.0e-6
    assert np.abs(obs.site.humidity) < 1.0e-6

    x_pix_arr = np.arange(700.0, 3301.0, 700.0)
    y_pix_arr = np.arange(700.0, 3301.0, 700.0)
    pix_grid = np.meshgrid(x_pix_arr, y_pix_arr)
    x_pix_arr = pix_grid[0].flatten()
    y_pix_arr = pix_grid[1].flatten()

    x_mm = []
    y_mm = []
    x_pix = []
    y_pix = []

    camera = lsst_camera()
    det_name_list = []
    for det in camera:
        if det.getType() == SCIENCE:
            det_name_list.append(det.getName())

    det_name_list.sort()
    for det_name in det_name_list:
        if args.chip is not None and args.chip != det_name:
            continue
        for xpix, ypix in zip(x_pix_arr, y_pix_arr):
            xmm, ymm = coord_converter.mmFromPix(xpix, ypix, det_name)
            x_mm.append(xmm)
            y_mm.append(ymm)
            x_pix.append(xpix)
            y_pix.append(ypix)
예제 #25
0
from lsst.sims.coordUtils import getCornerRaDec
from lsst.sims.coordUtils import focalPlaneCoordsFromRaDec
from lsst.sims.coordUtils import pixelCoordsFromRaDec
from lsst.sims.coordUtils import chipNameFromRaDec

if __name__ == "__main__":

    header_msg = '# This catalog was generated by\n#\n'
    header_msg += '# SIMS_COORDUTILS_DIR/tests/lsstCameraData/make_test_catalog.py\n'
    header_msg += '#\n# It contains data we will use to verify that we have\n'
    header_msg += '# correctly updated sims_coordUtils whenever the API for\n'
    header_msg += '# afwCameraGeom changes.  If obs_lsstSim ever changes in a\n'
    header_msg += '# physically meaningful way, this catalog will need to be\n'
    header_msg += '# regenerated.\n#\n'

    camera = lsst_camera()
    ra = 25.0
    dec = -62.0
    obs = ObservationMetaData(pointingRA=ra, pointingDec=dec,
                              rotSkyPos=57.2, mjd=59586.2)

    ra_range = np.arange(ra-4.0, ra+4.0, 0.1)
    dec_range = np.arange(dec-4.0, dec+4.0, 0.1)

    ra_grid, dec_grid = np.meshgrid(ra_range, dec_range)
    ra_grid = ra_grid.flatten()
    dec_grid = dec_grid.flatten()

    chip_name_grid = chipNameFromRaDec(ra_grid, dec_grid,
                                       obs_metadata=obs, camera=camera)
예제 #26
0
def pupilCoordsFromPixelCoordsLSST(xPix,
                                   yPix,
                                   chipName=None,
                                   band="r",
                                   includeDistortion=True):
    """
    Convert pixel coordinates into radians on the pupil

    Parameters
    ----------
    xPix -- the x pixel coordinate

    yPix -- the y pixel coordinate

    chipName -- the name(s) of the chips on which xPix, yPix are reckoned

    band -- the filter we are simulating (default=r)

    includeDistortion -- a boolean which turns on or off optical
    distortions (default=True)

    Returns
    -------
    a 2-D numpy array in which the first row is the x
    pupil coordinate and the second row is the y pupil
    coordinate (both in radians)
    """

    if not includeDistortion:
        return pupilCoordsFromPixelCoords(xPix,
                                          yPix,
                                          chipName=chipName,
                                          camera=lsst_camera(),
                                          includeDistortion=includeDistortion)

    are_arrays, \
    chipNameList = _validate_inputs_and_chipname([xPix, yPix], ['xPix', 'yPix'],
                                                 "pupilCoordsFromPixelCoords",
                                                 chipName,
                                                 chipname_can_be_none=False)

    pixel_to_focal_dict = {}
    camera = lsst_camera()
    name_to_int = {}
    name_to_int[None] = 0
    name_to_int['None'] = 0
    ii = 1

    if are_arrays:
        chip_name_int = np.zeros(len(xPix), dtype=int)

    have_transform = set()
    for i_obj, name in enumerate(chipNameList):
        if name not in have_transform and name is not None and name != 'None':
            pixel_to_focal_dict[name] = camera[name].getTransform(
                PIXELS, FOCAL_PLANE)
            name_to_int[name] = ii
            have_transform.add(name)
            ii += 1

        if are_arrays:
            chip_name_int[i_obj] = name_to_int[name]

    if are_arrays:
        x_f = np.zeros(len(xPix), dtype=float)
        y_f = np.zeros(len(yPix), dtype=float)

        for name in name_to_int:
            local_int = name_to_int[name]
            local_valid = np.where(chip_name_int == local_int)
            if len(local_valid[0]) == 0:
                continue

            if name is None or name == 'None':
                x_f[local_valid] = np.NaN
                y_f[local_valid] = np.NaN
                continue

            pixel_pt_arr = [
                geom.Point2D(xPix[ii], yPix[ii]) for ii in local_valid[0]
            ]

            focal_pt_arr = pixel_to_focal_dict[name].applyForward(pixel_pt_arr)
            focal_coord_arr = np.array([[pt.getX(), pt.getY()]
                                        for pt in focal_pt_arr]).transpose()
            x_f[local_valid] = focal_coord_arr[0]
            y_f[local_valid] = focal_coord_arr[1]

    else:
        if chipNameList[0] is None or chipNameList[0] == 'None':
            x_f = np.NaN
            y_f = np.NaN
        else:
            pixel_pt = geom.Point2D(xPix, yPix)
            focal_pt = pixel_to_focal_dict[chipNameList[0]].applyForward(
                pixel_pt)
            x_f = focal_pt.getX()
            y_f = focal_pt.getY()

    return pupilCoordsFromFocalPlaneCoordsLSST(x_f, y_f, band=band)
예제 #27
0
def chipNameFromPupilCoordsLSST(xPupil_in,
                                yPupil_in,
                                allow_multiple_chips=False,
                                band='r'):
    """
    Return the names of LSST detectors that see the object specified by
    either (xPupil, yPupil).

    @param [in] xPupil_in is the x pupil coordinate in radians.
    Must be a numpy array.

    @param [in] yPupil_in is the y pupil coordinate in radians.
    Must be a numpy array.

    @param [in] allow_multiple_chips is a boolean (default False) indicating whether or not
    this method will allow objects to be visible on more than one chip.  If it is 'False'
    and an object appears on more than one chip, only the first chip will appear in the list of
    chipNames and warning will be emitted.  If it is 'True' and an object falls on more than one
    chip, a list of chipNames will appear for that object.

    @param[in] band is the bandpass being simulated (default='r')

    @param [out] a numpy array of chip names

    """
    if (not hasattr(chipNameFromPupilCoordsLSST, '_focal_map')
            or not hasattr(chipNameFromPupilCoordsLSST, '_detector_arr')
            or len(chipNameFromPupilCoordsLSST._detector_arr) == 0):
        focal_map = _build_lsst_focal_coord_map()
        chipNameFromPupilCoordsLSST._focal_map = focal_map
        camera = lsst_camera()
        detector_arr = np.zeros(len(focal_map['name']), dtype=object)
        for ii in range(len(focal_map['name'])):
            detector_arr[ii] = camera[focal_map['name'][ii]]

        chipNameFromPupilCoordsLSST._detector_arr = detector_arr

        # build a Box2D that contains all of the detectors in the camera
        focal_to_field = camera.getTransformMap().getTransform(
            FOCAL_PLANE, FIELD_ANGLE)
        focal_bbox = camera.getFpBBox()
        focal_corners = focal_bbox.getCorners()
        camera_bbox = geom.Box2D()
        x_focal_max = None
        x_focal_min = None
        y_focal_max = None
        y_focal_min = None
        for cc in focal_corners:
            xx = cc.getX()
            yy = cc.getY()
            if x_focal_max is None or xx > x_focal_max:
                x_focal_max = xx
            if x_focal_min is None or xx < x_focal_min:
                x_focal_min = xx
            if y_focal_max is None or yy > y_focal_max:
                y_focal_max = yy
            if y_focal_min is None or yy < y_focal_min:
                y_focal_min = yy

        chipNameFromPupilCoordsLSST._x_focal_center = 0.5 * (x_focal_max +
                                                             x_focal_min)
        chipNameFromPupilCoordsLSST._y_focal_center = 0.5 * (y_focal_max +
                                                             y_focal_min)

        radius_sq_max = None
        for cc in focal_corners:
            xx = cc.getX()
            yy = cc.getY()
            radius_sq = (
                (xx - chipNameFromPupilCoordsLSST._x_focal_center)**2 +
                (yy - chipNameFromPupilCoordsLSST._y_focal_center)**2)
            if radius_sq_max is None or radius_sq > radius_sq_max:
                radius_sq_max = radius_sq

        chipNameFromPupilCoordsLSST._camera_focal_radius_sq = radius_sq_max * 1.1

    are_arrays = _validate_inputs([xPupil_in, yPupil_in],
                                  ['xPupil_in', 'yPupil_in'],
                                  "chipNameFromPupilCoordsLSST")

    if not are_arrays:
        xPupil_in = np.array([xPupil_in])
        yPupil_in = np.array([yPupil_in])

    xFocal, yFocal = focalPlaneCoordsFromPupilCoordsLSST(xPupil_in,
                                                         yPupil_in,
                                                         band=band)

    radius_sq_list = (
        (xFocal - chipNameFromPupilCoordsLSST._x_focal_center)**2 +
        (yFocal - chipNameFromPupilCoordsLSST._y_focal_center)**2)

    with np.errstate(invalid='ignore'):
        good_radii = np.where(radius_sq_list < chipNameFromPupilCoordsLSST.
                              _camera_focal_radius_sq)

    if len(good_radii[0]) == 0:
        return np.array([None] * len(xPupil_in))

    xFocal_good = xFocal[good_radii]
    yFocal_good = yFocal[good_radii]

    ############################################################
    # in the code below, we will only consider those points which
    # passed the 'good_radii' test above; the other points will
    # be added in with chipName == None at the end
    #
    focalPointList = [
        geom.Point2D(xFocal[i_pt], yFocal[i_pt]) for i_pt in good_radii[0]
    ]

    # Loop through every detector on the camera.  For each detector, assemble a list of points
    # whose centers are within 1.1 detector radii of the center of the detector.

    x_cam_list = chipNameFromPupilCoordsLSST._focal_map['xx']
    y_cam_list = chipNameFromPupilCoordsLSST._focal_map['yy']
    rrsq_lim_list = (1.1 * chipNameFromPupilCoordsLSST._focal_map['dp'])**2

    possible_points = []
    for i_chip, (x_cam, y_cam, rrsq_lim) in \
    enumerate(zip(x_cam_list, y_cam_list, rrsq_lim_list)):

        local_possible_pts = np.where(((xFocal_good - x_cam)**2 +
                                       (yFocal_good - y_cam)**2) < rrsq_lim)[0]

        possible_points.append(local_possible_pts)

    nameList_good = _findDetectorsListLSST(
        focalPointList,
        chipNameFromPupilCoordsLSST._detector_arr,
        possible_points,
        allow_multiple_chips=allow_multiple_chips)

    ####################################################################
    # initialize output as an array of Nones, effectively adding back in
    # the points which failed the initial radius cut
    nameList = np.array([None] * len(xPupil_in))

    nameList[good_radii] = nameList_good

    if not are_arrays:
        return nameList[0]

    return nameList
예제 #28
0
from lsst.sims.coordUtils import lsst_camera
from lsst.sims.catUtils.exampleCatalogDefinitions import write_phoSim_header
from lsst.sims.utils import observedFromICRS
from lsst.sims.utils import Site
from lsst.sims.GalSimInterface import LSSTCameraWrapper
from lsst.sims.coordUtils import focalPlaneCoordsFromRaDec

from lsst.afw.cameraGeom import SCIENCE

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument('--obs', type=int, default=230)
    args = parser.parse_args()

    camera = lsst_camera()
    det_name_list = []
    for det in camera:
        if det.getType() != SCIENCE:
            continue
        det_name_list.append(det.getName())
    det_name_list.sort()

    opsimdb = os.path.join('/Users', 'danielsf', 'physics', 'lsst_150412',
                           'Development', 'garage', 'OpSimData',
                           'minion_1016_sqlite.db')

    assert os.path.exists(opsimdb)
    obs_gen = ObservationMetaDataGenerator(database=opsimdb)
    obs_list = obs_gen.getObservationMetaData(obsHistID=args.obs)
    obs = obs_list[0]
예제 #29
0
    def test_naive_focal_plane_position(self):
        """
        Test deprecession of PhoSim coordinates by comparing
        the focal plane position predicted by CatSim from ICRS
        with the focal plane position predicted by CatSim from deprecessed
        coordinates.
        """

        phosim_mixin = PhoSimAstrometryBase()

        mjd = 59587.2

        # create site with no atmosphere so that we can avoid
        # refraction
        site = Site(name="LSST", pressure=0.0, humidity=0.0)

        obs = ObservationMetaData(mjd=mjd, site=site)
        ra, dec = raDecFromAltAz(31.0, 112.0, obs)

        d_sun = distanceToSun(ra, dec, obs.mjd)
        self.assertGreater(d_sun, 45.0)

        obs = ObservationMetaData(pointingRA=ra, pointingDec=dec,
                                  rotSkyPos=27.3, mjd=mjd,
                                  site=site)
        ra_icrs = np.arange(obs.pointingRA-2.0, obs.pointingRA+2.0, 0.05)
        dec_icrs = np.arange(obs.pointingDec-2.0, obs.pointingDec+2.0, 0.05)

        coord_grid = np.meshgrid(ra_icrs, dec_icrs)
        ra_icrs = coord_grid[0].flatten()
        dec_icrs = coord_grid[1].flatten()

        (xpup_icrs,
         ypup_icrs) = pupilCoordsFromRaDec(ra_icrs, dec_icrs,
                                           obs_metadata=obs,
                                           epoch=2000.0,
                                           includeRefraction=False)

        (x_focal_icrs,
         y_focal_icrs) = focalPlaneCoordsFromPupilCoords(xpup_icrs,
                                                         ypup_icrs,
                                                         camera=lsst_camera())

        ra_obs, dec_obs = observedFromICRS(ra_icrs, dec_icrs, obs_metadata=obs,
                                           epoch=2000.0,
                                           includeRefraction=False)

        ra_obs_rad = np.radians(ra_obs)
        dec_obs_rad = np.radians(dec_obs)

        (ra_deprecessed_rad,
         dec_deprecessed_rad) = phosim_mixin._dePrecess(ra_obs_rad,
                                                        dec_obs_rad, obs)

        (xpup_deprecessed,
         ypup_deprecessed) = _naivePupilCoordsFromObserved(ra_deprecessed_rad,
                                                           dec_deprecessed_rad,
                                                           obs._pointingRA,
                                                           obs._pointingDec,
                                                           obs._rotSkyPos)

        (x_focal_deprecessed,
         y_focal_deprecessed) = focalPlaneCoordsFromPupilCoords(xpup_deprecessed,
                                                                ypup_deprecessed,
                                                                camera=lsst_camera())

        dd = np.sqrt((x_focal_icrs-x_focal_deprecessed)**2
                     +(y_focal_icrs-y_focal_deprecessed)**2)

        self.assertLess(dd.max(), 5.0e-8)
예제 #30
0
def pixelCoordsFromPupilCoordsLSST(xPupil,
                                   yPupil,
                                   chipName=None,
                                   band="r",
                                   includeDistortion=True):
    """
    Convert radians on the pupil into pixel coordinates.

    Parameters
    ----------
    xPupil -- is the x coordinate on the pupil in radians

    yPupil -- is the y coordinate on the pupil in radians

    chipName -- designates the names of the chips on which the pixel
    coordinates will be reckoned.  Can be either single value, an array, or None.
    If an array, there must be as many chipNames as there are (xPupil, yPupil) pairs.
    If a single value, all of the pixel coordinates will be reckoned on the same
    chip.  If None, this method will calculate which chip each(xPupil, yPupil) pair
    actually falls on, and return pixel coordinates for each (xPupil, yPupil) pair on
    the appropriate chip.  Default is None.

    band -- the filter we are simulating (default=r)

    includeDistortion -- a boolean which turns on and off optical distortions
    (default=True)

    Returns
    -------
    a 2-D numpy array in which the first row is the x pixel coordinate
    and the second row is the y pixel coordinate
    """

    if not includeDistortion:
        return pixelCoordsFromPupilCoords(xPupil,
                                          yPupil,
                                          chipName=chipName,
                                          camera=lsst_camera(),
                                          includeDistortion=includeDistortion)

    are_arrays, \
    chipNameList = _validate_inputs_and_chipname([xPupil, yPupil],
                                                 ['xPupil', 'yPupil'],
                                                 'pixelCoordsFromPupilCoordsLSST',
                                                 chipName)

    if chipNameList is None:
        chipNameList = chipNameFromPupilCoordsLSST(xPupil, yPupil)
        if not isinstance(chipNameList, np.ndarray):
            chipNameList = np.array([chipNameList])
    else:
        if not isinstance(chipNameList, list) and not isinstance(
                chipNameList, np.ndarray):
            chipNameList = np.array([chipNameList])
        elif isinstance(chipNameList, list):
            chipNameList = np.array(chipNameList)

    x_f, y_f = focalPlaneCoordsFromPupilCoordsLSST(xPupil, yPupil, band=band)

    if are_arrays:

        has_transform = set()
        focal_to_pixel_dict = {}
        chip_name_int = np.zeros(len(x_f), dtype=int)
        name_to_int = {}
        name_to_int[None] = 0
        name_to_int['None'] = 0
        ii = 1
        for i_obj, chip_name in enumerate(chipNameList):
            if chip_name not in has_transform and chip_name is not None and chip_name != 'None':
                has_transform.add(chip_name)
                focal_to_pixel_dict[chip_name] = lsst_camera(
                )[chip_name].getTransform(FOCAL_PLANE, PIXELS)
                name_to_int[chip_name] = ii
                ii += 1

            chip_name_int[i_obj] = name_to_int[chip_name]

        x_pix = np.NaN * np.ones(len(x_f), dtype=float)
        y_pix = np.NaN * np.ones(len(x_f), dtype=float)

        for chip_name in has_transform:
            if chip_name == 'None' or chip_name is None:
                continue

            local_int = name_to_int[chip_name]
            local_valid = np.where(chip_name_int == local_int)
            if len(local_valid[0]) == 0:
                continue
            focal_pt_arr = [
                geom.Point2D(x_f[ii], y_f[ii]) for ii in local_valid[0]
            ]
            pixel_pt_arr = focal_to_pixel_dict[chip_name].applyForward(
                focal_pt_arr)
            pixel_coord_arr = np.array([[pp.getX(), pp.getY()]
                                        for pp in pixel_pt_arr]).transpose()

            x_pix[local_valid] = pixel_coord_arr[0]
            y_pix[local_valid] = pixel_coord_arr[1]
    else:
        chip_name = chipNameList[0]
        if chip_name is None:
            x_pix = np.NaN
            y_pix = np.NaN
        else:
            det = lsst_camera()[chip_name]
            focal_to_pixels = det.getTransform(FOCAL_PLANE, PIXELS)
            focal_pt = geom.Point2D(x_f, y_f)
            pixel_pt = focal_to_pixels.applyForward(focal_pt)
            x_pix = pixel_pt.getX()
            y_pix = pixel_pt.getY()

    return np.array([x_pix, y_pix])
    def test_LSST_camera_wrapper(self):
        """
        Test that LSSTCameraWrapper wraps its methods as expected.

        Recall that the LSSTCameraWrapper applies the 90 degree rotation
        to go from DM pixel coordinates to Camera team pixel coordinates.
        Namely,

        Camera +y = DM +x
        Camera +x = DM -y
        """
        camera = lsst_camera()
        camera_wrapper = LSSTCameraWrapper()

        obs_mjd = ObservationMetaData(mjd=60000.0)
        ra, dec = raDecFromAltAz(135.0, 112.0, obs_mjd)
        obs = ObservationMetaData(pointingRA=ra,
                                  pointingDec=dec,
                                  mjd=obs_mjd.mjd,
                                  rotSkyPos=22.4,
                                  bandpassName='u')

        rng = np.random.RandomState(8124)

        for detector in camera:
            name = detector.getName()
            bbox = camera[name].getBBox()
            bbox_wrapper = camera_wrapper.getBBox(name)
            self.assertEqual(bbox.getMinX(), bbox_wrapper.getMinY())
            self.assertEqual(bbox.getMaxX(), bbox_wrapper.getMaxY())
            self.assertEqual(bbox.getMinY(), bbox_wrapper.getMinX())
            self.assertEqual(bbox.getMaxY(), bbox_wrapper.getMaxX())
            self.assertGreater(bbox_wrapper.getMaxY() - bbox_wrapper.getMinY(),
                               bbox_wrapper.getMaxX() - bbox_wrapper.getMinX())

            center_point = camera[name].getCenter(FOCAL_PLANE)
            pixel_system = camera[name].makeCameraSys(PIXELS)
            center_pix = camera.transform(center_point, FOCAL_PLANE,
                                          pixel_system)
            center_pix_wrapper = camera_wrapper.getCenterPixel(name)
            self.assertEqual(center_pix.getX(), center_pix_wrapper.getY())
            self.assertEqual(center_pix.getY(), center_pix_wrapper.getX())

            # Note that DM and the Camera team agree on the orientation
            # of the pupil coordinate/field angle axes
            pupil_system = camera[name].makeCameraSys(FIELD_ANGLE)
            center_pupil = camera.transform(center_point, FOCAL_PLANE,
                                            pupil_system)
            center_pupil_wrapper = camera_wrapper.getCenterPupil(name)
            self.assertEqual(center_pupil.getX(), center_pupil_wrapper.getX())
            self.assertEqual(center_pupil.getY(), center_pupil_wrapper.getY())

            corner_pupil_wrapper = camera_wrapper.getCornerPupilList(name)
            corner_point_list = camera[name].getCorners(FOCAL_PLANE)
            for point in corner_point_list:
                point_pupil = camera.transform(point, FOCAL_PLANE,
                                               pupil_system)
                dd_min = 1.0e10
                for wrapper_point in corner_pupil_wrapper:
                    dd = np.sqrt(
                        (point_pupil.getX() - wrapper_point.getX())**2 +
                        (point_pupil.getY() - wrapper_point.getY())**2)

                    if dd < dd_min:
                        dd_min = dd
                self.assertLess(dd_min, 1.0e-20)

            xpix_min = None
            xpix_max = None
            ypix_min = None
            ypix_max = None
            focal_to_tan_pix = camera[name].getTransform(
                FOCAL_PLANE, TAN_PIXELS)
            for point in corner_point_list:
                pixel_point = focal_to_tan_pix.applyForward(point)
                xx = pixel_point.getX()
                yy = pixel_point.getY()
                if xpix_min is None or xx < xpix_min:
                    xpix_min = xx
                if ypix_min is None or yy < ypix_min:
                    ypix_min = yy
                if xpix_max is None or xx > xpix_max:
                    xpix_max = xx
                if ypix_max is None or yy > ypix_max:
                    ypix_max = yy

            pix_bounds_wrapper = camera_wrapper.getTanPixelBounds(name)
            self.assertEqual(pix_bounds_wrapper[0], ypix_min)
            self.assertEqual(pix_bounds_wrapper[1], ypix_max)
            self.assertEqual(pix_bounds_wrapper[2], xpix_min)
            self.assertEqual(pix_bounds_wrapper[3], xpix_max)

            # generate some random pupil coordinates;
            # verify that the relationship between the DM and Camera team
            # pixel coordinates corresponding to those pupil coordinates
            # is as expected
            x_pup = rng.random_sample(10) * 0.005 - 0.01
            y_pup = rng.random_sample(10) * 0.005 - 0.01
            x_pix, y_pix = pixelCoordsFromPupilCoordsLSST(x_pup,
                                                          y_pup,
                                                          chipName=name,
                                                          band=obs.bandpass)

            (x_pix_wrapper,
             y_pix_wrapper) = camera_wrapper.pixelCoordsFromPupilCoords(
                 x_pup, y_pup, name, obs)

            nan_x = np.where(np.isnan(x_pix))
            self.assertEqual(len(nan_x[0]), 0)
            np.testing.assert_allclose(x_pix - center_pix.getX(),
                                       y_pix_wrapper -
                                       center_pix_wrapper.getY(),
                                       atol=1.0e-10,
                                       rtol=0.0)
            np.testing.assert_allclose(y_pix - center_pix.getY(),
                                       center_pix_wrapper.getX() -
                                       x_pix_wrapper,
                                       atol=1.0e-10,
                                       rtol=0.0)

            # use camera_wrapper.pupilCoordsFromPixelCoords to go back to pupil
            # coordinates from x_pix_wrapper, y_pix_wrapper; make sure you get
            # the original pupil coordinates back out
            (x_pup_wrapper,
             y_pup_wrapper) = camera_wrapper.pupilCoordsFromPixelCoords(
                 x_pix_wrapper, y_pix_wrapper, name, obs)
            msg = 'worst error %e' % np.abs(x_pup - x_pup_wrapper).max()
            np.testing.assert_allclose(x_pup,
                                       x_pup_wrapper,
                                       atol=1.0e-10,
                                       rtol=0.0,
                                       err_msg=msg)
            msg = 'worst error %e' % np.abs(y_pup - y_pup_wrapper).max()
            np.testing.assert_allclose(y_pup,
                                       y_pup_wrapper,
                                       atol=1.0e-10,
                                       rtol=0.0,
                                       err_msg=msg)

            # generate some random sky coordinates; verify that the methods that
            # convert between (RA, Dec) and pixel coordinates behave as expected.
            # NOTE: x_pix, y_pix will be in DM pixel coordinate convention
            x_pix = bbox.getMinX() + rng.random_sample(10) * (bbox.getMaxX() -
                                                              bbox.getMinX())
            y_pix = bbox.getMinY() + rng.random_sample(10) * (bbox.getMaxY() -
                                                              bbox.getMinY())

            ra, dec = raDecFromPixelCoordsLSST(x_pix,
                                               y_pix,
                                               name,
                                               obs_metadata=obs,
                                               band=obs.bandpass)

            (ra_wrapper, dec_wrapper) = camera_wrapper.raDecFromPixelCoords(
                2.0 * center_pix.getY() - y_pix, x_pix, name, obs)

            nan_ra = np.where(np.isnan(ra))
            self.assertEqual(len(nan_ra[0]), 0)
            np.testing.assert_allclose(ra, ra_wrapper, atol=1.0e-10, rtol=0.0)
            np.testing.assert_allclose(dec,
                                       dec_wrapper,
                                       atol=1.0e-10,
                                       rtol=0.0)

            # make sure that the method that returns RA, Dec in radians agrees with
            # the method that returns RA, Dec in degrees
            (ra_rad, dec_rad) = camera_wrapper._raDecFromPixelCoords(
                2.0 * center_pix.getY() - y_pix, x_pix, name, obs)

            np.testing.assert_allclose(np.radians(ra_wrapper),
                                       ra_rad,
                                       atol=1.0e-10,
                                       rtol=0.0)
            np.testing.assert_allclose(np.radians(dec_wrapper),
                                       dec_rad,
                                       atol=1.0e-10,
                                       rtol=0.0)

            # Go back to pixel coordinates with pixelCoordsFromRaDec; verify that
            # the result relates to the original DM pixel coordinates as expected
            # (x_pix_inv, y_pix_inv will be in Camera pixel coordinates)
            (x_pix_inv,
             y_pix_inv) = camera_wrapper.pixelCoordsFromRaDec(ra_wrapper,
                                                              dec_wrapper,
                                                              chipName=name,
                                                              obs_metadata=obs)

            np.testing.assert_allclose(y_pix_inv, x_pix, atol=1.0e-4, rtol=0.0)
            np.testing.assert_allclose(x_pix_inv,
                                       2.0 * center_pix.getY() - y_pix,
                                       atol=1.0e-4,
                                       rtol=0.0)

            ra = np.radians(ra_wrapper)
            dec = np.radians(dec_wrapper)

            # check that the the method that accepts RA, Dec in radians agrees with the
            # method that accepts RA, Dec in degrees
            (x_pix_wrapper,
             y_pix_wrapper) = camera_wrapper._pixelCoordsFromRaDec(
                 ra, dec, chipName=name, obs_metadata=obs)

            np.testing.assert_allclose(x_pix_inv,
                                       x_pix_wrapper,
                                       atol=1.0e-10,
                                       rtol=0.0)
            np.testing.assert_allclose(y_pix_inv,
                                       y_pix_wrapper,
                                       atol=1.0e-10,
                                       rtol=0.0)

        del camera
        del camera_wrapper
        del lsst_camera._lsst_camera
예제 #32
0
 def __init__(self):
     self._camera = coordUtils.lsst_camera()
    def test_dmPixFromCameraPix(self):
        """
        Test that the method to return DM pixel coordinates from
        Camera Team pixel coordinates works.
        """
        camera = lsst_camera()
        camera_wrapper = LSSTCameraWrapper()
        obs = ObservationMetaData(bandpassName='u')

        npts = 100
        rng = np.random.RandomState(1824)
        dm_x_pix_list = rng.random_sample(npts) * 4000.0
        dm_y_pix_list = rng.random_sample(npts) * 4000.0
        name_list = []
        for det in camera:
            name_list.append(det.getName())
        chip_name_list = rng.choice(name_list, size=npts)

        (xPup_list,
         yPup_list) = pupilCoordsFromPixelCoordsLSST(dm_x_pix_list,
                                                     dm_y_pix_list,
                                                     chipName=chip_name_list,
                                                     band=obs.bandpass)

        (cam_x_pix_list,
         cam_y_pix_list) = camera_wrapper.pixelCoordsFromPupilCoords(
             xPup_list, yPup_list, chip_name_list, obs)

        (dm_x_test, dm_y_test) = camera_wrapper.dmPixFromCameraPix(
            cam_x_pix_list, cam_y_pix_list, chip_name_list)

        np.testing.assert_array_almost_equal(dm_x_test,
                                             dm_x_pix_list,
                                             decimal=4)
        np.testing.assert_array_almost_equal(dm_y_test,
                                             dm_y_pix_list,
                                             decimal=4)

        # test transformations made one at a time
        for ii in range(len(cam_x_pix_list)):
            dm_x, dm_y = camera_wrapper.dmPixFromCameraPix(
                cam_x_pix_list[ii], cam_y_pix_list[ii], chip_name_list[ii])

            self.assertAlmostEqual(dm_x_pix_list[ii], dm_x, 4)
            self.assertAlmostEqual(dm_y_pix_list[ii], dm_y, 4)

        # test case where an array of points is on a single chip
        chip_name = chip_name_list[10]

        (xPup_list,
         yPup_list) = pupilCoordsFromPixelCoordsLSST(dm_x_pix_list,
                                                     dm_y_pix_list,
                                                     chipName=chip_name,
                                                     band=obs.bandpass)

        (cam_x_pix_list,
         cam_y_pix_list) = camera_wrapper.pixelCoordsFromPupilCoords(
             xPup_list, yPup_list, chip_name, obs)

        (dm_x_test, dm_y_test) = camera_wrapper.dmPixFromCameraPix(
            cam_x_pix_list, cam_y_pix_list, chip_name)

        np.testing.assert_array_almost_equal(dm_x_test,
                                             dm_x_pix_list,
                                             decimal=4)
        np.testing.assert_array_almost_equal(dm_y_test,
                                             dm_y_pix_list,
                                             decimal=4)

        del camera
        del camera_wrapper
        del lsst_camera._lsst_camera
예제 #34
0
    def testObjectPlacement(self):
        """
        Test that GalSim places objects on the correct pixel by drawing
        images containing single objects and no background, reading those
        images back in, and comparing the flux-averaged centroids of the
        images with the expected pixel positions of the input objects.
        """
        scratchDir = tempfile.mkdtemp(dir=ROOT, prefix='testLSSTObjectPlacement-')
        if os.path.exists(scratchDir):
            shutil.rmtree(scratchDir)
        os.mkdir(scratchDir)

        detector = lsst_camera()['R:0,3 S:2,2']
        det_name = 'R03_S22'

        magNorm = 19.0

        pixel_transformer = DMtoCameraPixelTransformer()

        for band in 'ugrizy':
            obs = self.obs_dict[band]

            catName = os.path.join(scratchDir, 'placementCatalog.dat')
            imageRoot = os.path.join(scratchDir, 'placementImage')
            dbFileName = os.path.join(scratchDir, 'placementInputCatalog.dat')


            imageName = '%s_%s_%s.fits' % (imageRoot, det_name, obs.bandpass)

            ra_c, dec_c = raDecFromPixelCoordsLSST(2000.0, 2000.0,
                                                   detector.getName(),
                                                   band=obs.bandpass,
                                                   obs_metadata=obs)

            nSamples = 30
            rng = np.random.RandomState(42)
            fwhm = 0.12

            for iteration in range(nSamples):
                if os.path.exists(dbFileName):
                    os.unlink(dbFileName)

                ra_obj = ra_c + rng.random_sample()*0.2 - 0.1
                dec_obj = dec_c + rng.random_sample()*0.2 - 0.1

                dmx_wrong, dmy_wrong = pixelCoordsFromRaDec(ra_obj, dec_obj,
                                                            chipName=detector.getName(),
                                                            obs_metadata=obs,
                                                            camera=lsst_camera())

                dmx_pix, dmy_pix = pixelCoordsFromRaDecLSST(ra_obj, dec_obj,
                                                            chipName=detector.getName(),
                                                            obs_metadata=obs,
                                                            band=obs.bandpass)

                x_pix, y_pix = pixel_transformer.cameraPixFromDMPix(dmx_pix, dmy_pix,
                                                                    detector.getName())

                x_pix_wrong, y_pix_wrong = pixel_transformer.cameraPixFromDMPix(dmx_wrong, dmy_wrong,
                                                                                detector.getName())

                d_ra = 360.0*(ra_obj - obs.pointingRA)  # in arcseconds
                d_dec = 360.0*(dec_obj - obs.pointingDec)

                create_text_catalog(obs, dbFileName,
                                    np.array([d_ra]), np.array([d_dec]),
                                    mag_norm=[magNorm])

                db = LSSTPlacementFileDBObj(dbFileName, runtable='test')
                cat = LSSTPlacementCatalog(db, obs_metadata=obs)
                cat.camera_wrapper = LSSTCameraWrapper()
                psf = SNRdocumentPSF(fwhm=fwhm)
                cat.setPSF(psf)

                cat.write_catalog(catName)
                cat.write_images(nameRoot=imageRoot)

                im = afwImage.ImageF(imageName).getArray()
                tot_flux = im.sum()
                self.assertGreater(tot_flux, 10.0)

                y_centroid = sum([ii*im[ii,:].sum() for ii in range(im.shape[0])])/tot_flux
                x_centroid = sum([ii*im[:,ii].sum() for ii in range(im.shape[1])])/tot_flux
                dd = np.sqrt((x_pix-x_centroid)**2 + (y_pix-y_centroid)**2)
                self.assertLess(dd, 0.5*fwhm)

                dd_wrong = np.sqrt((x_pix_wrong-x_centroid)**2 +
                                   (y_pix_wrong-y_centroid)**2)

                self.assertLess(dd, dd_wrong)

                if os.path.exists(dbFileName):
                    os.unlink(dbFileName)
                if os.path.exists(catName):
                    os.unlink(catName)
                if os.path.exists(imageName):
                    os.unlink(imageName)

        if os.path.exists(scratchDir):
            shutil.rmtree(scratchDir)
예제 #35
0
    def test_avro_alert_generation_diff_dmag(self):
        """
        Make sure everything works properly when the AlertDataGenerator
        and the AvroAlertGenerator have different dmag thresholds
        """
        dmag_cutoff_sqlite = 0.005
        dmag_cutoff_avro = 0.2
        mag_name_to_int = {'u': 0, 'g': 1, 'r': 2, 'i': 3, 'z': 4, 'y': 5}

        star_db = StarAlertTestDBObj_avro(database=self.star_db_name, driver='sqlite')

        # assemble a dict of all of the alerts that need to be generated

        obshistid_list = []
        for obs in self.obs_list:
            obshistid_list.append(obs.OpsimMetaData['obsHistID'])
        obshistid_max = max(obshistid_list)
        obshistid_bits = int(np.ceil(np.log(obshistid_max)/np.log(2.0)))

        true_alert_dict = {}
        obs_dict = {}
        ignored_sqlite = 0  # count number of alerts written to sqlite, but not avro
        for obs in self.obs_list:
            obs_dict[obs.OpsimMetaData['obsHistID']] = obs
            obshistid = obs.OpsimMetaData['obsHistID']
            cat = TestAlertsTruthCat_avro(star_db, obs_metadata=obs)
            cat.camera = lsst_camera()

            for line in cat.iter_catalog():
                if line[1] is None:
                    continue

                dmag = line[2]
                mag = line[3]
                if (np.abs(dmag) > dmag_cutoff_avro and
                    mag <= self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]]):

                    alertId = (line[0] << obshistid_bits) + obshistid
                    self.assertNotIn(alertId, true_alert_dict)
                    true_alert_dict[alertId] = {}
                    true_alert_dict[alertId]['chipName'] = line[1]
                    true_alert_dict[alertId]['dmag'] = dmag
                    true_alert_dict[alertId]['mag'] = mag
                    true_alert_dict[alertId]['ra'] = np.degrees(line[4])
                    true_alert_dict[alertId]['decl'] = np.degrees(line[5])
                    true_alert_dict[alertId]['xPix'] = line[6]
                    true_alert_dict[alertId]['yPix'] = line[7]
                elif np.abs(dmag) > dmag_cutoff_sqlite:
                    ignored_sqlite += 1

        self.assertGreater(len(true_alert_dict), 10)

        self.assertGreater(ignored_sqlite, 50)  # just make sure that some sqlite
                                                # alerts were ignored by the more
                                                # stringent avro cut

        log_file_name = tempfile.mktemp(dir=self.alert_data_output_dir, suffix='log.txt')
        alert_gen = AlertDataGenerator(testing=True)

        alert_gen.subdivide_obs(self.obs_list, htmid_level=6)

        for htmid in alert_gen.htmid_list:
            alert_gen.alert_data_from_htmid(htmid, star_db,
                                            photometry_class=TestAlertsVarCat_avro,
                                            output_prefix='alert_test',
                                            output_dir=self.alert_data_output_dir,
                                            dmag_cutoff=dmag_cutoff_sqlite,
                                            log_file_name=log_file_name)

        obshistid_to_htmid = {}
        for htmid in alert_gen.htmid_list:
            for obs in alert_gen.obs_from_htmid(htmid):
                obshistid = obs.OpsimMetaData['obsHistID']
                if obshistid not in obshistid_to_htmid:
                    obshistid_to_htmid[obshistid] = []
                obshistid_to_htmid[obshistid].append(htmid)

        avro_gen = AvroAlertGenerator()
        avro_gen.load_schema(os.path.join(getPackageDir('sims_catUtils'), 'tests', 'testData', 'avroSchema'))
        sql_prefix_list = ['alert_test']
        out_prefix = 'test_avro'
        log_file_name = tempfile.mktemp(dir=self.avro_out_dir,
                                        prefix='test_avro',
                                        suffix='log.txt')
        for obshistid in obshistid_list:
            avro_gen.write_alerts(obshistid, self.alert_data_output_dir,
                                  sql_prefix_list,
                                  obshistid_to_htmid[obshistid],
                                  self.avro_out_dir, out_prefix,
                                  dmag_cutoff_avro, lock=None,
                                  log_file_name=log_file_name)

        list_of_avro_files = os.listdir(self.avro_out_dir)
        self.assertGreater(len(list_of_avro_files), 2)
        alert_ct = 0
        dummy_sed = Sed()
        bp_dict = BandpassDict.loadTotalBandpassesFromFiles()
        photParams = PhotometricParameters()
        diasourceId_set = set()
        for avro_file_name in list_of_avro_files:
            if avro_file_name.endswith('log.txt'):
                continue
            full_name = os.path.join(self.avro_out_dir, avro_file_name)
            with DataFileReader(open(full_name, 'rb'), DatumReader()) as data_reader:
                for alert in data_reader:
                    alert_ct += 1
                    obshistid = alert['alertId'] >> 20
                    obs = obs_dict[obshistid]
                    uniqueId = alert['diaObject']['diaObjectId']
                    true_alert_id = (uniqueId << obshistid_bits) + obshistid
                    self.assertIn(true_alert_id, true_alert_dict)
                    self.assertEqual(alert['l1dbId'], uniqueId)

                    true_alert = true_alert_dict[true_alert_id]

                    diaSource = alert['diaSource']
                    self.assertAlmostEqual(diaSource['ra'], true_alert['ra'], 10)
                    self.assertAlmostEqual(diaSource['decl'], true_alert['decl'], 10)
                    self.assertAlmostEqual(diaSource['x'], true_alert['xPix'], 3)
                    self.assertAlmostEqual(diaSource['y'], true_alert['yPix'], 3)
                    self.assertAlmostEqual(diaSource['midPointTai'], obs.mjd.TAI, 4)

                    true_tot_flux = dummy_sed.fluxFromMag(true_alert['mag'])
                    true_q_mag = true_alert['mag'] - true_alert['dmag']
                    true_q_flux = dummy_sed.fluxFromMag(true_q_mag)
                    true_dflux = true_tot_flux - true_q_flux
                    self.assertAlmostEqual(diaSource['psFlux']/true_dflux, 1.0, 6)
                    self.assertAlmostEqual(diaSource['totFlux']/true_tot_flux, 1.0, 6)
                    self.assertAlmostEqual(diaSource['diffFlux']/true_dflux, 1.0, 6)

                    true_tot_snr, gamma = calcSNR_m5(true_alert['mag'], bp_dict[obs.bandpass],
                                                     obs.m5[obs.bandpass], photParams)

                    true_q_snr, gamma = calcSNR_m5(true_q_mag, bp_dict[obs.bandpass],
                                                   self.obs_mag_cutoff[mag_name_to_int[obs.bandpass]],
                                                   photParams)

                    true_tot_err = true_tot_flux/true_tot_snr
                    true_q_err = true_q_flux/true_q_snr
                    true_diff_err = np.sqrt(true_tot_err**2 + true_q_err**2)

                    self.assertAlmostEqual(diaSource['snr']/np.abs(true_dflux/true_diff_err),
                                           1.0, 6)

                    self.assertAlmostEqual(diaSource['totFluxErr']/true_tot_err, 1.0, 6)
                    self.assertAlmostEqual(diaSource['diffFluxErr']/true_diff_err, 1.0, 6)

                    chipnum = int(true_alert['chipName'].replace('R', '').replace('S', '').
                                  replace(',', '').replace(':', '').replace(' ', ''))

                    true_ccdid = (chipnum*10**7)+obshistid
                    self.assertEqual(true_ccdid, diaSource['ccdVisitId'])
                    self.assertEqual(uniqueId, diaSource['diaObjectId'])

                    self.assertNotIn(diaSource['diaSourceId'], diasourceId_set)
                    diasourceId_set.add(diaSource['diaSourceId'])

                    diaObject = alert['diaObject']
                    obj_dex = (uniqueId//1024) - 1
                    self.assertAlmostEqual(0.001*diaObject['pmRa']/self.pmra_truth[obj_dex], 1.0, 5)
                    self.assertAlmostEqual(0.001*diaObject['pmDecl']/self.pmdec_truth[obj_dex], 1.0, 5)
                    self.assertAlmostEqual(0.001*diaObject['parallax']/self.px_truth[obj_dex], 1.0, 5)

                    (true_ra_base,
                     true_dec_base) = applyProperMotion(self.ra_truth[obj_dex],
                                                        self.dec_truth[obj_dex],
                                                        self.pmra_truth[obj_dex],
                                                        self.pmdec_truth[obj_dex],
                                                        self.px_truth[obj_dex],
                                                        self.vrad_truth[obj_dex],
                                                        mjd=ModifiedJulianDate(TAI=diaObject['radecTai']))

                    self.assertAlmostEqual(true_ra_base, diaObject['ra'], 7)
                    self.assertAlmostEqual(true_dec_base, diaObject['decl'], 7)

        self.assertEqual(alert_ct, len(true_alert_dict))