CCfits
2.7
|
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