Skip to content

Commit 9bfd465

Browse files
authored
Merge pull request #472 from Caltech-IPAC/DM-11883-UpgradeFITSSPackage
Dm 11883 upgrade the nom.tam.fits java package in Firefly
2 parents 68cec09 + de3313e commit 9bfd465

29 files changed

+126
-24
lines changed

buildScript/depends.gincl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,20 @@ ext {
3030
':websocket-api']
3131

3232
mysql_lib = ':mysql-connector-java-5.1.6-bin'
33-
starlink_lib = [':rayreg', ':regclient', ':stil']
33+
starlink_lib = [':rayreg',
34+
':starlink-registry-1.2+2016.05.03',
35+
':jcdf-1.2.2',
36+
':eag-healpix-2017.02.26',
37+
':ndx', ':mirage', ':gbin',
38+
':vecmath-1.5.2',
39+
':commons-compress-1.13',
40+
':starlink-pal-1.0.1+2016.08.11',
41+
':starlink-cdf-1.0+2017.01.04',
42+
':starlink-connect-0.1+2016.05.03',
43+
':starlink-fits-0.1+2017.03.29',
44+
':starlink-table-3.2',
45+
':starlink-util-1.0+2017.03.17',
46+
':starlink-votable-2.0+2016.12.22']
3447
xbeanfinder_lib = [':xbean-finder-4.1', ':asm-5.0.3']
3548
spring_lib = [':spring-beans', ':spring-core', ':spring-jdbc', ':spring-tx', ':spring-web']
3649
fits_io_lib = [':fits_io']

jars/fits-io/fits_io.jar

233 KB
Binary file not shown.
452 KB
Binary file not shown.
35.6 KB
Binary file not shown.

jars/starlink/gbin.jar

32.7 KB
Binary file not shown.

jars/starlink/jcdf-1.2.2.jar

122 KB
Binary file not shown.

jars/starlink/mirage.jar

8.32 KB
Binary file not shown.

jars/starlink/ndx.jar

44.4 KB
Binary file not shown.
20.6 KB
Binary file not shown.
Binary file not shown.
249 KB
Binary file not shown.
65.4 KB
Binary file not shown.
Binary file not shown.

jars/starlink/starlink-table-3.2.jar

668 KB
Binary file not shown.
262 KB
Binary file not shown.
Binary file not shown.

jars/starlink/vecmath-1.5.2.jar

377 KB
Binary file not shown.

src/firefly/java/edu/caltech/ipac/astro/FITSTableReader.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import edu.caltech.ipac.util.DataType;
1111
import edu.caltech.ipac.util.StringUtils;
1212
import nom.tam.fits.FitsException;
13+
import nom.tam.fits.FitsFactory;
1314
import uk.ac.starlink.table.*;
1415

1516
import java.io.File;
@@ -212,14 +213,28 @@ public static List<DataGroup> convertFitsToDataGroup(String fits_filename,
212213
* @return List of star tables.
213214
* @throws IOException
214215
*/
215-
public static List getStarTableList(String fits_filename) throws IOException {
216-
217-
TableSequence tseq;
218-
StarTableFactory stFactory = new StarTableFactory();
219-
tseq = stFactory.makeStarTables(fits_filename, null);
220-
List tList = new ArrayList();
221-
for (StarTable tbl; (tbl = tseq.nextTable()) != null; ) {
222-
tList.add(tbl);
216+
public static List getStarTableList(String fits_filename) {
217+
218+
ArrayList<StarTable> tList = new ArrayList<>();
219+
220+
// disable long string for HeaderCard create while collecting tables from StarTableFactory to work around the exception error
221+
// sent from nom.tam.fits.
222+
FitsFactory.setLongStringsEnabled(false);
223+
224+
try {
225+
TableSequence tseq;
226+
StarTableFactory stFactory = new StarTableFactory();
227+
tseq = stFactory.makeStarTables(fits_filename, null);
228+
229+
for (StarTable tbl; (tbl = tseq.nextTable()) != null; ) {
230+
DescribedValue dValue = tbl.getParameterByName("ZIMAGE"); // check if 'BINTABLE' is actually compressed image HDU
231+
if (dValue == null || dValue.getValue() != Boolean.TRUE) {
232+
tList.add(tbl);
233+
}
234+
}
235+
236+
} catch (Exception e) {
237+
logger.error("unable to get table from fits file " + fits_filename + ", reason: " + e.getMessage());
223238
}
224239
return tList;
225240
}

src/firefly/java/edu/caltech/ipac/firefly/server/visualize/ImagePlotBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ static void initState(PlotState state,
440440
if (state.getContextString() == null) {
441441
state.setContextString(CtxControl.makeCachedCtx());
442442
}
443+
state.setTileCompress(fi.getFitsRead().isTileCompress(), band);
443444
state.setOriginalImageIdx(fi.getOriginalImageIdx(), band);
444445
PlotStateUtil.setOriginalFitsFile(state, fi.getOriginalFile(), band);
445446
PlotStateUtil.setWorkingFitsFile(state, fi.getWorkingFile(), band);

src/firefly/java/edu/caltech/ipac/firefly/server/visualize/VisJsonSerializer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ public static JSONObject serializeBandState(BandState b) {
379379
map.put("fitsHeader", serializeClientFitsHeader(b.getHeader()));
380380
map.put("bandVisible", b.isBandVisible());
381381
map.put("multiImageFile", b.isMultiImageFile());
382+
map.put("tileCompress", b.isTileCompress());
382383
map.put("cubeCnt", b.getCubeCnt());
383384
map.put("cubePlaneNumber", b.getCubePlaneNumber());
384385
return map;
@@ -398,6 +399,7 @@ public static BandState deserializeBandState(JSONObject map) {
398399
b.setFitsHeader(deserializeClientFitsHeader((JSONObject)map.get("fitsHeader")));
399400
b.setBandVisible((Boolean) map.get("bandVisible"));
400401
b.setMultiImageFile((Boolean) map.get("multiImageFile"));
402+
b.setTileCompress((Boolean) map.get("tileCompress"));
401403
b.setCubeCnt(getInt(map,"cubeCnt"));
402404
b.setCubePlaneNumber(getInt(map, "cubePlaneNumber"));
403405
return b;

src/firefly/java/edu/caltech/ipac/firefly/server/visualize/VisServerOps.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,12 @@ private static boolean isDirectFluxAccessAvailable(PlotState state) {
250250
if (state.getWorkingFitsFileStr(b).endsWith("gz")) {
251251
return false;
252252
}
253+
254+
if (state.isTileCompress(b)) {
255+
return false;
256+
}
253257
}
258+
254259
return true;
255260

256261

@@ -303,7 +308,6 @@ public static String[] getFlux(PlotState stateAry[], ImagePt ipt) {
303308
// 3. return all the gathered fluxes
304309
return fluxList.toArray(new String[fluxList.size()]);
305310
}
306-
307311
public static String[] getFileFlux(FileAndHeaderInfo fileAndHeader[], ImagePt ipt) {
308312
try {
309313
String retval[] = new String[fileAndHeader.length];

src/firefly/java/edu/caltech/ipac/firefly/visualize/BandState.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class BandState implements Serializable, HandSerialize {
3535
private String fitsHeaderSerialize = null; // Serialized ClientFitsHeader
3636
private boolean bandVisible = true;
3737
private boolean multiImageFile = false;
38+
private boolean tileCompress = false;
3839
private int cubeCnt = 0;
3940
private int cubePlaneNumber = 0;
4041

@@ -62,6 +63,11 @@ public void setMultiImageFile(boolean multiImageFile) {
6263
this.multiImageFile = multiImageFile;
6364
}
6465

66+
public boolean isTileCompress() {return tileCompress; }
67+
public void setTileCompress(boolean tCompress) {
68+
this.tileCompress = tCompress;
69+
}
70+
6571
public int getCubePlaneNumber() { return cubePlaneNumber; }
6672
public void setCubePlaneNumber(int cubePlaneNumber) { this.cubePlaneNumber = cubePlaneNumber; }
6773

@@ -165,6 +171,7 @@ public String toString() {
165171
fitsHeaderSerialize,
166172
bandVisible +"",
167173
multiImageFile+"",
174+
tileCompress+"",
168175
cubeCnt+"",
169176
cubePlaneNumber+"");
170177
}
@@ -186,6 +193,7 @@ public static BandState parse(String s) {
186193
ClientFitsHeader header= ClientFitsHeader.parse(sAry[i++]);
187194
boolean bandVisible= Boolean.parseBoolean(sAry[i++]);
188195
boolean multiImageFile= Boolean.parseBoolean(sAry[i++]);
196+
boolean tileCompress = Boolean.parseBoolean(sAry[i++]);
189197
int cubeCnt= Integer.parseInt(sAry[i++]);
190198
int cubePlaneNumber= Integer.parseInt(sAry[i++]);
191199
if (req!=null && header!=null ) {
@@ -200,6 +208,7 @@ public static BandState parse(String s) {
200208
retval.setFitsHeader(header);
201209
retval.setBandVisible(bandVisible);
202210
retval.setMultiImageFile(multiImageFile);
211+
retval.setTileCompress(tileCompress);
203212
retval.setCubeCnt(cubeCnt);
204213
retval.setCubePlaneNumber(cubePlaneNumber);
205214
}

src/firefly/java/edu/caltech/ipac/firefly/visualize/PlotState.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,15 @@ public boolean isMultiImageFile(Band band) {
229229
public boolean isMultiImageFile() { return get(firstBand()).isMultiImageFile(); }
230230
public void setMultiImageFile(boolean multiImageFile, Band band) { get(band).setMultiImageFile(multiImageFile); }
231231

232+
public boolean isTileCompress(Band band) {
233+
if (band==null) band= firstBand();
234+
return get(band).isTileCompress();
235+
}
236+
237+
@JsNoExport
238+
public boolean isTileCompress() { return get(firstBand()).isTileCompress(); }
239+
public void setTileCompress(boolean tileCompress, Band band) { get(band).setTileCompress(tileCompress); }
240+
232241
public int getCubeCnt(Band band) {
233242
if (band==null) band= firstBand();
234243
return get(band).getCubeCnt();
@@ -344,6 +353,10 @@ public Map<String,String> originKeyValues() {
344353
keyVals.put("multiImageFile", firstBandState.isMultiImageFile()+"");
345354
keyVals.put("imageIdx", firstBandState.getImageIdx()+"");
346355
}
356+
if (firstBandState.isTileCompress()) {
357+
keyVals.put("tileCompress", firstBandState.isTileCompress()+"");
358+
keyVals.put("imageIdx", firstBandState.getImageIdx()+"");
359+
}
347360
if (!firstBandState.isFileOriginal()) {
348361
keyVals.put("originalFile",firstBandState.getOriginalFitsFileStr());
349362
if (firstBandState.isMultiImageFile()) {

src/firefly/java/edu/caltech/ipac/firefly/visualize/PlotStateCI.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public interface PlotStateCI {
6060

6161

6262
boolean isMultiImageFile(Band band);
63+
boolean isTileCompress(Band band);
6364

6465
int getCubeCnt(Band band);
6566

src/firefly/java/edu/caltech/ipac/util/FitsHDUUtil.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package edu.caltech.ipac.util;
55

66
import edu.caltech.ipac.astro.IpacTableWriter;
7+
import nom.tam.image.compression.hdu.CompressedImageHDU;
78
import org.json.simple.JSONObject;
89
import nom.tam.fits.Fits;
910
import nom.tam.fits.FitsException;
@@ -123,7 +124,8 @@ public static DataGroup fitsHeaderToDataGroup(String fitsFile) {
123124
JSONObject extensionInfo;
124125
List<List<String>> headerRows = new ArrayList<>();
125126

126-
String name = "NoName";
127+
Boolean isCompressed = (hdu instanceof CompressedImageHDU);
128+
String name = isCompressed ? "CompressedImage" : "NoName";
127129
String type = "IMAGE";
128130

129131
Header hduHeader = hdu.getHeader();
@@ -144,7 +146,7 @@ public static DataGroup fitsHeaderToDataGroup(String fitsFile) {
144146
type = "";
145147
}
146148
} else {
147-
if (key.equals("XTENSION")) {
149+
if (key.equals("XTENSION") && (!isCompressed)) {
148150
type = val;
149151
} else if (key.equals("NAME") || key.equals("EXTNAME")) {
150152
name = val;
@@ -169,6 +171,7 @@ public static DataGroup fitsHeaderToDataGroup(String fitsFile) {
169171

170172
name = String.format("%s/%d cols x %d rows", name, colNo, rowNo);
171173
}
174+
172175
row.setDataElement(cols.get(1), (index == 0) ? "Primary" : name);
173176
row.setDataElement(cols.get(2), type);
174177
dg.add(row);

src/firefly/java/edu/caltech/ipac/visualize/plot/FitsRead.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import nom.tam.fits.ImageHDU;
1414
import nom.tam.util.ArrayFuncs;
1515
import nom.tam.util.Cursor;
16+
import nom.tam.image.compression.hdu.*;
1617

1718
import java.io.DataOutputStream;
1819
import java.io.FileOutputStream;
@@ -21,6 +22,7 @@
2122
import java.io.Serializable;
2223
import java.util.ArrayList;
2324
import java.util.Arrays;
25+
import java.nio.Buffer;
2426

2527

2628
/**
@@ -75,6 +77,7 @@ public class FitsRead implements Serializable {
7577
private int indexInFile = -1; // -1 unknown, >=0 index in file
7678
private Histogram hist;
7779
private double defBetaValue= Double.NaN;
80+
private boolean tileCompress = false;
7881

7982
private static ArrayList<Integer> SUPPORTED_BIT_PIXS = new ArrayList<Integer>(Arrays.asList(8, 16, 32, -32, -64));
8083

@@ -155,6 +158,7 @@ public static FitsRead[] createFitsReadArray(Fits fits, boolean clearHdu)
155158
throw new FitsException("Bad format in FITS file");
156159
}
157160

161+
boolean isCompressed = anyCompressedImage(HDUs);
158162

159163
ArrayList<BasicHDU> HDUList = getHDUList(HDUs);
160164

@@ -165,6 +169,7 @@ public static FitsRead[] createFitsReadArray(Fits fits, boolean clearHdu)
165169
for (int i = 0; i < HDUList.size(); i++) {
166170
fitsReadAry[i] = new FitsRead((ImageHDU) HDUList.get(i), clearHdu);
167171
fitsReadAry[i].indexInFile = i;
172+
fitsReadAry[i].tileCompress = isCompressed;
168173
}
169174

170175
return fitsReadAry;
@@ -188,6 +193,8 @@ public static FitsRead[] createFitsReadArray(Fits fits, BasicHDU hdu)
188193
}
189194

190195
BasicHDU[] HDUs={hdu};
196+
197+
boolean isCompressed = anyCompressedImage(HDUs);
191198
ArrayList<BasicHDU> HDUList = getHDUList(HDUs);
192199

193200
if (HDUList.size() == 0)
@@ -197,7 +204,7 @@ public static FitsRead[] createFitsReadArray(Fits fits, BasicHDU hdu)
197204
for (int i = 0; i < HDUList.size(); i++) {
198205
fitsReadAry[i] = new FitsRead( (ImageHDU) HDUList.get(i), false);
199206
fitsReadAry[i].indexInFile = i;
200-
207+
fitsReadAry[i].tileCompress = isCompressed;
201208
}
202209

203210

@@ -537,40 +544,55 @@ private static void updateHeader(Header header, int pos, long hduOffset)
537544
}
538545

539546

547+
private static boolean anyCompressedImage(BasicHDU[] HDUs) {
548+
for (int j = 0; j < HDUs.length; j++) {
549+
if (HDUs[j] instanceof CompressedImageHDU)
550+
return true;
551+
}
552+
return false;
553+
}
554+
540555
private static ArrayList<BasicHDU> getHDUList(BasicHDU[] HDUs) throws FitsException {
541556
ArrayList<BasicHDU> HDUList = new ArrayList<BasicHDU>();
542557

543558
boolean hasExtension = HDUs.length > 1 ? true : false;
544559
for (int j = 0; j < HDUs.length; j++) {
545-
if (!(HDUs[j] instanceof ImageHDU)) {
546-
continue; //ignor non-image extensions
560+
if (!(HDUs[j] instanceof ImageHDU) && !(HDUs[j] instanceof CompressedImageHDU)) {
561+
continue; //ignore non-image extensions
547562
}
548-
//process image HDU
549-
Header header = HDUs[j].getHeader();
550-
if (header == null)
551-
throw new FitsException("Missing header in FITS file");
563+
//process image HDU or compressed image HDU as ImageHDU
564+
565+
ImageHDU hdu = null;
552566

567+
try {
568+
hdu = (HDUs[j] instanceof ImageHDU) ? (ImageHDU) HDUs[j] : ((CompressedImageHDU) HDUs[j]).asImageHDU();
569+
} catch(Exception e) {
570+
throw new FitsException(e.toString());
571+
}
553572

573+
Header header = (hdu != null) ? hdu.getHeader() : null;
574+
if (header == null)
575+
throw new FitsException("Missing header in FITS file");
554576

555577
int naxis = header.getIntValue("NAXIS", -1);
556578
boolean goodImage = isImageGood(header);
557579

558580
if (goodImage) {
559581
if (hasExtension) { // update this hdu by adding keywords/values
560-
updateHeader(header, j, HDUs[j].getFileOffset());
582+
updateHeader(header, j, hdu.getFileOffset());
561583
}
562584

563585
int naxis3 = header.getIntValue("NAXIS3", -1);
564586
if ((naxis > 2) && (naxis3 > 1)) { //it is a cube data
565587
if (SUTDebug.isDebug())
566588
System.out.println("GOT A FITS CUBE");
567-
BasicHDU[] splitHDUs = splitFitsCube( (ImageHDU) HDUs[j]);
589+
BasicHDU[] splitHDUs = splitFitsCube( hdu );
568590
/* for each plane of cube */
569591
for (int jj = 0; jj < splitHDUs.length; jj++) {
570592
HDUList.add(splitHDUs[jj]);
571593
}
572594
} else {
573-
HDUList.add(HDUs[j]);
595+
HDUList.add(hdu);
574596
}
575597
}
576598

@@ -1673,6 +1695,7 @@ public int getExtensionNumber() {
16731695
return extension_number;
16741696
}
16751697

1698+
public boolean isTileCompress() { return tileCompress; }
16761699
/**
16771700
* The Bscale keyword shall be used, along with the BZERO keyword, when the array pixel values are not the true physical values,
16781701
* to transform the primary data array values to the true physical values they represent, using Eq. 5.3. The value field shall contain a

src/firefly/java/edu/caltech/ipac/visualize/plot/PixelValue.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public static void main(String[] args)
5858
{
5959
HDU_offset = myHDUs[i].getFileOffset();
6060
System.out.println("getFileOffset = " + myHDUs[i].getFileOffset());
61-
myHDUs[i].info();
61+
myHDUs[i].info(System.out);
6262
Header header = myHDUs[i].getHeader();
6363
header_size = header.getOriginalSize();
6464
System.out.println("header.getSize() = " + header.getSize());

0 commit comments

Comments
 (0)