def getDECamCorners(header):
    """
    Get the DECam profile corners for a given header and WCS
    """

    wcs = wcsutil.WCS(header)
    nx = header['NAXIS1']
    ny = header['NAXIS2']
    ra0, dec0 = wcs.image2sky(nx / 2.0, ny / 2.0)
    DECam_header = createDECam_TANheader(ra0, dec0)
    DECam_wcs = wcsutil.WCS(DECam_header)
    r, d = DECam_wcs.image2sky(DECAM_CORNERS_X, DECAM_CORNERS_Y)
    x, y = wcs.sky2image(r, d)
    return x, y
def drawDECamCorners_Sky(ra,
                         dec,
                         pixscale=0.27,
                         label=False,
                         units='deg',
                         **kwargs):
    """
    Draws DECam Corners on the sky (RA,DEC) using matplotlib Plot function
    on the current plot
    """

    header = createDECam_TANheader(ra, dec, pixscale=pixscale)
    wcs = wcsutil.WCS(header)

    r, d = wcs.image2sky(DECAM_CORNERS_X, DECAM_CORNERS_Y)  # Into RA,DEC
    ax = plt.gca()

    if units == 'rad':
        r, d = deg2rad(r, d)

    ax.plot(r, d, **kwargs)

    if label:  # Probably will never use
        if units == 'rad':
            r0, d0 = deg2rad(numpy.array([ra]), numpy.array([dec]))
        else:
            r0, d0 = ra, dec
        ax.text(r0, d0, label, ha='center', va='center')
    return
def drawDECamCCDs_Sky(ra,
                      dec,
                      trim=True,
                      pixscale=0.27,
                      label=False,
                      **kwargs):
    """
    Draws DECam CCDs on the sky (RA,DEC) using matplotlib Plot function on
    the current plot
    """

    header = createDECam_TANheader(ra, dec, pixscale=pixscale)
    wcs = wcsutil.WCS(header)

    ax = plt.gca()
    if trim:
        SECTIONS = TRIM_CCDSECTIONS
    else:
        SECTIONS = CCDSECTIONS
    for k, v in list(SECTIONS.items()):
        (x1, x2, y1, y2) = v
        x = numpy.array([x1, x2, x2, x1, x1])
        y = numpy.array([y1, y1, y2, y2, y1])
        r, d = wcs.image2sky(x, y)  # Into RA,DEC
        ax.plot(r, d, **kwargs)
        if label:  # Probably will never use
            r1, d1 = wcs.image2sky(x1, y1)
            r2, d2 = wcs.image2sky(x2, y2)
            ax.text(0.5 * (r2 + r1),
                    0.5 * (d2 + d1),
                    "CCD%s" % k,
                    ha='center',
                    va='center')
    return
Beispiel #4
0
    def produce(self, RAS, DecS):
        outpath = os.path.normpath(self.outfile)
        outdir = os.path.dirname(self.outfile)
        if not os.path.exists(outdir):
            os.makedirs(outdir)
        if os.path.exists(outpath):
            os.remove(outpath)
        self.RA = string.atof(RAS)
        self.Dec = string.atof(DecS)
        if not os.path.exists(self.infile):
            self.posX = 0.
            self.posY = 0.
            return
        fitsfile = os.path.normpath(self.infile)
        fits = fitsio.FITS(fitsfile)
        if fitsfile.find('.fz') > 0:
            prihdr = fits[1].read_header()
            self.ncol = prihdr['ZNAXIS1']
            self.nrow = prihdr['ZNAXIS2']
            data1 = fits[self.ext + 1].read()
        else:
            prihdr = fits[0].read_header()
            self.ncol = prihdr['NAXIS1']
            self.nrow = prihdr['NAXIS2']
            data1 = fits[self.ext].read()

        w = wcsutil.WCS(prihdr)
        objx, objy = w.sky2image(self.RA, self.Dec)
        self.posX = objx
        self.posY = objy

        data = self.makeStamp(data1, objx, objy)

        self.writeStamp(data, prihdr)
def getDECamCCDs(header, plot=False, trim=True, **kwargs):
    """
    Get the x,y positions of the DECam CCDs for a given header
    with WCS and plot them (optional)
    """

    wcs = wcsutil.WCS(header)
    nx = header['NAXIS1']
    ny = header['NAXIS2']
    ra0, dec0 = wcs.image2sky(nx / 2.0, ny / 2.0)
    DECam_header = createDECam_TANheader(ra0, dec0)
    DECam_wcs = wcsutil.WCS(DECam_header)

    if plot:
        ax = plt.gca()
    if trim:
        SECTIONS = TRIM_CCDSECTIONS
    else:
        SECTIONS = CCDSECTIONS

    ccds = {}
    for k, v in list(SECTIONS.items()):
        (x1, x2, y1, y2) = v
        if plot:
            DECam_x = [x1, x2, x2, x1, x1]
            DECam_y = [y1, y1, y2, y2, y1]
            r_plot, d_plot = DECam_wcs.image2sky(DECam_x,
                                                 DECam_y)  # Into RA,DEC
            x_plot, y_plot = wcs.sky2image(r_plot, d_plot)
            ax.plot(x_plot, y_plot, **kwargs)

        r, d = DECam_wcs.image2sky([x1, x2], [y1, y2])
        x, y = wcs.sky2image(r, d)
        # Make the the interger (pixels)
        x = numpy.ceil(x).astype(int)
        y = numpy.ceil(y).astype(int)
        # Sort them to get the slices right
        x.sort()
        y.sort()
        ccds[k] = x.tolist(), y.tolist()  # We get back lists
    return ccds
Beispiel #6
0
def DESDM_corners(hdr, border=0):
    """ set the DESDM corners
        DESDM CCD Image Corner Coordinates definitions for DECam
        see: https://desdb.cosmology.illinois.edu/confluence/display/PUB/CCD+Image+Corners+Coordinates


                         x-axis
          (RA4,DEC4)                   (RA3,DEC3)
          Corner 4 +-----------------+ Corner 3
        (1,NAXIS2) |                 | (NAXIS1,NAXIS2)
                   |                 |
                   |                 |
                   |                 |
                   |                 |
                   |                 |
                   |                 |
                   |                 |
                   |                 |   y-axis
                   |                 |
                   |                 |
                   |                 |
                   |                 |
                   |                 |
                   |                 |
         (RA1,DEC1)|                 | (RA2,DEC2)
          Corner 1 +-----------------+ Corner 2
             (1,1)                     (NAXIS1,1)

        For fpacked images, NAXIS1/NAXIS2 do not represent the true
        dimensions of the image, so we need to use ZNAXIS1/ZNAXIS2
        instead when they are present.
    """
    if hdr.get('znaxis1') and  hdr.get('znaxis2'):
        nx = hdr['znaxis1']
        ny = hdr['znaxis2']
    else:
        nx = hdr['naxis1']
        ny = hdr['naxis2']
    wcs = wcsutil.WCS(hdr)
    rac1, decc1 = wcs.image2sky(1 + border, 1 + border)
    rac2, decc2 = wcs.image2sky(nx - border, 1 + border)
    rac3, decc3 = wcs.image2sky(nx - border, ny - border)
    rac4, decc4 = wcs.image2sky(1 + border, ny - border)
    ra0, dec0 = wcs.image2sky(nx / 2.0, ny / 2.0)
    return ra0, dec0, rac1, decc1, rac2, decc2, rac3, decc3, rac4, decc4
Beispiel #7
0
def update_wcs_matrix(header, x0, y0, naxis1, naxis2):
    """
    Update the wcs header object with the right CRPIX[1,2] CRVAL[1,2] for a given subsection
    """
    # We need to make a deep copy/otherwise if fails
    h = copy.deepcopy(header)
    # Get the wcs object
    wcs = wcsutil.WCS(h)
    # Recompute CRVAL1/2 on the new center x0,y0
    CRVAL1, CRVAL2 = wcs.image2sky(x0, y0)
    # Asign CRPIX1/2 on the new image
    CRPIX1 = int(naxis1 / 2.0)
    CRPIX2 = int(naxis2 / 2.0)
    # Update the values
    h['CRVAL1'] = CRVAL1
    h['CRVAL2'] = CRVAL2
    h['CRPIX1'] = CRPIX1
    h['CRPIX2'] = CRPIX2
    return h
Beispiel #8
0
def worker(image, return_dict, procnum):
    #Read image header and get coordinates of the image

    print(i, 'working with image', image)
    hdr = pf.open(image)
    w = astrowcs.WCS(hdr[1].header)
    corners_image = w.calc_footprint(center=False)
    corners_pixels = w.calc_footprint(center=True)
    nx = hdr[1].header['naxis1']
    ny = hdr[1].header['naxis2']

    coords1 = corners_image[0]
    coords2 = corners_image[1]
    coords3 = corners_image[2]
    coords4 = corners_image[3]
    #Read image data
    image_data = pf.getdata(image)

    #Define healsparse polygon within the image
    ra = [coords1[0], coords4[0], coords3[0], coords2[0]]
    dec = [coords1[1], coords4[1], coords3[1], coords2[1]]
    raC = (np.max(ra) + np.min(ra)) / 2.
    decC = (np.max(dec) + np.min(dec)) / 2.

    nside = 2**17
    poly = hs.Polygon(ra=ra, dec=dec, value=1)
    smap = poly.get_map(nside=nside, dtype=np.int16)
    a = smap.validPixels

    b = hp.nest2ring(nside, a)
    #a are pixels in NEST, b in RING
    #Get center coordinates of each pixel
    raF, decF = hp.pix2ang(nside, a, lonlat=True, nest=True)

    #Get nx, ny in image from healsparse pixels
    myhdr = hdr[1].header
    wcs = wc.WCS(myhdr)
    xn, yn = wcs.sky2image(raF, decF)
    #Get associated weight values
    values = []
    for x, y in zip(xn, yn):

        values.append(image_data[int(y - 1), int(x - 1)])

    values = np.array(values)
    #Define healsparse map
    hsp_map_2 = hs.HealSparseMap.makeEmpty(512, nside, dtype=np.int16)

    hsp_map_2.updateValues(a, values)

    #Degrade to nside=4096
    low_res_hsp = hsp_map_2.degrade(4096)

    j = low_res_hsp.validPixels

    test_values_2 = low_res_hsp.getValuePixel(j)

    #Uncomment if you want in RING format
    #k=hp.nest2ring(4096,j)

    #hp_aux = np.zeros(hp.nside2npix(4096))+hp.UNSEEN
    #hp_aux[j] = test_values_2

    hdr.close()

    return_dict[procnum] = np.array([j, test_values_2]).transpose()
Beispiel #9
0
    def __call__(cls,
                 streak_list,
                 image_list,
                 streak_name_in,
                 streak_name_out,
                 image_name_in,
                 image_name_out,
                 add_width,
                 max_extrapolate,
                 plotfile=None):
        """
        Read input list of streak detections and predict where a streak
        crossed a CCD but was missed.  Then create new copies of images,
        altering masks to set STREAK bit in new streaks.

        :Parameters:
            - `streak_list`: list of input streak file names
            - `image_list`: list of names of image files to be updated
            - `streak_name_in`: string to replace in input streak filenames
            - `streak_name_out`: replacement string for output streak filenames
            - `image_name_in`: string to replace in input image filenames
            - `image_name_out`: replacement string for output image filenames
            - `add_width`:  number of pixels to grow (or shrink) streak width
            - `max_extrapolate`: farthest to start a new streak from endpoint of an existing one (degrees)
            - `plotfile`: if given, a diagram of streaks is drawn into this file
        """

        logger.info('Reading {:d} streak files'.format(len(streak_list)))

        # Read in all the streak RA/Dec, into a dictionary keyed by CCDNUM,
        # which should be in the primary header.  Also save a dictionary of
        # the file names for these
        streak_corners = {}
        streak_names = {}
        for streakfile in streak_list:
            logger.info(f"Reading streak file {streakfile}")
            with fitsio.FITS(streakfile, 'r') as fits:
                ccdnum = fits[0].read_header()['CCDNUM']
                streak_names[ccdnum] = streakfile
                tab = fits[1].read()
                if len(tab) > 0:
                    streak_corners[ccdnum] = fits[1].read()['CORNERS_WCS']

        logger.info('Reading WCS from {:d} CCDs'.format(len(image_list)))

        # Read in the WCS for each CCD for which we have an image,
        # also put into dicts keyed by CCDNUM
        # Will get these directly from FITS instead of using DESImage in order
        # to save reading all of the data.
        wcs = {}
        crval1 = []
        crval2 = []
        for imgfile in image_list:
            try:
                hdr = fitsio.read_header(imgfile, 0)
                ccd = hdr['CCDNUM']
                crval1.append(hdr['CRVAL1'])
                crval2.append(hdr['CRVAL2'])
                # Due to a bug in fitsio 1.0.0rc1+0, we need to clean up the
                # header before feeding it to wcsutil and remove the 'None' and other problematic items
                for k in hdr:
                    # Try to access the item, if failed we have to remove it
                    if not k:
                        hdr.delete(k)
                        continue
                    try:
                        _ = hdr[k]
                    except:
                        logger.info(
                            "Removing keyword: {:s} from header".format(k))
                        hdr.delete(k)
                wcs[ccd] = wcsutil.WCS(hdr)
            except Exception as e:
                print(e)  ###
                logger.error('Failure reading WCS from {:s}'.format(imgfile))
                return 1

        # Determine a center for local gnomonic projection
        ra0 = np.median(crval1)
        dec0 = np.median(crval2)

        # Calculate upper and lower bounds of each CCD in the local
        # gnomonic system.
        ccd_x1 = np.zeros(63, dtype=float)
        ccd_x2 = np.zeros(63, dtype=float)
        ccd_y1 = np.zeros(63, dtype=float)
        ccd_y2 = np.zeros(63, dtype=float)

        ccd_xmin = 1.
        ccd_xmax = 2048.
        ccd_ymin = 1.
        ccd_ymax = 4096.
        ccd_corners_xpix = np.array([ccd_xmin, ccd_xmin, ccd_xmax, ccd_xmax])
        ccd_corners_ypix = np.array([ccd_ymin, ccd_ymax, ccd_ymax, ccd_ymin])
        for ccd, w in wcs.items():
            ra, dec = w.image2sky(ccd_corners_xpix, ccd_corners_ypix)
            x_corners, y_corners = gnomonic(ra, dec, ra0, dec0)
            ccd_x1[ccd] = np.min(x_corners)
            ccd_y1[ccd] = np.min(y_corners)
            ccd_x2[ccd] = np.max(x_corners)
            ccd_y2[ccd] = np.max(y_corners)

        # Now collect information on all of the streak segments that we have
        ccdnum = []
        ra_corner = []
        dec_corner = []

        for ccd, streaks in streak_corners.items():
            if ccd not in wcs:
                # Skip segments on CCDs that have no WCS
                logger.warning(
                    'No WCS found for streaks on CCD {:d}'.format(ccd))
                continue
            n1, _, _ = streaks.shape
            for i in range(n1):
                ccdnum.append(ccd)
                ra_corner.append(streaks[i, :, 0])
                dec_corner.append(streaks[i, :, 1])
        # Put streak corners into gnomonic system for this exposure
        x1, y1 = gnomonic(np.array([r[0] for r in ra_corner], dtype=float),
                          np.array([d[0] for d in dec_corner], dtype=float),
                          ra0, dec0)
        x2, y2 = gnomonic(np.array([r[1] for r in ra_corner], dtype=float),
                          np.array([d[1] for d in dec_corner], dtype=float),
                          ra0, dec0)
        x3, y3 = gnomonic(np.array([r[2] for r in ra_corner], dtype=float),
                          np.array([d[2] for d in dec_corner], dtype=float),
                          ra0, dec0)
        x4, y4 = gnomonic(np.array([r[3] for r in ra_corner], dtype=float),
                          np.array([d[3] for d in dec_corner], dtype=float),
                          ra0, dec0)
        ccdnum = np.array(ccdnum, dtype=int)

        # Describe each segmet by two endpoints at the midpoints of short sides
        # Will need to decide which is the short side
        d12 = np.hypot(x2 - x1, y2 - y1)
        d23 = np.hypot(x3 - x2, y3 - y2)
        xleft = np.where(d12 < d23, 0.5 * (x1 + x2), 0.5 * (x2 + x3))
        yleft = np.where(d12 < d23, 0.5 * (y1 + y2), 0.5 * (y2 + y3))
        xright = np.where(d12 < d23, 0.5 * (x3 + x4), 0.5 * (x4 + x1))
        yright = np.where(d12 < d23, 0.5 * (y3 + y4), 0.5 * (y4 + y1))
        dx = xright - xleft
        dy = yright - yleft
        # Calculate a width as 2x the
        # largest perp distance from a vertex to this line
        w1 = np.abs(dx * (y1 - yleft) - dy * (x1 - xleft)) / np.hypot(dx, dy)
        w2 = np.abs(dx * (y2 - yleft) - dy * (x2 - xleft)) / np.hypot(dx, dy)
        w3 = np.abs(dx * (y3 - yleft) - dy * (x3 - xleft)) / np.hypot(dx, dy)
        w4 = np.abs(dx * (y4 - yleft) - dy * (x4 - xleft)) / np.hypot(dx, dy)
        wmax = np.maximum(w1, w2)
        wmax = np.maximum(wmax, w3)
        wmax = np.maximum(wmax, w4)
        wmax = 2 * wmax

        # Rearrange so that xleft <= xright
        swapit = xright < xleft
        tmp = np.where(swapit, xleft, xright)
        xleft = np.where(swapit, xright, xleft)
        xright = np.array(tmp)
        tmp = np.where(swapit, yleft, yright)
        yleft = np.where(swapit, yright, yleft)
        yright = np.array(tmp)

        # Get the crossing points of the lines into CCDs
        xc1, xc2, yc1, yc2 = boxCross(xleft, yleft, dx, dy, ccd_x1[ccdnum],
                                      ccd_x2[ccdnum], ccd_y1[ccdnum],
                                      ccd_y2[ccdnum])

        # Get rid of segments that appear to miss their host CCDs
        miss = xc2 < xc1

        # Take 1st crossing point instead of left point if it has higher x, or vertical
        # with higher y, i.e. truncate the track segment at the edge of the CCD.
        replace = np.where(dx == 0, yc1 > yleft, xc1 > xleft)
        xc1 = np.where(replace, xc1, xleft)
        yc1 = np.where(replace, yc1, yleft)
        # Likewise truncate segment at right-hand crossing
        replace = np.where(dx == 0, yc2 < yright, xc2 < xright)
        xc2 = np.where(replace, xc2, xright)
        yc2 = np.where(replace, yc2, yright)

        # Backfill the non-intersections again - note that above
        # maneuvers will leave xc2<xc1 for streaks that miss their CCDs,
        # unless vertical ???
        xc1[miss] = 0.
        xc2[miss] = -1.

        # Get a final verdict on hit or miss
        miss = np.where(dx == 0, yc2 < yc1, xc2 < xc1)

        # Save information on all valid streaks
        xc1 = xc1[~miss]
        xc2 = xc2[~miss]
        yc1 = yc1[~miss]
        yc2 = yc2[~miss]
        wmax = wmax[~miss]
        ccdnum = ccdnum[~miss]

        # Express segments as slopes and midpoints
        dx = xc2 - xc1
        dy = yc2 - yc1
        mx = dx / np.hypot(dx, dy)
        my = dy / np.hypot(dx, dy)

        # Mark segments that are probably spurious edge detections
        EDGE_SLOPE = 2.  # Degrees from horizontal for edge streaks
        EDGE_DISTANCE = 0.005  # Max degrees from streak center to CCD edge for spurious streaks
        horizontal = np.abs(my) < np.sin(EDGE_SLOPE * np.pi / 180.)
        ymid = 0.5 * (yc1 + yc2)
        nearedge = np.logical_or(ccd_y2[ccdnum] - ymid < EDGE_DISTANCE,
                                 ymid - ccd_y1[ccdnum] < EDGE_DISTANCE)
        nearedge = np.logical_and(nearedge, horizontal)

        # Check short edges too
        vertical = np.abs(mx) < np.sin(EDGE_SLOPE * np.pi / 180.)
        xmid = 0.5 * (xc1 + xc2)
        tmp = np.logical_or(ccd_x2[ccdnum] - xmid < EDGE_DISTANCE,
                            xmid - ccd_x1[ccdnum] < EDGE_DISTANCE)
        nearedge = np.logical_or(nearedge, np.logical_and(tmp, vertical))

        # Decide which segments are "friends" of each other.
        # To be a friend, the center of each must be close
        # to the extension of the line of the other.
        # Accumulate a list of tracks, each track is a list of
        # individual streaks that are friends of friends
        tracks = []

        for i in range(len(xc1)):
            if nearedge[i]:
                continue  # Do not use edge tracks
            itstrack = [i]  # start new track with just this
            for t in tracks:
                # Search other tracks for friends
                for j in t:
                    if friends(xc1, xc2, yc1, yc2, mx, my, ccdnum, i, j):
                        itstrack += t  # Merge track
                        tracks.remove(t)  # Get rid of old one
                        break  # No need to check others
            tracks.append(itstrack)

        # Now iterate through tracks, seeing if they have missing segments
        # Create arrays to hold information on new tracks
        new_ccdnum = []
        new_xc1 = []
        new_xc2 = []
        new_yc1 = []
        new_yc2 = []
        new_ra1 = []
        new_ra2 = []
        new_dec1 = []
        new_dec2 = []
        new_width = []
        new_extrapolated = []
        new_nearest = []

        for t in tracks:
            if len(t) < 2:
                continue  # Do not extrapolate singlet tracks
            ids = np.array(
                t)  # Make an array of indices of segments in this track
            # Fit a quadratic path to the streak endpoints
            xx = np.concatenate((xc1[ids], xc2[ids]))
            yy = np.concatenate((yc1[ids], yc2[ids]))

            # If the track slope is mostly along x, then we'll have the independent
            # variable xx be x and dependent yy will be y.  But if track
            # is more vertical, then we'll look at functions x(y) instead.
            xOrder = np.median(np.abs(mx[ids])) > np.median(np.abs(my[ids]))
            if not xOrder:
                xx, yy = yy, xx

            # Record limits of detected tracks' independent variable
            xxmin = np.min(xx)
            xxmax = np.max(xx)

            # Fit a quadratic to the points, or
            # linear if only one streak
            # Allow up to nclip points to clip
            RESID_TOLERANCE = 6. / 3600.  # Clip >6" deviants
            nclip = 2
            for i in range(nclip + 1):
                if len(xx) > 2:
                    A = np.vstack((np.ones_like(xx), xx, xx * xx))
                else:
                    A = np.vstack((np.ones_like(xx), xx))
                coeffs = np.linalg.lstsq(A.T, yy, rcond=None)[0]
                resid = yy - np.dot(A.T, coeffs)
                j = np.argmax(np.abs(resid))
                if i == nclip or np.abs(resid[j]) < RESID_TOLERANCE:
                    break
                xx = np.delete(xx, j)
                yy = np.delete(yy, j)

            # Calculate the y(x1),y(x2) where tracks
            # cross the left/right of every CCD, then
            # find the ones that will cross CCD's y.

            # These are CCD bounds, with xx being the quadratic's argument
            if xOrder:
                xx1 = ccd_x1
                xx2 = ccd_x2
                yy1 = ccd_y1
                yy2 = ccd_y2
            else:
                xx1 = ccd_y1
                xx2 = ccd_y2
                yy1 = ccd_x1
                yy2 = ccd_x2

            if len(coeffs) == 2:
                A2 = np.vstack((np.ones_like(xx2), xx2)).T
                A1 = np.vstack((np.ones_like(xx1), xx1)).T
            else:
                A2 = np.vstack((np.ones_like(xx2), xx2, xx2 * xx2)).T
                A1 = np.vstack((np.ones_like(xx1), xx1, xx1 * xx1)).T

            # yyc[12] are the dependent coordinate at crossings of xx[12] bounds
            yyc1 = np.dot(A1, coeffs)
            yyc2 = np.dot(A2, coeffs)
            # Now we ask whether the y value of streak at either edge crossing
            # is in the y range of a CCD
            missed = np.logical_or(
                np.maximum(yyc1, yyc2) < yy1,
                np.minimum(yyc1, yyc2) > yy2)
            # Also skip any CCD where we already have a streak
            for iccd in ccdnum[ids]:
                missed[iccd] = True
            missed[0] = True  # There is no CCD0
            missed[61] = True  # Never use this one either, it's always dead

            # Now find intersection of new streaks with edges of their CCDs
            # Define a function for the streak path that we'll use for solving
            def poly(x, coeffs, ysolve):
                y = coeffs[0] + x * coeffs[1]
                if len(coeffs) > 2:
                    y += coeffs[2] * x * x
                return y - ysolve

            EDGE_TOLERANCE = 0.2 / 3600.  # Find x/y of edge to this accuracy (0.2 arcsec)
            for iccd in np.where(~missed)[0]:
                # This is a loop over every CCD that the track crosses but has no detected segment
                # Determine an (xx,yy) pair for its entry and exit from the CCD
                new_yy1 = yyc1[iccd]
                new_yy2 = yyc2[iccd]
                new_xx1 = xx1[iccd]
                new_xx2 = xx2[iccd]
                # left side:
                if new_yy1 < yy1[iccd]:
                    new_xx1 = newton(poly,
                                     new_xx1,
                                     args=(coeffs, yy1[iccd]),
                                     tol=EDGE_TOLERANCE)
                elif new_yy1 > yy2[iccd]:
                    new_xx1 = newton(poly,
                                     new_xx1,
                                     args=(coeffs, yy2[iccd]),
                                     tol=EDGE_TOLERANCE)
                new_yy1 = poly(new_xx1, coeffs, 0.)
                # right side
                if new_yy2 < yy1[iccd]:
                    new_xx2 = newton(poly,
                                     new_xx2,
                                     args=(coeffs, yy1[iccd]),
                                     tol=EDGE_TOLERANCE)
                elif new_yy2 > yy2[iccd]:
                    new_xx2 = newton(poly,
                                     new_xx2,
                                     args=(coeffs, yy2[iccd]),
                                     tol=EDGE_TOLERANCE)
                new_yy2 = poly(new_xx2, coeffs, 0.)
                # Does the solution lie outside the input streaks?
                extrapolated = new_xx1 < xxmin or new_xx2 > xxmax
                width = np.median(wmax[ids])

                # Calculate distance to nearest unclipped streak member
                nearest = min(np.min(np.hypot(xx - new_xx1, yy - new_yy1)),
                              np.min(np.hypot(xx - new_xx2, yy - new_yy2)))

                if not xOrder:
                    # swap xx,yy back if we had y as the independent variable
                    new_xx1, new_yy1 = new_yy1, new_xx1
                    new_xx2, new_yy2 = new_yy2, new_xx2

                # Project the coordinates back to RA, Dec
                ra1, dec1 = gnomonicInverse(new_xx1, new_yy1, ra0, dec0)
                ra2, dec2 = gnomonicInverse(new_xx2, new_yy2, ra0, dec0)

                # Append this streak to list of new ones
                new_ccdnum.append(iccd)
                new_xc1.append(new_xx1)
                new_xc2.append(new_xx2)
                new_yc1.append(new_yy1)
                new_yc2.append(new_yy2)
                new_ra1.append(ra1)
                new_ra2.append(ra2)
                new_dec1.append(dec1)
                new_dec2.append(dec2)
                new_width.append(width)
                new_extrapolated.append(extrapolated)
                new_nearest.append(nearest)

        # Make all lists into arrays
        new_ccdnum = np.array(new_ccdnum, dtype=int)
        new_xc1 = np.array(new_xc1, dtype=float)
        new_xc2 = np.array(new_xc2, dtype=float)
        new_yc1 = np.array(new_yc1, dtype=float)
        new_yc2 = np.array(new_yc2, dtype=float)
        new_ra1 = np.array(new_ra1, dtype=float)
        new_ra2 = np.array(new_ra2, dtype=float)
        new_dec1 = np.array(new_dec1, dtype=float)
        new_dec2 = np.array(new_dec2, dtype=float)
        new_width = np.array(new_width, dtype=float)
        new_extrapolated = np.array(new_extrapolated, dtype=bool)
        new_nearest = np.array(new_nearest, dtype=float)

        # Decide which new segments will be masked
        maskit = np.logical_or(~new_extrapolated,
                               new_nearest <= max_extrapolate)

        logger.info('Identified {:d} missing streak segments for masking'.format(\
                    np.count_nonzero(maskit)))

        # Make the diagnostic plot if desired
        if plotfile is not None:
            pl.figure(figsize=(6, 6))
            pl.xlim(-1.1, 1.1)
            pl.ylim(-1.1, 1.1)
            pl.gca().set_aspect('equal')

            # Draw CCD outlines and numbers
            for ccd, w in wcs.items():
                ra, dec = w.image2sky(ccd_corners_xpix, ccd_corners_ypix)
                x_corners, y_corners = gnomonic(ra, dec, ra0, dec0)
                x = x_corners.tolist()
                y = y_corners.tolist()
                x.append(x[0])
                y.append(y[0])
                pl.plot(x, y, 'k-', label=None)
                x = np.mean(x_corners)
                y = np.mean(y_corners)
                pl.text(x,
                        y,
                        str(ccd),
                        horizontalalignment='center',
                        verticalalignment='center',
                        fontsize=14)

            # Draw input streaks marked as edge
            labelled = False
            for i in np.where(nearedge)[0]:
                x = (xc1[i], xc2[i])
                y = (yc1[i], yc2[i])
                if not labelled:
                    pl.plot(x, y, 'm-', lw=2, label='edge')
                    labelled = True
                else:
                    pl.plot(x, y, 'm-', lw=2, label=None)

            # Draw linked tracks
            s = set()
            for t in tracks:
                if len(t) > 1:
                    s = s.union(set(t))
            labelled = False
            for i in s:
                x = (xc1[i], xc2[i])
                y = (yc1[i], yc2[i])
                if not labelled:
                    pl.plot(x, y, 'b-', lw=2, label='connected')
                    labelled = True
                else:
                    pl.plot(x, y, 'b-', lw=2, label=None)

            # Draw singleton tracks as those that are neither edge nor connected
            s = s.union(set(np.where(nearedge)[0]))
            single = set(range(len(xc1)))
            single = single.difference(s)
            labelled = False
            for i in single:
                x = (xc1[i], xc2[i])
                y = (yc1[i], yc2[i])
                if not labelled:
                    pl.plot(x, y, 'c-', lw=2, label='unconnected')
                    labelled = True
                else:
                    pl.plot(x, y, 'c-', lw=2, label=None)

            # Draw missed tracks that will be masked
            labelled = False
            for i in np.where(maskit)[0]:
                x = (new_xc1[i], new_xc2[i])
                y = (new_yc1[i], new_yc2[i])
                if not labelled:
                    pl.plot(x, y, 'r-', lw=2, label='new masked')
                    labelled = True
                else:
                    pl.plot(x, y, 'r-', lw=2, label=None)

            # Draw missed tracks that will not be masked
            labelled = False
            for i in np.where(~maskit)[0]:
                x = (new_xc1[i], new_xc2[i])
                y = (new_yc1[i], new_yc2[i])
                if not labelled:
                    pl.plot(x, y, 'r:', lw=2, label='new skipped')
                    labelled = True
                else:
                    pl.plot(x, y, 'r:', lw=2, label=None)

            # legend
            pl.legend(framealpha=0.3, fontsize='small')
            pl.savefig(plotfile)

        # Now accumulate pixel coordinates of corners of all new streaks to mask
        added_streak_ccds = []
        added_streak_corners = []

        for id, ccd in enumerate(new_ccdnum):
            ccd = new_ccdnum[id]
            if not maskit[id]:
                continue  # Only proceed with the ones to be masked
            # Get a pixel scale from the WCS, in arcsec/pix
            xmid = np.mean(ccd_corners_xpix)
            ymid = np.mean(ccd_corners_ypix)
            ra, dec = wcs[ccd].image2sky(xmid, ymid)
            ra2, dec2 = wcs[ccd].image2sky(xmid + 1, ymid)
            pixscale = np.hypot(
                np.cos(dec * np.pi / 180.) * (ra - ra2), dec - dec2)

            # width of streak, in pixels
            w = new_width[id] / pixscale + add_width
            if w <= 0.:
                continue  # Don't mask streaks of zero width
            # Make RA/Dec of track endpoints
            x = np.array([new_xc1[id], new_xc2[id]])
            y = np.array([new_yc1[id], new_yc2[id]])
            ra, dec = gnomonicInverse(x, y, ra0, dec0)
            # Convert to pixel coordinates
            x, y = wcs[ccd].sky2image(ra, dec)
            line = Line(x[0], y[0], x[1], y[1])
            # Create bounding rectangle of track
            corners_pix = boxTrack(line, w, ccd_xmin, ccd_xmax, ccd_ymin,
                                   ccd_ymax)
            added_streak_ccds.append(ccd)
            added_streak_corners.append(np.array(corners_pix))

        added_streak_ccds = np.array(added_streak_ccds)

        # Make new copies of streak files, adding new ones
        logger.debug('Rewriting streak files')

        for ccd, streakfile_in in streak_names.items():
            nmatch = len(re.findall(streak_name_in, streakfile_in))
            if nmatch != 1:
                logger.error('Could not update streak file named <' +
                             streakfile_in + '>')
                return 1
            streakfile_out = re.sub(streak_name_in, streak_name_out,
                                    streakfile_in)
            # Use file system to make fresh copy of table's FITS file
            shutil.copy2(streakfile_in, streakfile_out)

            # Find new streaks for this ccd
            add_ids = np.where(added_streak_ccds == ccd)[0]
            if len(add_ids) > 0:
                # Open the table and add new streaks' info
                try:
                    fits = fitsio.FITS(streakfile_out, 'rw')
                    addit = np.recarray(len(add_ids),
                                        dtype=[('LABEL', '>i4'),
                                               ('CORNERS', '>f4', (4, 2)),
                                               ('CORNERS_WCS', '>f8', (4, 2))])
                    if fits[1]['LABEL'][:]:
                        first_label = np.max(fits[1]['LABEL'][:]) + 1
                    else:
                        first_label = 1
                    addit.LABEL = np.arange(first_label,
                                            first_label + len(addit))

                    for i, id in enumerate(add_ids):
                        corners_pix = added_streak_corners[id]
                        addit.CORNERS[i] = corners_pix
                        ra, dec = wcs[ccd].image2sky(corners_pix[:, 0],
                                                     corners_pix[:, 1])
                        addit.CORNERS_WCS[i] = np.vstack((ra, dec)).T

                    fits[1].append(addit)
                    fits.close()
                except Exception as e:
                    print(e)
                    logger.error('Failure updating streak file <{:s}>'.format(
                        streakfile_out))
                    return 1

        logger.debug('Remasking images')

        for imgfile_in in image_list:
            # Make the name needed for output
            nmatch = len(re.findall(image_name_in, imgfile_in))
            if nmatch != 1:
                logger.error(
                    'Could not create output name for image file named <' +
                    imgfile_in + '>')
                return 1
            imgfile_out = re.sub(image_name_in, image_name_out, imgfile_in)

            logger.info(f"Loading image: {imgfile_in}")
            sci = DESImage.load(imgfile_in)
            ccd = sci.header['CCDNUM']

            # Find added streaks for this ccd
            add_ids = np.where(added_streak_ccds == ccd)[0]
            if len(add_ids) > 0:
                shape = sci.mask.shape
                yy, xx = np.indices(shape)
                points = np.vstack((xx.flatten(), yy.flatten())).T
                inside = None

                for id in add_ids:
                    # From Alex's immask routine: mark interior pixels
                    # for each added streak
                    v = added_streak_corners[id]
                    vertices = [(v[0, 0], v[0, 1]), (v[1, 0], v[1, 1]),
                                (v[2, 0], v[2, 1]), (v[3, 0], v[3, 1]),
                                (v[0, 0], v[0, 1])]
                    path = matplotlib.path.Path(vertices)

                    if inside is None:
                        inside = path.contains_points(points)
                    else:
                        inside = np.logical_or(inside,
                                               path.contains_points(points))

                # Make the list of masked pixels
                if inside is None:
                    ymask, xmask = np.array(0, dtype=int), np.array(0,
                                                                    dtype=int)
                else:
                    ymask, xmask = np.nonzero(inside.reshape(shape))

                sci.mask[ymask, xmask] |= parse_badpix_mask('STREAK')

            # Write something into the image header

            sci['DESCNCTS'] = time.asctime(time.localtime()) + \
                            ' Mask {:d} new streaks'.format(len(add_ids))
            #            sci['HISTORY'] = time.asctime(time.localtime()) + \
            #                             ' Mask {:d} new streaks'.format(len(add_ids))
            logger.info(f"Saving to: {imgfile_out}")
            sci.save(imgfile_out)

        logger.info('Finished connecting streaks')
        ret_code = 0
        return ret_code
Beispiel #10
0
    def streakMask(self, streak_file, addWidth=0., addLength=100., maxExtrapolate=0):
        '''
        Produce a list of pixels in the image that should be masked for
        streaks in the input table.  streaktab is the output table of new
        streaks to add image is a FITS HDU, with header and image data
        addWidth is additional number of pixels to add to half-width
        addLength is length added to each end of streak (pixels)

        Returns:
        ypix, xpix: 1d arrays with indices of affected pixels
        nStreaks: number of new streaks masked
        '''

        # Read the streaks table first
        try:
            tab = fitsio.FITS(streak_file)
            streaktab = tab[1].read()
        except:
            logger.error('Could not read streak file {:s}'.format(streak_file))
            sys.exit(1)

        image_header = self.sci.header
        image_data = self.sci.data
        # Pixscale in degrees
        pixscale = astrometry.get_pixelscale(image_header, units='arcsec') / 3600.
        shape = image_data.shape

        # # Due to a bug in fitsio 1.0.0rc1+0, we need to clean up the
        # # header before feeding it to wcsutil and remove the 'None' and other problematic items
        # for k in image_header:
        #     # Try to access the item, if failed we hace to remove it
        #     try:
        #         item = image_header[k]
        #     except:
        #         logger.info("Removing keyword: {:s} from header".format(k))
        #         image_header.delete(k)

        w = wcsutil.WCS(image_header)

        # WE NEED TO UPDATE THIS WHEN THE TABLE IS PER EXPNUM
        use = np.logical_and(streaktab['expnum'] == image_header['EXPNUM'],
                             streaktab['ccdnum'] == image_header['CCDNUM'])
        logger.info('{:d} streaks found to mask'.format(np.count_nonzero(use)))

        nStreaks = 0
        inside = None


        for row in streaktab[use]:
            if maxExtrapolate > 0:
                if row['extrapolated'] and row['nearest'] > maxExtrapolate:
                    logger.info('Skipping extrapolated streak')
                    continue
            width = row['width']
            ra = np.array((row['ra1'], row['ra2']))
            dec = np.array((row['dec1'], row['dec2']))
            x, y = w.sky2image(ra, dec)

            x1, x2, y1, y2 = x[0], x[1], y[0], y[1]

            # Slope of the line, cos/sin form
            mx = (x2 - x1) / np.hypot(x2 - x1, y2 -y1)
            my = (y2 - y1) / np.hypot(x2 - x1, y2 -y1)

            #displacement for width of streak:
            wx = width / pixscale + addWidth
            wy = wx * mx
            wx = wx * -my

            # grow length
            x1 -= addLength * mx
            x2 += addLength * mx
            y1 -= addLength * my
            y2 += addLength * my

            # From Alex's immask routine: mark interior pixels
            vertices = [(x1 + wx, y1 + wy), (x2 + wx, y2 + wy), (x2 - wx, y2 - wy), (x1 - wx, y1 - wy)]
            vertices.append(vertices[0])  # Close the path

            if inside is None:
                # Set up coordinate arrays
                yy, xx = np.indices(shape)
                points = np.vstack((xx.flatten(), yy.flatten())).T
                path = matplotlib.path.Path(vertices)
                inside = path.contains_points(points)
            else:
                # use logical_and for additional streaks
                path = matplotlib.path.Path(vertices)
                inside = np.logical_or(inside, path.contains_points(points))

            nStreaks = nStreaks + 1

        logger.info('Masked {:d} new streaks'.format(nStreaks))

        # Make the list of masked pixels
        if inside is None:
            ymask, xmask = np.array(0, dtype=int), np.array(0, dtype=int)
        else:
            ymask, xmask = np.nonzero(inside.reshape(shape))

        logger.info('Setting bits in MSK image for STREAK: {:d}'.format(parse_badpix_mask('STREAK')))
        self.sci.mask[ymask, xmask] |= parse_badpix_mask('STREAK')
Beispiel #11
0
def fitscutter(filename,
               ra,
               dec,
               xsize=1.0,
               ysize=1.0,
               units='arcmin',
               prefix='DES',
               outdir=os.getcwd(),
               tilename=None,
               verb=False):
    """
    Makes cutouts around ra, dec for a give xsize and ysize
    ra,dec can be scalars or lists/arrays
    """
    # Check and fix inputs
    ra, dec, xsize, ysize = check_inputs(ra, dec, xsize, ysize)

    # Check for the units
    if units == 'arcsec':
        scale = 1
    elif units == 'arcmin':
        scale = 60
    elif units == 'degree':
        scale = 3600
    else:
        sys.exit("ERROR: must define units as arcses/arcmin/degree only")

    # Get header/extensions/hdu
    header, hdunum = get_headers_hdus(filename)
    extnames = header.keys()

    # Now we add the tilename to the headers -- if not already present
    if tilename and 'TILENAME' not in header['SCI']:
        if verb:
            SOUT.write("Will add TILENAME keyword to header for file: %s\n" %
                       filename)
        tile_rec = {
            'name': 'TILENAME',
            'value': tilename,
            'comment': 'Name of DES parent TILENAME'
        }
        for EXTNAME in extnames:
            header[EXTNAME].add_record(tile_rec)

    # Get the pixel-scale of the input image
    pixelscale = astrometry.get_pixelscale(header['SCI'], units='arcsec')

    # Read in the WCS with wcsutil
    wcs = wcsutil.WCS(header['SCI'])

    # Extract the band/filter from the header
    if 'BAND' in header['SCI']:
        band = header['SCI']['BAND'].strip()
    elif 'FILTER' in header['SCI']:
        band = header['SCI']['FILTER'].strip()
    else:
        raise Exception(
            "ERROR: Cannot provide suitable BAND/FILTER from SCI header")

    # Intitialize the FITS object
    ifits = fitsio.FITS(filename, 'r')

    ######################################
    # Loop over ra/dec and xsize,ysize
    for k in range(len(ra)):

        # Define the geometry of the thumbnail
        x0, y0 = wcs.sky2image(ra[k], dec[k])
        yL = 10000
        xL = 10000
        x0 = round(x0)
        y0 = round(y0)
        dx = int(0.5 * xsize[k] * scale / pixelscale)
        dy = int(0.5 * ysize[k] * scale / pixelscale)
        naxis1 = 2 * dx  #+1
        naxis2 = 2 * dy  #+1
        y1 = y0 - dy
        y2 = y0 + dy
        x1 = x0 - dx
        x2 = x0 + dx

        if y1 < 0:
            y1 = 0
            dy = y0
            y2 = y0 + dy
        if y2 > yL:
            y2 = yL
            dy = yL - y0
            y1 = y0 - dy

        if x1 < 0:
            x1 = 0
            dx = x0
            x2 = x0 + dx
        if x2 > xL:
            x2 = xL
            dx = xL - x0
            x1 = x0 - dx

        im_section = OrderedDict()
        h_section = OrderedDict()
        for EXTNAME in extnames:
            # The hdunum for that extname
            HDUNUM = hdunum[EXTNAME]
            # Create a canvas
            im_section[EXTNAME] = numpy.zeros((naxis1, naxis2))
            # Read in the image section we want for SCI/WGT
            im_section[EXTNAME] = ifits[HDUNUM][int(y1):int(y2),
                                                int(x1):int(x2)]
            # Correct NAXIS1 and NAXIS2
            naxis1 = numpy.shape(im_section[EXTNAME])[1]
            naxis2 = numpy.shape(im_section[EXTNAME])[0]
            # Update the WCS in the headers and make a copy
            h_section[EXTNAME] = update_wcs_matrix(header[EXTNAME], x0, y0,
                                                   naxis1, naxis2, ra[k],
                                                   dec[k])

        # Construct the name of the Thumbmail using BAND/FILTER/prefix/etc
        outname = get_thumbFitsName(ra[k],
                                    dec[k],
                                    band,
                                    prefix=prefix,
                                    outdir=outdir)

        # Write out the file
        ofits = fitsio.FITS(outname, 'rw', clobber=True)
        for EXTNAME in extnames:
            ofits.write(im_section[EXTNAME],
                        extname=EXTNAME,
                        header=h_section[EXTNAME])

        ofits.close()
        if verb: SOUT.write("# Wrote: %s\n" % outname)

    return
Beispiel #12
0
    def run(self):
        runstat = 0
        list_file = self.objlist
        outfile = ''
        for line in open(list_file):
            #            line = line.rstrip('\n')
            line = line.rstrip()
            print(' line=%s \n' % line)
            tokens = line.split(',')
            objname = tokens[0]
            self.RA = tokens[1]
            self.Dec = tokens[2]
            byband = {}
            byband['g'] = []
            byband['r'] = []
            byband['i'] = []
            byband['z'] = []
            byband['Y'] = []
            byband['u'] = []
            t0 = timeit.default_timer()
            if not os.path.exists('./' + objname):
                os.mkdir(objname)
            explist = self.makeExpList(self.RA, self.Dec)
            #            print explist
            if len(explist) >= 1:
                query = self.makeQueryString(self.RA, self.Dec, explist)
                #                print query
                try:
                    t1 = timeit.default_timer()
                    self.cur.execute(query)
                    res = self.cur.fetchall()
                    print res
                    t2 = timeit.default_timer()
                    print "Query time=%f \n" % (t2 - t1)
                    if len(res) == 0:
                        print " No records found for object %s \n" % line
                        runstat = -999
                        continue
                    " Create directory if not exists "
                    imperobj = {}
                    for row in res:
                        filename = row[0]
                        band = row[1]
                        ccdnum = row[2]
                        if ccdnum == 'c31': continue
                        nite = row[3]
                        teff = float(row[4])
                        expnum = row[5]
                        rac2 = float(row[6])
                        rac4 = float(row[7])
                        decc2 = float(row[8])
                        decc4 = float(row[9])
                        naxis1 = int(row[10])
                        naxis2 = int(row[11])
                        ra_cent = float(row[12])
                        dec_cent = float(row[13])
                        print "naxis1=%d naxis2=%d ra_cent=%f dec_cent=%f rac2=%f rac4=%f decc2=%f decc4=%f \n" % (
                            naxis1, naxis2, ra_cent, dec_cent, rac2, rac4,
                            decc2, decc4)
                        # unpack filename
                        tokens2 = filename.split('_')
                        Dpart = tokens2[0]  # D00233091
                        band = tokens2[1]
                        ccdnum = tokens2[2]  # c01
                        expnum = string.atoi(Dpart[1:])
                        Year = self.expToYear(expnum)
                        revp = tokens2[3]
                        # r1984p01
                        tokens3 = revp.split('p')
                        rev = (tokens3[0])[1:]
                        proc = "p" + tokens3[1]
                        imrec = [
                            band, teff, ccdnum, nite, expnum, naxis1, naxis2,
                            ra_cent, dec_cent, rev, proc, rac2, rac4, decc2,
                            decc4
                        ]
                        imperobj[filename] = imrec
                    " We have all images in the dictionary lets select best"
                    print imperobj
                    selfiles = self.sortIm(imperobj)
                    print 'Selected files \n'
                    print selfiles

                    for band in selfiles:
                        if len(selfiles[band]) == 0: continue
                        filename = selfiles[band][0]
                        teff = float(selfiles[band][2])
                        ccdnum = selfiles[band][3]
                        nite = selfiles[band][4]
                        expnum = selfiles[band][5]
                        rev = selfiles[band][10]
                        proc = selfiles[band][11]
                        revp = 'r' + rev + 'p' + proc
                        Year = self.expToYear(expnum)
                        ccdnum = selfiles[band][3]

                        ra_cent = float(selfiles[band][8])
                        dec_cent = float(selfiles[band][9])

                        (filepath,
                         comp) = self.makeFilePath(expnum, rev, proc, Year,
                                                   ccdnum)
                        print "band=%s filepath=%s comp=%s \n" % (
                            band, filepath, comp)
                        infile = filepath + '/' + filename
                        if comp == '.fz': infile += comp
                        outfileZ = './' + objname + '/' + filename + '.fz'
                        outfileF = './' + objname + '/' + filename
                        outfile = outfileF
                        #
                        psfFile = Dpart + '_' + band + '_' + ccdnum + '_' + revp + '_psfexcat.psf'
                        outfileP = './' + objname + '/' + psfFile
                        copys = False

                        if self.file_exists(infile):

                            (mag_zero, sigma_mag_zero) = self.getZeropoint(
                                ccdnum, expnum)
                            " throw away bad exposures "
                            if mag_zero == 0. or teff <= 0.3:
                                print "file rejected by mag_zero \n"
                                continue
                            tag = objname + '_' + str(
                                expnum) + '_' + ccdnum + '_' + str(
                                    nite
                                ) + '_' + band + '_' + self.RA + '_' + self.Dec
                            psfFile = filename.split(
                                'immask')[0] + 'psfexcat.psf'
                            outfileP = './' + objname + '/' + psfFile
                            psfpath = filepath.split('red')[0] + 'psf'
                            psfinF = psfpath + '/' + psfFile
                            print "start coping psf file %s \n" % psfinF
                            print " psf path=%s \n" % psfpath
                            stat = self.get_file(self.opener, psfinF, outfileP)
                            print " got the file \n"
                            print stat
                            if comp == '.fz':
                                outfile = outfileZ
                                copys = self.get_file(self.opener, infile,
                                                      outfileZ)
                                if not copys: continue
                                " Now uncompress the file as swarp do not work with .fz "
                                #
                                command = ['funpack', "%s" % outfileZ]
                                try:
                                    subprocess.check_output(command)
                                except subprocess.CalledProcessError as e:
                                    print "error %s" % e

                                outfile = outfileF

                                try:
                                    os.remove(outfileZ)
                                except:
                                    print "remove failed on file %s \n" % outfileZ
                            else:
                                outfile = outfileF
                                copys = self.get_file(infile, outfileF)

                            if not copys: continue
                            stampname = './' + objname + '/' + tag
                            outPSF = './' + objname + '/' + tag + '_psf.fits'
                            filelist = [outfile]
                            self.MakeStamp(filelist, stampname, band, objname)
                            #                            print "After MakeStamp \n"
                            """ Now create PSF """
                            RAV = float(self.RA)
                            DecV = float(self.Dec)
                            print "Start conversion with file %s \n" % stampname + '.fits'
                            fitsfile = os.path.normpath(stampname + '.fits')
                            fits = fitsio.FITS(fitsfile)
                            prihdr = fits[0].read_header()
                            w = wcsutil.WCS(prihdr)
                            #                        print "RA=%f Dec=%f \n" % (RAV,DecV)
                            (objx, objy) = w.sky2image(RAV, DecV)
                            print "objx=%f objy=%f \n" % (objx, objy)

                            try:
                                psfcatF = stampname + '_psfex.psf'
                                print " psfcat.psf=%s outPSF=%s \n" % (psfcatF,
                                                                       outPSF)
                                mkpsf = CreatePSFFile(outfileP, outPSF)
                                mkpsf.setPSFAtt(objname, band)
                                mkpsf.produce(objx, objy)
                                try:
                                    #                                    os.remove(outfileF)
                                    print "Now removing file %s \n" % outfileF
                                except:
                                    print "remove failed on file %s \n" % outfileF
                            except:
                                print " Failed on psf file %s \n" % outPSF
#                            self.clean(filelist,stampname)
                            byband[band].append(
                                (tag, mag_zero, sigma_mag_zero, teff))
                        else:
                            continue

                except:
                    print(' Failed on object %s \n' % objname)
                    print("Unexpected error:", sys.exc_info()[0])
                    runstat += 1
                    continue
            else:
                print " No exposures found for Ra=%s Dec=%s \n" % (self.RA,
                                                                   self.Dec)

            " Now we have cutouts in ./objname subdir lets make fits file "
            if self.restype == '1':
                keys = byband.keys()
                fitsout = objname + '_cutouts.fits'
                if os.path.exists(fitsout):
                    os.remove(fitsout)
                for key in keys:
                    tags = byband.get(key)

                    for t in tags:
                        self.writeResFile(fitsout, objname, t, key)
                shutil.rmtree('./' + objname)
            t3 = timeit.default_timer()

            exectime = float((t3 - t0) / 60.)
            print " end work with line %s  exectime=%.2f min \n" % (line,
                                                                    exectime)

        SystemExit(runstat)
    def cross_RA_zero_center(self):
        """
        Check if crossing the RA=0.0 by the min and max
        values for the centers of all CCDs. We loop over all of the
        wcs of the images... slower (a few secs) but safer in case
        some CCDs are missing.
        """

        d2r = math.pi / 180.  # degrees to radians shorthand
        DECam_width = 2.3  # approx width in degrees

        # Collect the centers of all CCDS first and store to compare later
        # Slowers than asking for particular CCDs, but safer
        print("# Figuring out edges of CCDs")
        t0 = time.time()
        ra0 = []
        dec0 = []
        for filename in self.imgfiles:
            hdr = fitsio.read_header(filename)
            wcs = wcsutil.WCS(hdr)
            nx = hdr['NAXIS1']
            ny = hdr['NAXIS2']
            ra, dec = wcs.image2sky(nx / 2.0, ny / 2.0)
            ra0.append(ra)
            dec0.append(dec)

        self.ra0 = numpy.array(ra0)
        self.dec0 = numpy.array(dec0)

        # Get min and max values
        dec1 = self.dec0.min()
        dec2 = self.dec0.max()
        ra1 = self.ra0.min()
        ra2 = self.ra0.max()

        print(f"# Cross RA examination: {elapsed_time(t0)}")
        dec0 = (dec1 + dec2) / 2.0
        D_ra = abs(ra1 - ra2)
        D_dec = abs(dec1 - dec2)

        # in case ras near 360 have negative values
        # so, we need to check that both ras have the same sign
        if math.copysign(1, ra1) == math.copysign(1, ra2):
            same_sign = True
        else:
            same_sign = False

        # Define the tolerances for ra/dec
        tol_ra = 2.5 * DECam_width / math.cos(dec0 * d2r)
        tol_dec = 2.5 * DECam_width

        # Check WCS solution is sane, by making sure that the distance
        # between ra.min and ra.max or dec.min/dec.max in D > tol and
        # D < 360-tol (for RA)
        if (D_ra > tol_ra and D_ra < 360 - tol_ra) or D_dec > tol_dec:
            print(
                "# ***************************************************************"
            )
            print(
                "# **  WARNING: Distance between CCDs greated that DECam FOV    **"
            )
            print(
                "# **  WARNING: Projection will not be performed -- bye         **"
            )
            print(
                "# ***************************************************************"
            )
            sys.exit()

        # The tolerace for deciding when we crossed RA=0 is ~2x a
        # DECam FOV at the declination
        if D_ra > tol_ra or same_sign is False:
            self.crossRA = True
            print("# *****************************************")
            print("# **  WARNING: exposure crosses RA=0.0   **")
            print("# *****************************************")

            # Bring to zero the values near 360
            idx = numpy.where(self.ra0 > tol_ra)
            self.ra0[idx] = self.ra0[idx] - 360
        else:
            self.crossRA = False
    def read_exposure_catalogs_files(self):
        """ Read the 62 exposure SEx catalogs"""

        # Define the output name
        self.pngfile_ell = f"{self.basename}_ell.png"

        if os.path.exists(self.pngfile_ell) and not self.force:
            print("# PNG/Ell file already exists")
            print("# Skipping PNG/Ell creation")
            return

        t0 = time.time()
        print(f"# Reading {self.pngfile}")

        image = Image.open(self.pngfile).convert("L")
        self.png_array = numpy.asarray(image)
        self.png_array = self.png_array[::-1, :]
        print(f"# Shape (ny,nx): {self.png_array.shape}")
        print(f"# Done in {time.time()-t0} sec.")

        # Figure out the size
        dpi = 90.
        (self.ny, self.nx) = self.png_array.shape
        x_size = float(self.nx) / float(dpi)
        y_size = float(self.ny) / float(dpi)

        pylab.figure(1, figsize=(x_size, y_size))
        pylab.axes([0, 0, 1, 1], frameon=False)
        pylab.imshow(self.png_array,
                     origin='lower',
                     cmap='gray',
                     interpolation='none')
        ec_ima1 = 'red'
        ec_ima2 = 'blue'
        pylab.axis('off')

        i = 0
        t0 = time.time()

        for catfile in self.catlist:
            print(f"# Reading {catfile}")
            tbdata = fitsio.read(catfile, ext=2)
            # Store the Relevant information to draw ellipse
            if i == 0:
                ra = tbdata['ALPHA_J2000']
                dec = tbdata['DELTA_J2000']
                a_image = tbdata['A_IMAGE'] * tbdata['KRON_RADIUS']
                b_image = tbdata['B_IMAGE'] * tbdata['KRON_RADIUS']
                theta = tbdata['THETA_IMAGE']
                imaflag_iso = tbdata['IMAFLAGS_ISO']

            else:
                ra = numpy.append(ra, tbdata['ALPHA_J2000'])
                dec = numpy.append(dec, tbdata['DELTA_J2000'])
                a_image = numpy.append(
                    a_image, tbdata['A_IMAGE'] * tbdata['KRON_RADIUS'])
                b_image = numpy.append(
                    b_image, tbdata['B_IMAGE'] * tbdata['KRON_RADIUS'])
                theta = numpy.append(theta, tbdata['THETA_IMAGE'])
                imaflag_iso = numpy.append(imaflag_iso, tbdata['IMAFLAGS_ISO'])

            i = i + 1

        print(f"# Read {i} SEx catalogs in time: {elapsed_time(t0)}")
        # Now let's put the positions on the projected image
        hdr = fitsio.read_header(self.swarp_outname)
        wcs = wcsutil.WCS(hdr)
        x, y = wcs.sky2image(ra, dec)

        # Draw all at once -- faster
        t1 = time.time()
        print(f"# Drawing ellipses for {len(x)} objects")

        # Drawing imaflags > 0 blue and the rest 'red'
        idx1 = numpy.where(imaflag_iso == 0)
        idx2 = numpy.where(imaflag_iso > 0)
        draw.PEllipse_multi((x[idx1], y[idx1]), (a_image[idx1], b_image[idx1]),
                            resolution=60,
                            angle=theta,
                            facecolor='none',
                            edgecolor=ec_ima1,
                            linewidth=0.5)
        draw.PEllipse_multi((x[idx2], y[idx2]), (a_image[idx2], b_image[idx2]),
                            resolution=60,
                            angle=theta,
                            facecolor='none',
                            edgecolor=ec_ima2,
                            linewidth=0.5)
        print(f"# Ellipses draw time: {elapsed_time(t1)}")
        print("# Saving PNG file with ellipses")
        pylab.savefig(self.pngfile_ell, dpi=dpi)
        print("# Done")
        pylab.close()
        return