Ejemplo n.º 1
0
def plot_header(fname, ff, iod_line):
    # ppgplot arrays
    heat_l = np.array([0.0, 0.2, 0.4, 0.6, 1.0])
    heat_r = np.array([0.0, 0.5, 1.0, 1.0, 1.0])
    heat_g = np.array([0.0, 0.0, 0.5, 1.0, 1.0])
    heat_b = np.array([0.0, 0.0, 0.0, 0.3, 1.0])

    # Plot
    ppg.pgopen(fname)
    ppg.pgpap(0.0, 1.0)
    ppg.pgsvp(0.1, 0.95, 0.1, 0.8)

    ppg.pgsch(0.8)
    ppg.pgmtxt("T", 6.0, 0.0, 0.0,
               "UT Date: %.23s  COSPAR ID: %04d" % (ff.nfd, ff.site_id))
    if is_calibrated(ff):
        ppg.pgsci(1)
    else:
        ppg.pgsci(2)
    ppg.pgmtxt(
        "T", 4.8, 0.0, 0.0, "R.A.: %10.5f (%4.1f'') Decl.: %10.5f (%4.1f'')" %
        (ff.crval[0], 3600.0 * ff.crres[0], ff.crval[1], 3600.0 * ff.crres[1]))
    ppg.pgsci(1)
    ppg.pgmtxt("T", 3.6, 0.0, 0.0, ("FoV: %.2f\\(2218)x%.2f\\(2218) "
                                    "Scale: %.2f''x%.2f'' pix\\u-1\\d") %
               (ff.wx, ff.wy, 3600.0 * ff.sx, 3600.0 * ff.sy))
    ppg.pgmtxt(
        "T", 2.4, 0.0, 0.0, "Stat: %5.1f+-%.1f (%.1f-%.1f)" %
        (np.mean(ff.zmax), np.std(ff.zmax), ff.zmaxmin, ff.zmaxmax))
    ppg.pgmtxt("T", 0.3, 0.0, 0.0, iod_line)

    ppg.pgsch(1.0)
    ppg.pgwnad(0.0, ff.nx, 0.0, ff.ny)
    ppg.pglab("x (pix)", "y (pix)", " ")
    ppg.pgctab(heat_l, heat_r, heat_g, heat_b, 5, 1.0, 0.5)
Ejemplo n.º 2
0
def plot2d(z, x=None, y=None, title=None, rangex=None, rangey=None, \
           rangez=None, labx='', laby='', rangex2=None, rangey2=None, \
           labx2='', laby2='', image=ppgplot_palette_, contours=None, \
           logx=0, logy=0, logx2=0, logy2=0, \
           line=ppgplot_linestyle_, width=ppgplot_linewidth_, \
           color=ppgplot_color_, labels=ppgplot_labels_, \
           labelint=ppgplot_labelint_, labelmin=ppgplot_labelmin_, \
           font=ppgplot_font_, id=0, noscale=0, aspect=1, \
           fontsize=ppgplot_font_size_, ticks='out', panels=[1,1], \
           device=ppgplot_device_):
    """
    plot2d(z, ...)
        An interface to make various 2D plots using PGPLOT.
            'z' is the 2D Numpy array to be plotted.
        The optional entries are:
            x:         x values                    (default = 0, 1, ...) 
            y:         y values                    (default = 0, 1, ...) 
            title:     graph title                 (default = None)      
            rangex:    range for the x-axis        (default = automatic) 
            rangey:    range for the y-axis        (default = automatic) 
            rangez:    range for the z-axis        (default = automatic) 
            labx:      label for the x-axis        (default = None)      
            laby:      label for the y-axis        (default = None)      
            rangex2:   range for 2nd x-axis        (default = None)      
            rangey2:   range for 2nd y-axis        (default = None)      
            labx2:     label for the 2nd x-axis    (default = None)      
            laby2:     label for the 2nd y-axis    (default = None)      
            logx:      make the 1st x-axis log     (default = 0 (no))
            logy:      make the 1st y-axis log     (default = 0 (no))
            logx2:     make the 2nd x-axis log     (default = 0 (no))
            logy2:     make the 2nd y-axis log     (default = 0 (no))
            image:     color palette for image     (default = 'rainbow') 
            contours:  list of contour values      (default = None)      
            line:      contour line style          (default = 1 (solid)) 
            width:     contour line width          (default = 1 (thin))  
            color:     contour line color          (default = 'white')   
            labels:    color of contour labels     (default = None)      
            labelint:  contour label spacing       (default = 20)        
            labelmin:  min contour label spacing   (default = 20)        
            font:      PGPLOT font to use          (default = 1 (normal))
            fontsize:  PGPLOT font size to use     (default = 1.0 (normal))
            id:        show ID line on plot        (default = 0 (no))    
            noscale:   turn off auto scaling       (default = 0 (no))    
            aspect:    Aspect ratio                (default = 1 (square))
            ticks:     Ticks point in or out       (default = 'out')   
            panels:    Number of subpanels [r,c]   (default = [1,1])
            device:    PGPLOT device to use        (default = '/XWIN')   
        Note:  Many default values are defined in global variables
            with names like ppgplot_font_ or ppgplot_device_.
    """
    # Make sure the input data is a 2D array
    z = Num.asarray(z);
    if not len(z.shape)==2:
        print 'Input data array must be 2 dimensional.'
        return
    # Announce the global variables we will be using
    global ppgplot_dev_open_, ppgplot_dev_prep_, pgpalette
    # Define the X and Y axis limits if needed
    if x is None: x=Num.arange(z.shape[1], dtype='f')
    else: x = Num.asarray(x)
    if y is None: y=Num.arange(z.shape[0], dtype='f')
    else: y = Num.asarray(y)
    # Determine the scaling to use for the axes
    if rangex is None: rangex=[Num.minimum.reduce(x), \
                             Num.maximum.reduce(x)]
    if rangey is None: rangey=[Num.minimum.reduce(y), \
                             Num.maximum.reduce(y)]
    if rangez is None: rangez=[Num.minimum.reduce(Num.ravel(z)), \
                             Num.maximum.reduce(Num.ravel(z))]
    # Prep the plotting device...
    if (not ppgplot_dev_prep_):
        prepplot(rangex, rangey, title, labx, laby, \
                 rangex2, rangey2, labx2, laby2, logx, logy, \
                 logx2, logy2, font, fontsize, id, aspect, \
                 ticks, panels, device=device)
    if image is not None:
        # Set the color indices and the color table
        lo_col_ind, hi_col_ind = ppgplot.pgqcol()
        lo_col_ind = lo_col_ind + 2
        ppgplot.pgscir(lo_col_ind, hi_col_ind)
        pgpalette.setpalette(image)
        ppgplot.pgctab(pgpalette.l,pgpalette.r,pgpalette.g,pgpalette.b)
        # Construct the image
        ppgplot.pgimag_s(z, 0.0, 0.0, rangex[0], rangey[0], \
                         rangex[1], rangey[1])  
        reset_colors()
    if contours is not None:
        contours = Num.asarray(contours)
        # Choose the line style
        ppgplot.pgsls(line)
        # Choose the line width
        ppgplot.pgslw(width)
        # Choose the line color for the contourlines
        if type(color) == types.StringType:
            ppgplot.pgsci(ppgplot_colors_[color])
        else:
            ppgplot.pgsci(color)
        # Construct the contours
        ppgplot.pgcont_s(z, len(contours), contours, rangex[0], \
                         rangey[0], rangex[1], rangey[1])  
        # Label the contours if requested
        if labels is not None:
            # Choose the line color for the contourlines
            if type(labels) == types.StringType:
                ppgplot.pgsci(ppgplot_colors_[labels])
            else:
                ppgplot.pgsci(labels)
            for i in range(len(contours)):
                ppgplot.pgconl_s(z, contours[i], str(contours[i]),
                                 labelint, labelmin)
Ejemplo n.º 3
0
def plot2d(z, x=None, y=None, title=None, rangex=None, rangey=None, \
           rangez=None, labx='', laby='', rangex2=None, rangey2=None, \
           labx2='', laby2='', image=ppgplot_palette_, contours=None, \
           logx=0, logy=0, logx2=0, logy2=0, \
           line=ppgplot_linestyle_, width=ppgplot_linewidth_, \
           color=ppgplot_color_, labels=ppgplot_labels_, \
           labelint=ppgplot_labelint_, labelmin=ppgplot_labelmin_, \
           font=ppgplot_font_, id=0, noscale=0, aspect=1, \
           fontsize=ppgplot_font_size_, ticks='out', panels=[1,1], \
           device=ppgplot_device_):
    """
    plot2d(z, ...)
        An interface to make various 2D plots using PGPLOT.
            'z' is the 2D Numpy array to be plotted.
        The optional entries are:
            x:         x values                    (default = 0, 1, ...) 
            y:         y values                    (default = 0, 1, ...) 
            title:     graph title                 (default = None)      
            rangex:    range for the x-axis        (default = automatic) 
            rangey:    range for the y-axis        (default = automatic) 
            rangez:    range for the z-axis        (default = automatic) 
            labx:      label for the x-axis        (default = None)      
            laby:      label for the y-axis        (default = None)      
            rangex2:   range for 2nd x-axis        (default = None)      
            rangey2:   range for 2nd y-axis        (default = None)      
            labx2:     label for the 2nd x-axis    (default = None)      
            laby2:     label for the 2nd y-axis    (default = None)      
            logx:      make the 1st x-axis log     (default = 0 (no))
            logy:      make the 1st y-axis log     (default = 0 (no))
            logx2:     make the 2nd x-axis log     (default = 0 (no))
            logy2:     make the 2nd y-axis log     (default = 0 (no))
            image:     color palette for image     (default = 'rainbow') 
            contours:  list of contour values      (default = None)      
            line:      contour line style          (default = 1 (solid)) 
            width:     contour line width          (default = 1 (thin))  
            color:     contour line color          (default = 'white')   
            labels:    color of contour labels     (default = None)      
            labelint:  contour label spacing       (default = 20)        
            labelmin:  min contour label spacing   (default = 20)        
            font:      PGPLOT font to use          (default = 1 (normal))
            fontsize:  PGPLOT font size to use     (default = 1.0 (normal))
            id:        show ID line on plot        (default = 0 (no))    
            noscale:   turn off auto scaling       (default = 0 (no))    
            aspect:    Aspect ratio                (default = 1 (square))
            ticks:     Ticks point in or out       (default = 'out')   
            panels:    Number of subpanels [r,c]   (default = [1,1])
            device:    PGPLOT device to use        (default = '/XWIN')   
        Note:  Many default values are defined in global variables
            with names like ppgplot_font_ or ppgplot_device_.
    """
    # Make sure the input data is a 2D array
    z = Num.asarray(z)
    if not len(z.shape) == 2:
        print 'Input data array must be 2 dimensional.'
        return
    # Announce the global variables we will be using
    global ppgplot_dev_open_, ppgplot_dev_prep_, pgpalette
    # Define the X and Y axis limits if needed
    if x is None: x = Num.arange(z.shape[1], dtype='f')
    else: x = Num.asarray(x)
    if y is None: y = Num.arange(z.shape[0], dtype='f')
    else: y = Num.asarray(y)
    # Determine the scaling to use for the axes
    if rangex is None:
        dx = x[-1] - x[-2]
        rangex = [x[0], x[-1] + dx]
    if rangey is None:
        dy = y[-1] - y[-2]
        rangey = [y[0], y[-1] + dy]
    if rangez is None:        rangez=[Num.minimum.reduce(Num.ravel(z)), \
              Num.maximum.reduce(Num.ravel(z))]
    # Prep the plotting device...
    if (not ppgplot_dev_prep_):
        prepplot(rangex, rangey, title, labx, laby, \
                 rangex2, rangey2, labx2, laby2, logx, logy, \
                 logx2, logy2, font, fontsize, id, aspect, \
                 ticks, panels, device=device)
    if image is not None:
        # Set the color indices and the color table
        lo_col_ind, hi_col_ind = ppgplot.pgqcol()
        lo_col_ind = lo_col_ind + 2
        ppgplot.pgscir(lo_col_ind, hi_col_ind)
        pgpalette.setpalette(image)
        ppgplot.pgctab(pgpalette.l, pgpalette.r, pgpalette.g, pgpalette.b)
        # Construct the image
        ppgplot.pgimag_s(z, 0.0, 0.0, rangex[0], rangey[0], \
                         rangex[1], rangey[1])
        reset_colors()
    if contours is not None:
        contours = Num.asarray(contours)
        # Choose the line style
        ppgplot.pgsls(line)
        # Choose the line width
        ppgplot.pgslw(width)
        # Choose the line color for the contourlines
        if type(color) == types.StringType:
            ppgplot.pgsci(ppgplot_colors_[color])
        else:
            ppgplot.pgsci(color)
        # Construct the contours
        ppgplot.pgcont_s(z, len(contours), contours, rangex[0], \
                         rangey[0], rangex[1], rangey[1])
        # Label the contours if requested
        if labels is not None:
            # Choose the line color for the contourlines
            if type(labels) == types.StringType:
                ppgplot.pgsci(ppgplot_colors_[labels])
            else:
                ppgplot.pgsci(labels)
            for i in range(len(contours)):
                ppgplot.pgconl_s(z, contours[i], str(contours[i]), labelint,
                                 labelmin)
Ejemplo n.º 4
0
ppgplot.pgsvp(margin + imfract, 1.0 - margin / 2, margin, margin + imfract)
ppgplot.pgswin(-0.1, 1.1, min(zs), max(zs))
ppgplot.pgbox("BCNST", 0.0, 0, "BCST", 0.0, 0)
ppgplot.pgline(fdotcut, zs)
ppgplot.pgmtxt("B", 2.4, 0.5, 0.5, "Relative Power")

# f-fdot image
ppgplot.pgsvp(margin, margin + imfract, margin, margin + imfract)
ppgplot.pgswin(min(rs), max(rs), min(zs), max(zs))
ppgplot.pgmtxt("B", 2.4, 0.5, 0.5, labx)
ppgplot.pgmtxt("L", 2.0, 0.5, 0.5, laby)
lo_col_ind, hi_col_ind = ppgplot.pgqcol()
lo_col_ind = lo_col_ind + 2
ppgplot.pgscir(lo_col_ind, hi_col_ind)
pgpalette.setpalette(image)
ppgplot.pgctab(pgpalette.l, pgpalette.r, pgpalette.g, pgpalette.b)
ppgplot.pgimag_s(pffdot, 0.0, 0.0, rgx[0], rgy[0], rgx[1], rgy[1])
ppgplot.pgsci(1)
ppgplot.pgcont_s(pffdot, len(contours), contours, rgx[0], rgy[0], rgx[1],
                 rgy[1])
ppgplot.pgbox("BCST", 0.0, 0, "BCST", 0.0, 0)
ppgplot.pgsci(1)
ppgplot.pgbox("N", 0.0, 0, "N", 0.0, 0)

# gray axes
ppgplot.pgscr(1, 0.5, 0.5, 0.5)
ppgplot.pgsci(1)
ppgplot.pgslw(2)
ppgplot.pgline(rgx, num.asarray([0.0, 0.0]))
ppgplot.pgline(num.asarray([0.0, 0.0]), rgy)
Ejemplo n.º 5
0
ppgplot.pgsvp(margin+imfract, 1.0-margin/2, margin, margin+imfract)
ppgplot.pgswin(-0.1, 1.1, min(zs), max(zs))
ppgplot.pgbox("BCNST", 0.0, 0, "BCST", 0.0, 0)
ppgplot.pgline(fdotcut, zs)
ppgplot.pgmtxt("B", 2.4, 0.5, 0.5, "Relative Power");

# f-fdot image
ppgplot.pgsvp(margin, margin+imfract, margin, margin+imfract)
ppgplot.pgswin(min(rs), max(rs), min(zs), max(zs))
ppgplot.pgmtxt("B", 2.4, 0.5, 0.5, labx);
ppgplot.pgmtxt("L", 2.0, 0.5, 0.5, laby);
lo_col_ind, hi_col_ind = ppgplot.pgqcol()
lo_col_ind = lo_col_ind + 2
ppgplot.pgscir(lo_col_ind, hi_col_ind)
pgpalette.setpalette(image)
ppgplot.pgctab(pgpalette.l, pgpalette.r, pgpalette.g, pgpalette.b)
ppgplot.pgimag_s(pffdot, 0.0, 0.0, rgx[0], rgy[0], rgx[1], rgy[1])  
ppgplot.pgsci(1)
ppgplot.pgcont_s(pffdot, len(contours), contours, rgx[0], rgy[0], rgx[1], rgy[1])  
ppgplot.pgbox("BCST", 0.0, 0, "BCST", 0.0, 0)
ppgplot.pgsci(1)
ppgplot.pgbox("N", 0.0, 0, "N", 0.0, 0)

# gray axes
ppgplot.pgscr(1, 0.5, 0.5, 0.5)
ppgplot.pgsci(1)
ppgplot.pgslw(2)
ppgplot.pgline(rgx, num.asarray([0.0, 0.0]))
ppgplot.pgline(num.asarray([0.0, 0.0]), rgy)

ppgplot.pgclos()
Ejemplo n.º 6
0
def extract_tracks(fname, trkrmin, drdtmin, trksig, ntrkmin):
    # Read four frame
    ff = fourframe(fname)

    # Skip saturated frames
    if np.sum(ff.zavg > 240.0) / float(ff.nx * ff.ny) > 0.95:
        return

    # Read satelite IDs
    try:
        f = open(fname + ".id")
    except OSError:
        print("Cannot open", fname + ".id")
    else:
        lines = f.readlines()
        f.close()

    # ppgplot arrays
    tr = np.array([-0.5, 1.0, 0.0, -0.5, 0.0, 1.0])
    heat_l = np.array([0.0, 0.2, 0.4, 0.6, 1.0])
    heat_r = np.array([0.0, 0.5, 1.0, 1.0, 1.0])
    heat_g = np.array([0.0, 0.0, 0.5, 1.0, 1.0])
    heat_b = np.array([0.0, 0.0, 0.0, 0.3, 1.0])

    # Loop over identifications
    for line in lines:
        # Decode
        id = satid(line)

        # Skip slow moving objects
        drdt = np.sqrt(id.dxdt**2 + id.dydt**2)
        if drdt < drdtmin:
            continue

        # Extract significant pixels
        x, y, t, sig = ff.significant(trksig, id.x0, id.y0, id.dxdt, id.dydt,
                                      trkrmin)

        # Fit tracks
        if len(t) > ntrkmin:
            # Get times
            tmin = np.min(t)
            tmax = np.max(t)
            tmid = 0.5 * (tmax + tmin)
            mjd = ff.mjd + tmid / 86400.0

            # Skip if no variance in time
            if np.std(t - tmid) == 0.0:
                continue

            # Very simple polynomial fit; no weighting, no cleaning
            px = np.polyfit(t - tmid, x, 1)
            py = np.polyfit(t - tmid, y, 1)

            # Extract results
            x0, y0 = px[1], py[1]
            dxdt, dydt = px[0], py[0]
            xmin = x0 + dxdt * (tmin - tmid)
            ymin = y0 + dydt * (tmin - tmid)
            xmax = x0 + dxdt * (tmax - tmid)
            ymax = y0 + dydt * (tmax - tmid)

            cospar = get_cospar(id.norad)
            obs = observation(ff, mjd, x0, y0)
            iod_line = "%s" % format_iod_line(id.norad, cospar, ff.site_id,
                                              obs.nfd, obs.ra, obs.de)

            print(iod_line)

            if id.catalog.find("classfd.tle") > 0:
                outfname = "classfd.dat"
            elif id.catalog.find("inttles.tle") > 0:
                outfname = "inttles.dat"
            else:
                outfname = "catalog.dat"

            f = open(outfname, "a")
            f.write("%s\n" % iod_line)
            f.close()

            # Plot
            ppgplot.pgopen(
                fname.replace(".fits", "") + "_%05d.png/png" % id.norad)
            #ppgplot.pgopen("/xs")
            ppgplot.pgpap(0.0, 1.0)
            ppgplot.pgsvp(0.1, 0.95, 0.1, 0.8)

            ppgplot.pgsch(0.8)
            ppgplot.pgmtxt(
                "T", 6.0, 0.0, 0.0,
                "UT Date: %.23s  COSPAR ID: %04d" % (ff.nfd, ff.site_id))
            if (3600.0 * ff.crres[0] < 1e-3
                ) | (3600.0 * ff.crres[1] < 1e-3) | (
                    ff.crres[0] / ff.sx > 2.0) | (ff.crres[1] / ff.sy > 2.0):
                ppgplot.pgsci(2)
            else:
                ppgplot.pgsci(1)
            ppgplot.pgmtxt(
                "T", 4.8, 0.0, 0.0,
                "R.A.: %10.5f (%4.1f'') Decl.: %10.5f (%4.1f'')" %
                (ff.crval[0], 3600.0 * ff.crres[0], ff.crval[1],
                 3600.0 * ff.crres[1]))
            ppgplot.pgsci(1)
            ppgplot.pgmtxt(
                "T", 3.6, 0.0, 0.0,
                "FoV: %.2f\\(2218)x%.2f\\(2218) Scale: %.2f''x%.2f'' pix\\u-1\\d"
                % (ff.wx, ff.wy, 3600.0 * ff.sx, 3600.0 * ff.sy))
            ppgplot.pgmtxt(
                "T", 2.4, 0.0, 0.0, "Stat: %5.1f+-%.1f (%.1f-%.1f)" %
                (np.mean(ff.zmax), np.std(ff.zmax), ff.vmin, ff.vmax))
            ppgplot.pgmtxt("T", 0.3, 0.0, 0.0, iod_line)

            ppgplot.pgsch(1.0)
            ppgplot.pgwnad(0.0, ff.nx, 0.0, ff.ny)
            ppgplot.pglab("x (pix)", "y (pix)", " ")
            ppgplot.pgctab(heat_l, heat_r, heat_g, heat_b, 5, 1.0, 0.5)

            ppgplot.pgimag(ff.zmax, ff.nx, ff.ny, 0, ff.nx - 1, 0, ff.ny - 1,
                           ff.vmax, ff.vmin, tr)
            ppgplot.pgbox("BCTSNI", 0., 0, "BCTSNI", 0., 0)
            ppgplot.pgstbg(1)

            ppgplot.pgsci(0)
            if id.catalog.find("classfd.tle") > 0:
                ppgplot.pgsci(4)
            elif id.catalog.find("inttles.tle") > 0:
                ppgplot.pgsci(3)
            ppgplot.pgpt(np.array([x0]), np.array([y0]), 4)
            ppgplot.pgmove(xmin, ymin)
            ppgplot.pgdraw(xmax, ymax)
            ppgplot.pgsch(0.65)
            ppgplot.pgtext(np.array([x0]), np.array([y0]), " %05d" % id.norad)
            ppgplot.pgsch(1.0)
            ppgplot.pgsci(1)

            ppgplot.pgend()

        elif id.catalog.find("classfd.tle") > 0:
            # Track and stack
            t = np.linspace(0.0, ff.texp)
            x, y = id.x0 + id.dxdt * t, id.y0 + id.dydt * t
            c = (x > 0) & (x < ff.nx) & (y > 0) & (y < ff.ny)

            # Skip if no points selected
            if np.sum(c) == 0:
                continue

            # Compute track
            tmid = np.mean(t[c])
            mjd = ff.mjd + tmid / 86400.0
            xmid = id.x0 + id.dxdt * tmid
            ymid = id.y0 + id.dydt * tmid
            ztrk = ndimage.gaussian_filter(ff.track(id.dxdt, id.dydt, tmid),
                                           1.0)
            vmin = np.mean(ztrk) - 2.0 * np.std(ztrk)
            vmax = np.mean(ztrk) + 6.0 * np.std(ztrk)

            # Select region
            xmin = int(xmid - 100)
            xmax = int(xmid + 100)
            ymin = int(ymid - 100)
            ymax = int(ymid + 100)
            if xmin < 0: xmin = 0
            if ymin < 0: ymin = 0
            if xmax > ff.nx: xmax = ff.nx - 1
            if ymax > ff.ny: ymax = ff.ny - 1

            # Find peak
            x0, y0, w, sigma = peakfind(ztrk[ymin:ymax, xmin:xmax])
            x0 += xmin
            y0 += ymin

            # Skip if peak is not significant
            if sigma < trksig:
                continue

            # Skip if point is outside selection area
            if inside_selection(id, xmid, ymid, x0, y0) == False:
                continue

            # Format IOD line
            cospar = get_cospar(id.norad)
            obs = observation(ff, mjd, x0, y0)
            iod_line = "%s" % format_iod_line(id.norad, cospar, ff.site_id,
                                              obs.nfd, obs.ra, obs.de)

            print(iod_line)

            if id.catalog.find("classfd.tle") > 0:
                outfname = "classfd.dat"
            elif id.catalog.find("inttles.tle") > 0:
                outfname = "inttles.dat"
            else:
                outfname = "catalog.dat"

            f = open(outfname, "a")
            f.write("%s\n" % iod_line)
            f.close()

            # Plot
            ppgplot.pgopen(
                fname.replace(".fits", "") + "_%05d.png/png" % id.norad)
            ppgplot.pgpap(0.0, 1.0)
            ppgplot.pgsvp(0.1, 0.95, 0.1, 0.8)

            ppgplot.pgsch(0.8)
            ppgplot.pgmtxt(
                "T", 6.0, 0.0, 0.0,
                "UT Date: %.23s  COSPAR ID: %04d" % (ff.nfd, ff.site_id))
            ppgplot.pgmtxt(
                "T", 4.8, 0.0, 0.0,
                "R.A.: %10.5f (%4.1f'') Decl.: %10.5f (%4.1f'')" %
                (ff.crval[0], 3600.0 * ff.crres[0], ff.crval[1],
                 3600.0 * ff.crres[1]))
            ppgplot.pgmtxt(
                "T", 3.6, 0.0, 0.0,
                "FoV: %.2f\\(2218)x%.2f\\(2218) Scale: %.2f''x%.2f'' pix\\u-1\\d"
                % (ff.wx, ff.wy, 3600.0 * ff.sx, 3600.0 * ff.sy))
            ppgplot.pgmtxt(
                "T", 2.4, 0.0, 0.0, "Stat: %5.1f+-%.1f (%.1f-%.1f)" %
                (np.mean(ff.zmax), np.std(ff.zmax), ff.vmin, ff.vmax))
            ppgplot.pgmtxt("T", 0.3, 0.0, 0.0, iod_line)

            ppgplot.pgsch(1.0)
            ppgplot.pgwnad(0.0, ff.nx, 0.0, ff.ny)
            ppgplot.pglab("x (pix)", "y (pix)", " ")
            ppgplot.pgctab(heat_l, heat_r, heat_g, heat_b, 5, 1.0, 0.5)

            ppgplot.pgimag(ztrk, ff.nx, ff.ny, 0, ff.nx - 1, 0, ff.ny - 1,
                           vmax, vmin, tr)
            ppgplot.pgbox("BCTSNI", 0., 0, "BCTSNI", 0., 0)
            ppgplot.pgstbg(1)

            plot_selection(id, xmid, ymid)

            ppgplot.pgsci(0)
            if id.catalog.find("classfd.tle") > 0:
                ppgplot.pgsci(4)
            elif id.catalog.find("inttles.tle") > 0:
                ppgplot.pgsci(3)
            ppgplot.pgpt(np.array([id.x0]), np.array([id.y0]), 17)
            ppgplot.pgmove(id.x0, id.y0)
            ppgplot.pgdraw(id.x1, id.y1)
            ppgplot.pgpt(np.array([x0]), np.array([y0]), 4)
            ppgplot.pgsch(0.65)
            ppgplot.pgtext(np.array([id.x0]), np.array([id.y0]),
                           " %05d" % id.norad)
            ppgplot.pgsch(1.0)
            ppgplot.pgsci(1)

            ppgplot.pgend()