001 package util;
002
003 import java.text.DecimalFormat;
004 import org.eso.fits.*;
005 import java.lang.*;
006 import java.util.*;
007 import java.io.*;
008
009 import javax.swing.*;
010 import ui.recognizer.PlotFileFilter;
011
012 /** Convert FITS from 2QZ format to one or more text files
013 * @version 1.0 Oct 17 2003
014 * @author John Talbot
015 */
016 public class ConvertFits2qz {
017 /** Static method for converting FITS to text files.
018 *
019 * @param argv array of arguments i.e. FITS files
020 */
021
022 /**
023 *group of pixels | has number of pixels | one or more
024 * continuous range of pixels | is a kind of | group of pixels
025 * continuous range of pixels | has definition | A kind of group of pixels which are continuous
026 * continuous range of pixels | has lower bound | given as an integer or wavelength
027 * continuous range of pixels | has upper bound | given as an integer or wavelength
028 * hole | is a kind of | continuous range of pixels
029 * hole | has definition | A kind of continuous range of pixels with intensity value equal to -200
030 * hole | has intensity value | -200
031 * hole | is dealt with using the procedure | which depends the range of the hole
032 * leading hole | is a kind of | hole
033 * leading hole | has definition | A kind of hole located at the beginning of the pixel array
034 * leading hole | has lower bound | beginning of the pixel array
035 * leading hole | has upper bound | a given pixel
036 * leading hole | is dealt with using the procedure | truncate the spectra range up to the first non-hole value
037 * trailing hole | is a kind of | hole
038 * trailing hole | has definition | A kind of hole located at the end of the pixel array
039 * trailing hole | has lower bound | a given pixel
040 * trailing hole | has upper bound | end of the pixel array
041 * trailing hole | is dealt with using the procedure | truncate the spectra range down to the last non-hole value
042 * internal hole | is a kind of | hole
043 * internal hole | has definition | A kind of hole located within the non-hole pixel array
044 * internal hole | has lower bound | a given pixel
045 * internal hole | has upper bound | a higher pixel location than the lower bound
046 * internal hole | is dealt with using the procedure | linear interpolation between the first non-hole value below lower bound and the first non-hole value above the upper bound
047 */
048 public static final double HOLE = -199; // should be -200 but some values are like -199.9999
049
050 /** truncate spectra range to non-hole values and only export non-hole intensities */
051 public static final boolean SKIP_HOLES = true;
052
053 /** interpolate between the lower and upper bound of internal holes */
054 public static final boolean INTERPOLATE_INTERNAL_HOLES = true;
055
056 public static void main(String[] argv) {
057
058 if (argv.length < 1) {
059 javax.swing.filechooser.FileFilter filter = new PlotFileFilter("FITS Files", new String[] {"fits", "fit"});
060
061 JFileChooser loadFileChooser = new JFileChooser();
062 loadFileChooser.setDialogTitle("Convert FITS files or directory");
063 loadFileChooser.setCurrentDirectory(new File("."));
064 loadFileChooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
065 loadFileChooser.addChoosableFileFilter(filter);
066 loadFileChooser.setFileFilter(filter);
067
068 JFrame f = new JFrame("Convert FITS files or directory");
069
070 f.setSize(300, 150);
071 f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
072 f.pack();
073 f.setVisible(true);
074
075 File file = null;
076 if (loadFileChooser.showOpenDialog(f) == JFileChooser.APPROVE_OPTION) { // BUG: 'up' icon in file chooser is disabled
077 file = loadFileChooser.getSelectedFile();
078 }
079 convertFiles(file);
080 } else {
081 for (int na = 0; na < argv.length; na++) {
082 convertFiles(new File(argv[na]));
083 }
084 }
085 //TODO: handle command line arguments for (int na=0; na<argv.length; na++) {
086 System.exit(0);
087 }
088
089 // Handle recursive directories
090 public static void convertFiles(File aFile) {
091 if (aFile == null)
092 return;
093 else if (aFile.isDirectory()) { // if File is a directory then process all files in that directory
094 System.out.println("Dir : " + aFile);
095 File[] files = aFile.listFiles();
096 for (int i = 0 ; i < files.length; i++) {
097 convertFiles(files[i]);
098 }
099 } else {
100 convertFile(aFile);
101 }
102 }
103
104 public static void convertFile(File aFile) {
105 DecimalFormat xFormatter = new DecimalFormat("0.000");
106 DecimalFormat yFormatter = new DecimalFormat("0.000");
107 FitsFile file = null;
108 try {
109 file = new FitsFile(aFile);
110 String name = aFile.getName();
111 int noHDU = file.getNoHDUnits();
112 for (int i = 0; i < 1; i++) {
113 FitsHDUnit hdu = file.getHDUnit(i);
114 FitsHeader hdr = hdu.getHeader();
115 int noKw = hdr.getNoKeywords();
116 int type = hdr.getType();
117 int size = (int) hdr.getDataSize();
118 String fileName = name.split("fits")[0] + "txt";
119 FileWriter writer = new FileWriter(fileName);
120 System.out.println("Creating spectra " + fileName);
121 Enumeration enumeration = hdr.getKeywords();
122 while (enumeration.hasMoreElements()) {
123 FitsKeyword kw = (FitsKeyword) enumeration.nextElement();
124 writer.write("#" + kw.getName());
125 switch (kw.getType()) {
126 case FitsKeyword.COMMENT:
127 writer.write("(C) " + kw.getComment());
128 break;
129 case FitsKeyword.STRING:
130 writer.write("(S)= '" + kw.getString() + "'");
131 break;
132 case FitsKeyword.BOOLEAN:
133 writer.write("(B)= " + kw.getBool());
134 break;
135 case FitsKeyword.INTEGER:
136 writer.write("(I)= " + kw.getInt());
137 break;
138 case FitsKeyword.REAL:
139 writer.write("(R)= " + kw.getReal());
140 break;
141 case FitsKeyword.DATE:
142 writer.write("(D)= " + kw.getString());
143 break;
144 default:
145 }
146 if (0<kw.getComment().length() && (kw.getType()!=FitsKeyword.COMMENT)) {
147 writer.write(" / " + kw.getComment());
148 }
149 writer.write("\n");
150 }
151 if (type == Fits.IMAGE) {
152 FitsMatrix dm = (FitsMatrix) hdu.getData();
153 int naxis[] = dm.getNaxis();
154 double crval[] = dm.getCrval();
155 double crpix[] = dm.getCrpix();
156 double cdelt[] = dm.getCdelt();
157 int nv, off, npix;
158 int nval = dm.getNoValues();
159 if (0 < nval) {
160 int ncol = naxis[0];
161 int nrow = nval/ncol;
162 float data[] = new float[ncol];
163 off = 0;
164 nrow = 1; // Only get first row
165 for (int nr = 0; nr < nrow; nr++) {
166 try {
167 dm.getFloatValues(off, ncol, data);
168 if (INTERPOLATE_INTERNAL_HOLES) { // linear interpolation internal holes
169 boolean firstHole = true;
170 boolean inHole = false;
171 int hole_start = 0;
172 int hole_end = 0;
173 for (int n = 0; n < ncol; n++) {
174 double val = data[n];
175 if (firstHole && val < HOLE) // ignore leading hole
176 continue;
177 else
178 firstHole = false;
179
180 if (!inHole && val < HOLE) {
181 inHole = true;
182 hole_start = n - 1;
183 } else if(inHole && val > HOLE) {
184 inHole = false;
185 hole_end = n;
186 if (hole_end != ncol - 1) { // ignore trailing hole
187 // linear interpolation of this instance of internal hole
188 double x1 = (double) hole_start;
189 double x2 = (double) hole_end;
190 double y1 = data[hole_start];
191 double y2 = data[hole_end];
192 double slope = (y2-y1)/(x2-x1);
193 for (int j = 1; j < hole_end - hole_start; j++) {
194 data[hole_start + j] = (float) (slope*((double)j) + y1);
195 }
196 }
197 }
198
199 }
200 }
201
202 // wavelength computation verified with FV fits viewer
203 FitsKeyword kw = hdr.getKeyword("CD1_1");
204 double deltaWavelength = kw.getReal(); //cdelt[0];
205 double startWavelength = crval[0] - (crpix[0]-1)*deltaWavelength;
206 for (int n = 0; n < ncol; n++) {
207 double val = data[n];
208 // avoid floating point truncation error by not using wavelength += deltaWavelength
209 double wavelength = startWavelength + n*deltaWavelength;
210 // don't export leading hole and trailing hole (truncate spectra range)
211 if (!SKIP_HOLES || val > HOLE) {
212 StringBuffer s = new StringBuffer(xFormatter.format(wavelength));
213 s.append(" ");
214 String y = yFormatter.format(val);
215 s.append(y);
216 s.append("\n");
217 writer.write(s.toString());
218 }
219 }
220 } catch (FitsException e) {
221 }
222 off += ncol;
223 }
224 }
225 }
226 if (writer != null) writer.close();
227
228
229
230
231 }
232 if (file != null) file.closeFile();
233 } catch (FitsException e) {
234 System.out.println("Error: is not a FITS file >" + aFile + "<");
235 return;
236 } catch (IOException e) {
237 System.out.println("Error: cannot open file >" + aFile + "<");
238 return;
239 }
240 }
241 }