casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
FITSTable.h
Go to the documentation of this file.
00001 //# FITSTable.h: Simplified interface to FITS tables with AIPS++ Look and Feel.
00002 //# Copyright (C) 1995,1996,1997,1999,2000,2001
00003 //# Associated Universities, Inc. Washington DC, USA.
00004 //#
00005 //# This library is free software; you can redistribute it and/or modify it
00006 //# under the terms of the GNU Library General Public License as published by
00007 //# the Free Software Foundation; either version 2 of the License, or (at your
00008 //# option) any later version.
00009 //#
00010 //# This library is distributed in the hope that it will be useful, but WITHOUT
00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013 //# License for more details.
00014 //#
00015 //# You should have received a copy of the GNU Library General Public License
00016 //# along with this library; if not, write to the Free Software Foundation,
00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
00018 //#
00019 //# Correspondence concerning AIPS++ should be addressed as follows:
00020 //#        Internet email: aips2-request@nrao.edu.
00021 //#        Postal address: AIPS++ Project Office
00022 //#                        National Radio Astronomy Observatory
00023 //#                        520 Edgemont Road
00024 //#                        Charlottesville, VA 22903-2475 USA
00025 //#
00026 //#
00027 //# $Id: FITSTable.h 20299 2008-04-03 05:56:44Z gervandiepen $
00028 
00029 #ifndef FITS_FITSTABLE_H
00030 #define FITS_FITSTABLE_H
00031 
00032 
00033 #include <casa/aips.h>
00034 #include <casa/Containers/Record.h>
00035 #include <tables/Tables/TableRecord.h>
00036 #include <casa/Containers/Block.h>
00037 #include <fits/FITS/hdu.h>
00038 #include <fits/FITS/fitsio.h>
00039 #include <casa/iosfwd.h>
00040 
00041 namespace casa { //# NAMESPACE CASA - BEGIN
00042 
00043 class String;
00044 class FITSFieldCopier;
00045 class TableDesc;
00046 template<class T> class Vector;
00047 
00048 // <summary>
00049 // Simplified interface to FITS tables with AIPS++ Look and Feel.
00050 // </summary>
00051 //
00052 // <use visibility=export>
00053 //
00054 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00055 // </reviewed>
00056 //
00057 // <prerequisite>
00058 //   <li> General knowledge of FITS binary and ASCII tables.
00059 // </prerequisite>
00060 //
00061 // <etymology>
00062 // </etymology>
00063 //
00064 // <synopsis>
00065 // FITSTablular is an obstract base class which is used for read-only access to
00066 // tabular FITS-like data structures.
00067 // </synopsis>
00068 //
00069 // <example>
00070 // </example>
00071 //
00072 // <motivation>
00073 // </motivation>
00074 //
00075 // <todo asof="1995/06/01">
00076 //   <li> Eventually we'd like to be able to write the tables as well as read
00077 //        them.
00078 // </todo>
00079 
00080 class FITSTabular
00081 {
00082 public:
00083     virtual ~FITSTabular();
00084     // isValid() returns False if this object isn't a valid Tabular data
00085     // structure.
00086     virtual Bool isValid() const = 0;
00087     // Returns keywords which are associated with the underlying FITS files.
00088     virtual const TableRecord &keywords() const = 0;
00089     // Returns the description of the underlying FITS table.
00090     virtual const RecordDesc &description() const = 0;
00091     // Returns any TUNITnnn associated with a column (the field names
00092     // are the column names, each field value is the TUNITnnn value for
00093     // that field).  Note that only those columns with a non-empty
00094     // TUNITnnn have an entry in the units() Record. 
00095     virtual const Record &units() const = 0;
00096     // Returns any TDISPnnn associated with a column (the field names
00097     // are the column names, each field value is the TDISPnnn value for
00098     // that field).  Note that only those columns with a non-empty
00099     // TDISPnnn have an entry in the displayFormats() Record.
00100     virtual const Record &displayFormats() const = 0;
00101     // Returns any TNULLnnn associated with a column (the field names
00102     // are the column names, each field value is the TNULLnnn value for
00103     // that field).  Note that only those columns with a specific entry for
00104     // TNULLnnn and which have not been promoted to doubles due TSCAL
00105     // and TZERO values will have an entry in the nulls() Record.
00106     // The meaning of TNULL is only defined for integer and byte columns. 
00107     // When a column is promoted to a double because of scaling,
00108     // any TNULL values will be assigned a value of NaN.
00109     virtual const Record &nulls() const = 0;
00110 
00111     // Returns True if we have advanced past the end of data.
00112     virtual Bool pastEnd() const = 0;
00113 
00114     // Advance the row if possible (guaranteed harmless if pastEnd() is True.
00115     virtual void next() = 0;
00116 
00117     // Reopen the table, default behavior is to do nothing, return False
00118     virtual Bool reopen(const String&) { return False; }
00119 
00120     // return the name
00121     virtual const String &name() const = 0;
00122 
00123     // Has the description changed since construction, default is False
00124     virtual Bool hasChanged() const { return False;}
00125     // reset the changed flag, default do nothing
00126     virtual void resetChangedFlag() {;}
00127 
00128     // Return the currentRow. This is guaranteed to be valid so long as only
00129     // member functions of this base class are called (so you can safely attach
00130     // RecordFieldPtr objects to it. The result is undefined if pastEnd() is True.
00131     virtual const Record &currentRow() const = 0;
00132 
00133     // Helper function for retrieving keywords from a native-FITS hdu.
00134     // If allKeywords is not True, some keywords will be excluded
00135     // from the list.  Currently the list of excluded keywords
00136     // includes TTYPEnnn, TFORMnnn, and TUNITnnn
00137     static TableRecord keywordsFromHDU(HeaderDataUnit &hdu,
00138                                        Bool allKeywords = False);
00139 
00140     // Helper function for retrieving a description from a native-FITS hdu.
00141     static RecordDesc descriptionFromHDU(BinaryTableExtension &hdu);
00142 
00143     // Help function for retrieving any shape information from String columns
00144     // using the SubString convention.
00145     // Information is returned in a Record having named fields = all String
00146     // columns following those convention. Each of these fields is, in turn,
00147     // a sub-record having these three fields: NCHAR, NELEM, DELIM.  
00148     // If NELEM == -1 then there must have been a DELIM specified and
00149     // this field is a variable shaped string array where each element has
00150     // at most NCHAR and they are separated by DELIM (which is a String field here).
00151     // Otherwise, DELIM is not used and there are NCHAR per element for each
00152     // of NELEM in each cell for this column.
00153     static Record subStringShapeFromHDU(BinaryTableExtension &hdu);
00154 
00155     // Helper function for retrieving the TUNITnnn from a native-FITS hdu.
00156     static Record unitsFromHDU(BinaryTableExtension &hdu);
00157 
00158     // Helper function for retrieving the TDISPnnn from a native-FITS hdu.
00159     static Record displayFormatsFromHDU(BinaryTableExtension &hdu);
00160 
00161     // Helper function for retrieving the TNULLnnn from a native-FITS hdu.
00162     static Record nullsFromHDU(BinaryTableExtension &hdu);
00163 
00164     // Get a TableDesc appropriate to hold a FITSTabular
00165     // the keywords, description, units, displayFormats, and nulls are all used
00166     static TableDesc tableDesc(const FITSTabular &fitstabular);
00167 };
00168 
00169 // <summary>
00170 // Attach a FITSTabular to a binary or ASCII table
00171 // </summary>
00172 //
00173 // <use visibility=export>
00174 //
00175 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00176 // </reviewed>
00177 //
00178 // <prerequisite>
00179 //   <li> General knowledge of FITS binary and ASCII tables.
00180 // </prerequisite>
00181 //
00182 // <etymology>
00183 // </etymology>
00184 //
00185 // <synopsis>
00186 // FITSTable is a FITSTabular which is attached to a FITS table (on disk only
00187 // presently), either Binary or ASCII.
00188 // </synopsis>
00189 //
00190 // <example>
00191 // </example>
00192 //
00193 // <motivation>
00194 // </motivation>
00195 //
00196 // <todo asof="1995/06/01">
00197 //   <li>
00198 // </todo>
00199 
00200 class FITSTable : public FITSTabular
00201 {
00202 public:
00203     // this creates an invalid (isValid() return False) FITSTable
00204     // Its primary purpose is so that FITSTables can be created before
00205     // the file name is known.  reopen() is then used to open the file.
00206     FITSTable(uInt whichHDU=1, Bool allKeywords=False);
00207 
00208     // 0-relative HDU. It can never be zero by the FITS rules.
00209     // allKeywords is passed to FITSTabular::keywordsFromHDU
00210     // See the documentation for that function for a list of
00211     // excluded keywords when allKeywords is False.
00212     FITSTable(const String &fileName, uInt whichHDU=1,
00213               Bool allKeywords = False);
00214     ~FITSTable() { clear_self();}
00215 
00216     // Has the end of file been reached yet
00217     virtual Bool eof() const {return io_p->eof();}
00218 
00219     // Attach this FITSTable to a new file name, same HDU# as at open time
00220     virtual Bool reopen(const String &fileName);
00221     virtual const String& name() const { return name_p;}
00222 
00223     virtual Bool isValid() const {return isValid_p;}
00224 
00225     virtual const TableRecord &keywords() const {return keywords_p;}
00226     virtual const RecordDesc &description() const {return description_p;}
00227     virtual const Record &units() const {return units_p;}
00228     virtual const Record &displayFormats() const {return disps_p;}
00229     virtual const Record &nulls() const {return nulls_p;}
00230 
00231     virtual Bool pastEnd() const;
00232     virtual void next();
00233     virtual const Record &currentRow() const;
00234 
00235     // single FITS tables know how many rows there are
00236     // unlike general FITSTabulars, which may not know
00237     // (e.g. if it is a FITSMultiTable)
00238     virtual uInt nrow() const {return raw_table_p->nrows();}
00239 
00240     // these tables should also know where they are
00241     virtual Int rownr() const {return row_nr_p;}
00242 
00243     // and it should be possible to move to a desired row
00244     // the rownr() member can be used to verify that a move 
00245     // was successful - this will happen if the requested row
00246     // was < rownr() or >= nrow() - i.e. movements backwards or
00247     // beyond the end of the file are not possible.
00248     virtual void move(Int torow);
00249 
00250     // the keywords from the Primary HDU
00251     virtual const TableRecord &primaryKeywords() const {return primaryKeys_p;}
00252 protected:
00253     // SDFITSTable needs to make some keywords appear as
00254     // columns, this requires access to description_p, keywords_p, and
00255     // row_p.  However, its not something that typical FITSTable 
00256     // users will want.  Therefore, I've provided this protected
00257     // function for SDFITSTable to use so as to not have to provide
00258     // direct access to those data members at the public level.
00259     // The named keywords and values are appended to the end of
00260     // row_p and removed from keywords_p, description_p is modified
00261     // appropriately.  The returned value is False if any named
00262     // keyword did not appear in keywords_p (however, all named
00263     // keywords that DO appear in keywords_p will have been correctly
00264     // moved).
00265     Bool virtualColumns(const Vector<String>& keyNames); 
00266 private:
00267     // Undefined and inaccessible. An alternative would be to use reference
00268     // semantics like Table.
00269     FITSTable(const FITSTable &);
00270     FITSTable &operator=(const FITSTable &);
00271 
00272     void fill_row();
00273     void clear_self();
00274 
00275     Bool isValid_p;
00276 
00277     String name_p;
00278 
00279     uInt hdu_nr_p;
00280 
00281     Int row_nr_p;
00282     BinaryTableExtension *raw_table_p;
00283     FitsInput *io_p;
00284     TableRecord keywords_p;
00285     TableRecord primaryKeys_p;
00286     RecordDesc description_p;
00287     Record row_p;
00288     Record units_p;
00289     Record disps_p;
00290     Record nulls_p;
00291     Record subStrShapes_p;
00292     Bool allKeys_p;
00293     // One per field in row_p, of the right type. i.e. casting required.
00294     uInt nfields_p;
00295     Block<void *> row_fields_p;
00296     Block<Int> field_types_p;
00297     Block<Bool> promoted_p;
00298     Block<Int> tdims_p;
00299     // these are used by VADESC columns
00300     Block<Int> vatypes_p;
00301     Block<void *> vaptr_p;
00302     // I had trouble making a Block<VADescFitsField>
00303     VADescFitsField *va_p;
00304     char *theheap_p;
00305 
00306     // It is necessary to read the PDA to get the primary keywords.
00307     // If there is any data there, the FITS classes do not provide any way to
00308     // just skip over them to get to the next HDU.  The only way to do that is
00309     // to actually read all of the data.  If there is no data, this step is
00310     // unnecessary and so this subroutine need only be called after the primary
00311     // keywords have been read AND the PDA has some data in it.  Closing the
00312     // FitsInput and reopening it is faster in most cases than reading in each
00313     // data value.
00314     void reopenAtFirstHDU(const String &name);
00315 };
00316 
00317 // <summary>
00318 // Simplified interface to create and write to a FITS Binary Table
00319 // </summary>
00320 //
00321 // <use visibility=export>
00322 //
00323 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00324 // </reviewed>
00325 //
00326 // <prerequisite>
00327 //   <li> General knowledge of FITS binary and ASCII tables.
00328 // </prerequisite>
00329 //
00330 // <etymology>
00331 // </etymology>
00332 //
00333 // <synopsis>
00334 // </synopsis>
00335 //
00336 // <example>
00337 // </example>
00338 //
00339 // <motivation>
00340 // </motivation>
00341 //
00342 // <todo asof="1995/06/01">
00343 //   <li> probably much
00344 // </todo>
00345 
00346 class FITSTableWriter
00347 {
00348 public:
00349     enum {DefaultMaxStringSize = 16};
00350 
00351     // You MUST have already written a first HDU to FitsOutput.
00352     // description contains the names and types of the table columns to be written.
00353     // The row is not rearranged (i.e. they are used in order) for alignment purposes.
00354     // Array columns must have fixed shape unless tdimColumns is used. Use the 
00355     // maxLengths record to indicate any string columns which should have a length other 
00356     // than the default value by providing an int field of the same name as the string 
00357     // field in this record.
00358     // The size of the table (nrows) must be given at creation.  Use extraKeywords to
00359     // indicate any keywords not automatically created.  The units record is used to
00360     // indicate the units for any column.  Provide a string field with the same name as
00361     // the column field in description.  If freeOutput is True, file must come from new
00362     // since it will be deleted upon destruction.  You might not want this to happen if
00363     // you are going to write many tables to the same fits file.  Use variableShapes to
00364     // signal which array columns have variable shape and use maxLengths to indicate
00365     // the maximum size of those variable shaped columns.  The variableShapes record
00366     // should contain a String corresponding to the longest TDIM value appropriate for
00367     // each variable shaped column.  The maxLengths record should contain an int field
00368     // for each variable shaped column which indicates the maximum number of elements
00369     // to be found in that column.  Unused values in any cell in the variable shaped
00370     // columns will be filled with zero.  These columns will use the SDFITS TDIM convention
00371     // where for column nnn there is a corresponding TDIMnnn column where
00372     // the values in each row are the true shape of the data in column nnn.
00373     // variableShapes appears as the last argument for backwards compatibility with
00374     // existing code.
00375     FITSTableWriter(FitsOutput *file, 
00376                     const RecordDesc &description,
00377                     const Record &maxLengths,
00378                     uInt nrows,
00379                     const Record &extraKeywords,
00380                     const Record &units,
00381                     Bool freeOutput = True,
00382                     const Record &variableShapes = Record());
00383 
00384     ~FITSTableWriter();
00385 
00386     // use this to set the value of the current row to be written
00387     RecordInterface &row() {return row_p;}
00388 
00389     // Write the current row()
00390     void write();
00391 
00392     // Don't delete this out from under us!
00393     FitsOutput *writer() {return writer_p;}
00394 
00395     // Returns a writer, with the first HDU filled in (set to null). The caller
00396     // is responsible for deleting the pointer returned from makeWriter.
00397     static FitsOutput *makeWriter(const String &fileName);
00398 private:
00399     // Undefined and inaccessible
00400     FITSTableWriter();
00401     FITSTableWriter(const FITSTableWriter&);
00402     FITSTableWriter& operator=(const FITSTableWriter&);
00403 
00404     Bool delete_writer_p;
00405     FitsOutput *writer_p;
00406     uInt nrows_written_p;
00407     BinaryTableExtension *bintable_p;
00408     Record row_p;
00409     PtrBlock<FITSFieldCopier *> copiers_p;
00410 };
00411 
00412 // <summary>
00413 // Simplified interface to create and write to FITS random groups
00414 // </summary>
00415 //
00416 // <use visibility=export>
00417 //
00418 // <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
00419 // </reviewed>
00420 //
00421 // <prerequisite>
00422 //   <li> General knowledge of FITS binary and ASCII tables.
00423 // </prerequisite>
00424 //
00425 // <etymology>
00426 // </etymology>
00427 //
00428 // <synopsis>
00429 // Like FITSTableWriter except that this must be the first HDU and
00430 // all "columns" in the description must have the same type, i.e. float.
00431 // </synopsis>
00432 //
00433 // <example>
00434 // </example>
00435 //
00436 // <motivation>
00437 // </motivation>
00438 //
00439 // <todo asof="1995/06/01">
00440 //   <li> probably much
00441 // </todo>
00442 
00443 class FITSGroupWriter
00444 {
00445 public:
00446     // Since this must always be the first HDU, there is no point in constructing it
00447     // with a FitsOutput.  description indicates the names of the random groups parameters.
00448     // nrows is a synonym for ngroups.  Use extraKeywords to
00449     // indicate any keywords not automatically created (SIMPLE, BITPIX, NAXIS*, EXTEND,
00450     // BLOCKED, GROUPS, PCOUNT, GOUNT, ORIGIN, END). If freeOutput is True, file will be
00451     // deleted by the destructor.  You might not want this to happen if
00452     // you are going to write any extensions to the same fits file.  You can get the
00453     // FitsOutput used here from write()
00454     FITSGroupWriter(const String &fileName,
00455                     const RecordDesc &description,
00456                     uInt nrows,
00457                     const Record &extraKeywords,
00458                     Bool freeOutput = True);
00459 
00460     ~FITSGroupWriter();
00461 
00462     // Set the values for the current group
00463     RecordInterface &row() {return row_p;}
00464 
00465     // Write the current group (row()).
00466     void write();
00467 
00468     // Don't delete this out from under us!
00469     FitsOutput *writer() {return writer_p;}
00470 private:
00471     // Undefined and inaccessible
00472     FITSGroupWriter();
00473     FITSGroupWriter(const FITSGroupWriter&);
00474     FITSGroupWriter& operator=(const FITSGroupWriter&);
00475 
00476     Bool delete_writer_p;
00477     FitsOutput *writer_p;
00478     uInt nrows_written_p, nrows_total_p;
00479     PrimaryGroup<Float> *group_p;
00480     Record row_p;
00481     Int error_count_p;
00482 
00483     // Checks error status of writer_p and group_p. Cleans up and throws an exception if bad.
00484     void check_error(const char *extra_info = 0);
00485 };
00486 
00487 } //# NAMESPACE CASA - END
00488 
00489 #endif