ColumnData.h

00001 //   Read the documentation to learn more about C++ code generator
00002 //   versioning.
00003 //      This is version 1.7 release dated June 2007
00004 //      Astrophysics Science Division,
00005 //      NASA/ Goddard Space Flight Center
00006 //      HEASARC
00007 //      http://heasarc.gsfc.nasa.gov
00008 //      e-mail: ccfits@legacy.gsfc.nasa.gov
00009 //
00010 //      Original author: Ben Dorman, L3-Communications EER Systems Inc.
00011 
00012 #ifndef COLUMNDATA_H
00013 #define COLUMNDATA_H 1
00014 #include "CCfits.h"
00015 
00016 // Column
00017 #include "Column.h"
00018 // vector
00019 #include <vector>
00020 #ifdef _MSC_VER
00021 #include "MSconfig.h"
00022 #endif
00023 
00024 #include <complex>
00025 #include <memory>
00026 #include "FITSUtil.h"
00027 using std::complex;
00028 #include "FITS.h"
00029 
00030 
00031 namespace CCfits {
00032 
00033 
00034 
00035   template <typename T>
00036   class ColumnData : public Column  //## Inherits: <unnamed>%385E51565EE8
00037   {
00038 
00039     public:
00040         ColumnData(const ColumnData< T > &right);
00041         ColumnData (Table* p = 0, T nullVal = FITSUtil::FitsNullValue<T>()());
00042         ColumnData (int columnIndex, const string &columnName, ValueType type, const String &format, const String &unit, Table* p, int rpt = 1, long w = 1, const String &comment = "", T nullVal = FITSUtil::FitsNullValue<T>()());
00043         ~ColumnData();
00044 
00045         virtual ColumnData<T>* clone () const;
00046         virtual void readData (long firstRow, long nelements, long firstElem = 1);
00047         void setDataLimits (T* limits);
00048         const T minLegalValue () const;
00049         void minLegalValue (T value);
00050         const T maxLegalValue () const;
00051         void maxLegalValue (T value);
00052         const T minDataValue () const;
00053         void minDataValue (T value);
00054         const T maxDataValue () const;
00055         void maxDataValue (T value);
00056         const std::vector<T>& data () const;
00057         void setData (const std::vector<T>& value);
00058         T data (int i);
00059         void data (int i, T value);
00060 
00061       // Additional Public Declarations
00062         friend class Column;
00063     protected:
00064       // Additional Protected Declarations
00065 
00066     private:
00067         ColumnData< T > & operator=(const ColumnData< T > &right);
00068 
00069         void readColumnData (long firstRow, long nelements, T* nullValue = 0);
00070         virtual bool compare (const Column &right) const;
00071         virtual std::ostream& put (std::ostream& s) const;
00072         void writeData (T* indata, long nRows = 1, long firstRow = 1, T* nullValue = 0);
00073         void writeData (const std::vector<T>& indata, long firstRow = 1, T* nullValue = 0);
00074         //      Insert one or more blank rows into a FITS column.
00075         virtual void insertRows (long first, long number = 1);
00076         virtual void deleteRows (long first, long number = 1);
00077         const T nullValue () const;
00078         void nullValue (T value);
00079 
00080       // Additional Private Declarations
00081 
00082     private: //## implementation
00083       // Data Members for Class Attributes
00084         T m_nullValue;
00085         T m_minLegalValue;
00086         T m_maxLegalValue;
00087         T m_minDataValue;
00088         T m_maxDataValue;
00089 
00090       // Data Members for Associations
00091         std::vector<T> m_data;
00092 
00093       // Additional Implementation Declarations
00094 
00095   };
00096 
00097   // Parameterized Class CCfits::ColumnData 
00098 
00099   template <typename T>
00100   inline void ColumnData<T>::readData (long firstRow, long nelements, long firstElem)
00101   {
00102    readColumnData(firstRow,nelements,static_cast<T*>(0));
00103   }
00104 
00105   template <typename T>
00106   inline const T ColumnData<T>::nullValue () const
00107   {
00108     return m_nullValue;
00109   }
00110 
00111   template <typename T>
00112   inline void ColumnData<T>::nullValue (T value)
00113   {
00114     m_nullValue = value;
00115   }
00116 
00117   template <typename T>
00118   inline const T ColumnData<T>::minLegalValue () const
00119   {
00120     return m_minLegalValue;
00121   }
00122 
00123   template <typename T>
00124   inline void ColumnData<T>::minLegalValue (T value)
00125   {
00126     m_minLegalValue = value;
00127   }
00128 
00129   template <typename T>
00130   inline const T ColumnData<T>::maxLegalValue () const
00131   {
00132     return m_maxLegalValue;
00133   }
00134 
00135   template <typename T>
00136   inline void ColumnData<T>::maxLegalValue (T value)
00137   {
00138     m_maxLegalValue = value;
00139   }
00140 
00141   template <typename T>
00142   inline const T ColumnData<T>::minDataValue () const
00143   {
00144     return m_minDataValue;
00145   }
00146 
00147   template <typename T>
00148   inline void ColumnData<T>::minDataValue (T value)
00149   {
00150     m_minDataValue = value;
00151   }
00152 
00153   template <typename T>
00154   inline const T ColumnData<T>::maxDataValue () const
00155   {
00156     return m_maxDataValue;
00157   }
00158 
00159   template <typename T>
00160   inline void ColumnData<T>::maxDataValue (T value)
00161   {
00162     m_maxDataValue = value;
00163   }
00164 
00165   template <typename T>
00166   inline const std::vector<T>& ColumnData<T>::data () const
00167   {
00168     return m_data;
00169   }
00170 
00171   template <typename T>
00172   inline void ColumnData<T>::setData (const std::vector<T>& value)
00173   {
00174     m_data = value;
00175   }
00176 
00177   template <typename T>
00178   inline T ColumnData<T>::data (int i)
00179   {
00180     // return data stored in the ith row, which is in the i-1 th location in the array.
00181     return m_data[i - 1];
00182   }
00183 
00184   template <typename T>
00185   inline void ColumnData<T>::data (int i, T value)
00186   {
00187     // assign data to i-1 th location in the array, representing the ith row.
00188     m_data[i - 1] = value;
00189   }
00190 
00191   // Parameterized Class CCfits::ColumnData 
00192 
00193   template <typename T>
00194   ColumnData<T>::ColumnData(const ColumnData<T> &right)
00195       :Column(right),
00196        m_nullValue(right.m_nullValue),
00197        m_minLegalValue(right.m_minLegalValue),
00198        m_maxLegalValue(right.m_maxLegalValue),
00199        m_minDataValue(right.m_minDataValue),
00200        m_maxDataValue(right.m_maxDataValue),
00201        m_data(right.m_data)
00202   {
00203   }
00204 
00205   template <typename T>
00206   ColumnData<T>::ColumnData (Table* p, T nullVal)
00207   : Column(p), m_nullValue(nullVal),
00208        m_minLegalValue(),
00209        m_maxLegalValue(),
00210        m_minDataValue(),
00211        m_maxDataValue(), 
00212        m_data()
00213   {
00214   }
00215 
00216   template <typename T>
00217   ColumnData<T>::ColumnData (int columnIndex, const string &columnName, ValueType type, const String &format, const String &unit, Table* p, int rpt, long w, const String &comment, T nullVal)
00218         : Column(columnIndex,columnName,type,format,unit,p,rpt,w,comment), 
00219         m_nullValue(nullVal), 
00220         m_minLegalValue(),
00221         m_maxLegalValue(),
00222         m_minDataValue(),
00223         m_maxDataValue(),
00224         m_data()
00225   {
00226   }
00227 
00228 
00229   template <typename T>
00230   ColumnData<T>::~ColumnData()
00231   {
00232   }
00233 
00234 
00235   template <typename T>
00236   void ColumnData<T>::readColumnData (long firstRow, long nelements, T* nullValue)
00237   {
00238   if ( rows() < nelements ) 
00239   {
00240         std::cerr << "CCfits: More data requested than contained in table. ";
00241         std::cerr << "Extracting complete column.\n";
00242         nelements = rows();
00243    }   
00244 
00245    int   status(0);
00246    int   anynul(0);
00247 
00248    FITSUtil::auto_array_ptr<T> array(new T[nelements]); 
00249 
00250    makeHDUCurrent();
00251 
00252    if ( fits_read_col(fitsPointer(),type(),  index(), firstRow, 1, 
00253         nelements, nullValue, array.get(), &anynul, &status) ) throw FitsError(status);
00254 
00255 
00256    if (m_data.size() != static_cast<size_t>( rows() ) ) m_data.resize(rows());
00257 
00258    std::copy(&array[0],&array[nelements],m_data.begin()+firstRow-1);
00259    if (nelements == rows()) isRead(true); 
00260   }
00261 
00262   template <typename T>
00263   bool ColumnData<T>::compare (const Column &right) const
00264   {
00265   if ( !Column::compare(right) ) return false;
00266   const ColumnData<T>& that = static_cast<const ColumnData<T>&>(right);
00267   unsigned int n = m_data.size();
00268   if ( that.m_data.size() != n ) return false;
00269   for (unsigned int i = 0; i < n ; i++)
00270   {
00271         if (m_data[i] != that.m_data[i]) return false;   
00272   }
00273   return true;
00274   }
00275 
00276   template <typename T>
00277   ColumnData<T>* ColumnData<T>::clone () const
00278   {
00279         return new ColumnData<T>(*this);
00280   }
00281 
00282   template <typename T>
00283   std::ostream& ColumnData<T>::put (std::ostream& s) const
00284   {
00285   Column::put(s);
00286   if (FITS::verboseMode() && type() != Tstring)
00287   {
00288         s << " Column Legal limits: ( " << m_minLegalValue << "," << m_maxLegalValue << " )\n" 
00289         << " Column Data  limits: ( " << m_minDataValue << "," << m_maxDataValue << " )\n";
00290   }
00291   if (!m_data.empty())
00292   {
00293         std::ostream_iterator<T> output(s,"\n");
00294         // output each row on a separate line.
00295         // user can supply manipulators to stream for formatting.
00296         std::copy(m_data.begin(),m_data.end(),output);
00297   }
00298 
00299     return s;
00300   }
00301 
00302   template <typename T>
00303   void ColumnData<T>::writeData (T* indata, long nRows, long firstRow, T* nullValue)
00304   {
00305 
00306           // set columnData's data member to equal what's written to file.
00307           // indata has size nRows: elements firstRow to firstRow + nRows - 1 will be written.
00308           // if this exceeds the current rowlength of the HDU, update the return value for
00309           // rows() in the parent after the fitsio call.
00310           int status(0);
00311           long elementsToWrite(nRows + firstRow -1);
00312           // get a copy for restorative action.   
00313           std::vector<T> __tmp(m_data);
00314 
00315           if (nullValue) m_nullValue = *nullValue;
00316 
00317           if (elementsToWrite != static_cast<long>(m_data.size())) 
00318           {
00319 
00320                   m_data.resize(elementsToWrite,T());
00321           }
00322 
00323           std::copy(&indata[0],&indata[nRows],m_data.begin()+firstRow-1);
00324 
00325           // if successful, write to disk.
00326 
00327           try
00328           {
00329 
00330                 if (fits_write_colnull(fitsPointer(), type(), index(), firstRow, 1, nRows,
00331                                   indata, nullValue, &status) != 0) throw FitsError(status);
00332 
00333                 // tell the Table that the number of rows has changed
00334                 parent()->updateRows();
00335           }
00336           catch (FitsError) // the only thing that can throw here.
00337           {
00338                   // reset to original content and rethrow the exception.
00339                   m_data = __tmp;
00340                   if (status == NO_NULL) throw NoNullValue(name());
00341                   else throw;
00342           }      
00343   }
00344 
00345   template <typename T>
00346   void ColumnData<T>::writeData (const std::vector<T>& indata, long firstRow, T* nullValue)
00347   {
00348         FITSUtil::CVarray<T> convert;
00349         FITSUtil::auto_array_ptr<T> pcolData (convert(indata));
00350         T* columnData  = pcolData.get();
00351         writeData(columnData,indata.size(),firstRow,nullValue);
00352   }
00353 
00354   template <typename T>
00355   void ColumnData<T>::insertRows (long first, long number)
00356   {
00357     FITSUtil::FitsNullValue<T> blank;
00358     typename std::vector<T>::iterator in;
00359     if (first !=0) 
00360     {
00361             in = m_data.begin()+first;
00362     }
00363     else
00364     {
00365             in = m_data.begin();
00366     }           
00367 
00368     // non-throwing operations.
00369     m_data.insert(in,number,blank());
00370   }
00371 
00372   template <typename T>
00373   void ColumnData<T>::deleteRows (long first, long number)
00374   {
00375     m_data.erase(m_data.begin()+first-1,m_data.begin()+first-1+number);
00376   }
00377 
00378   template <typename T>
00379   void ColumnData<T>::setDataLimits (T* limits)
00380   {
00381     m_minLegalValue = limits[0];
00382     m_maxLegalValue = limits[1];
00383     m_minDataValue = std::max(limits[2],limits[0]);
00384     m_maxDataValue = std::min(limits[3],limits[1]);
00385   }
00386 
00387   // Additional Declarations
00388 
00389   // all functions that operate on strings or complex data that call cfitsio 
00390   // need to be specialized.
00391 
00392 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00393 template <>
00394 inline void ColumnData<complex<float> >::setDataLimits (complex<float>* limits)
00395        {
00396                 m_minLegalValue = limits[0];
00397                 m_maxLegalValue = limits[1];
00398                 m_minDataValue =  limits[2];
00399                 m_maxDataValue =  limits[3];
00400         }
00401 #else
00402 template <>
00403   void ColumnData<complex<float> >::setDataLimits (complex<float>* limits);
00404 #endif
00405 
00406 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00407 template <>
00408 inline void ColumnData<complex<double> >::setDataLimits (complex<double>* limits)
00409         {
00410                 m_minLegalValue = limits[0];
00411                 m_maxLegalValue = limits[1];
00412                 m_minDataValue =  limits[2];
00413                 m_maxDataValue =  limits[3];
00414         }
00415 #else
00416  template <>
00417   void ColumnData<complex<double> >::setDataLimits (complex<double>* limits);
00418 #endif
00419 
00420 
00421 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00422         template <>
00423         inline void ColumnData<string>::readColumnData (long firstRow, 
00424                                         long nelements, 
00425                                         string* nullValue)
00426         {
00427           int status = 0;
00428 
00429            int   anynul = 0;
00430            char** array = new char*[nelements]; 
00431 
00432            int j(0);
00433            for ( ; j < nelements; ++j)
00434            {
00435                array[j] = new char[width() + 1];
00436            }
00437 
00438            char* nulval = 0;
00439            if (nullValue) 
00440            {
00441                    nulval = const_cast<char*>(nullValue->c_str());
00442            }
00443            else
00444            {
00445                 nulval = new char;
00446                 *nulval = '\0';       
00447            }
00448 
00449 
00450           try
00451           {
00452                 makeHDUCurrent();
00453                 if (fits_read_col_str(fitsPointer(),index(), firstRow,1,nelements,
00454                   nulval,array, &anynul,&status) ) throw FitsError(status);
00455           }
00456           catch (FitsError)
00457           {
00458                 // ugly. but better than leaking resources.       
00459                 for (int jj = 0; jj < nelements; ++jj)
00460                 {
00461                         delete [] array[jj];
00462                 }     
00463 
00464                 delete [] array; 
00465                 delete nulval;
00466                 throw; 
00467           }
00468 
00469 
00470           if (m_data.size() == 0) setData(std::vector<string>(rows(),string(nulval)));
00471 
00472           // the 'first -1 ' converts to zero based indexing.
00473 
00474           for ( j = 0; j < nelements; j++)
00475           {
00476                 m_data[j - 1 + firstRow] = string(array[j]);
00477           }
00478 
00479           for ( j = 0; j < nelements; j++)
00480           {
00481                 delete [] array[j];
00482           }     
00483 
00484           delete [] array; 
00485           delete nulval; 
00486 
00487         }
00488 #else 
00489  template <>
00490 void ColumnData<string>::readColumnData (long firstRow, long nelements, string* nullValue);
00491 #endif
00492 
00493 
00494 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00495         template <>
00496         inline void ColumnData<complex<float> >::readColumnData (long firstRow,
00497                                                 long nelements,
00498                                                 complex<float>* nullValue)
00499         {
00500           // specialization for ColumnData<string> 
00501           int status(0);
00502           int   anynul(0);
00503           FITSUtil::auto_array_ptr<float> pArray(new float[nelements*2]); 
00504           float* array = pArray.get();
00505           float nulval(0);
00506           makeHDUCurrent();
00507 
00508 
00509           if (fits_read_col_cmp(fitsPointer(),index(), firstRow,1,nelements,
00510                   nulval,array, &anynul,&status) ) throw FitsError(status);
00511 
00512 
00513           if (m_data.size() == 0) m_data.resize(rows());
00514 
00515           // the 'j -1 ' converts to zero based indexing.
00516 
00517           for (int j = firstRow; j < nelements; ++j)
00518           {
00519 
00520                 m_data[j - 1] = std::complex<float>(array[2*j],array[2*j+1]);
00521           }
00522 
00523         }
00524 #else
00525 template <> 
00526 void ColumnData<complex<float> >::readColumnData (long firstRow, long nelements,complex<float>* nullValue );
00527 #endif
00528 
00529 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
00530         template <>
00531         inline void ColumnData<complex<double> >::readColumnData (long firstRow, 
00532                                                         long nelements,
00533                                                         complex<double>* nullValue)
00534         {
00535           // specialization for ColumnData<complex<double> > 
00536            int status(0);
00537            int   anynul(0);
00538            FITSUtil::auto_array_ptr<double> pArray(new double[nelements*2]); 
00539            double* array = pArray.get();
00540            double nulval(0);
00541            makeHDUCurrent();
00542 
00543 
00544           if (fits_read_col_dblcmp(fitsPointer(), index(), firstRow,1,nelements,
00545                   nulval,array, &anynul,&status) ) throw FitsError(status);
00546 
00547 
00548 
00549 
00550           if (m_data.size() == 0) setData(std::vector<complex<double> >(rows(),nulval));
00551 
00552           // the 'j -1 ' converts to zero based indexing.
00553 
00554           for (int j = firstRow; j < nelements; j++)
00555           {
00556 
00557                 m_data[j - 1] = std::complex<double>(array[2*j],array[2*j+1]);
00558           }
00559 
00560         }
00561 #else
00562 template <>
00563 void ColumnData<complex<double> >::readColumnData (long firstRow, long nelements,complex<double>* nullValue);
00564 #endif
00565 
00566 #if SPEC_TEMPLATE_DECL_DEFECT
00567   template <>
00568   inline void ColumnData<string>::writeData (const std::vector<string>& indata, 
00569                                       long firstRow, string* nullValue)
00570   {
00571     int    status=0;
00572     char** columnData=FITSUtil::CharArray(indata);
00573 
00574     if ( fits_write_colnull(fitsPointer(), TSTRING, index(), firstRow, 1, indata.size(),
00575                             columnData, 0, &status) != 0 )
00576       throw FitsError(status);
00577     unsigned long elementsToWrite (indata.size() + firstRow - 1);
00578     std::vector<string> __tmp(m_data);
00579     if (m_data.size() < elementsToWrite) 
00580       {
00581         m_data.resize(elementsToWrite,"");
00582         std::copy(__tmp.begin(),__tmp.end(),m_data.begin());
00583       }
00584     std::copy(indata.begin(),indata.end(),m_data.begin()+firstRow-1);
00585 
00586 
00587     for (size_t i = 0; i < indata.size(); ++i)
00588       {
00589         delete [] columnData[i];
00590       }
00591     delete [] columnData;
00592   }  
00593 #else
00594 template <>
00595 void ColumnData<string>::writeData (const std::vector<string>& inData, long firstRow, string* nullValue);
00596 #endif
00597 
00598 #ifdef SPEC_TEMPLATE_DECL_DEFECT
00599   template <>
00600   inline void ColumnData<complex<float> >::writeData (const std::vector<complex<float> >& inData, 
00601                                                long firstRow, 
00602                                                complex<float>* nullValue)
00603   {
00604     int status(0);
00605     int nRows (inData.size());
00606     FITSUtil::auto_array_ptr<float> pData(new float[nRows*2]);
00607     float* Data = pData.get();
00608     std::vector<complex<float> > __tmp(m_data);
00609     for (int j = firstRow; j < nRows; ++j)
00610       {
00611         Data[ 2*j] = inData[j].real();
00612         Data[ 2*j + 1] = inData[j].imag();
00613       }     
00614 
00615     try
00616       {
00617 
00618         if (fits_write_col_cmp(fitsPointer(), index(), firstRow, 1, 
00619                                nRows,Data, &status) != 0) throw FitsError(status);
00620         long elementsToWrite(nRows + firstRow -1);
00621         if (elementsToWrite > static_cast<long>(m_data.size())) 
00622           {
00623 
00624             m_data.resize(elementsToWrite);
00625           }
00626 
00627         std::copy(inData.begin(),inData.end(),m_data.begin()+firstRow-1);
00628 
00629         // tell the Table that the number of rows has changed
00630         parent()->updateRows();
00631       }
00632     catch (FitsError) // the only thing that can throw here.
00633       {
00634         // reset to original content and rethrow the exception.
00635         m_data.resize(__tmp.size());
00636         m_data = __tmp;
00637       }      
00638 
00639   }
00640 
00641 #else
00642 template <>
00643 void ColumnData<complex<float> >::writeData (const std::vector<complex<float> >& inData, long firstRow, 
00644                                 complex<float>* nullValue);
00645 #endif
00646 
00647 #ifdef SPEC_TEMPLATE_DECL_DEFECT
00648   template <>
00649   inline void ColumnData<complex<double> >::writeData (const std::vector<complex<double> >& inData, 
00650                                                 long firstRow, 
00651                                                 complex<double>* nullValue)
00652   {
00653     int status(0);
00654     int nRows (inData.size());
00655     FITSUtil::auto_array_ptr<double> pData(new double[nRows*2]);
00656     double* Data = pData.get();
00657     std::vector<complex<double> > __tmp(m_data);
00658     for (int j = firstRow; j < nRows; ++j)
00659       {
00660         pData[ 2*j] = inData[j].real();
00661         pData[ 2*j + 1] = inData[j].imag();
00662       }     
00663 
00664     try
00665       {
00666 
00667         if (fits_write_col_dblcmp(fitsPointer(), index(), firstRow, 1, 
00668                                   nRows,Data, &status) != 0) throw FitsError(status);
00669         long elementsToWrite(nRows + firstRow -1);
00670         if (elementsToWrite > static_cast<long>(m_data.size())) 
00671           {
00672 
00673             m_data.resize(elementsToWrite);
00674           }
00675 
00676         std::copy(inData.begin(),inData.end(),m_data.begin()+firstRow-1);
00677 
00678         // tell the Table that the number of rows has changed
00679         parent()->updateRows();
00680       }
00681     catch (FitsError) // the only thing that can throw here.
00682       {
00683         // reset to original content and rethrow the exception.
00684         m_data.resize(__tmp.size());
00685         m_data = __tmp;
00686       }      
00687 
00688   }
00689 
00690 #else
00691 template <>
00692 void ColumnData<complex<double> >::writeData (const std::vector<complex<double> >& inData, long firstRow, 
00693                                 complex<double>* nullValue);
00694 
00695 #endif
00696 } // namespace CCfits
00697 
00698 
00699 #endif

Generated on Thu Jun 28 11:49:08 2007 for CCfits by  doxygen 1.4.7