Last active
October 30, 2019 17:32
-
-
Save jmeyers314/3c5e69ada9d2276fac401eefa8b42f9f to your computer and use it in GitHub Desktop.
Batoid ImSim integration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2019-10-11T20:25:58.314624Z", | |
"start_time": "2019-10-11T20:25:53.884963Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"import lsst.afw.cameraGeom as cameraGeom\n", | |
"from lsst.obs.lsst import LsstCamMapper\n", | |
"import lsst.obs.lsst.cameraTransforms as cameraTransforms\n", | |
"\n", | |
"import batoid\n", | |
"import galsim\n", | |
"\n", | |
"import numpy as np" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2019-10-11T20:26:04.503467Z", | |
"start_time": "2019-10-11T20:25:58.316967Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"camera = LsstCamMapper().camera" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1028, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2019-10-11T20:26:04.520761Z", | |
"start_time": "2019-10-11T20:26:04.508135Z" | |
} | |
}, | |
"outputs": [], | |
"source": [ | |
"class BatoidWCS(galsim.wcs.CelestialWCS):\n", | |
" \"\"\"\n", | |
" Parameters\n", | |
" ----------\n", | |
" boresight : galsim.CelestialCoord\n", | |
" rotSkyPos : galsim.Angle\n", | |
" rotTelPos : galsim.Angle\n", | |
" fiducial_telescope : batoid.Optic\n", | |
" Telescope before application of rotator\n", | |
" wavelength : float\n", | |
" Nanometers\n", | |
" camera : lsst.afw.cameraGeom.camera.camera.Camera\n", | |
" det : lsst.afw.cameraGeom.detector.detector.Detector\n", | |
" \"\"\"\n", | |
" def __init__(self, boresight, rotSkyPos, rotTelPos, fiducial_telescope, wavelength, camera, det):\n", | |
" self.boresight = boresight\n", | |
" self.rotSkyPos = rotSkyPos\n", | |
" self.rotTelPos = rotTelPos\n", | |
" self.fiducial_telescope = fiducial_telescope\n", | |
" self.wavelength = wavelength\n", | |
" self.camera = camera\n", | |
" self.det = det\n", | |
" \n", | |
" # Initialize RaDec -> field\n", | |
" q = rotTelPos - rotSkyPos\n", | |
" cq, sq = np.cos(q), np.sin(q) # +q or -q here?\n", | |
" jac = [cq, -sq, sq, cq]\n", | |
" affine = galsim.AffineTransform(*jac)\n", | |
" self._radec2field = galsim.TanWCS(affine, boresight, units=galsim.radians)\n", | |
"\n", | |
" # Initialize field -> focal\n", | |
" _pz = fiducial_telescope.stopSurface.surface.sag(0.0, 0.0)\n", | |
" transform = batoid.CoordTransform(fiducial_telescope.stopSurface.coordSys, batoid.globalCoordSys)\n", | |
" _, _, self._pz = transform.applyForward(0, 0, _pz)\n", | |
" self._refractive_index = fiducial_telescope.inMedium.getN(wavelength*1e-9)\n", | |
" self._telescope = fiducial_telescope.withLocallyRotatedOptic(\"LSSTCamera\", batoid.RotZ(-self.rotTelPos))\n", | |
"\n", | |
" # Initialize focal -> pixel\n", | |
" lct = cameraTransforms.LsstCameraTransforms(camera)\n", | |
" center = 509*4 + 0.5, 2000.5\n", | |
" # Focal plane coords of center of CCD\n", | |
" _x, _y = lct.ccdPixelToFocalMm(*center, det.getName())\n", | |
" self._focal_x = _x*1e-3 # meters\n", | |
" self._focal_y = _y*1e-3 # meters\n", | |
" \n", | |
" # Also calculate field angle of CCD center\n", | |
" self._field_x, self._field_y = self._focalToField(self._focal_x, self._focal_y)\n", | |
" \n", | |
" # Required by galsim.BaseWCS\n", | |
" self._color = None\n", | |
" self.origin = galsim.PositionD(0, 0)\n", | |
"\n", | |
" def _fieldToFocal(self, field_x, field_y):\n", | |
" ray = batoid.Ray.fromStop(\n", | |
" 0.0, 0.0,\n", | |
" optic=self._telescope,\n", | |
" wavelength=self.wavelength*1e-9,\n", | |
" theta_x=field_x, theta_y=field_y, projection='gnomonic' \n", | |
" )\n", | |
" self._telescope.traceInPlace(ray)\n", | |
" return ray.x, ray.y\n", | |
" \n", | |
" def _fieldToFocalMany(self, field_x, field_y):\n", | |
" # Setup rays to trace with batoid. For each input coordinate, we'll \n", | |
" # trace exactly 1 ray, the chief ray. Any displacements between the \n", | |
" # mean optics/atmosphere and the chief ray can then be considered \n", | |
" # part of the PSF.\n", | |
" n = len(field_x)\n", | |
" dirCos = np.array(batoid.utils.fieldToDirCos(field_x, field_y, projection='gnomonic'))\n", | |
" w = np.empty(n); w.fill(self.wavelength*1e-9)\n", | |
" pz = np.empty(n); pz.fill(self._pz)\n", | |
" rays = batoid.RayVector.fromArrays(\n", | |
" np.zeros(n), np.zeros(n), pz, # Chief ray -> start at center of the entrance pupil.\n", | |
" *(dirCos/self._refractive_index), # velocity = dirCos adjusted for refractive index\n", | |
" np.zeros(n), # doesn't matter what we set time to, so just use 0.0\n", | |
" w # wavelength\n", | |
" )\n", | |
" self._telescope.traceInPlace(rays)\n", | |
" return rays.x, rays.y\n", | |
" \n", | |
" def _focalToField(self, x, y):\n", | |
" from scipy.optimize import least_squares\n", | |
"\n", | |
" def _resid(args):\n", | |
" fx1, fy1 = args\n", | |
" x1, y1 = self._fieldToFocal(fx1, fy1)\n", | |
" return np.array([x1-x, y1-y])\n", | |
"\n", | |
" result = least_squares(_resid, np.array([0.0, 0.0]))\n", | |
" return result.x[0], result.x[1]\n", | |
"\n", | |
" def _focalToFieldMany(self, x, y):\n", | |
" if not hasattr(self, '_xinterp'):\n", | |
" from scipy.interpolate import RectBivariateSpline\n", | |
" # radius of circle circumscribing CCD, plus some fudge\n", | |
" half_length = 2000*10e-6*np.sqrt(2)*1.2\n", | |
" N = 4 # seems to be sufficient, kinda surprising...\n", | |
" focal_xs = self._focal_x + half_length*np.linspace(-1,1,N)\n", | |
" focal_ys = self._focal_y + half_length*np.linspace(-1,1,N)\n", | |
" field_xs = np.empty((N, N), dtype=float)\n", | |
" field_ys = np.empty((N, N), dtype=float)\n", | |
" for i in range(N):\n", | |
" for j in range(N):\n", | |
" field_xs[i,j], field_ys[i,j] = self._focalToField(focal_xs[i], focal_ys[j])\n", | |
" self._xinterp = RectBivariateSpline(focal_xs, focal_ys, field_xs)\n", | |
" self._yinterp = RectBivariateSpline(focal_xs, focal_ys, field_ys)\n", | |
" return self._xinterp(x, y, grid=False), self._yinterp(x, y, grid=False)\n", | |
" \n", | |
" def _xy(self, ra, dec, color=None):\n", | |
" \"\"\"\n", | |
" Parameters\n", | |
" ----------\n", | |
" ra : array_like\n", | |
" Right ascension in radians\n", | |
" dec : array_like\n", | |
" Declination in radians\n", | |
" \n", | |
" Returns\n", | |
" -------\n", | |
" xpix, ypix : array_like\n", | |
" \"\"\"\n", | |
" # Abuse GalSim's TanWCS to convert ra/dec into field angles \n", | |
" # centered at ra/dec and aligned with alt/az.\n", | |
" field_x, field_y = self._radec2field.radecToxy(ra, dec, 'rad')\n", | |
"\n", | |
" # Field -> Focal via batoid.\n", | |
" focal_x, focal_y = self._fieldToFocalMany(field_x, field_y)\n", | |
" \n", | |
" # For the moment, focal -> pixel is just an offset and a scaling by the pixel size.\n", | |
" pixSize = 10e-6 # m\n", | |
" pixel_x = (focal_x - self._focal_x)/pixSize + (509*4 + 0.5)\n", | |
" pixel_y = (focal_y - self._focal_y)/pixSize + 2000.5\n", | |
" return pixel_x, pixel_y\n", | |
" \n", | |
" def _radec(self, x, y, color=None):\n", | |
" # reverse of _xy.\n", | |
"\n", | |
" # pixel -> focal\n", | |
" pixSize = 10e-6\n", | |
" focal_x = pixSize*(x-(509*4+0.5)) + self._focal_x\n", | |
" focal_y = pixSize*(y-2000.5) + self._focal_y\n", | |
"\n", | |
" # focal -> field using interpolating function derived from field->focal\n", | |
" field_x, field_y = self._focalToFieldMany(focal_x, focal_y)\n", | |
"\n", | |
" # field -> ra, dec using GalSim TanWCS\n", | |
" return self._radec2field.xyToradec(field_x, field_y, units='rad')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1038, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2019-10-11T20:26:04.610210Z", | |
"start_time": "2019-10-11T20:26:04.547881Z" | |
} | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"R02_S21\n" | |
] | |
} | |
], | |
"source": [ | |
"# Construct a WCS for some detector\n", | |
"det = camera[16]\n", | |
"print(det.getName())\n", | |
"\n", | |
"boresight = galsim.CelestialCoord(ra=30*galsim.degrees, dec=-10*galsim.degrees)\n", | |
"rotTelPos = 35.0*galsim.degrees\n", | |
"rotSkyPos = 10.0*galsim.degrees\n", | |
"\n", | |
"wcs = BatoidWCS(\n", | |
" boresight, rotSkyPos, rotTelPos,\n", | |
" batoid.Optic.fromYaml(\"LSST_r.yaml\"),\n", | |
" 620, # nm\n", | |
" camera, det\n", | |
")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1039, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"4.4306630586632416e-05 pixel\n" | |
] | |
} | |
], | |
"source": [ | |
"# Test focal<->field roundtrip for individual points\n", | |
"# Mostly probing the accuracy of the scipy least_squares inversion. \n", | |
"errs = []\n", | |
"for _ in range(1000):\n", | |
" xy = np.random.uniform(-0.3, 0.3, size=2)\n", | |
" w = np.hypot(*xy)\n", | |
" if w > 0.3:\n", | |
" continue\n", | |
" errs.append((wcs._fieldToFocal(*wcs._focalToField(*xy)) - xy)/10e-6)\n", | |
"print(np.max(errs), \"pixel\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1041, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Roundtrip field -> focal -> field for many points at once.\n", | |
"# This uses an interpolation trained only in the region of the particular sensor, so \n", | |
"# don't wander too far away from that.\n", | |
"fieldx = wcs._field_x + np.deg2rad(2000*0.2/3600)*np.linspace(-1, 1, 800)\n", | |
"fieldy = wcs._field_y + np.deg2rad(2000*0.2/3600)*np.linspace(-1, 1, 800)\n", | |
"fieldx, fieldy = np.meshgrid(fieldx, fieldy)\n", | |
"fieldx = fieldx.ravel()\n", | |
"fieldy = fieldy.ravel()\n", | |
"\n", | |
"focalx, focaly = wcs._fieldToFocalMany(fieldx, fieldy)\n", | |
"fieldx1, fieldy1 = wcs._focalToFieldMany(focalx, focaly)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1042, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"-1.8315910536664856e-06 arcsec\n", | |
"-2.623459060261082e-06 arcsec\n", | |
"2.7497054732218163e-06 arcsec\n", | |
"3.9374238444648215e-06 arcsec\n" | |
] | |
} | |
], | |
"source": [ | |
"print(3600*np.rad2deg(np.median(fieldx1-fieldx)), \"arcsec\")\n", | |
"print(3600*np.rad2deg(np.median(fieldy1-fieldy)), \"arcsec\")\n", | |
"\n", | |
"print(3600*np.rad2deg(np.median(np.abs(fieldx1-fieldx))), \"arcsec\")\n", | |
"print(3600*np.rad2deg(np.median(np.abs(fieldy1-fieldy))), \"arcsec\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1043, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Roundtrip focal -> field -> focal\n", | |
"focalx = wcs._focal_x + np.linspace(-2000*10e-6, 2000*10e-6, 80)\n", | |
"focaly = wcs._focal_y + np.linspace(-2000*10e-6, 2000*10e-6, 80)\n", | |
"focalx, focaly = np.meshgrid(focalx, focaly)\n", | |
"focalx = focalx.ravel()\n", | |
"focaly = focaly.ravel()\n", | |
"\n", | |
"fieldx, fieldy = wcs._focalToFieldMany(focalx, focaly)\n", | |
"focalx1, focaly1 = wcs._fieldToFocalMany(fieldx, fieldy)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1044, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"-2.983737389106178e-08 pixel\n", | |
"-9.86531689672887e-06 pixel\n", | |
"2.320837749411608e-07 pixel\n", | |
"2.4014325250565346e-05 pixel\n" | |
] | |
} | |
], | |
"source": [ | |
"print(np.median(focalx1-focalx)/10e-6, \"pixel\")\n", | |
"print(np.median(focaly1-focaly)/10e-6, \"pixel\")\n", | |
"\n", | |
"print(np.median(np.abs(focalx1-focalx))/10e-6, \"pixel\")\n", | |
"print(np.median(np.abs(focaly1-focaly))/10e-6, \"pixel\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1046, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"R01_S00 7.2544181594384275e-06 arcsec\n", | |
"R01_S01 1.433698188485654e-05 arcsec\n", | |
"R01_S02 1.0243720362907117e-05 arcsec\n", | |
"R01_S10 1.1135579939677904e-05 arcsec\n", | |
"R01_S11 6.403266541792628e-06 arcsec\n", | |
"R01_S12 4.3049784043895906e-06 arcsec\n", | |
"R01_S20 5.1013095839763515e-06 arcsec\n", | |
"R01_S21 2.938842067336334e-06 arcsec\n", | |
"R01_S22 2.499024072583775e-06 arcsec\n", | |
"R02_S00 7.734938030505143e-06 arcsec\n", | |
"R02_S01 6.839891060860329e-06 arcsec\n", | |
"R02_S02 6.315694818984418e-06 arcsec\n", | |
"R02_S10 3.7584564577118143e-06 arcsec\n", | |
"R02_S11 3.874487684417425e-06 arcsec\n", | |
"R02_S12 4.002426728944234e-06 arcsec\n", | |
"R02_S20 2.515082693170484e-06 arcsec\n", | |
"R02_S21 2.7497054732218163e-06 arcsec\n", | |
"R02_S22 2.940118920891674e-06 arcsec\n", | |
"R03_S00 6.270739447745473e-06 arcsec\n", | |
"R03_S01 4.728063033819002e-06 arcsec\n", | |
"R03_S02 4.066500866608575e-06 arcsec\n", | |
"R03_S10 3.801634932564093e-06 arcsec\n", | |
"R03_S11 3.450567518303577e-06 arcsec\n", | |
"R03_S12 3.5868656098312167e-06 arcsec\n", | |
"R03_S20 2.6899331798830387e-06 arcsec\n", | |
"R03_S21 2.8450070620697365e-06 arcsec\n", | |
"R03_S22 3.27941683418751e-06 arcsec\n", | |
"R10_S00 7.98434114633824e-06 arcsec\n", | |
"R10_S01 1.1894259235862296e-05 arcsec\n", | |
"R10_S02 5.5671659450104484e-06 arcsec\n", | |
"R10_S10 1.2412012349821431e-05 arcsec\n", | |
"R10_S11 7.963518253623366e-06 arcsec\n", | |
"R10_S12 4.0037586856094305e-06 arcsec\n", | |
"R10_S20 1.347066975575221e-05 arcsec\n", | |
"R10_S21 6.1102042301456175e-06 arcsec\n", | |
"R10_S22 3.748152891793479e-06 arcsec\n", | |
"R11_S00 3.054649840197105e-06 arcsec\n", | |
"R11_S01 2.3180289629505335e-06 arcsec\n", | |
"R11_S02 2.0360890709030687e-06 arcsec\n", | |
"R11_S10 2.8091171811128166e-06 arcsec\n", | |
"R11_S11 2.169762953697558e-06 arcsec\n", | |
"R11_S12 1.7243557503247962e-06 arcsec\n", | |
"R11_S20 2.7216649676467637e-06 arcsec\n", | |
"R11_S21 2.017735262665882e-06 arcsec\n", | |
"R11_S22 1.4528247999479564e-06 arcsec\n", | |
"R12_S00 1.8810879588135593e-06 arcsec\n", | |
"R12_S01 2.0238459828615106e-06 arcsec\n", | |
"R12_S02 2.1910730079972984e-06 arcsec\n", | |
"R12_S10 1.4105771740586084e-06 arcsec\n", | |
"R12_S11 1.4753980214786736e-06 arcsec\n", | |
"R12_S12 1.526639798802465e-06 arcsec\n", | |
"R12_S20 1.0214354341290098e-06 arcsec\n", | |
"R12_S21 9.762393893233948e-07 arcsec\n", | |
"R12_S22 1.051031037128247e-06 arcsec\n", | |
"R13_S00 2.137109351734044e-06 arcsec\n", | |
"R13_S01 2.5018915811707152e-06 arcsec\n", | |
"R13_S02 3.101745197957306e-06 arcsec\n", | |
"R13_S10 1.757518139160202e-06 arcsec\n", | |
"R13_S11 2.2671283150251795e-06 arcsec\n", | |
"R13_S12 3.013809937749006e-06 arcsec\n", | |
"R13_S20 1.497208431695592e-06 arcsec\n", | |
"R13_S21 2.188673428578635e-06 arcsec\n", | |
"R13_S22 3.1698466483820334e-06 arcsec\n", | |
"R14_S00 4.2217800436607286e-06 arcsec\n", | |
"R14_S01 6.832533185538698e-06 arcsec\n", | |
"R14_S02 5.945353258263084e-06 arcsec\n", | |
"R14_S10 4.323315753256302e-06 arcsec\n", | |
"R14_S11 6.079756899450768e-06 arcsec\n", | |
"R14_S12 1.1456109720338699e-05 arcsec\n", | |
"R14_S20 4.307878831717484e-06 arcsec\n", | |
"R14_S21 5.943440393163785e-06 arcsec\n", | |
"R14_S22 1.0007420337222983e-05 arcsec\n", | |
"R20_S00 1.0828928986452875e-05 arcsec\n", | |
"R20_S01 5.506583653847402e-06 arcsec\n", | |
"R20_S02 3.7189901076206055e-06 arcsec\n", | |
"R20_S10 9.785994930888448e-06 arcsec\n", | |
"R20_S11 5.572951413732964e-06 arcsec\n", | |
"R20_S12 3.939686471186748e-06 arcsec\n", | |
"R20_S20 9.589423889598343e-06 arcsec\n", | |
"R20_S21 5.745308931990021e-06 arcsec\n", | |
"R20_S22 4.172441649407592e-06 arcsec\n", | |
"R21_S00 2.7216953817009056e-06 arcsec\n", | |
"R21_S01 1.9736783583675165e-06 arcsec\n", | |
"R21_S02 1.306465662436552e-06 arcsec\n", | |
"R21_S10 2.8951590769977083e-06 arcsec\n", | |
"R21_S11 2.1056587150649266e-06 arcsec\n", | |
"R21_S12 1.3914768796984484e-06 arcsec\n", | |
"R21_S20 3.146439992314739e-06 arcsec\n", | |
"R21_S21 2.324068836290633e-06 arcsec\n", | |
"R21_S22 1.5178732607820305e-06 arcsec\n", | |
"R22_S00 7.1918190586734e-07 arcsec\n", | |
"R22_S01 4.883078592584228e-07 arcsec\n", | |
"R22_S02 7.426067209140189e-07 arcsec\n", | |
"R22_S10 6.9465632569349e-07 arcsec\n", | |
"R22_S11 3.294776848423244e-08 arcsec\n", | |
"R22_S12 6.941710649870074e-07 arcsec\n", | |
"R22_S20 7.426626738283292e-07 arcsec\n", | |
"R22_S21 4.877863141380839e-07 arcsec\n", | |
"R22_S22 7.191050656540824e-07 arcsec\n", | |
"R23_S00 1.517322453316218e-06 arcsec\n", | |
"R23_S01 2.324434431112034e-06 arcsec\n", | |
"R23_S02 3.1471060601004372e-06 arcsec\n", | |
"R23_S10 1.3920246010322965e-06 arcsec\n", | |
"R23_S11 2.1065595077861174e-06 arcsec\n", | |
"R23_S12 2.895786501044027e-06 arcsec\n", | |
"R23_S20 1.3063172597429615e-06 arcsec\n", | |
"R23_S21 1.9739438551695517e-06 arcsec\n", | |
"R23_S22 2.721433105210485e-06 arcsec\n", | |
"R24_S00 4.175982560934465e-06 arcsec\n", | |
"R24_S01 5.747482642330133e-06 arcsec\n", | |
"R24_S02 9.603075148346651e-06 arcsec\n", | |
"R24_S10 3.941847479186602e-06 arcsec\n", | |
"R24_S11 5.573866340044021e-06 arcsec\n", | |
"R24_S12 9.81152269887281e-06 arcsec\n", | |
"R24_S20 3.7215638522257794e-06 arcsec\n", | |
"R24_S21 5.518217566275126e-06 arcsec\n", | |
"R24_S22 1.0854861082451119e-05 arcsec\n", | |
"R30_S00 1.0017236920462652e-05 arcsec\n", | |
"R30_S01 5.9422669473925256e-06 arcsec\n", | |
"R30_S02 4.308993954067273e-06 arcsec\n", | |
"R30_S10 1.1476235236682728e-05 arcsec\n", | |
"R30_S11 6.081246293572697e-06 arcsec\n", | |
"R30_S12 4.3230023095924425e-06 arcsec\n", | |
"R30_S20 5.945557569144434e-06 arcsec\n", | |
"R30_S21 6.830938773476881e-06 arcsec\n", | |
"R30_S22 4.225583768396624e-06 arcsec\n", | |
"R31_S00 3.170048812388974e-06 arcsec\n", | |
"R31_S01 2.188900907812993e-06 arcsec\n", | |
"R31_S02 1.4973043254192379e-06 arcsec\n", | |
"R31_S10 3.0144734113947926e-06 arcsec\n", | |
"R31_S11 2.2670820677722642e-06 arcsec\n", | |
"R31_S12 1.7577331173237774e-06 arcsec\n", | |
"R31_S20 3.101438016010477e-06 arcsec\n", | |
"R31_S21 2.501484905012948e-06 arcsec\n", | |
"R31_S22 2.1371761284735044e-06 arcsec\n", | |
"R32_S00 1.0514580415030835e-06 arcsec\n", | |
"R32_S01 9.759213835514153e-07 arcsec\n", | |
"R32_S02 1.022961861834511e-06 arcsec\n", | |
"R32_S10 1.5278763537360677e-06 arcsec\n", | |
"R32_S11 1.475563599167544e-06 arcsec\n", | |
"R32_S12 1.4116999893750321e-06 arcsec\n", | |
"R32_S20 2.1930427652684625e-06 arcsec\n", | |
"R32_S21 2.023010669809824e-06 arcsec\n", | |
"R32_S22 1.881710194580054e-06 arcsec\n", | |
"R33_S00 1.4539624644790492e-06 arcsec\n", | |
"R33_S01 2.019470831720156e-06 arcsec\n", | |
"R33_S02 2.724100596664895e-06 arcsec\n", | |
"R33_S10 1.724750596310033e-06 arcsec\n", | |
"R33_S11 2.1714554063574315e-06 arcsec\n", | |
"R33_S12 2.811880208478471e-06 arcsec\n", | |
"R33_S20 2.036897369118429e-06 arcsec\n", | |
"R33_S21 2.318973229878527e-06 arcsec\n", | |
"R33_S22 3.051145783347603e-06 arcsec\n", | |
"R34_S00 3.749451035186719e-06 arcsec\n", | |
"R34_S01 6.1130645824845245e-06 arcsec\n", | |
"R34_S02 1.3462606453280697e-05 arcsec\n", | |
"R34_S10 4.000617092722815e-06 arcsec\n", | |
"R34_S11 7.975109228562888e-06 arcsec\n", | |
"R34_S12 1.239076437597338e-05 arcsec\n", | |
"R34_S20 5.553458151902675e-06 arcsec\n", | |
"R34_S21 1.189067681809683e-05 arcsec\n", | |
"R34_S22 7.97652580786108e-06 arcsec\n", | |
"R41_S00 3.27887620201187e-06 arcsec\n", | |
"R41_S01 2.844243222045283e-06 arcsec\n", | |
"R41_S02 2.691016367475978e-06 arcsec\n", | |
"R41_S10 3.5872512072044937e-06 arcsec\n", | |
"R41_S11 3.4524245646682166e-06 arcsec\n", | |
"R41_S12 3.8054942971284477e-06 arcsec\n", | |
"R41_S20 4.067613752630853e-06 arcsec\n", | |
"R41_S21 4.7327789118198416e-06 arcsec\n", | |
"R41_S22 6.282363878144554e-06 arcsec\n", | |
"R42_S00 2.940192988058819e-06 arcsec\n", | |
"R42_S01 2.7486082414921117e-06 arcsec\n", | |
"R42_S02 2.5140707996985763e-06 arcsec\n", | |
"R42_S10 4.002620663265936e-06 arcsec\n", | |
"R42_S11 3.876953190771095e-06 arcsec\n", | |
"R42_S12 3.7531969732197456e-06 arcsec\n", | |
"R42_S20 6.321685493119289e-06 arcsec\n", | |
"R42_S21 6.846602190265953e-06 arcsec\n", | |
"R42_S22 7.741481345894385e-06 arcsec\n", | |
"R43_S00 2.500785225224768e-06 arcsec\n", | |
"R43_S01 2.939119014135222e-06 arcsec\n", | |
"R43_S02 5.119268546228302e-06 arcsec\n", | |
"R43_S10 4.31645631061019e-06 arcsec\n", | |
"R43_S11 6.415219265070235e-06 arcsec\n", | |
"R43_S12 1.1143159837594767e-05 arcsec\n", | |
"R43_S20 1.0250233264242218e-05 arcsec\n", | |
"R43_S21 1.4361027593873208e-05 arcsec\n", | |
"R43_S22 7.255121260807699e-06 arcsec\n" | |
] | |
} | |
], | |
"source": [ | |
"# Repeat focal -> field -> focal for all detectors\n", | |
"for det in camera:\n", | |
" wcs = BatoidWCS(\n", | |
" boresight, rotSkyPos, rotTelPos,\n", | |
" batoid.Optic.fromYaml(\"LSST_r.yaml\"),\n", | |
" 620, # nm\n", | |
" camera, det\n", | |
" )\n", | |
" \n", | |
" fieldx = wcs._field_x + np.deg2rad(2000*0.2/3600)*np.linspace(-1, 1, 800)\n", | |
" fieldy = wcs._field_y + np.deg2rad(2000*0.2/3600)*np.linspace(-1, 1, 800)\n", | |
" fieldx, fieldy = np.meshgrid(fieldx, fieldy)\n", | |
" fieldx = fieldx.ravel()\n", | |
" fieldy = fieldy.ravel()\n", | |
"\n", | |
" focalx, focaly = wcs._fieldToFocalMany(fieldx, fieldy)\n", | |
" fieldx1, fieldy1 = wcs._focalToFieldMany(focalx, focaly)\n", | |
" \n", | |
" print(det.getName(), 3600*np.rad2deg(np.median(np.abs(fieldx1-fieldx))), \"arcsec\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1049, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"2.2471421630143595e-05 pixel\n", | |
"4.088101013621781e-05 pixel\n", | |
"5.574985804668309e-06 arcsec\n", | |
"7.499402895974616e-06 arcsec\n" | |
] | |
} | |
], | |
"source": [ | |
"# Try pixel -> radec -> pixel -> radec roundtrip\n", | |
"x = np.random.uniform(-50, 4050, size=100000)\n", | |
"y = np.random.uniform(-50, 4050, size=100000)\n", | |
"ra, dec = wcs.xyToradec(x, y, units='rad')\n", | |
"x1, y1 = wcs.radecToxy(ra, dec, units='rad')\n", | |
"ra1, dec1 = wcs.xyToradec(x1, y1, units='rad')\n", | |
"\n", | |
"print(np.median(np.abs(x-x1)), \"pixel\")\n", | |
"print(np.median(np.abs(y-y1)), \"pixel\")\n", | |
"print(206265*np.median(np.abs(ra-ra1)), \"arcsec\")\n", | |
"print(206265*np.median(np.abs(dec-dec1)), \"arcsec\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.2" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment