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