Exemplo n.º 1
0
    def focalMmToCcdPixel(self, focalPlaneX, focalPlaneY):
        r"""Given focal plane position return the detector position

        Parameters
        ----------
        focalPlaneX : `float`
           The x-focal plane position (mm) relative to the centre of the camera
        focalPlaneY : `float`
           The y-focal plane position (mm) relative to the centre of the camera

        N.b. all pixel coordinates have the centre of the bottom-left pixel
        at (0.0, 0.0) and CCD columns are taken to be vertical, with "R00" in
        the bottom left of the image

        Returns
        -------
        detectorName : `str`
           The name of the detector
        ccdX : `int`
           The column pixel position relative to the corner of the detector
        ccdY : `int`
           The row pixel position relative to the corner of the detector

        Raises
        ------
        RuntimeError
            If the requested position doesn't lie on a detector
        """
        detector, ccdXY = focalMmToCcdPixel(self.camera, geom.PointD(focalPlaneX, focalPlaneY))
        ccdX, ccdY = ccdXY

        return detector.getName(), ccdX, ccdY
Exemplo n.º 2
0
    def ccdPixelToAmpPixel(self, ccdX, ccdY, detectorName=None):
        r"""Given position within a detector, return the amplifier position

        Parameters
        ----------
        ccdX : `int`
           column pixel position within detector
        ccdY : `int`
           row pixel position within detector
        detectorName : `str`
           Name of detector (or default from setDetectorName() if None)

        N.b. all pixel coordinates have the centre of the bottom-left pixel
        at (0.0, 0.0)

        Returns
        -------
        channel: `int`
           Channel number of amplifier (1-indexed; identical to HDU)
        ampX : `int`
           The column coordinate relative to the corner of the single-amp image
        ampY : `int`
           The row coordinate relative to the corner of the single-amp image

        Raises
        ------
        RuntimeError
            If the requested pixel doesn't lie on the detector
        """

        amp, ampXY = ccdPixelToAmpPixel(geom.PointD(ccdX, ccdY), self.getDetector(detectorName))

        ampX, ampY = ampXY
        return ampToChannel(amp), ampX, ampY
Exemplo n.º 3
0
    def testSwap(self):
        x00, y00, x01, y01 = (0., 1., 2., 3.)
        x10, y10, x11, y11 = (4., 5., 6., 7.)

        box0 = geom.Box2D(geom.PointD(x00, y00), geom.PointD(x01, y01))
        box1 = geom.Box2D(geom.PointD(x10, y10), geom.PointD(x11, y11))
        box0.swap(box1)

        self.assertEqual(box0.getMinX(), x10)
        self.assertEqual(box0.getMinY(), y10)
        self.assertEqual(box0.getMaxX(), x11)
        self.assertEqual(box0.getMaxY(), y11)

        self.assertEqual(box1.getMinX(), x00)
        self.assertEqual(box1.getMinY(), y00)
        self.assertEqual(box1.getMaxX(), x01)
        self.assertEqual(box1.getMaxY(), y01)
Exemplo n.º 4
0
def makeitLsst(prefs, context, saveWcs=False, plot=dict()):
    """This is the python wrapper that reads lsst tables
    """
    # Create an array of PSFs (one PSF for each extension)
    if prefs.getVerboseType() != prefs.QUIET:
        print("----- %d input catalogues:" % prefs.getNcat())

    if saveWcs:  # only needed for making plots
        wcssList = []

    fields = psfexLib.vectorField()
    for cat in prefs.getCatalogs():
        field = psfexLib.Field(cat)
        wcss = []
        wcssList.append(wcss)
        with fits.open(cat):
            # Hack: I want the WCS so I'll guess where the calexp is to be
            # found
            calexpFile = guessCalexp(cat)
            md = readMetadata(calexpFile)
            wcs = afwGeom.makeSkyWcs(md)

            if not wcs:
                cdMatrix = np.array([1.0, 0.0, 0.0, 1.0])
                cdMatrix.shape = (2, 2)
                wcs = afwGeom.makeSkyWcs(crpix=geom.PointD(0, 0),
                                         crval=geom.SpherePoint(
                                             0.0, 0.0, geom.degrees),
                                         cdMatrix=cdMatrix)

            naxis1, naxis2 = md.getScalar("NAXIS1"), md.getScalar("NAXIS2")
            # Find how many rows there are in the catalogue
            md = readMetadata(cat)

            field.addExt(wcs, naxis1, naxis2, md.getScalar("NAXIS2"))
            if saveWcs:
                wcss.append((wcs, naxis1, naxis2))

        field.finalize()
        fields.append(field)

    fields[0].getNext()  # number of extensions

    prefs.getPsfStep()

    sets = psfexLib.vectorSet()
    for set in load_samplesLsst(prefs, context, plot=plot):
        sets.append(set)

    psfexLib.makeit(fields, sets)

    ret = [[f.getPsfs() for f in fields], sets]
    if saveWcs:
        ret.append(wcssList)

    return ret
Exemplo n.º 5
0
    def focalMmToAmpPixel(self, focalPlaneX, focalPlaneY):
        r"""Given a focal plane position plane return the amplifier position

        Parameters
        ----------
        focalPlaneX : `float`
           The x-focal plane position (mm) relative to the centre of the camera
        focalPlaneY : `float`
           The y-focal plane position (mm) relative to the centre of the camera

        N.b. all pixel coordinates have the centre of the bottom-left pixel
        at (0.0, 0.0) and CCD columns are taken to be vertical, with "R00" in
        the bottom left of the image

        Returns
        -------
        detectorName : `str`
           The name of the detector
        channel: `int`
           Channel number of amplifier (1-indexed; identical to HDU)
        ampX : `int`
           The column coordinate relative to the corner of the single-amp image
        ampY : `int`
           The row coordinate relative to the corner of the single-amp image

        Raises
        ------
        RuntimeError
            If the requested position doesn't lie on a detector
        """

        detector, ccdXY = focalMmToCcdPixel(self.camera, geom.PointD(focalPlaneX, focalPlaneY))
        amp, ampXY = ccdPixelToAmpPixel(ccdXY, detector)

        ampX, ampY = ampXY
        return detector.getName(), ampToChannel(amp), ampX, ampY
Exemplo n.º 6
0
    def setUp(self):
        config = SingleFrameMeasurementTask.ConfigClass()
        config.slots.apFlux = 'base_CircularApertureFlux_12_0'
        self.schema = afwTable.SourceTable.makeMinimalSchema()

        self.measureSources = SingleFrameMeasurementTask(self.schema,
                                                         config=config)

        width, height = 110, 301

        self.mi = afwImage.MaskedImageF(geom.ExtentI(width, height))
        self.mi.set(0)
        sd = 3  # standard deviation of image
        self.mi.getVariance().set(sd * sd)
        self.mi.getMask().addMaskPlane("DETECTED")

        self.ksize = 31  # size of desired kernel

        sigma1 = 1.75
        sigma2 = 2 * sigma1

        self.exposure = afwImage.makeExposure(self.mi)
        self.exposure.setPsf(
            measAlg.DoubleGaussianPsf(self.ksize, self.ksize, 1.5 * sigma1, 1,
                                      0.1))
        cdMatrix = np.array([1.0, 0.0, 0.0, 1.0])
        cdMatrix.shape = (2, 2)
        wcs = afwGeom.makeSkyWcs(crpix=geom.PointD(0, 0),
                                 crval=geom.SpherePoint(
                                     0.0, 0.0, geom.degrees),
                                 cdMatrix=cdMatrix)
        self.exposure.setWcs(wcs)

        #
        # Make a kernel with the exactly correct basis functions.
        # Useful for debugging
        #
        basisKernelList = []
        for sigma in (sigma1, sigma2):
            basisKernel = afwMath.AnalyticKernel(
                self.ksize, self.ksize,
                afwMath.GaussianFunction2D(sigma, sigma))
            basisImage = afwImage.ImageD(basisKernel.getDimensions())
            basisKernel.computeImage(basisImage, True)
            basisImage /= np.sum(basisImage.getArray())

            if sigma == sigma1:
                basisImage0 = basisImage
            else:
                basisImage -= basisImage0

            basisKernelList.append(afwMath.FixedKernel(basisImage))

        order = 1  # 1 => up to linear
        spFunc = afwMath.PolynomialFunction2D(order)

        exactKernel = afwMath.LinearCombinationKernel(basisKernelList, spFunc)
        exactKernel.setSpatialParameters([[1.0, 0, 0],
                                          [0.0, 0.5 * 1e-2, 0.2e-2]])

        rand = afwMath.Random()  # make these tests repeatable by setting seed

        addNoise = True

        if addNoise:
            im = self.mi.getImage()
            afwMath.randomGaussianImage(im, rand)  # N(0, 1)
            im *= sd  # N(0, sd^2)
            del im

        xarr, yarr = [], []

        for x, y in [
            (20, 20),
            (60, 20),
            (30, 35),
            (50, 50),
            (20, 90),
            (70, 160),
            (25, 265),
            (75, 275),
            (85, 30),
            (50, 120),
            (70, 80),
            (60, 210),
            (20, 210),
        ]:
            xarr.append(x)
            yarr.append(y)

        for x, y in zip(xarr, yarr):
            dx = rand.uniform() - 0.5  # random (centered) offsets
            dy = rand.uniform() - 0.5

            k = exactKernel.getSpatialFunction(1)(
                x, y)  # functional variation of Kernel ...
            b = (k * sigma1**2 / ((1 - k) * sigma2**2)
                 )  # ... converted double Gaussian's "b"

            # flux = 80000 - 20*x - 10*(y/float(height))**2
            flux = 80000 * (1 + 0.1 * (rand.uniform() - 0.5))
            I0 = flux * (1 + b) / (2 * np.pi * (sigma1**2 + b * sigma2**2))
            for iy in range(y - self.ksize // 2, y + self.ksize // 2 + 1):
                if iy < 0 or iy >= self.mi.getHeight():
                    continue

                for ix in range(x - self.ksize // 2, x + self.ksize // 2 + 1):
                    if ix < 0 or ix >= self.mi.getWidth():
                        continue

                    II = I0 * psfVal(ix, iy, x + dx, y + dy, sigma1, sigma2, b)
                    Isample = rand.poisson(II) if addNoise else II
                    self.mi.image[ix, iy, afwImage.LOCAL] += Isample
                    self.mi.variance[ix, iy, afwImage.LOCAL] += II

        bbox = geom.BoxI(geom.PointI(0, 0), geom.ExtentI(width, height))
        self.cellSet = afwMath.SpatialCellSet(bbox, 100)

        self.footprintSet = afwDetection.FootprintSet(
            self.mi, afwDetection.Threshold(100), "DETECTED")

        self.catalog = self.measure(self.footprintSet, self.exposure)

        for source in self.catalog:
            try:
                cand = measAlg.makePsfCandidate(source, self.exposure)
                self.cellSet.insertCandidate(cand)

            except Exception as e:
                print(e)
                continue
Exemplo n.º 7
0
def plotKernelSpatialModel(kernel, kernelCellSet, showBadCandidates=True,
                           numSample=128, keepPlots=True, maxCoeff=10):
    """Plot the Kernel spatial model.
    """
    try:
        import matplotlib.pyplot as plt
        import matplotlib.colors
    except ImportError as e:
        print("Unable to import numpy and matplotlib: %s" % e)
        return

    x0 = kernelCellSet.getBBox().getBeginX()
    y0 = kernelCellSet.getBBox().getBeginY()

    candPos = list()
    candFits = list()
    badPos = list()
    badFits = list()
    candAmps = list()
    badAmps = list()
    for cell in kernelCellSet.getCellList():
        for cand in cell.begin(False):
            if not showBadCandidates and cand.isBad():
                continue
            candCenter = geom.PointD(cand.getXCenter(), cand.getYCenter())
            try:
                im = cand.getTemplateMaskedImage()
            except Exception:
                continue

            targetFits = badFits if cand.isBad() else candFits
            targetPos = badPos if cand.isBad() else candPos
            targetAmps = badAmps if cand.isBad() else candAmps

            # compare original and spatial kernel coefficients
            kp0 = np.array(cand.getKernel(diffimLib.KernelCandidateF.ORIG).getKernelParameters())
            amp = cand.getCandidateRating()

            targetFits = badFits if cand.isBad() else candFits
            targetPos = badPos if cand.isBad() else candPos
            targetAmps = badAmps if cand.isBad() else candAmps

            targetFits.append(kp0)
            targetPos.append(candCenter)
            targetAmps.append(amp)

    xGood = np.array([pos.getX() for pos in candPos]) - x0
    yGood = np.array([pos.getY() for pos in candPos]) - y0
    zGood = np.array(candFits)

    xBad = np.array([pos.getX() for pos in badPos]) - x0
    yBad = np.array([pos.getY() for pos in badPos]) - y0
    zBad = np.array(badFits)
    numBad = len(badPos)

    xRange = np.linspace(0, kernelCellSet.getBBox().getWidth(), num=numSample)
    yRange = np.linspace(0, kernelCellSet.getBBox().getHeight(), num=numSample)

    if maxCoeff:
        maxCoeff = min(maxCoeff, kernel.getNKernelParameters())
    else:
        maxCoeff = kernel.getNKernelParameters()

    for k in range(maxCoeff):
        func = kernel.getSpatialFunction(k)
        dfGood = zGood[:, k] - np.array([func(pos.getX(), pos.getY()) for pos in candPos])
        yMin = dfGood.min()
        yMax = dfGood.max()
        if numBad > 0:
            dfBad = zBad[:, k] - np.array([func(pos.getX(), pos.getY()) for pos in badPos])
            # Can really screw up the range...
            yMin = min([yMin, dfBad.min()])
            yMax = max([yMax, dfBad.max()])
        yMin -= 0.05*(yMax - yMin)
        yMax += 0.05*(yMax - yMin)

        fRange = np.ndarray((len(xRange), len(yRange)))
        for j, yVal in enumerate(yRange):
            for i, xVal in enumerate(xRange):
                fRange[j][i] = func(xVal, yVal)

        fig = plt.figure(k)

        fig.clf()
        try:
            fig.canvas._tkcanvas._root().lift()  # == Tk's raise, but raise is a python reserved word
        except Exception:                                 # protect against API changes
            pass

        fig.suptitle('Kernel component %d' % k)

        # LL
        ax = fig.add_axes((0.1, 0.05, 0.35, 0.35))
        vmin = fRange.min()  # - 0.05*np.fabs(fRange.min())
        vmax = fRange.max()  # + 0.05*np.fabs(fRange.max())
        norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax)
        im = ax.imshow(fRange, aspect='auto', norm=norm,
                       extent=[0, kernelCellSet.getBBox().getWidth() - 1,
                               0, kernelCellSet.getBBox().getHeight() - 1])
        ax.set_title('Spatial polynomial')
        plt.colorbar(im, orientation='horizontal', ticks=[vmin, vmax])

        # UL
        ax = fig.add_axes((0.1, 0.55, 0.35, 0.35))
        ax.plot(-2.5*np.log10(candAmps), zGood[:, k], 'b+')
        if numBad > 0:
            ax.plot(-2.5*np.log10(badAmps), zBad[:, k], 'r+')
        ax.set_title("Basis Coefficients")
        ax.set_xlabel("Instr mag")
        ax.set_ylabel("Coeff")

        # LR
        ax = fig.add_axes((0.55, 0.05, 0.35, 0.35))
        ax.set_autoscale_on(False)
        ax.set_xbound(lower=0, upper=kernelCellSet.getBBox().getHeight())
        ax.set_ybound(lower=yMin, upper=yMax)
        ax.plot(yGood, dfGood, 'b+')
        if numBad > 0:
            ax.plot(yBad, dfBad, 'r+')
        ax.axhline(0.0)
        ax.set_title('dCoeff (indiv-spatial) vs. y')

        # UR
        ax = fig.add_axes((0.55, 0.55, 0.35, 0.35))
        ax.set_autoscale_on(False)
        ax.set_xbound(lower=0, upper=kernelCellSet.getBBox().getWidth())
        ax.set_ybound(lower=yMin, upper=yMax)
        ax.plot(xGood, dfGood, 'b+')
        if numBad > 0:
            ax.plot(xBad, dfBad, 'r+')
        ax.axhline(0.0)
        ax.set_title('dCoeff (indiv-spatial) vs. x')

        fig.show()

    global keptPlots
    if keepPlots and not keptPlots:
        # Keep plots open when done
        def show():
            print("%s: Please close plots when done." % __name__)
            try:
                plt.show()
            except Exception:
                pass
            print("Plots closed, exiting...")
        import atexit
        atexit.register(show)
        keptPlots = True
Exemplo n.º 8
0
    if sensorName in mapperSensors:

        # update the defocal shift
        deformationCoeff = splitContent[19]
        defCoeff = float(deformationCoeff)
        if abs(defCoeff) > 10:
            sgn = np.sign(defCoeff)  # change +/- 1000 to +/- 1500
            newDeformationCoeff = str(defCoeff + sgn * 500.0)
            #print(newDeformationCoeff)
            newSplitContent[19] = newDeformationCoeff

        # update the x,y position
        detector = camera.get(sensorName)
        bbox = detector.getBBox()
        xc_px, yc_px = bbox.centerX, bbox.centerY
        xc_mm, yc_mm = detector.transform(geom.PointD(xc_px, yc_px),
                                          cameraGeom.PIXELS,
                                          cameraGeom.FOCAL_PLANE)

        xc_microns, yc_microns = 1000 * xc_mm, 1000 * yc_mm
        #xpos, ypos = float(splitContent[1]), float(splitContent[2])
        #print(xpos, ypos, '-->',
        #      yp_microns, xp_microns,
        #      'dx:', xpos - yp_microns,
        #      'dy:', ypos-xp_microns)

        # [1] is x-pos, [2] is y-pos
        if derotate_phosim:  # x_phosim <-- x_lsst, i.e. no transpose
            newSplitContent[1] = str(round(xc_microns, 2))
            newSplitContent[2] = str(round(yc_microns, 2))
Exemplo n.º 9
0
def main(butler,
         visits,
         fields,
         fieldRadius,
         showCCDs=False,
         aitoff=False,
         alpha=0.2,
         byFilter=False,
         byVisit=False,
         title="",
         verbose=False):
    ra, dec = [], []
    filters = {}
    _visits, visits = visits, []
    for v in _visits:
        try:
            exp = butler.get("raw", visit=v, ccd=49)
        except RuntimeError as e:
            if verbose:
                print(e, file=sys.stderr)
            continue

        ccd = exp.getDetector()

        xy = ccd.getPixelFromPosition(afwCG.FpPoint(0, 0))
        sky = exp.getWcs().pixelToSky(xy)
        visits.append(v)
        ra.append(sky[0].asDegrees())
        dec.append(sky[1].asDegrees())
        filters[v] = exp.getFilter().getName()

    plt.clf()
    if aitoff:
        axes = plt.gcf().add_axes((0.1, 0.1, 0.85, 0.80), projection="aitoff")
        axes.grid(1)
    else:
        axes = plt.gca()
        axes.set_aspect('equal')

    ctypes = dict(
        BIAS="orange",
        DARK="cyan",
    )
    if byFilter:
        ctypeFilters = dict(
            g="green",
            r="red",
            r1="orange",
            i="magenta",
            z="brown",
            y="black",
            nb0921='darkgray',
        )
    else:
        ctypeKeys = {}
        colors = list("rgbcmyk") + ["orange", "brown", "orchid"
                                    ]  # colours for ctypeKeys

    if aitoff:
        fieldRadius = np.radians(fieldRadius)
        dec = np.radians(dec)
        ra = np.array(ra)
        ra = np.radians(np.where(ra > 180, ra - 360, ra))

    plots, labels = [], []
    for v, r, d in zip(visits, ra, dec):
        field = fields.get(v)
        if verbose:
            print("Drawing %s %s         \r" % (v, field), end=' ', flush=True)

        if byFilter:
            facecolor = ctypes.get(field, ctypeFilters.get(filters[v], "gray"))
        else:
            key = v if byVisit else field
            if key not in ctypeKeys:
                ctypeKeys[key] = colors[len(ctypeKeys) % len(colors)]
            facecolor = ctypeKeys[key]

        circ = Circle(xy=(r, d),
                      radius=fieldRadius,
                      fill=False if showCCDs else True,
                      facecolor=facecolor,
                      alpha=alpha)
        axes.add_artist(circ)

        if showCCDs:
            pathCodes = [
                Path.MOVETO,
                Path.LINETO,
                Path.LINETO,
                Path.LINETO,
                Path.CLOSEPOLY,
            ]

            for ccd in butler.queryMetadata("raw", "visit", ["ccd"], visit=v):
                try:
                    md = butler.get("raw_md", visit=v, ccd=ccd)
                except RuntimeError as e:
                    if verbose:
                        print(e, file=sys.stderr)
                    continue

                width, height = md.getScalar("NAXIS1"), md.getScalar("NAXIS2")
                wcs = afwGeom.makeSkyWcs(md)

                verts = []
                for p in [(0, 0), (width, 0), (width, height), (0, height)]:
                    sky = wcs.pixelToSky(geom.PointD(*p))
                    verts.append([sky[0].asDegrees(), sky[1].asDegrees()])
                verts.append((0, 0))  # dummy

                axes.add_patch(
                    PathPatch(Path(verts, pathCodes),
                              alpha=alpha,
                              facecolor=facecolor))

        if byFilter:
            key = filters[v]
        else:
            key = v if byVisit else field

        if not labels.count(key):
            plots.append(Circle((0, 0), facecolor=facecolor))
            labels.append(key)

    plt.legend(plots, labels, loc='best',
               bbox_to_anchor=(0, 1.02, 1, 0.102)).draggable()

    if not aitoff:
        raRange = np.max(ra) - np.min(ra) + 1.2 * fieldRadius
        decRange = np.max(dec) - np.min(dec) + 1.2 * fieldRadius
        raRange *= np.cos(np.radians(np.mean(dec)))

        plt.xlim(0.5 * (np.max(ra) + np.min(ra)) + raRange * np.array((1, -1)))
        plt.ylim(0.5 * (np.max(dec) + np.min(dec)) +
                 decRange * np.array((-1, 1)))

    plt.xlabel("ra")
    plt.ylabel("dec")

    return plt
Exemplo n.º 10
0
def main(dataDir, visit, title="", outputTxtFileName=None,
         showFwhm=False, minFwhm=None, maxFwhm=None,
         correctDistortion=False,
         showEllipticity=False, ellipticityDirection=False,
         showNdataFwhm=False, showNdataEll=False,
         minNdata=None, maxNdata=None,
         gridPoints=30, verbose=False):

    butler = dafPersist.ButlerFactory(mapper=hscSim.HscSimMapper(root=dataDir)).create()
    camera = butler.get("camera")

    if not (showFwhm or showEllipticity or showNdataFwhm or showNdataEll or outputTxtFileName):
        showFwhm = True
    #
    # Get a dict of cameraGeom::Ccd indexed by serial number
    #
    ccds = {}
    for raft in camera:
        for ccd in raft:
            ccd.setTrimmed(True)
            ccds[ccd.getId().getSerial()] = ccd
    #
    # Read all the tableSeeingMap files, converting their (x, y) to focal
    # plane coordinates
    #
    xArr = []
    yArr = []
    ellArr = []
    fwhmArr = []
    paArr = []
    aArr = []
    bArr = []
    e1Arr = []
    e2Arr = []
    elle1e2Arr = []
    for tab in butler.subset("tableSeeingMap", visit=visit):
        # we could use tab.datasetExists() but it prints a rude message
        fileName = butler.get("tableSeeingMap_filename", **tab.dataId)[0]
        if not os.path.exists(fileName):
            continue

        with open(fileName) as fd:
            ccd = None
            for line in fd.readlines():
                if re.search(r"^\s*#", line):
                    continue
                fields = [float(_) for _ in line.split()]

                if ccd is None:
                    ccd = ccds[int(fields[0])]

                x, y, fwhm, ell, pa, a, b = fields[1:8]
                x, y = ccd.getPositionFromPixel(geom.PointD(x, y)).getMm()
                xArr.append(x)
                yArr.append(y)
                ellArr.append(ell)
                fwhmArr.append(fwhm)
                paArr.append(pa)
                aArr.append(a)
                bArr.append(b)
                if len(fields) == 11:
                    e1 = fields[8]
                    e2 = fields[9]
                    elle1e2 = fields[10]
                else:
                    e1 = -9999.
                    e2 = -9999.
                    elle1e2 = -9999.
                e1Arr.append(e1)
                e2Arr.append(e2)
                elle1e2Arr.append(elle1e2)

    xArr = np.array(xArr)
    yArr = np.array(yArr)
    ellArr = np.array(ellArr)
    fwhmArr = np.array(fwhmArr)*0.168   # arcseconds
    paArr = np.radians(np.array(paArr))
    aArr = np.array(aArr)
    bArr = np.array(bArr)

    e1Arr = np.array(e1Arr)
    e2Arr = np.array(e2Arr)
    elle1e2Arr = np.array(elle1e2Arr)

    if correctDistortion:
        import lsst.afw.geom.ellipses as afwEllipses

        dist = camera.getDistortion()
        for i in range(len(aArr)):
            axes = afwEllipses.Axes(aArr[i], bArr[i], paArr[i])
            if False:                                                       # testing only!
                axes = afwEllipses.Axes(1.0, 1.0, np.arctan2(yArr[i], xArr[i]))
            quad = afwGeom.Quadrupole(axes)
            quad = quad.transform(dist.computeQuadrupoleTransform(geom.PointD(xArr[i], yArr[i]), False))
            axes = afwEllipses.Axes(quad)
            aArr[i], bArr[i], paArr[i] = axes.getA(), axes.getB(), axes.getTheta()

        ellArr = 1 - bArr/aArr

    if len(xArr) == 0:
        gridPoints = 0
        xs, ys = [], []
    else:
        N = gridPoints*1j
        extent = [min(xArr), max(xArr), min(yArr), max(yArr)]
        xs, ys = np.mgrid[extent[0]:extent[1]:N, extent[2]:extent[3]:N]

    title = [title, ]

    title.append("\n#")

    if outputTxtFileName:
        f = open(outputTxtFileName, 'w')
        f.write("# %s visit %s\n" % (" ".join(title), visit))
        for x, y, ell, fwhm, pa, a, b, e1, e2, elle1e2 \
                in zip(xArr, yArr, ellArr, fwhmArr, paArr, aArr, bArr, e1Arr, e2Arr, elle1e2Arr):
            f.write('%f %f %f %f %f %f %f %f %f %f\n' % (x, y, ell, fwhm, pa, a, b, e1, e2, elle1e2))

    if showFwhm:
        title.append("FWHM (arcsec)")
        if len(xs) > 0:
            fwhmResampled = griddata(xArr, yArr, fwhmArr, xs, ys)
            plt.imshow(fwhmResampled.T, extent=extent, vmin=minFwhm, vmax=maxFwhm, origin='lower')
            plt.colorbar()

        if outputTxtFileName:

            ndataGrids = getNumDataGrids(xArr, yArr, fwhmArr, xs, ys)

            f = open(outputTxtFileName+'-fwhm-grid.txt', 'w')
            f.write("# %s visit %s\n" % (" ".join(title), visit))
            for xline, yline, fwhmline, ndataline \
                    in zip(xs.tolist(), ys.tolist(), fwhmResampled.tolist(), ndataGrids):
                for xx, yy, fwhm, ndata in zip(xline, yline, fwhmline, ndataline):
                    if fwhm is None:
                        fwhm = -9999
                    f.write('%f %f %f %d\n' % (xx, yy, fwhm, ndata))

    elif showEllipticity:
        title.append("Ellipticity")
        scale = 4

        if ellipticityDirection:        # we don't care about the magnitude
            ellArr = 0.1

        u = -ellArr*np.cos(paArr)
        v = -ellArr*np.sin(paArr)
        if gridPoints > 0:
            u = griddata(xArr, yArr, u, xs, ys)
            v = griddata(xArr, yArr, v, xs, ys)
            x, y = xs, ys
        else:
            x, y = xArr, yArr

        Q = plt.quiver(x, y, u, v, scale=scale,
                       pivot="middle",
                       headwidth=0,
                       headlength=0,
                       headaxislength=0,
                       )
        keyLen = 0.10
        if not ellipticityDirection:    # we care about the magnitude
            plt.quiverkey(Q, 0.20, 0.95, keyLen, "e=%g" % keyLen, labelpos='W')

        if outputTxtFileName:
            ndataGrids = getNumDataGrids(xArr, yArr, ellArr, xs, ys)

            f = open(outputTxtFileName+'-ell-grid.txt', 'w')
            f.write("# %s visit %s\n" % (" ".join(title), visit))
            # f.write('# %f %f %f %f %f %f %f\n' % (x, y, ell, fwhm, pa, a, b))
            for xline, yline, uline, vline, ndataline \
                    in zip(x.tolist(), y.tolist(), u.tolist(), v.tolist(), ndataGrids):
                for xx, yy, uu, vv, ndata in zip(xline, yline, uline, vline, ndataline):
                    if uu is None:
                        uu = -9999
                    if vv is None:
                        vv = -9999
                    f.write('%f %f %f %f %d\n' % (xx, yy, uu, vv, ndata))

    elif showNdataFwhm:
        title.append("N per fwhm grid")
        if len(xs) > 0:
            ndataGrids = getNumDataGrids(xArr, yArr, fwhmArr, xs, ys)
            plt.imshow(ndataGrids, interpolation='nearest', extent=extent,
                       vmin=minNdata, vmax=maxNdata, origin='lower')
            plt.colorbar()
        else:
            pass

    elif showNdataEll:
        title.append("N per ell grid")
        if len(xs) > 0:
            ndataGrids = getNumDataGrids(xArr, yArr, ellArr, xs, ys)
            plt.imshow(ndataGrids, interpolation='nearest', extent=extent,
                       vmin=minNdata, vmax=maxNdata, origin='lower')
            plt.colorbar()
        else:
            pass

    # plt.plot(xArr, yArr, "r.")
    # plt.plot(xs, ys, "b.")
    plt.axes().set_aspect('equal')
    plt.axis([-20000, 20000, -20000, 20000])

    def frameInfoFrom(filepath):
        with fits.open(filepath) as hdul:
            h = hdul[0].header
            # 'object=ABELL2163 filter=HSC-I exptime=360.0 alt=62.11143274 '
            # ' azm=202.32265181 hst=(23:40:08.363-23:40:48.546)'
            return 'object=%s filter=%s exptime=%.1f azm=%.2f hst=%s' % \
                (h['OBJECT'], h['FILTER01'], h['EXPTIME'], h['AZIMUTH'], h['HST'])

    title.insert(0, frameInfoFrom(butler.get('raw_filename', {'visit': visit, 'ccd': 0})[0]))
    title.append(r'$\langle$FWHM$\rangle %4.2f$"' % np.median(fwhmArr))
    plt.title("%s visit=%s" % (" ".join(title), visit), fontsize=9)

    return plt
Exemplo n.º 11
0
def showPsf(psf,
            set,
            ext=None,
            wcsData=None,
            trim=0,
            nspot=5,
            diagnostics=False,
            outDir="",
            frame=None,
            title=None):
    """Show a PSF on display (e.g., ds9)
    """

    if ext is not None:
        psf = psf[ext]

    if wcsData:
        if ext is not None:
            wcsData = wcsData[ext]
        wcs, naxis1, naxis2 = wcsData
    else:
        wcs, naxis1, naxis2 = None, None, None

    naxis = [naxis1, naxis2]
    for i in range(2):
        if naxis[i] is None:
            # cmin, cmax are the range of input star positions
            cmin, cmax = [
                set.getContextOffset(i) + d * set.getContextScale(i)
                for d in (-0.5, 0.5)
            ]
            naxis[i] = cmax + cmin  # a decent guess

    if naxis[0] > naxis[1]:
        nx, ny = int(nspot * naxis[0] / float(naxis[1]) + 0.5), nspot
    else:
        nx, ny = nspot, int(nspot * naxis[1] / float(naxis[0]) + 0.5)

    mos = afwDisplay.utils.Mosaic(gutter=2, background=0.02)

    xpos, ypos = np.linspace(0, naxis[0], nx), np.linspace(0, naxis[1], ny)
    for y in ypos:
        for x in xpos:
            psf.build(x, y)

            im = afwImage.ImageF(*psf.getLoc().shape)
            im.getArray()[:] = psf.getLoc()
            im /= float(im.getArray().max())
            if trim:
                if trim > im.getHeight() // 2:
                    trim = im.getHeight() // 2

                im = im[trim:-trim, trim:-trim]

            mos.append(im)

    mosaic = mos.makeMosaic(mode=nx)
    if frame is not None:
        afwDisplay.Display(frame=frame).mtv(mosaic, title=title)
    #
    # Figure out the WCS for the mosaic
    #
    pos = []
    pos.append([geom.PointD(0, 0), wcs.pixelToSky(geom.PointD(0, 0))])
    pos.append([
        geom.PointD(*mosaic.getDimensions()),
        wcs.pixelToSky(geom.PointD(naxis1, naxis2))
    ])

    CD = []
    for i in range(2):
        delta = pos[1][1][i].asDegrees() - pos[0][1][i].asDegrees()
        CD.append(delta / (pos[1][0][i] - pos[0][0][i]))
    CD = np.array(CD)
    CD.shape = (2, 2)
    mosWcs = afwGeom.makeSkyWcs(crval=pos[0][0], crpix=pos[0][1], cdMatrix=CD)

    if ext is not None:
        title = "%s-%d" % (title, ext)

    if frame is not None:
        afwDisplay.Display(frame=frame).mtv(mosaic, title=title, wcs=mosWcs)

    if diagnostics:
        outFile = "%s-mod.fits" % title
        if outDir:
            outFile = os.path.join(outDir, outFile)
        mosaic.writeFits(outFile, mosWcs.getFitsMetadata())

    mos = afwDisplay.utils.Mosaic(gutter=4, background=0.002)
    for i in range(set.getNsample()):
        s = set.getSample(i)
        if ext is not None and s.getExtindex() != ext:
            continue

        smos = afwDisplay.utils.Mosaic(gutter=2, background=-0.003)
        for func in [s.getVig, s.getVigResi]:
            arr = func()
            if func == s.getVig:
                norm = float(arr.max()) if True else s.getNorm()

            arr /= norm
            im = afwImage.ImageF(*arr.shape)
            im.getArray()[:] = arr
            smos.append(im)

        mos.append(smos.makeMosaic(mode="x"))

    mosaic = mos.makeMosaic(title=title)

    if frame is not None:
        afwDisplay.Display(frame=frame + 1).mtv(mosaic, title=title)

    if diagnostics:
        outFile = "%s-psfstars.fits" % title
        if outDir:
            outFile = os.path.join(outDir, outFile)

        mosaic.writeFits(outFile)
Exemplo n.º 12
0
def main(update_euler, use_obs_euler):
    '''
    A program to perform updates to the content of 
    focalplanelayout.txt and segmentation.txt
    
    # read all the lines to a list.
    # as a base for all changes is the copy of segmentation.txt from before I started 
    # to change anything that had to do with orientation,
    # i.e. as of v1.0.4 https://github.com/lsst-ts/phosim_syseng4/releases/tag/v1.0.4 

    # The geometry update for LSSTCam was https://github.com/lsst-ts/phosim_syseng4/releases/tag/v1.0.5
    # The geometry update for LSSTComCam was https://github.com/lsst-ts/phosim_syseng4/releases/tag/v1.0.6
    # Fix gain, variance for LSSTComCam https://github.com/lsst-ts/phosim_syseng4/releases/tag/v1.0.7 


    ###########################################
    #                                         # 
    #  Update focalplanelayout for lsstCam    #
    #                                         #
    ###########################################


    '''
    camera = LsstCam().getCamera()

    # Need to store each line of the other focalplanelayout to convey the zernike perturbations ...
    headerLines, contentLinesZer = up.readFile(
        '/project/scichris/aos/phosim_syseng4/data/lsst/focalplanelayout_old.txt'
    )

    splitLinesZerDic = {}
    for line in contentLinesZer:
        splitLinesZerDic[line.split()
                         [0]] = line.split()  # sensor name is the key

    # read the file and split into two lists
    headerLines, contentLines = up.readFile(
        '/project/scichris/aos/phosim_syseng4/data/lsst/focalplanelayout_old.txt'
    )

    # UPDATE EULER ANGLE?
    #update_euler = True

    # RESHUFFLE OFF-DIAGONAL SENSORS
    reshuffle_sensors = False

    if update_euler:
        print('Updating Euler angle ')
        ticket_number = 'DM-30367'  # both: obs_lsst orientation
    else:
        if use_obs_euler:
            print('Using obs_lsst Euler angle')
            ticket_number = 'DM-30367'
        else:
            print('Keeping  original Euler angle')
            ticket_number = 'DM-28557'  # lsstCam

    if reshuffle_sensors:
        print('Reshuffle sensors')
        ticket_number = 'DM-30367'

    # update the content
    newContentLines = []
    for line in contentLines:
        splitContent = line.split()
        newSplitContent = splitContent.copy()

        # update the sensor name
        sensorName = splitContent[0]
        newName = up.getNewSensorName(sensorName)

        newSplitContent[0] = newName

        # update the defocal shift
        deformationCoeff = splitContent[19]
        defCoeff = float(deformationCoeff)
        if abs(defCoeff) > 10:
            sgn = np.sign(defCoeff)  # change +/- 1000 to +/- 1500
            newDeformationCoeff = str(defCoeff + sgn * 500.0)
            #print(newDeformationCoeff)
            newSplitContent[19] = newDeformationCoeff

        # update the x,y position
        detector = camera.get(newName)
        bbox = detector.getBBox()
        xc_px, yc_px = bbox.centerX, bbox.centerY
        xc_mm, yc_mm = detector.transform(geom.PointD(xc_px, yc_px),
                                          cameraGeom.PIXELS,
                                          cameraGeom.FOCAL_PLANE)

        xc_microns, yc_microns = 1000 * xc_mm, 1000 * yc_mm
        xpos, ypos = float(splitContent[1]), float(splitContent[2])
        #print(xpos, ypos, '-->',
        #      yp_microns, xp_microns,
        #      'dx:', xpos - yp_microns,
        #      'dy:', ypos-xp_microns)
        newSplitContent[1] = str(round(yc_microns, 2))
        newSplitContent[2] = str(round(xc_microns, 2))

        # update the number of  x px, y px
        xpx, ypx = splitContent[4], splitContent[5]

        xnew, ynew = bbox.getHeight(), bbox.getWidth(
        )  # rotated wrt lsstCam ...
        newSplitContent[4] = str(xnew)
        newSplitContent[5] = str(ynew)

        # Update Euler angles for corner sensors only
        if update_euler:
            corner_rotations = {
                'R04_SW0': 180,
                'R40_SW0': 180,
                'R44_SW0': 180,
                'R00_SW0': 180
            }
            if newName in corner_rotations.keys():
                eulerAngle1 = float(splitContent[12])
                rotation = corner_rotations[newName]
                newEulerAngle1 = eulerAngle1 + rotation
                print(
                    f'For {newName} changed from {eulerAngle1} to {newEulerAngle1}'
                )
                newSplitContent[12] = str(newEulerAngle1)
        if use_obs_euler:
            yaw = -detector.getOrientation().getYaw().asDegrees()
            newSplitContent[12] = str(yaw)

        # update the dx, dy - since we know the actual position, set these to 0 ...
        dx, dy, dz = float(splitContent[15]), float(splitContent[16]), float(
            splitContent[17])
        newSplitContent[15] = '0'  # <-- set dx to 0
        newSplitContent[16] = '0'  # <-- set dy to 0

        # change sensor.txt to zern, and append all parts that follow...
        # that way I can also use the 'new' format of focalplanelayout,
        # changing all after 'sensor.txt' to zern and the coefficients ...
        newSplitContent[18] = 'zern'
        newSplitContent[20:] = splitLinesZerDic[sensorName][20:]

        if reshuffle_sensors:
            raftName, sensorName = newName.split('_')
            sensorNameMap = {
                'S01': 'S10',
                'S02': 'S20',
                'S12': 'S21',
                'S21': 'S12',
                'S10': 'S01',
                'S20': 'S02'
            }
            if sensorName in sensorNameMap.keys():

                newSensorName = sensorNameMap[sensorName]
                updatedName = f'{raftName}_{newSensorName}'
                newSplitContent[0] = updatedName
                print('\n Changed ', newName, ' to ', updatedName)

        # append updated line
        newContentLines.append(' '.join(newSplitContent) + '\n')

    # store the updated version: the header and  updated  content lines
    fname = f"/project/scichris/aos/phosim_syseng4/data/lsst/focalplanelayout_{ticket_number}.txt"
    f = open(fname, "w")
    f.writelines(headerLines)
    f.writelines(newContentLines)
    f.close()
    print('Saved as %s' % fname)