ColumnData.h

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

Generated on Fri Nov 3 17:09:04 2006 for CCfits by  doxygen 1.4.7