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