00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #ifndef COLUMNDATA_H
00013 #define COLUMNDATA_H 1
00014 #include "CCfits.h"
00015
00016
00017 #include <vector>
00018
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
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
00063 friend class Column;
00064 protected:
00065
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
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
00082
00083 private:
00084
00085 T m_nullValue;
00086 T m_minLegalValue;
00087 T m_maxLegalValue;
00088 T m_minDataValue;
00089 T m_maxDataValue;
00090
00091
00092 std::vector<T> m_data;
00093
00094
00095
00096 };
00097
00098
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
00182 return m_data[i - 1];
00183 }
00184
00185 template <typename T>
00186 inline void ColumnData<T>::data (int i, T value)
00187 {
00188
00189 m_data[i - 1] = value;
00190 }
00191
00192
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
00296
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
00308
00309
00310
00311 int status(0);
00312 long elementsToWrite(nRows + firstRow -1);
00313
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
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
00342 parent()->updateRows();
00343 }
00344 catch (FitsError)
00345 {
00346
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
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
00396
00397
00398
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
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
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
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
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
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
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
00638 parent()->updateRows();
00639 }
00640 catch (FitsError)
00641 {
00642
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
00687 parent()->updateRows();
00688 }
00689 catch (FitsError)
00690 {
00691
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 }
00705
00706
00707 #endif