001/***************************************************************************** 002 * Copyright by The HDF Group. * 003 * Copyright by the Board of Trustees of the University of Illinois. * 004 * All rights reserved. * 005 * * 006 * This file is part of the HDF Java Products distribution. * 007 * The full copyright notice, including terms governing use, modification, * 008 * and redistribution, is contained in the files COPYING and Copyright.html. * 009 * COPYING can be found at the root of the source code distribution tree. * 010 * Or, see https://support.hdfgroup.org/products/licenses.html * 011 * If you do not have access to either file, you may request a copy from * 012 * help@hdfgroup.org. * 013 ****************************************************************************/ 014 015package hdf.object.fits; 016 017import java.io.DataInput; 018import java.io.IOException; 019import java.io.InputStream; 020import java.io.RandomAccessFile; 021 022import hdf.object.Dataset; 023import hdf.object.Datatype; 024import hdf.object.FileFormat; 025import hdf.object.Group; 026import hdf.object.HObject; 027import nom.tam.fits.AsciiTableHDU; 028import nom.tam.fits.BasicHDU; 029import nom.tam.fits.BinaryTableHDU; 030import nom.tam.fits.Fits; 031import nom.tam.fits.ImageHDU; 032import nom.tam.fits.RandomGroupsHDU; 033import nom.tam.fits.TableHDU; 034 035/** 036 * This class provides file level APIs. File access APIs include retrieving the 037 * file hierarchy, opening and closing file, and writing file content to disk. 038 * <p> 039 * @version 2.4 9/4/2007 040 * @author Peter X. Cao 041 */ 042public class FitsFile extends FileFormat 043{ 044 private static final long serialVersionUID = -1965689032980605791L; 045 046 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(FitsFile.class); 047 048 /** 049 * The root object of the file hierarchy. 050 */ 051 private HObject rootObject; 052 053 /** the fits file */ 054 private Fits fitsFile; 055 056 private static boolean isFileOpen; 057 058 /** 059 * Constructs an empty FitsFile with read-only access. 060 */ 061 public FitsFile() { 062 this(""); 063 } 064 065 /** 066 * Constructs an FitsFile object of given file name with read-only access. 067 * @param pathname the file name. 068 */ 069 public FitsFile(String pathname) { 070 super(pathname); 071 072 isReadOnly = true; 073 isFileOpen = false; 074 this.fid = -1; 075 try { 076 fitsFile = new Fits(fullFileName); 077 } 078 catch (Exception ex) { 079 if(!pathname.isEmpty()) 080 log.debug("Fits({}):", fullFileName, ex); 081 } 082 } 083 084 085 /** 086 * Checks if the given file format is a Fits file. 087 * <p> 088 * @param fileformat the fileformat to be checked. 089 * @return true if the given file is an Fits file; otherwise returns false. 090 */ 091 @Override 092 public boolean isThisType(FileFormat fileformat) { 093 return (fileformat instanceof FitsFile); 094 } 095 096 /** 097 * Checks if a given file is a Fits file. 098 * <p> 099 * @param filename the file to be checked. 100 * @return true if the given file is an Fits file; otherwise returns false. 101 */ 102 @Override 103 public boolean isThisType(String filename) 104 { 105 boolean is_fits = false; 106 RandomAccessFile raf = null; 107 try { 108 raf = new RandomAccessFile(filename, "r"); 109 } 110 catch (Exception ex) { 111 raf = null; 112 } 113 114 if (raf == null) { 115 return false; 116 } 117 118 byte[] header = new byte[80]; 119 try { 120 raf.read(header); 121 } 122 catch (Exception ex) { 123 header = null; 124 } 125 126 if (header != null) { 127 String front = new String(header, 0, 9); 128 if (!front.startsWith("SIMPLE =")) { 129 try { 130 raf.close(); 131 } 132 catch (Exception ex) { 133 log.debug("closing RandomAccessFile({}):", filename, ex); 134 } 135 return false; 136 } 137 138 String back = new String(header, 9, 70); 139 back = back.trim(); 140 if ((back.length() < 1) || (back.charAt(0) != 'T')) { 141 try { 142 raf.close(); 143 } 144 catch (Exception ex) { 145 log.debug("closing RandomAccessFile({}):", filename, ex); 146 } 147 return false; 148 } 149 150 is_fits = true;; 151 } 152 153 try { 154 raf.close(); 155 } 156 catch (Exception ex) { 157 log.debug("closing RandomAccessFile({}):", filename, ex); 158 } 159 160 return is_fits; 161 } 162 163 164 /** 165 * Creates a FitsFile instance with specified file name and READ access. 166 * <p> 167 * @param filename the full path name of the file. 168 * @param access the access properties of the file. 169 * Regardless of specified access, the FitsFile implementation uses* READ. 170 */ 171 @Override 172 public FileFormat createInstance(String filename, int access) 173 throws Exception { 174 return new FitsFile(filename); 175 } 176 177 178 // Implementing FileFormat 179 @Override 180 public long open() throws Exception { 181 if (!isFileOpen) { 182 isFileOpen = true; 183 rootObject = loadTree(); 184 } 185 186 return 0; 187 } 188 189 private HObject loadTree() { 190 191 long[] oid = {0}; 192 // root object does not have a parent path or a parent node 193 FitsGroup rootGroup = new FitsGroup(this, "/", null, null, oid); 194 195 if (fitsFile == null) { 196 return rootGroup; 197 } 198 199 BasicHDU[] hdus = null; 200 201 try { 202 hdus = fitsFile.read(); 203 } 204 catch (Exception ex) { 205 log.debug("fitsFile.read():", ex); 206 } 207 208 if (hdus == null) { 209 return rootGroup; 210 } 211 212 int n = hdus.length; 213 int nImageHDU = 0; 214 int nTableHDU = 0; 215 String hduName = null; 216 BasicHDU hdu = null; 217 for (int i=0; i<n; i++) { 218 hdu = hdus[i]; 219 hduName = null; 220 // only deal with ImageHDU and TableHDU 221 if (hdu instanceof ImageHDU) { 222 hduName = "ImageHDU #"+nImageHDU++; 223 } 224 else if (hdu instanceof RandomGroupsHDU) { 225 hduName = "RandomGroupsHDU #"+nImageHDU++; 226 } 227 else if (hdu instanceof TableHDU) { 228 if (hdu instanceof AsciiTableHDU) { 229 hduName = "AsciiTableHDU #"+nTableHDU++; 230 } 231 else if (hdu instanceof BinaryTableHDU) { 232 hduName = "BinaryTableHDU #"+nTableHDU++; 233 } 234 else { 235 hduName = "TableHDU #"+nTableHDU++; 236 } 237 } 238 239 if (hduName != null) { 240 oid[0] = hdu.hashCode(); 241 FitsDataset d = new FitsDataset(this, hdu, hduName, oid); 242 rootGroup.addToMemberList(d); 243 } 244 } 245 246 return rootGroup; 247 } 248 249 // Implementing FileFormat 250 @Override 251 public void close() throws IOException { 252 if (fitsFile == null) { 253 return; 254 } 255 256 DataInput di = fitsFile.getStream(); 257 if (di instanceof InputStream) { 258 ((InputStream)di).close(); 259 } 260 } 261 262 // Implementing FileFormat 263 @Override 264 public HObject getRootObject() { 265 return rootObject; 266 } 267 268 public Fits getFitsFile() { 269 return fitsFile; 270 } 271 272 // implementign FileFormat 273 @Override 274 public Group createGroup(String name, Group pgroup) throws Exception { 275 throw new UnsupportedOperationException("Unsupported createGroup operation for Fits."); 276 } 277 278 // implementign FileFormat 279 @Override 280 public Datatype createDatatype(int tclass, int tsize, int torder, int tsign) throws Exception { 281 throw new UnsupportedOperationException("Unsupported createDatatype operation for Fits."); 282 } 283 284 // implementign FileFormat 285 @Override 286 public Datatype createNamedDatatype(Datatype tnative, String name) throws Exception { 287 throw new UnsupportedOperationException("Fits does not support named datatype."); 288 } 289 290 // implementign FileFormat 291 @Override 292 public Dataset createScalarDS(String name, Group pgroup, Datatype type, 293 long[] dims, long[] maxdims, long[] chunks, 294 int gzip, Object fillValue, Object data) throws Exception { 295 throw new UnsupportedOperationException("Unsupported createScalarDS operation."); 296 } 297 298 // implementign FileFormat 299 @Override 300 public Dataset createImage(String name, Group pgroup, Datatype type, 301 long[] dims, long[] maxdims, long[] chunks, 302 int gzip, int ncomp, int intelace, Object data) throws Exception { 303 throw new UnsupportedOperationException("Unsupported createImage operation."); 304 } 305 306 // implementing FileFormat 307 @Override 308 public void delete(HObject obj) throws Exception { 309 throw new UnsupportedOperationException("Unsupported delete operation."); 310 } 311 312 // implementing FileFormat 313 @Override 314 public HObject copy(HObject srcObj, Group dstGroup, String dstName) throws Exception { 315 throw new UnsupportedOperationException("Unsupported copy operation."); 316 } 317 318 /** copy a dataset into another group. 319 * @param srcDataset the dataset to be copied. 320 * @param pgroup the group where the dataset is copied to. 321 * @return the treeNode containing the new copy of the dataset. 322 */ 323 private void copyDataset(Dataset srcDataset, FitsGroup pgroup) throws Exception { 324 throw new UnsupportedOperationException("Unsupported copyDataset operation."); 325 } 326 327 private void copyGroup(FitsGroup srcGroup, FitsGroup pgroup) throws Exception { 328 throw new UnsupportedOperationException("Unsupported copyGroup operation."); 329 } 330 331 /* 332 * Copy attributes of the source object to the destination object. 333 */ 334 public void copyAttributes(HObject src, HObject dst) { 335 throw new UnsupportedOperationException("Unsupported copyAttributes operation."); 336 } 337 338 /* 339 * Copy attributes of the source object to the destination object. 340 */ 341 public void copyAttributes(long srcID, long dstID) { 342 throw new UnsupportedOperationException("Unsupported copyAttributes with id operation."); 343 } 344 345 /** 346 * Creates a new attribute and attached to the object if attribute does 347 * not exist. Otherwise, just update the value of the attribute. 348 * 349 * <p> 350 * @param obj the object which the attribute is to be attached to. 351 * @param attr the atribute to attach. 352 * @param attrExisted The indicator if the given attribute exists. 353 */ 354 @Override 355 public void writeAttribute(HObject obj, hdf.object.Attribute attr, boolean attrExisted) throws Exception { 356 throw new UnsupportedOperationException("Unsupported operation."); 357 } 358 359 /** 360 * Returns the version of the library. 361 */ 362 @Override 363 public String getLibversion() 364 { 365 String ver = "Fits Java (version 2.4)"; 366 367 return ver; 368 } 369 370 // implementing FileFormat 371 @Override 372 public HObject get(String path) throws Exception 373 { 374 throw new UnsupportedOperationException("get() is not supported"); 375 } 376} 377