func main() { flag.Usage = func() { const msg = `Usage: go-fitsio-mergefiles -o outfname file1 file2 [file3 ...] Merge FITS tables into a single file/table. ` fmt.Fprintf(os.Stderr, "%v\n", msg) flag.PrintDefaults() } outfname := flag.String("o", "out.fits", "path to merged FITS file") flag.Parse() if flag.NArg() < 2 { flag.Usage() os.Exit(1) } _, err := os.Stat(*outfname) if err == nil { err = os.Remove(*outfname) if err != nil { panic(err) } } start := time.Now() defer func() { delta := time.Since(start) fmt.Printf("::: timing: %v\n", delta) }() fmt.Printf("::: creating merged file [%s]...\n", *outfname) w, err := os.Create(*outfname) if err != nil { panic(err) } defer w.Close() out, err := fits.Create(w) if err != nil { panic(err) } defer out.Close() infiles := make([]string, 0, flag.NArg()) for i := 0; i < flag.NArg(); i++ { fname := flag.Arg(i) infiles = append(infiles, fname) } var table *fits.Table fmt.Printf("::: merging [%d] FITS files...\n", len(infiles)) for i, fname := range infiles { r, err := os.Open(fname) if err != nil { panic(err) } defer r.Close() f, err := fits.Open(r) if err != nil { panic(err) } defer f.Close() hdu := f.HDU(1).(*fits.Table) nrows := hdu.NumRows() fmt.Printf("::: reading [%s] -> nrows=%d\n", fname, nrows) if i == 0 { // get header from first input file err = fits.CopyHDU(out, f, 0) if err != nil { panic(err) } // get schema from first input file cols := hdu.Cols() table, err = fits.NewTable(hdu.Name(), cols, hdu.Type()) if err != nil { panic(err) } defer table.Close() } err = fits.CopyTable(table, hdu) if err != nil { panic(err) } } err = out.Write(table) if err != nil { panic(err) } fmt.Printf("::: merging [%d] FITS files... [done]\n", len(infiles)) fmt.Printf("::: nrows: %d\n", table.NumRows()) }
func run() int { var single bool flag.Usage = func() { const msg = `Usage: go-fitsio-listhead filename[ext] List the FITS header keywords in a single extension, or, if ext is not given, list the keywords in all the extensions. Examples: go-fitsio-listhead file.fits - list every header in the file go-fitsio-listhead file.fits[0] - list primary array header go-fitsio-listhead file.fits[2] - list header of 2nd extension go-fitsio-listhead file.fits+2 - same as above go-fitsio-listhead file.fits[GTI] - list header of GTI extension Note that it may be necessary to enclose the input file name in single quote characters on the Unix command line. ` fmt.Fprintf(os.Stderr, "%v\n", msg) flag.PrintDefaults() } flag.Parse() if flag.NArg() != 1 { flag.Usage() return 1 } fname := flag.Arg(0) r, err := os.Open(fname) if err != nil { fmt.Fprintf(os.Stderr, "**error** %v\n", err) return 1 } defer r.Close() f, err := fits.Open(r) if err != nil { fmt.Fprintf(os.Stderr, "**error** %v\n", err) return 1 } defer f.Close() // list only a single header if a specific extension was given if strings.Contains(fname, "[") { single = true } for i := 0; i < len(f.HDUs()); i++ { hdu := f.HDU(i) hdr := hdu.Header() fmt.Printf("Header listing for HDU #%d:\n", i) for _, n := range hdr.Keys() { card := hdr.Get(n) if card == nil { fmt.Fprintf(os.Stderr, "**error** could not retrieve card [%v]", n) return 1 } fmt.Printf( "%-8s= %-29s / %s\n", card.Name, fmt.Sprintf("%v", card.Value), card.Comment) } fmt.Printf("END\n\n") // quit if only listing a single header if single { break } } if err != nil && err != io.EOF { fmt.Fprintf(os.Stderr, "**error** %v\n", err) return 1 } return 0 }
func run() int { flag.Usage = func() { const msg = `Usage: go-fitsio-tablist filename[ext][col filter][row filter] List the contents of a FITS table Examples: tablist tab.fits[GTI] - list the GTI extension tablist tab.fits[1][#row < 101] - list first 100 rows tablist tab.fits[1][col X;Y] - list X and Y cols only tablist tab.fits[1][col -PI] - list all but the PI col tablist tab.fits[1][col -PI][#row < 101] - combined case Display formats can be modified with the TDISPn keywords. ` fmt.Fprintf(os.Stderr, "%v\n", msg) flag.PrintDefaults() } flag.Parse() if flag.NArg() != 1 { flag.Usage() return 1 } fname := flag.Arg(0) r, err := os.Open(fname) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) return 1 } defer r.Close() f, err := fits.Open(r) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) return 1 } defer f.Close() for _, hdu := range f.HDUs() { if hdu.Type() == fits.IMAGE_HDU { //fmt.Fprintf(os.Stderr, "Error: this program only displays tables, not images\n") //return 1 continue } table := hdu.(*fits.Table) ncols := len(table.Cols()) nrows := table.NumRows() rows, err := table.Read(0, nrows) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) return 1 } w := os.Stdout hdrline := strings.Repeat("=", 80-15) maxname := 10 for _, col := range table.Cols() { if len(col.Name) > maxname { maxname = len(col.Name) } } data := make([]interface{}, ncols) names := make([]string, ncols) for i, col := range table.Cols() { names[i] = col.Name data[i] = reflect.New(col.Type()).Interface() } rowfmt := fmt.Sprintf("%%-%ds | %%v\n", maxname) for irow := 0; rows.Next(); irow++ { err = rows.Scan(data...) if err != nil { fmt.Printf("Error: (row=%v) %v\n", irow, err) } fmt.Fprintf(w, "== %05d/%05d %s\n", irow, nrows, hdrline) for i := 0; i < ncols; i++ { rv := reflect.Indirect(reflect.ValueOf(data[i])) fmt.Fprintf(w, rowfmt, names[i], rv.Interface()) } } err = rows.Err() if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) return 1 } } return 0 }
func main() { flag.Parse() if flag.NArg() != 2 { flag.Usage = func() { const msg = `Usage: go-fitsio-fitscopy inputfile outputfile Copy an input file to an output file, optionally filtering the file in the process. This seemingly simple program can apply powerful filters which transform the input file as it is being copied. Filters may be used to extract a subimage from a larger image, select rows from a table, filter a table with a GTI time extension or a SAO region file, create or delete columns in a table, create an image by binning (histogramming) 2 table columns, and convert IRAF format *.imh or raw binary data files into FITS images. See the CFITSIO User's Guide for a complete description of the Extended File Name filtering syntax. Examples: go-fitsio-fitscopy in.fit out.fit (simple file copy) go-fitsio-fitscopy - - (stdin to stdout) go-fitsio-fitscopy in.fit[11:50,21:60] out.fit (copy a subimage) go-fitsio-fitscopy iniraf.imh out.fit (IRAF image to FITS) go-fitsio-fitscopy in.dat[i512,512] out.fit (raw array to FITS) go-fitsio-fitscopy in.fit[events][pi>35] out.fit (copy rows with pi>35) go-fitsio-fitscopy in.fit[events][bin X,Y] out.fit (bin an image) go-fitsio-fitscopy in.fit[events][col x=.9*y] out.fit (new x column) go-fitsio-fitscopy in.fit[events][gtifilter()] out.fit (time filter) go-fitsio-fitscopy in.fit[2][regfilter("pow.reg")] out.fit (spatial filter) Note that it may be necessary to enclose the input file name in single quote characters on the Unix command line. ` fmt.Fprintf(os.Stderr, "%v\n", msg) } flag.Usage() os.Exit(1) } var err error ifname := flag.Arg(0) ofname := flag.Arg(1) // open input file var r io.Reader if ifname == "-" { r = os.Stdin } else { f, err := os.Open(ifname) if err != nil { panic(err) } defer f.Close() r = f } in, err := fits.Open(r) if err != nil { panic(err) } defer in.Close() // create output file var w io.Writer if ofname == "-" { w = os.Stdout } else { f, err := os.Create(ofname) if err != nil { panic(err) } defer f.Close() w = f } out, err := fits.Create(w) if err != nil { panic(err) } defer out.Close() // copy every HDU until we get an error for ihdu := range in.HDUs() { err = fits.CopyHDU(out, in, ihdu) if err != nil { panic(err) } } }