CCfits: ColumnData.h Source File

CCfits 2.7

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List

ColumnData.h

    00001 //  Astrophysics Science Division,
    00002 //  NASA/ Goddard Space Flight Center
    00003 //  HEASARC
    00004 //  http://heasarc.gsfc.nasa.gov
    00005 //  e-mail: ccfits@legacy.gsfc.nasa.gov
    00006 //
    00007 //  Original author: Ben Dorman
    00008
    00009 #ifndef COLUMNDATA_H
    00010 #define COLUMNDATA_H 1
    00011 #include "CCfits.h"
    00012
    00013 // vector
    00014 #include <vector>
    00015 // Column
    00016 #include "Column.h"
    00017 #ifdef _MSC_VER
    00018 #include "MSconfig.h"
    00019 #endif
    00020
    00021 #include <complex>
    00022 #include <memory>
    00023 #include <iterator>
    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);
    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 = "");
    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
    00076         virtual size_t getStoredDataSize() const;
    00077
    00078       // Additional Private Declarations
    00079
    00080     private: //## implementation
    00081       // Data Members for Class Attributes
    00082         T m_minLegalValue;
    00083         T m_maxLegalValue;
    00084         T m_minDataValue;
    00085         T m_maxDataValue;
    00086
    00087       // Data Members for Associations
    00088         std::vector<T> m_data;
    00089
    00090       // Additional Implementation Declarations
    00091
    00092   };
    00093
    00094   // Parameterized Class CCfits::ColumnData
    00095
    00096   template <typename T>
    00097   inline void ColumnData<T>::readData (long firstRow, long nelements, long firstElem)
    00098   {
    00099    readColumnData(firstRow,nelements,static_cast<T*>(0));
    00100   }
    00101
    00102   template <typename T>
    00103   inline const T ColumnData<T>::minLegalValue () const
    00104   {
    00105     return m_minLegalValue;
    00106   }
    00107
    00108   template <typename T>
    00109   inline void ColumnData<T>::minLegalValue (T value)
    00110   {
    00111     m_minLegalValue = value;
    00112   }
    00113
    00114   template <typename T>
    00115   inline const T ColumnData<T>::maxLegalValue () const
    00116   {
    00117     return m_maxLegalValue;
    00118   }
    00119
    00120   template <typename T>
    00121   inline void ColumnData<T>::maxLegalValue (T value)
    00122   {
    00123     m_maxLegalValue = value;
    00124   }
    00125
    00126   template <typename T>
    00127   inline const T ColumnData<T>::minDataValue () const
    00128   {
    00129     return m_minDataValue;
    00130   }
    00131
    00132   template <typename T>
    00133   inline void ColumnData<T>::minDataValue (T value)
    00134   {
    00135     m_minDataValue = value;
    00136   }
    00137
    00138   template <typename T>
    00139   inline const T ColumnData<T>::maxDataValue () const
    00140   {
    00141     return m_maxDataValue;
    00142   }
    00143
    00144   template <typename T>
    00145   inline void ColumnData<T>::maxDataValue (T value)
    00146   {
    00147     m_maxDataValue = value;
    00148   }
    00149
    00150   template <typename T>
    00151   inline const std::vector<T>& ColumnData<T>::data () const
    00152   {
    00153     return m_data;
    00154   }
    00155
    00156   template <typename T>
    00157   inline void ColumnData<T>::setData (const std::vector<T>& value)
    00158   {
    00159     m_data = value;
    00160   }
    00161
    00162   template <typename T>
    00163   inline T ColumnData<T>::data (int i)
    00164   {
    00165     // return data stored in the ith row, which is in the i-1 th location in the array.
    00166     return m_data[i - 1];
    00167   }
    00168
    00169   template <typename T>
    00170   inline void ColumnData<T>::data (int i, T value)
    00171   {
    00172     // assign data to i-1 th location in the array, representing the ith row.
    00173     m_data[i - 1] = value;
    00174   }
    00175
    00176   // Parameterized Class CCfits::ColumnData
    00177
    00178   template <typename T>
    00179   ColumnData<T>::ColumnData(const ColumnData<T> &right)
    00180       :Column(right),
    00181        m_minLegalValue(right.m_minLegalValue),
    00182        m_maxLegalValue(right.m_maxLegalValue),
    00183        m_minDataValue(right.m_minDataValue),
    00184        m_maxDataValue(right.m_maxDataValue),
    00185        m_data(right.m_data)
    00186   {
    00187   }
    00188
    00189   template <typename T>
    00190   ColumnData<T>::ColumnData (Table* p)
    00191   : Column(p),
    00192        m_minLegalValue(),
    00193        m_maxLegalValue(),
    00194        m_minDataValue(),
    00195        m_maxDataValue(),
    00196        m_data()
    00197   {
    00198   }
    00199
    00200   template <typename T>
    00201   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)
    00202         : Column(columnIndex,columnName,type,format,unit,p,rpt,w,comment),
    00203         m_minLegalValue(),
    00204         m_maxLegalValue(),
    00205         m_minDataValue(),
    00206         m_maxDataValue(),
    00207         m_data()
    00208   {
    00209   }
    00210
    00211
    00212   template <typename T>
    00213   ColumnData<T>::~ColumnData()
    00214   {
    00215   }
    00216
    00217
    00218   template <typename T>
    00219   void ColumnData<T>::readColumnData (long firstRow, long nelements, T* nullValue)
    00220   {
    00221   if ( rows() < nelements )
    00222   {
    00223         std::cerr << "CCfits: More data requested than contained in table. ";
    00224         std::cerr << "Extracting complete column.\n";
    00225         nelements = rows();
    00226    }
    00227
    00228    int   status(0);
    00229    int   anynul(0);
    00230
    00231    FITSUtil::auto_array_ptr<T> array(new T[nelements]);
    00232
    00233    makeHDUCurrent();
    00234
    00235    if ( fits_read_col(fitsPointer(),type(),  index(), firstRow, 1,
    00236     nelements, nullValue, array.get(), &anynul, &status) ) throw FitsError(status);
    00237
    00238
    00239    if (m_data.size() != static_cast<size_t>( rows() ) ) m_data.resize(rows());
    00240
    00241    std::copy(&array[0],&array[nelements],m_data.begin()+firstRow-1);
    00242    if (nelements == rows()) isRead(true);
    00243   }
    00244
    00245   template <typename T>
    00246   bool ColumnData<T>::compare (const Column &right) const
    00247   {
    00248   if ( !Column::compare(right) ) return false;
    00249   const ColumnData<T>& that = static_cast<const ColumnData<T>&>(right);
    00250   unsigned int n = m_data.size();
    00251   if ( that.m_data.size() != n ) return false;
    00252   for (unsigned int i = 0; i < n ; i++)
    00253   {
    00254         if (m_data[i] != that.m_data[i]) return false;
    00255   }
    00256   return true;
    00257   }
    00258
    00259   template <typename T>
    00260   ColumnData<T>* ColumnData<T>::clone () const
    00261   {
    00262         return new ColumnData<T>(*this);
    00263   }
    00264
    00265   template <typename T>
    00266   std::ostream& ColumnData<T>::put (std::ostream& s) const
    00267   {
    00268   Column::put(s);
    00269   if (FITS::verboseMode() && type() != Tstring)
    00270   {
    00271         s << " Column Legal limits: ( " << m_minLegalValue << "," << m_maxLegalValue << " )\n"
    00272         << " Column Data  limits: ( " << m_minDataValue << "," << m_maxDataValue << " )\n";
    00273   }
    00274   if (!m_data.empty())
    00275   {
    00276         std::ostream_iterator<T> output(s,"\n");
    00277         // output each row on a separate line.
    00278         // user can supply manipulators to stream for formatting.
    00279         std::copy(m_data.begin(),m_data.end(),output);
    00280   }
    00281
    00282     return s;
    00283   }
    00284
    00285   template <typename T>
    00286   void ColumnData<T>::writeData (T* indata, long nRows, long firstRow, T* nullValue)
    00287   {
    00288
    00289      // set columnData's data member to equal what's written to file.
    00290      // indata has size nRows: elements firstRow to firstRow + nRows - 1 will be written.
    00291      // if this exceeds the current rowlength of the HDU, update the return value for
    00292      // rows() in the parent after the fitsio call.
    00293      int status(0);
    00294
    00295      try
    00296      {
    00297         if (nullValue)
    00298         {
    00299            if (fits_write_colnull(fitsPointer(), type(), index(), firstRow, 1, nRows,
    00300                  indata, nullValue, &status) != 0) throw FitsError(status);
    00301         }
    00302         else
    00303         {
    00304            if (fits_write_col(fitsPointer(), type(), index(), firstRow, 1, nRows,
    00305                  indata, &status) != 0) throw FitsError(status);
    00306         }
    00307
    00308      }
    00309      catch (FitsError) // the only thing that can throw here.
    00310      {
    00311           if (status == NO_NULL) throw NoNullValue(name());
    00312           else throw;
    00313      }
    00314      long elementsToWrite(nRows + firstRow -1);
    00315
    00316      if (elementsToWrite > static_cast<long>(m_data.size()))
    00317      {
    00318         m_data.resize(elementsToWrite,T());
    00319      }
    00320
    00321      std::copy(&indata[0],&indata[nRows],m_data.begin()+firstRow-1);
    00322      // tell the Table that the number of rows has changed
    00323      parent()->updateRows();
    00324
    00325   }
    00326
    00327   template <typename T>
    00328   void ColumnData<T>::writeData (const std::vector<T>& indata, long firstRow, T* nullValue)
    00329   {
    00330         FITSUtil::CVarray<T> convert;
    00331         FITSUtil::auto_array_ptr<T> pcolData (convert(indata));
    00332         T* columnData  = pcolData.get();
    00333         writeData(columnData,indata.size(),firstRow,nullValue);
    00334   }
    00335
    00336   template <typename T>
    00337   void ColumnData<T>::insertRows (long first, long number)
    00338   {
    00339     // Don't assume the calling routine (ie. Table's insertRows)
    00340     // knows Column's current m_data size.  m_data may still be
    00341     // size 0 if no read operations have been performed on Column.
    00342     // Therefore perform range checking before inserting.
    00343
    00344     // As with CFITSIO, rows are inserted AFTER 1-based 'first'.
    00345     if (first >= 0 && first <= static_cast<long>(m_data.size()))
    00346     {
    00347        typename std::vector<T>::iterator in;
    00348        if (first !=0)
    00349        {
    00350                in = m_data.begin()+first;
    00351        }
    00352        else
    00353        {
    00354                in = m_data.begin();
    00355        }
    00356
    00357        // non-throwing operations.
    00358        m_data.insert(in,number,T());
    00359     }
    00360   }
    00361
    00362   template <typename T>
    00363   void ColumnData<T>::deleteRows (long first, long number)
    00364   {
    00365     // Don't assume the calling routine (ie. Table's deleteRows)
    00366     // knows Column's current m_data size.  m_data may still be
    00367     // size 0 if no read operations have been performed on Column.
    00368     // Therefore perform range checking before erasing.
    00369     const long curSize = static_cast<long>(m_data.size());
    00370     if (curSize>0 && first <= curSize)
    00371     {
    00372        const long last = std::min(curSize, first-1+number);
    00373        m_data.erase(m_data.begin()+first-1,m_data.begin()+last);
    00374     }
    00375   }
    00376
    00377   template <typename T>
    00378   size_t ColumnData<T>::getStoredDataSize() const
    00379   {
    00380      return m_data.size();
    00381   }
    00382
    00383   template <typename T>
    00384   void ColumnData<T>::setDataLimits (T* limits)
    00385   {
    00386     m_minLegalValue = limits[0];
    00387     m_maxLegalValue = limits[1];
    00388     m_minDataValue = std::max(limits[2],limits[0]);
    00389     m_maxDataValue = std::min(limits[3],limits[1]);
    00390   }
    00391
    00392   // Additional Declarations
    00393
    00394   // all functions that operate on strings or complex data that call cfitsio
    00395   // need to be specialized.
    00396
    00397 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
    00398 template <>
    00399 inline void ColumnData<complex<float> >::setDataLimits (complex<float>* limits)
    00400        {
    00401                 m_minLegalValue = limits[0];
    00402                 m_maxLegalValue = limits[1];
    00403                 m_minDataValue =  limits[2];
    00404                 m_maxDataValue =  limits[3];
    00405         }
    00406 #else
    00407 template <>
    00408   void ColumnData<complex<float> >::setDataLimits (complex<float>* limits);
    00409 #endif
    00410
    00411 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
    00412 template <>
    00413 inline void ColumnData<complex<double> >::setDataLimits (complex<double>* limits)
    00414         {
    00415                 m_minLegalValue = limits[0];
    00416                 m_maxLegalValue = limits[1];
    00417                 m_minDataValue =  limits[2];
    00418                 m_maxDataValue =  limits[3];
    00419         }
    00420 #else
    00421  template <>
    00422   void ColumnData<complex<double> >::setDataLimits (complex<double>* limits);
    00423 #endif
    00424
    00425
    00426 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
    00427         template <>
    00428         inline void ColumnData<string>::readColumnData (long firstRow,
    00429                                         long nelements,
    00430                                         string* nullValue)
    00431         {
    00432            // nelements = nrows to read.
    00433            if (nelements < 1)
    00434               throw Column::InvalidNumberOfRows((int)nelements);
    00435            if (firstRow < 1 || (firstRow+nelements-1)>rows())
    00436               throw Column::InvalidRowNumber(name());
    00437
    00438            int status = 0;
    00439            int   anynul = 0;
    00440
    00441            char** array = new char*[nelements];
    00442            // Initialize pointers to NULL so we can safely delete
    00443            //  during error handling, even if they haven't been allocated.
    00444            for (long i=0; i<nelements; ++i)
    00445               array[i]=static_cast<char*>(0);
    00446            bool isError = false;
    00447
    00448            // Strings are unusual.  The variable length case is still
    00449            //  handled by a ColumnData class, not a ColumnVectorData.
    00450            char* nulval = 0;
    00451            if (nullValue)
    00452            {
    00453               nulval = const_cast<char*>(nullValue->c_str());
    00454            }
    00455            else
    00456            {
    00457               nulval = new char;
    00458               *nulval = '\0';
    00459            }
    00460            makeHDUCurrent();
    00461            if (varLength())
    00462            {
    00463               long* strLengths = new long[nelements];
    00464               long* offsets = new long[nelements];
    00465               if (fits_read_descripts(fitsPointer(), index(), firstRow,
    00466                    nelements, strLengths, offsets, &status))
    00467               {
    00468                  isError = true;
    00469               }
    00470               else
    00471               {
    00472                  // For variable length cols, must read 1 and only 1 row
    00473                  //  at a time into array.
    00474                  for (long j=0; j<nelements; ++j)
    00475                  {
    00476                     array[j] = new char[strLengths[j] + 1];
    00477                  }
    00478
    00479                  const long lastRow = firstRow+nelements-1;
    00480                  for (long iRow=firstRow; !isError && iRow<=lastRow; ++iRow)
    00481                  {
    00482                     if (fits_read_col_str(fitsPointer(),index(), iRow, 1, 1,
    00483                       nulval, &array[iRow-firstRow], &anynul,&status) )
    00484                        isError=true;
    00485                  }
    00486               }
    00487               delete [] strLengths;
    00488               delete [] offsets;
    00489            }
    00490            else
    00491            {
    00492               // Fixed length strings, length is stored in Column's m_width.
    00493               for (long j=0; j<nelements; ++j)
    00494               {
    00495                   array[j] = new char[width() + 1];
    00496               }
    00497               if (fits_read_col_str(fitsPointer(),index(), firstRow,1,nelements,
    00498                 nulval,array, &anynul,&status))
    00499                 isError=true;
    00500            }
    00501
    00502            if (isError)
    00503            {
    00504               // It's OK to do this even if error occurred before
    00505               //  array rows were allocated.  In that case their pointers
    00506               //  were set to NULL.
    00507               for (long j = 0; j < nelements; ++j)
    00508               {
    00509                  delete [] array[j];
    00510               }
    00511               delete [] array;
    00512               delete nulval;
    00513               throw FitsError(status);
    00514            }
    00515
    00516           if (m_data.size() != static_cast<size_t>(rows()))
    00517               setData(std::vector<String>(rows(),String(nulval)));
    00518
    00519           for (long j=0; j<nelements; ++j)
    00520           {
    00521              m_data[j - 1 + firstRow] = String(array[j]);
    00522           }
    00523
    00524           for (long j=0; j<nelements; j++)
    00525           {
    00526              delete [] array[j];
    00527           }
    00528           delete [] array;
    00529           delete nulval;
    00530           if (nelements == rows()) isRead(true);
    00531
    00532         }
    00533 #else
    00534  template <>
    00535 void ColumnData<string>::readColumnData (long firstRow, long nelements, string* nullValue);
    00536 #endif
    00537
    00538
    00539 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
    00540         template <>
    00541         inline void ColumnData<complex<float> >::readColumnData (long firstRow,
    00542                                                 long nelements,
    00543                                                 complex<float>* nullValue)
    00544         {
    00545           // specialization for ColumnData<string>
    00546           int status(0);
    00547           int   anynul(0);
    00548           FITSUtil::auto_array_ptr<float> pArray(new float[nelements*2]);
    00549           float* array = pArray.get();
    00550           float nulval(0);
    00551           makeHDUCurrent();
    00552
    00553
    00554           if (fits_read_col_cmp(fitsPointer(),index(), firstRow,1,nelements,
    00555                   nulval,array, &anynul,&status) ) throw FitsError(status);
    00556
    00557
    00558           if (m_data.size() != rows()) m_data.resize(rows());
    00559
    00560           // the 'j -1 ' converts to zero based indexing.
    00561
    00562           for (int j = 0; j < nelements; ++j)
    00563           {
    00564
    00565                 m_data[j - 1 + firstRow] = std::complex<float>(array[2*j],array[2*j+1]);
    00566           }
    00567           if (nelements == rows()) isRead(true);
    00568
    00569         }
    00570 #else
    00571 template <>
    00572 void ColumnData<complex<float> >::readColumnData (long firstRow, long nelements,complex<float>* nullValue );
    00573 #endif
    00574
    00575 #if SPEC_TEMPLATE_IMP_DEFECT || SPEC_TEMPLATE_DECL_DEFECT
    00576         template <>
    00577         inline void ColumnData<complex<double> >::readColumnData (long firstRow,
    00578                                                         long nelements,
    00579                                                         complex<double>* nullValue)
    00580         {
    00581           // specialization for ColumnData<complex<double> >
    00582            int status(0);
    00583            int   anynul(0);
    00584            FITSUtil::auto_array_ptr<double> pArray(new double[nelements*2]);
    00585            double* array = pArray.get();
    00586            double nulval(0);
    00587            makeHDUCurrent();
    00588
    00589
    00590           if (fits_read_col_dblcmp(fitsPointer(), index(), firstRow,1,nelements,
    00591                   nulval,array, &anynul,&status) ) throw FitsError(status);
    00592
    00593
    00594
    00595
    00596           if (m_data.size() != rows()) setData(std::vector<complex<double> >(rows(),nulval));
    00597
    00598           // the 'j -1 ' converts to zero based indexing.
    00599
    00600           for (int j = 0; j < nelements; j++)
    00601           {
    00602
    00603                 m_data[j - 1 + firstRow] = std::complex<double>(array[2*j],array[2*j+1]);
    00604           }
    00605           if (nelements == rows()) isRead(true);
    00606
    00607         }
    00608 #else
    00609 template <>
    00610 void ColumnData<complex<double> >::readColumnData (long firstRow, long nelements,complex<double>* nullValue);
    00611 #endif
    00612
    00613 #if SPEC_TEMPLATE_DECL_DEFECT
    00614   template <>
    00615   inline void ColumnData<string>::writeData (const std::vector<string>& indata,
    00616                       long firstRow, string* nullValue)
    00617   {
    00618     int    status=0;
    00619     char** columnData=FITSUtil::CharArray(indata);
    00620
    00621     if ( fits_write_colnull(fitsPointer(), TSTRING, index(), firstRow, 1, indata.size(),
    00622                 columnData, 0, &status) != 0 )
    00623       throw FitsError(status);
    00624     unsigned long elementsToWrite (indata.size() + firstRow - 1);
    00625     std::vector<string> __tmp(m_data);
    00626     if (m_data.size() < elementsToWrite)
    00627       {
    00628     m_data.resize(elementsToWrite,"");
    00629     std::copy(__tmp.begin(),__tmp.end(),m_data.begin());
    00630       }
    00631     std::copy(indata.begin(),indata.end(),m_data.begin()+firstRow-1);
    00632
    00633
    00634     for (size_t i = 0; i < indata.size(); ++i)
    00635       {
    00636     delete [] columnData[i];
    00637       }
    00638     delete [] columnData;
    00639   }
    00640 #else
    00641 template <>
    00642 void ColumnData<string>::writeData (const std::vector<string>& inData, long firstRow, string* nullValue);
    00643 #endif
    00644
    00645 #ifdef SPEC_TEMPLATE_DECL_DEFECT
    00646   template <>
    00647   inline void ColumnData<complex<float> >::writeData (const std::vector<complex<float> >& inData,
    00648                            long firstRow,
    00649                            complex<float>* nullValue)
    00650   {
    00651     int status(0);
    00652     int nRows (inData.size());
    00653     FITSUtil::auto_array_ptr<float> pData(new float[nRows*2]);
    00654     float* Data = pData.get();
    00655     std::vector<complex<float> > __tmp(m_data);
    00656     for (int j = 0; j < nRows; ++j)
    00657       {
    00658     Data[ 2*j] = inData[j].real();
    00659     Data[ 2*j + 1] = inData[j].imag();
    00660       }
    00661
    00662     try
    00663       {
    00664
    00665     if (fits_write_col_cmp(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<float> >::writeData (const std::vector<complex<float> >& inData, long firstRow,
    00691                                 complex<float>* nullValue);
    00692 #endif
    00693
    00694 #ifdef SPEC_TEMPLATE_DECL_DEFECT
    00695   template <>
    00696   inline void ColumnData<complex<double> >::writeData (const std::vector<complex<double> >& inData,
    00697                         long firstRow,
    00698                         complex<double>* nullValue)
    00699   {
    00700     int status(0);
    00701     int nRows (inData.size());
    00702     FITSUtil::auto_array_ptr<double> pData(new double[nRows*2]);
    00703     double* Data = pData.get();
    00704     std::vector<complex<double> > __tmp(m_data);
    00705     for (int j = 0; j < nRows; ++j)
    00706       {
    00707     pData[ 2*j] = inData[j].real();
    00708     pData[ 2*j + 1] = inData[j].imag();
    00709       }
    00710
    00711     try
    00712       {
    00713
    00714     if (fits_write_col_dblcmp(fitsPointer(), index(), firstRow, 1,
    00715                                   nRows,Data, &status) != 0) throw FitsError(status);
    00716     long elementsToWrite(nRows + firstRow -1);
    00717     if (elementsToWrite > static_cast<long>(m_data.size()))
    00718       {
    00719
    00720         m_data.resize(elementsToWrite);
    00721       }
    00722
    00723     std::copy(inData.begin(),inData.end(),m_data.begin()+firstRow-1);
    00724
    00725     // tell the Table that the number of rows has changed
    00726     parent()->updateRows();
    00727       }
    00728     catch (FitsError) // the only thing that can throw here.
    00729       {
    00730     // reset to original content and rethrow the exception.
    00731     m_data.resize(__tmp.size());
    00732     m_data = __tmp;
    00733       }
    00734
    00735   }
    00736
    00737 #else
    00738 template <>
    00739 void ColumnData<complex<double> >::writeData (const std::vector<complex<double> >& inData, long firstRow,
    00740                                 complex<double>* nullValue);
    00741
    00742 #endif
    00743 } // namespace CCfits
    00744
    00745
    00746 #endif