package org.cass; import java.io.*; import java.util.*; import java.util.zip.*; /** A program designed to read the headers of FITS image files and output specific information based on a set of command line arguments. This program is meant to be referenced through the name 'readfits' which should be defined as an alias or batch file, depending on the underlying system. @author Zachary Vaughan @version 1.2 06/14/2006 */ public final class ReadFits { private static Vector fset = new Vector(); private static TreeSet kset = new TreeSet(); private static TreeSet iset = new TreeSet(); private static boolean allimages = false, keysonly = false; /** The entry point for this program. The method is synchronized to allow only one process or thread to use the program at a time per instance of the Virtual Machine.

This method NEVER RETURNS control to the user; rather it terminates the Virtual Machine with an exit code representing the results of the program. A value of 0 indicates success, and all other values represent some sort of error or failure of the program.

@param args the command-line arguments supplied to this program. */ public static synchronized void main(String[] args) { if(args.length == 0) { printUsage(System.out); System.exit(1); } try { /* parse command line arguments */ for(int i = 0; i < args.length; i++) { if(args[i].startsWith("-")) // if an argument switch, treat as such { if(args[i].equals("-a")) allimages = true; else if(args[i].equals("-k")) keysonly = true; else if(args[i].equals("-x")) parseKeys(args[++i]); else if(args[i].equals("-i")) parseImages(args[++i]); else throw new IllegalArgumentException("Illegal argument, " + args[i]); } else parseFiles(args[i]); // else parse and add files matching the pattern } } catch(Exception e) { System.err.println("Error: " + e); printUsage(System.err); System.exit(1); } /* check image search parameters */ if(allimages) System.out.println("-> Looking in all internal images"); else if(iset.isEmpty()) System.out.println("-> Looking in first internal image only"); else { Iterator ii = iset.iterator(); System.out.print("-> Looking in internal image(s) " + ii.next()); while(ii.hasNext()) System.out.print("," + ii.next()); System.out.println(); } /* check entry search parameters */ if(kset.isEmpty()) System.out.println("-> Displaying all entries"); else { Iterator ki = kset.iterator(); System.out.print("-> Displaying entries with keyword(s) " + ki.next()); while(ki.hasNext()) System.out.print("," + ki.next()); System.out.println(); } /* check entry display paramters */ if(keysonly) System.out.println("-> Formatting output as a keyword list"); /* check file count */ if(fset.isEmpty()) { System.out.println("-> No files found"); System.err.println("Error: No files found."); System.exit(1); } else System.out.println("-> " + fset.size() + " file(s) found"); System.out.println(); /* begin the processing phase */ try { process(); } catch(Exception e) { System.err.println("Error: " + e); System.exit(1); } /* exit normally */ System.out.println("All done!"); System.exit(0); } /** Prints an informative usage message describing command line syntax to the given output stream. @param out the desired output stream to print to. */ public static void printUsage(PrintStream out) { out.println("Usage:"); out.println(" % readfits [options] files"); out.println(); out.println("Options:"); out.println(" where indicates a plus-sign-separated list of arguments..."); out.println(" -a read all internal image headers, not just the first."); out.println(" -i read only specified internal image headers."); out.println(" -k display entry keys only in a comma separated list."); out.println(" -x read only entries with specified keys."); out.println(); out.println("Examples:"); out.println(" % readfits c3sky*.fts"); out.println(" -> This will read all files matching the pattern c3sky*.fts,"); out.println(" displaying all header entries in the first internal image of each."); out.println(" % readfits -x CREATED c*sky_2004_117*.fts.gz"); out.println(" -> This will read all files matching the pattern c*sky_2004_117*.fts.gz,"); out.println(" displaying only the CREATED entry in the first image of each file."); out.println(" % readfits -i 1+4+7 -x NAXIS1+NAXIS2 test.fts"); out.println(" -> This will read the file test.fts and output the NAXIS1 and NAXIS2"); out.println(" entries of internal images 1, 4 and 7 only."); out.println(" % readfits -k /my/temp/dir/abc123.fts.gz"); out.println(" -> This will display the entries of the first image in the given file."); out.println(" No values are shown; just a comma-separated list of keywords."); out.println(" % readfits -a -x MAP c1sky_2005_001_235847.fts.gz"); out.println(" -> This will display the values of the MAP keywords in every internal"); out.println(" image of the given skymap."); out.println(); } private static void parseKeys(String arg) { String[] p = arg.split("\\+"); for(int i = 0; i < p.length; i++) kset.add(p[i].trim().toUpperCase()); } private static void parseImages(String arg) { String[] p = arg.split("\\+"); for(int i = 0; i < p.length; i++) iset.add(new Integer(p[i])); } private static void parseFiles(String arg) { File[] farr = Utilities.getFiles(arg); if(farr != null) for(int i = 0; i < farr.length; i++) if(farr[i] != null) fset.add(farr[i]); } private static void process() throws IOException { /* begin looping over all parsed files */ for(Iterator fi = fset.iterator(); fi.hasNext();) { /* check basic starting conditions of this file */ File f = fi.next(); if(f.isDirectory()) { System.err.println("\'" + f + "\' is a directory. Skipping."); continue; } else if(f.canRead() == false) { System.err.println("Cannot read file \'" + f + "\'. Skipping."); continue; } else System.out.println("Reading \'" + f + "\'... "); /* open an input stream to read the file */ boolean gz = f.getName().toLowerCase().endsWith(".gz"); InputStream in = new BufferedInputStream(gz ? (InputStream) new GZIPInputStream(new FileInputStream(f)) : (InputStream) new FileInputStream(f)); /* if reading all or specific images, use the following */ if(allimages || !iset.isEmpty()) { /* get last possible image number for speedup purposes (break early when reached) */ Integer i = new Integer(0); Integer max = allimages ? new Integer(Integer.MAX_VALUE) : iset.last(); /* loop over images until max is reached or no more are found in file */ for(Map header = Fits.readHeader(in); header != null; header = Fits.readHeader(in)) { i = new Integer(i.intValue() + 1); if(i.compareTo(max) > 0) break; // check early termination condition Fits.skipMap(in, header); // skip the map itself if(!allimages && !iset.contains(i)) continue; System.out.println("Image " + i + ":"); display(header); } } /* otherwise only read first image header */ else { Map header = Fits.readHeader(in); display(header); } /* close input stream */ in.close(); System.out.println(); } } private static void display(Map header) throws IOException { boolean first = true; for(Iterator> ki = header.entrySet().iterator(); ki.hasNext();) { Map.Entry e = ki.next(); if(kset.isEmpty() || kset.contains(e.getKey())) { if(keysonly) if(first) {System.out.print(" " + e.getKey()); first = false;} else System.out.print(", " + e.getKey()); else System.out.println(" " + e.getKey() + " = " + e.getValue()); } } } private ReadFits() {} }