00001
00012 #include "FitsNTuple.h"
00013
00014 #include "FitsFile.h"
00015
00016 #include "axes/Range.h"
00017 #include "datasrcs/DataColumn.h"
00018 #include "pattern/string_convert.h"
00019
00020 #include <algorithm>
00021 #include <stdexcept>
00022
00023 #include <cassert>
00024
00025 using std::for_each;
00026 using std::mem_fun;
00027 using std::runtime_error;
00028 using std::string;
00029 using std::vector;
00030
00031 using namespace hippodraw;
00032
00033 FitsNTuple::
00034 FitsNTuple ( FitsFile * file )
00035 : DataSource ( false ),
00036 m_file ( file )
00037 {
00038 m_hdu_num = m_file -> getHDUNumber ();
00039 initColumns ();
00040 }
00041
00042 FitsNTuple::
00043 FitsNTuple ( )
00044 : DataSource ( false ),
00045 m_file ( 0 )
00046 {
00047 }
00048
00049 FitsNTuple::~FitsNTuple()
00050 {
00051 }
00052
00053 void
00054 FitsNTuple::
00055 copy ( const DataSource & )
00056 {
00057 assert ( false );
00058 }
00059
00060 const FitsFile *
00061 FitsNTuple::
00062 getFile () const
00063 {
00064 return m_file;
00065 }
00066
00067 void
00068 FitsNTuple::
00069 initColumns ( )
00070 {
00071 m_dups.clear();
00072
00073 vector < string > labels;
00074 vector < double > values;
00075 m_file -> fillColumnNames ( labels );
00076 unsigned int size = labels.size ();
00077 for ( unsigned int i = 0; i < size; i++ ) {
00078 const string & label = labels [i];
00079 int index = indexOf ( label );
00080 if ( index < 0 ) {
00081 addColumn ( label, values );
00082 }
00083 else {
00084 m_dups.push_back ( label );
00085 }
00086 }
00087 }
00088
00089 void
00090 FitsNTuple::
00091 notifyObservers ( ) const
00092 {
00093 Observable::notifyObservers ();
00094 }
00095
00096 unsigned int
00097 FitsNTuple::
00098 rows() const
00099 {
00100 return m_file -> getNumberOfRows ();
00101 }
00102 std::size_t
00103 FitsNTuple::
00104 size ( unsigned int column ) const
00105 {
00106 const DataColumn * dc = m_columns [ column ];
00107
00108 return dc -> size ();
00109 }
00110
00111 int
00112 FitsNTuple::
00113 fillDataCache ( unsigned int column )
00114 {
00115 DataColumn * data_column = m_columns [ column ];
00116
00117 vector < intptr_t > shape;
00118 m_file -> fillShape ( shape, column );
00119 data_column -> setShape ( shape );
00120
00121 std::size_t size = data_column -> size ();
00122 vector < double > & data = data_column -> getData ();
00123 data.resize ( size );
00124 int status = m_file -> fillDoubleVectorFromColumn ( data, column );
00125
00126 return status;
00127 }
00128
00129 void
00130 FitsNTuple::
00131 clear ()
00132 {
00133 for_each ( m_columns.begin(), m_columns.end (),
00134 std::mem_fun ( &DataColumn::clear ) );
00135 }
00136
00137 void
00138 FitsNTuple::
00139 reserve ( unsigned int )
00140 {
00141 assert ( false );
00142 }
00143
00144 bool
00145 FitsNTuple::
00146 empty () const
00147 {
00148 return rows () == 0;
00149 }
00150
00151 double
00152 FitsNTuple::
00153 operator [] ( std::vector < unsigned int > & ) const
00154 {
00155 assert ( false );
00156 return 0.0;
00157 }
00158
00159 double
00160 FitsNTuple::
00161 valueAt ( unsigned int row, unsigned int column ) const
00162 {
00163 const vector < double > & data = m_columns[ column ] -> getData();
00164 if ( data.empty () ) {
00165 FitsNTuple * tuple = const_cast < FitsNTuple * > ( this );
00166 tuple -> fillDataCache ( column );
00167 }
00168
00169 return data [ row ];
00170 }
00171
00172 const vector < double > &
00173 FitsNTuple::
00174 getColumn ( unsigned int index ) const
00175 {
00176 isValidColumn ( index );
00177
00178 DataColumn * dc = m_columns [ index ];
00179 const vector < double > & data = dc -> getData ();
00180 if ( data.empty () ) {
00181 FitsNTuple * tuple = const_cast < FitsNTuple * > ( this );
00182 tuple -> fillDataCache ( index );
00183 }
00184
00185 return data;
00186 }
00187
00188 const std::vector < double > &
00189 FitsNTuple::
00190 getRow ( unsigned int row ) const
00191 {
00192 unsigned int size = m_columns.size();
00193 m_array.resize ( size );
00194 for ( unsigned int column = 0; column < size; column++ ) {
00195 m_array [ column ] = valueAt ( row, column );
00196 }
00197
00198 return m_array;
00199 }
00200
00201 bool
00202 FitsNTuple::
00203 fillRange ( unsigned int column, Range & range ) const
00204 {
00205 bool isValid = true;;
00206 const vector < double > & data = m_columns [ column ] -> getData ();
00207
00208 if ( data.empty () ) {
00209 FitsNTuple * rtuple = const_cast < FitsNTuple * > ( this );
00210 int status = rtuple -> fillDataCache ( column );
00211 if ( status != 0 ) isValid = false;
00212 }
00213
00214 range.setRange ( data.begin(), data.end() );
00215
00216 return isValid;
00217 }
00218
00219 void
00220 FitsNTuple::
00221 checkLabel ( const std::string & label )
00222 {
00223 if ( isValidLabel ( label ) == true ) {
00224 string what ( "FitsNTuple: The column label `" );
00225 what += label;
00226 what += "' already exists in this DataSource.";
00227 throw runtime_error ( what );
00228 }
00229 }
00230
00231 int
00232 FitsNTuple::
00233 addColumn ( const std::string & label,
00234 const std::vector < double > & column )
00235 {
00236 unsigned int size = column.size ();
00237 const vector < intptr_t > shape ( 1, size );
00238
00239 return addColumn ( label, column, shape );
00240 }
00241
00244 int
00245 FitsNTuple::
00246 addColumn ( const std::string & label,
00247 const std::vector < double > & column,
00248 const std::vector < intptr_t > & shape )
00249 {
00250 checkLabel ( label );
00251
00252
00253 if ( m_columns.empty () == false &&
00254 column.empty() == false ) {
00255 unsigned int old_size = rows ();
00256 unsigned int new_size = shape[0];
00257
00258 if ( old_size != 0 && old_size != new_size ) {
00259 string what ( "FitsNTuple Attempt to add a column whose size"
00260 " is not equal to other columns." );
00261 throw runtime_error ( what );
00262 }
00263 }
00264
00265 DataColumn * dc = new DataColumn();
00266 m_columns.push_back ( dc );
00267 if ( column.empty () == false ) {
00268 vector < double > & data = m_columns.back() -> getData();
00269 data = column;
00270 }
00271 addLabel ( label );
00272 dc -> setShape ( shape );
00273
00274 return m_columns.size () - 1;
00275 }
00276
00277 void
00278 FitsNTuple::
00279 replaceColumn ( unsigned int index, const std::vector < double > & data )
00280 {
00281 int size = data.size();
00282 const vector < intptr_t > shape ( 1, size );
00283
00284 replaceColumn ( index, data, shape );
00285 }
00286
00287 void
00288 FitsNTuple::
00289 replaceColumn ( unsigned int index,
00290 const std::vector < double > & data,
00291 const std::vector < intptr_t > & shape )
00292 {
00293 unsigned int size = columns ();
00294 if ( index >= size ) {
00295 string what ( "FitsNTuple: Attempt to replace column " );
00296 what += String::convert ( index );
00297 what += " with only ";
00298 what += String ::convert ( size );
00299 what += " columns in data source.";
00300 throw runtime_error ( what );
00301 }
00302 size = rows ();
00303 unsigned int new_size = data.size ();
00304 if ( size != 0 && size != new_size ) {
00305 const string what
00306 ( "FitsNTuple: Attempt to replace column with one whose "
00307 "size is not equal to other columns." );
00308 throw runtime_error ( what );
00309 }
00310 DataColumn * dc = m_columns [ index ];
00311 vector < double > & pvec = dc -> getData ();
00312 pvec.resize ( new_size );
00313 std::copy ( data.begin(), data.end (), pvec.begin () );
00314 dc -> setShape ( shape );
00315
00316 notifyObservers ();
00317 }
00318
00319 void
00320 FitsNTuple::
00321 replaceColumn ( const std::string & label,
00322 const std::vector < double > & data,
00323 const std::vector < intptr_t > & shape )
00324 {
00325 unsigned int index = indexOf ( label );
00326 replaceColumn ( index, data, shape );
00327 }
00328
00329 void
00330 FitsNTuple::
00331 setShape ( std::vector < unsigned int > & shape )
00332 {
00333 assert ( false );
00334 m_shape = shape;
00335 }
00336
00337 const vector < unsigned int > &
00338 FitsNTuple::
00339 getShape () const
00340 {
00341 assert ( false );
00342 return m_shape;
00343 }
00344
00345
00348 void
00349 FitsNTuple::
00350 fillShape ( std::vector < intptr_t > & shape, unsigned int column ) const
00351 {
00352 DataColumn * dc = m_columns [ column ];
00353 shape = dc -> getShape ();
00354 }
00355
00356 double *
00357 FitsNTuple::
00358 doubleArrayAt ( unsigned int row, unsigned int column ) const
00359 {
00360 DataColumn * data = m_columns [ column ];
00361
00362 return data -> doubleArrayAt ( row );
00363 }