ColumnData.h

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

Generated on Thu Nov 6 10:44:38 2008 for CCfits by  doxygen 1.5.4