/*******************************************************************************
* ALMA - Atacama Large Millimeter Array
* Copyright (c) ESO - European Southern Observatory, 2011
* (in the framework of the ALMA collaboration).
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*******************************************************************************/
/*
* Created on Apr 14, 2004
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
package alma.eso.org;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Enumeration;
import org.eso.fits.*;
/**
* @author acaproni
*
* The class to test the jfits library
*
* It has the same functionalities of the python program to test the python
* FITS library
*
*/
public class FITStest {
/**
* The stream for stdin
*/
private BufferedReader inStream;
/**
* The name of the fits file (read from the command line)
*/
private String imageName;
/**
* The FITS file
*/
FitsFile file;
/**
* The starting point of the project
*
* @param args Command line args
*/
public static void main(String[] args) {
if (args.length!=1) {
System.out.println("USAGE:");
System.out.println("FITStest <img>");
System.exit(-1);
}
new FITStest(args[0]);
}
/**
* Constructor
*
* @param imgName The name of the FITS (read from command line)
*/
FITStest(String imgName) {
// Join the stdin
inStream = new BufferedReader(new InputStreamReader(System.in));
// Open the FITS file
try {
file = new FitsFile(imgName);
} catch (FitsException fe) {
System.err.println("Error opening "+imgName);
System.err.println("FITS exception: "+fe.toString());
System.exit(-1);
} catch (IOException ioe) {
System.err.println("Error opening "+imgName);
System.err.println("IO exception: "+ioe.toString());
System.exit(-1);
}
// Print some info about the headers
int noHDU = file.getNoHDUnits();
System.out.println("FITS file has " + noHDU + " headers");
for (int t=0; t<noHDU; t++) {
FitsHDUnit hdu = file.getHDUnit(t);
FitsHeader hdr = hdu.getHeader();
System.out.print("Header "+t+": Name = "+hdr.getName()+"; ");
System.out.print("Type = "+hdr.getType()+"; Data size = "+hdr.getDataSize());
System.out.println("; Num of keys = "+hdr.getNoKeywords());
}
// Print some info about the data
printImageInfo();
// Enters the loop
commandLoop();
}
/**
* Print keywords and values of the specified header
*
* @param hdrNum The number of the header
*/
private void printHeader(int hdrNum) {
FitsHDUnit hdu = file.getHDUnit(hdrNum);
FitsHeader hdr = hdu.getHeader();
int noKw = hdr.getNoKeywords();
int type = hdr.getType();
int size = (int) hdr.getDataSize();
System.out.println("HEADER " + hdrNum);
System.out.println("\theader name " + hdr.getName());
System.out.println("\theader type " + Fits.getType(type));
System.out.println("\tnumber of keywords in the header: " + noKw);
System.out.println("\tsyze of the header: " + size + " bytes");
System.out.println(" Keywords:");
Enumeration enum1 = hdr.getKeywords();
while (enum1.hasMoreElements()) {
FitsKeyword kw = (FitsKeyword) enum1.nextElement();
System.out.print(" " + kw.getName());
switch (kw.getType()) {
case FitsKeyword.COMMENT:
System.out.print("(C) " + kw.getComment());
break;
case FitsKeyword.STRING:
System.out.print("(S)= '" + kw.getString() + "'");
break;
case FitsKeyword.BOOLEAN:
System.out.print("(B)= " + kw.getBool());
break;
case FitsKeyword.INTEGER:
System.out.print("(I)= " + kw.getInt());
break;
case FitsKeyword.REAL:
System.out.print("(R)= " + kw.getReal());
break;
case FitsKeyword.DATE:
System.out.print("(D)= " + kw.getString());
break;
default:
}
if (0<kw.getComment().length() && (kw.getType()!=FitsKeyword.COMMENT)) {
System.out.print(" / " + kw.getComment());
}
System.out.println();
}
if (type == Fits.IMAGE) {
System.out.println("\n Check data matrix " + "- compute mean and rms");
FitsMatrix dm = (FitsMatrix) hdu.getData();
int naxis[] = dm.getNaxis();
double crval[] = dm.getCrval();
double crpix[] = dm.getCrpix();
double cdelt[] = dm.getCdelt();
System.out.println(" Dimension of matrix: "+ naxis.length);
for (int n=0; n<naxis.length; n++) {
System.out.println(" Axis " + n + ": " + naxis[n]
+ ", " + crpix[n] + ", "
+ crval[n] + ", " + cdelt[n]);
}
System.out.println("\n");
int nv, off, npix;
int nval = dm.getNoValues();
if (0<nval) {
int ncol = naxis[0];
int nrow = nval/ncol;
System.out.println(" Npixel,row,col: " + nval+ ", " + nrow + ", " + ncol);
float data[] = new float[ncol];
double mean, rms, val;
off = nv = npix = 0 ;
mean = rms = 0.0;
long time = System.currentTimeMillis();
for (int nr=0; nr<nrow; nr++) {
try {
dm.getFloatValues(off, ncol, data);
for (int n = 0; n<ncol; n++) {
val = data[n];
npix++;
mean += val;
rms += val*val;
}
} catch (FitsException e) {
}
off += ncol;
}
mean = mean/npix;
rms = rms/npix - mean*mean;
rms = ((0.0<rms) ? Math.sqrt(rms) : 0.0);
float dtime =
(float) (1000.0*(System.currentTimeMillis()-time)/
((double) nval));
System.out.println(" Mean: " + (float)mean +
", rms: " + (float)rms +
", Time: " + dtime
+ " S/Mp, Pixels: " + npix);
}
} else if (type==Fits.BTABLE || type==Fits.ATABLE) {
System.out.println("\n Check table data - list columns");
FitsTable dm = (FitsTable) hdu.getData();
int nrow = dm.getNoRows();
int ncol = dm.getNoColumns();
FitsColumn col[] = new FitsColumn[ncol];
System.out.println(" Columns: " + ncol
+ ", Rows: " + nrow);
for (int n=0; n<ncol; n++) {
col[n] = dm.getColumn(n);
System.out.print(" " + n + " >"
+ col[n].getLabel() + "<, ");
System.out.print(col[n].getRepeat() + " ");
System.out.print(col[n].getDataType() + ", >");
System.out.print(col[n].getDisplay() + "<, >");
System.out.println(col[n].getUnit() + "<");
if (col[n].getDataType() == 'F'
|| col[n].getDataType() == 'E'
|| col[n].getDataType() == 'D') {
int npix = 0;
double mean, rms, val;
mean = rms = 0.0;
long time = System.currentTimeMillis();
for (int nr=0; nr<nrow; nr++) {
val = col[n].getReal(nr);
if (Double.isNaN(val)) continue;
npix++;
mean += val;
rms += val*val;
}
float dtime =
(float) (1000.0*(System.currentTimeMillis()-time)/((double) nrow));
mean = mean/npix;
rms = rms/npix - mean*mean;
rms = ((0.0<rms) ? Math.sqrt(rms) : 0.0);
System.out.println(" no,mean,rms: " + npix
+ ", " + (float)mean + ", "
+ (float)rms + "; "
+ dtime + " S/Mp");
} else if (col[n].getDataType() == 'I'
|| col[n].getDataType() == 'J'
|| col[n].getDataType() == 'B') {
int npix = 0;
double mean, rms, val;
mean = rms = 0.0;
long time = System.currentTimeMillis();
for (int nr=0; nr<nrow; nr++) {
val = col[n].getInt(nr);
if (val == Long.MIN_VALUE) continue;
npix++;
mean += val;
rms += val*val;
}
float dtime =
(float) (1000.0*(System.currentTimeMillis()-time)/((double) nrow));
mean = mean/npix;
rms = rms/npix - mean*mean;
rms = ((0.0<rms) ? Math.sqrt(rms) : 0.0);
System.out.println(" no,mean,rms: " + npix
+ ", " + (float)mean + ", "
+ (float)rms + "; "
+ dtime + " S/Mp");
}
}
}
}
/**
* Print keywords and values of all the headers
*
*/
private void printHeaders() {
int noHDU = file.getNoHDUnits();
System.out.println("FITS file has " + noHDU + " HDUnits");
for (int i=0; i<noHDU; i++) {
printHeader(i);
}
}
/**
* Print some info about DATA
*
*/
private void printImageInfo() {
int noHDU = file.getNoHDUnits();
for (int i=0; i<noHDU; i++) {
FitsHDUnit hdu = file.getHDUnit(i);
FitsData data=hdu.getData();
if (data!=null) {
System.out.print("DATA for hdr "+i+": num. of axes:"+data.getNoAxes());
if (data.getNoAxes()>0) {
System.out.print(' ');
// Get the dimensions of the axes
int dimAxes[]=data.getNaxis();
System.out.print('[');
for (int j=0; j<data.getNoAxes(); j++) {
if (j>0) {
System.out.print('x');
}
System.out.print(""+dimAxes[j]);
}
System.out.print(']');
}
System.out.println(" type: "+data.getType());
}
}
}
/**
* Get the value of a keyword
*
* @param name The name of the keyword
* @return null if the keyword is not found, otherwise a String with
* its value and comment
*/
private String getKeyword(String name) {
// The value of the keyword (if any)
String value=null;
// The comment of the keyword (if any)
String comment=null;
// Looks for the keyword in all the headers
for (int i=0; i<file.getNoHDUnits(); i++) {
FitsHDUnit hdu = file.getHDUnit(i);
FitsHeader hdr = hdu.getHeader();
FitsKeyword kw=hdr.getKeyword(name.toUpperCase());
if (kw!=null) {
// Keyword found!
value=kw.getString();
comment=kw.getComment();
System.out.println("Key "+name.toUpperCase()+" found on hdr "+i);
break;
}
}
if (value==null && comment==null) {
return null;
} else {
if (value==null) value="";
if (comment==null) comment="";
return value+" / "+comment;
}
}
/**
* Delete a keyword
* It deletes the first occurrence of the keyword it founds starting
* from FITS header 0
*
* @param name The name of the keyword
* @return true if the keyword is found and deleted
*/
private boolean deleteKeyword(String name) {
// Scans the headers to find the keyword
for (int hdrNum=0; hdrNum<file.getNoHDUnits(); hdrNum++) {
int pos = getKeywordPosition(hdrNum,name);
if (pos!=-1) { // Keyword found at pos position
FitsHDUnit hdu = file.getHDUnit(hdrNum);
FitsHeader hdr = hdu.getHeader();
hdr.removeKeywordAt(pos);
return true;
}
}
return false;
}
/**
* Update a keyword
* If the keyword doesn't exist then adds the key to header 0
* If more then one key exists it updates the first one
*
* @param key The keyword
* @param value The value of the keyword
* @param comment The comment of the keyword
*/
private void updateKeyword(String key, String value, String comment) {
// Build the FitsKeyword
FitsKeyword kw = new FitsKeyword(key,value,comment);
updateKeyword(kw);
}
/**
* Update a keyword
* If the keyword doesn't exist then adds the key to header 0
* If more then one key exists it updates the first one
*
* @param key The FitsKeyword
*
*/
private void updateKeyword(FitsKeyword key) {
// Try to find the keyword in a header
for (int hdrNum=0; hdrNum<file.getNoHDUnits(); hdrNum++) {
int pos = getKeywordPosition(hdrNum,key.getName());
if (pos!=-1) { // Keyword found at pos position
FitsHDUnit hdu = file.getHDUnit(hdrNum);
FitsHeader hdr = hdu.getHeader();
hdr.removeKeywordAt(pos);
hdr.insertKeywordAt(key,pos);
return;
}
}
// The key doesnt exist: add the keyword to header 0
FitsHDUnit hdu = file.getHDUnit(0);
FitsHeader hdr = hdu.getHeader();
hdr.addKeyword(key);
}
/**
* Return the position of a keyword
*
* @param header The header to search for the keyword
* @param name The name of the keyword
* @return The position of the keyword or -1 if the keyword doesn't exist
*/
private int getKeywordPosition(int header, String name){
FitsHDUnit hdu = file.getHDUnit(header);
FitsHeader hdr = hdu.getHeader();
// Check if the keyword exists
FitsKeyword kw=hdr.getKeyword(name.toUpperCase());
if (kw==null) return -1;
// Scans the list of the keyword
Enumeration enum1 = hdr.getKeywords();
int pos=-1;
while (enum1.hasMoreElements()) {
pos++;
kw = (FitsKeyword) enum1.nextElement();
if (kw.getName().trim().compareToIgnoreCase(name.trim())==0) {
// Keyword found
return pos;
}
}
return -1;
}
/**
* Process the command.
* Valid commands are:
* read keyword
* delete keyword
* readall
* update keyword = va;ue / comment
* save filename
*
* @param cmd The command read from stdin
*/
private void processCommand(String cmd) {
String words[]=cmd.trim().split("\\s+");
if (words[0].compareToIgnoreCase("READ")==0) {
if (words.length!=2) {
System.err.println("Invalid command: "+cmd);
System.err.println("Use: READ <keyword>");
return;
}
String valueAndComment=getKeyword(words[1]);
if (valueAndComment==null) {
System.out.println("Keyword "+words[1]+" NOT found");
} else {
System.out.println(words[1].toUpperCase()+" = "+valueAndComment.toUpperCase());
}
return;
} else if (words[0].compareToIgnoreCase("DELETE")==0) {
if (words.length!=2) {
System.err.println("Invalid command: "+cmd);
System.err.println("Use: DELETE <keyword>");
return;
}
if (deleteKeyword(words[1])) {
System.out.println(words[1].trim().toUpperCase()+" deleted");
} else {
System.out.println(words[1].trim().toUpperCase()+" NOT found");
}
return;
} else if (words[0].compareToIgnoreCase("READALL")==0) {
if (words.length!=1) {
System.err.println("Invalid command: "+cmd);
System.err.println("Use: READALL");
return;
}
printHeaders();
return;
} else if (words[0].compareToIgnoreCase("UPDATE")==0) {
String myCmd=cmd.toUpperCase().replaceFirst("UPDATE","").trim();
String keyName="";
String value="";
String comment="";
// Extract name, value and comment of the keyword from cmd
int equalPos=myCmd.indexOf("=");
if (equalPos!=-1) {
keyName=myCmd.substring(0,equalPos).trim();
} else {
System.err.println("Invalid command: "+cmd);
System.err.println("Use: UPDATE KEY = VALUE / COMMENT");
return;
}
String valueAndComment=myCmd.substring(equalPos+1);
int separatorPos=valueAndComment.indexOf('/');
if (separatorPos!=-1) {
value = valueAndComment.substring(0,separatorPos).trim();
comment=valueAndComment.substring(separatorPos+1).trim();
} else {
System.err.println("Invalid command: "+cmd);
System.err.println("Use: UPDATE KEY = VALUE / COMMENT");
return;
}
updateKeyword(keyName,value,comment);
return;
} else if (words[0].compareToIgnoreCase("SAVE")==0) {
if (words.length!=2) {
System.err.println("Invalid command: "+cmd);
System.err.println("Use: SAVE <filename>");
return;
}
try {
file.writeFile(words[1]);
} catch (FitsException fe) {
System.err.println("Error saving "+words[1]);
System.err.println("\tFitsException: "+fe.getMessage());
} catch (IOException ioe) {
System.err.println("Error saving "+words[1]);
System.err.println("\tIOException: "+ioe.getMessage());
}
return;
} else if (words[0].compareToIgnoreCase("HELP")==0 || words[0].compareTo("?")==0) {
System.out.println("Available commands commands:");
System.out.println("\tREAD KEY");
System.out.println("\tREADALL");
System.out.println("\tUPDATE KEY = VALUE / COMMENT");
System.out.println("\tDELETE KEY");
System.out.println("\tSAVE FILENAME");
System.out.println("\tHELP");
System.out.println("\t?");
System.out.println("\tQUIT");
System.out.println("Use EOF or quit to terminate");
return;
} else if (words[0].compareToIgnoreCase("QUIT")==0) {
} else {
System.err.println("? Unrecognized command: "+words[0]+" ?");
System.err.println("Use help or ? for help");
return;
}
}
/**
* The command loop: read and executes command
* The commands are read from inStream (stdin) and executed
* on the FITS file passed on the command line
*
*/
private void commandLoop() {
String line="";
do {
System.out.print("> ");
try {
line = inStream.readLine();
} catch (Exception e) {
System.err.println("Error:\n"+e.toString());
System.exit(-1);
}
// Execute the command
processCommand(line.trim());
} while (line.trim().compareToIgnoreCase("QUIT")!=0);
}
}