00001
00013 #ifdef HAVE_CONFIG_H
00014
00015 #include "config.h"
00016 #endif
00017
00018
00019 #ifdef _MSC_VER
00020 #include "msdevstudio/MSconfig.h"
00021 #endif
00022
00023
00024 #include <boost/python.hpp>
00025
00026 #include "PyDataSource.h"
00027
00028 #include "ListTuple.h"
00029 #include "PyApp.h"
00030
00031 #include "datasrcs/DataSourceController.h"
00032 #include "datasrcs/NTuple.h"
00033 #include "pattern/string_convert.h"
00034
00035 #ifdef HAVE_NUMARRAY
00036 #include "numarray/NumArrayTuple.h"
00037 #include "numarray/num_util.h"
00038 #endif
00039
00040 #ifdef HAVE_NUMPY
00041 #include "numpy/oldnumeric.h"
00042 #endif
00043
00044 #ifdef HAVE_CFITSIO
00045 #include "fits/FitsNTuple.h"
00046 #endif
00047
00048 #ifdef HAVE_ROOT
00049 #include "root/QtRootNTuple.h"
00050 #endif
00051
00052 using namespace boost::python;
00053
00054 #ifdef HAVE_NUMARRAY
00055 namespace hippodraw {
00056 namespace Python {
00057
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 }
00143 }
00144 #endif
00145
00146 namespace hippodraw {
00147 namespace Python {
00148
00149 void PyDataSourceExceptionTranslator( const PyDataSource::StopIteration & e ) {
00150 PyErr_SetString ( PyExc_StopIteration, e.what() );
00151 }
00152
00153 void
00154 export_DataArray()
00155 {
00156 class_ < PyDataSource >
00157 ( "DataArray",
00158 "A DataArray wraps a DataSource object so that numerical Python\n"
00159 "arrays can be used as both input and output. The numerical array\n"
00160 "can be either a numarray.array or Numeric.array depending on\n"
00161 "how the hippo module was configured.\n"
00162 "\n"
00163 "Access to the array is done like a Python list or dictionary.\n"
00164 "\tarray = my_data_array [ index ] # list form\n"
00165 "\tarray = my_data_array [ 'my_label' ] # dict form\n"
00166 "\n"
00167 "Storage to the array is also done like a Python list or dictionary.\n"
00168 "\tmy_data_array [ index ] = ... # list form\n"
00169 "\tmy_data_array [ 'my_label' ] = ... # dict form\n" )
00170
00171 .def ( init < const std::string & > (
00172 "DataArray ( string ) -> DataArray\n"
00173 "\n"
00174 "Creates a DataArray. The string can be one of\n"
00175 "\tListTuple\n"
00176 "\tNTuple\n"
00177 "\tNumArrayTuple" ) )
00178
00179 .add_property ( "columns",
00180 &PyDataSource::columns )
00181
00182 .add_property ( "rows",
00183 &PyDataSource::rows )
00184
00185 .def ( "getCurrent",
00186 &PyDataSource::getCurrentDataSource,
00187 return_value_policy < reference_existing_object > (),
00188 "getCurrent () -> DataArray\n"
00189 "\n"
00190 "Returns a DataArray that wraps the current DataSource." )
00191
00192 .staticmethod ( "getCurrent" )
00193
00194 .def ( "dataSource",
00195 &PyDataSource::dataSource,
00196 return_value_policy < reference_existing_object > (),
00197 "dataSource () -> DataSource\n"
00198 "\n"
00199 "Returns reference to underlying DataSource" )
00200
00201 .def ( "getTitle",
00202 &PyDataSource::getTitle,
00203 return_value_policy < copy_const_reference > (),
00204 "getTitle () -> string\n"
00205 "\n"
00206 "Returns title of the DataSource." )
00207
00208 .def ( "setName",
00209 &PyDataSource::setName,
00210 "setName ( string ) -> None\n"
00211 "\n"
00212 "Sets the name of the DataSource. The name should be unique\n"
00213 "with one application and may appear in the Inspector panel." )
00214
00215 .def ( "setTitle",
00216 &PyDataSource::setTitle,
00217 "setTitle ( string ) -> None\n"
00218 "\n"
00219 "Sets the title of the DataSource. The title is what appears,\n"
00220 "by default, at the top of a Display." )
00221
00222 .def ( "getLabels",
00223 &PyDataSource::getLabels,
00224 return_value_policy < copy_const_reference > (),
00225 "getLabels () -> list\n"
00226 "\n"
00227 "Returns the list of string objects of column labels." )
00228
00229 .def ( "addColumn",
00230 ( int (PyDataSource:: * )
00231 (const std::string &, const std::vector<double> &) )
00232 &PyDataSource::addColumn,
00233 "addColumn ( string, list ) -> value\n"
00234 "addColumn ( string, array ) -> value\n"
00235 "\n"
00236 "Adds a column. The string will be the label of the column.\n"
00237 "A copy of the list or array values will be the contents.\n"
00238 "The second form is only available if HippoDraw was configured\n"
00239 "with numerical Python support. Returns the new column's index." )
00240
00241 #ifdef HAVE_NUMARRAY
00242 .def ( "addColumn",
00243 ( int (PyDataSource:: * )
00244 (const std::string &, boost::python::numeric::array) )
00245 &PyDataSource::addColumn )
00246 #endif
00247
00248 .def ( "getColumn",
00249 ( const std::vector < double > & (PyDataSource:: * )
00250 ( unsigned int ) const)
00251 &PyDataSource::getColumn,
00252 return_value_policy < copy_const_reference> (),
00253 "getColumn ( value ) -> list\n"
00254 "\n"
00255 "Returns a column as list of floats. 'value' maybe either\n"
00256 "the column label or its index." )
00257
00258 .def ( "getColumn",
00259 ( const std::vector < double > & (PyDataSource:: * )
00260 ( const std::string & ) const)
00261 &PyDataSource::getColumn,
00262 return_value_policy < copy_const_reference> () )
00263
00264 .def ( "replaceColumn",
00265 ( void (PyDataSource:: * )
00266 ( const std::string &, const std::vector<double> & ) )
00267 &PyDataSource::replaceColumn,
00268 "replaceColumn ( value, list ) -> None\n"
00269 "replaceColumn ( value, array ) -> None\n"
00270 "\n"
00271 "Replace column by its label or index. The second form is \n"
00272 "only available if HippoDraw was configure with numerical\n"
00273 "arrays." )
00274
00275 .def ( "replaceColumn",
00276 ( void (PyDataSource:: * )
00277 ( unsigned int index, const std::vector<double> & ) )
00278 &PyDataSource::replaceColumn )
00279
00280 #ifdef HAVE_NUMARRAY
00281 .def ( "replaceColumn",
00282 ( void (PyDataSource:: * )
00283 ( const std::string &, numeric::array ) )
00284 &PyDataSource::replaceColumn )
00285
00286 .def ( "replaceColumn",
00287 ( void (PyDataSource:: * )
00288 ( unsigned int index, numeric::array ) )
00289 &PyDataSource::replaceColumn )
00290 #endif
00291
00292
00293
00294
00295
00296
00297 .def ("has_key",
00298 &PyDataSource::hasColumn,
00299 "has_key ( string ) -> Boolean\n"
00300 "\n"
00301 "Returns True if column with label exists.")
00302
00303 .def ( "keys",
00304 &PyDataSource::getLabels,
00305 return_value_policy < copy_const_reference > (),
00306 "keys () -> list\n"
00307 "\n"
00308 "Returns the list of column labels." )
00309
00310 .def ( "register",
00311 ( void (PyDataSource:: * ) ( const std::string & ) )
00312 &PyDataSource::registerNTuple,
00313 "register ( string ) -> None\n"
00314 "register ( ) -> string\n"
00315 "\n"
00316 "Register the underlying DataSource with the\n"
00317 "DataSourceController. The first form registers it with the\n"
00318 "given name, while the second from returns a unique name\n"
00319 "generated by the controller." )
00320
00321 .def ( "register",
00322 ( std::string (PyDataSource:: * ) () )
00323 &PyDataSource::registerNTuple )
00324
00325
00326
00327
00328
00329 .def ( "__setitem__",
00330 &PyDataSource::saveColumnFrom,
00331 "__setitem__ ( label, sequence ) -> None\n"
00332 "\n"
00333 "Copies the contensts of the sequence. If column with label\n"
00334 "already exists, replaces it, otherwise add a new column." )
00335
00336 .def ( "addRow",
00337 &PyDataSource::addRow,
00338 "addRow ( sequence ) -> None\n"
00339 "\n"
00340 "Adds a row to the held DataSource object if supported, otherwise"
00341 " throws Runtime exception." )
00342
00343 .def ( "append",
00344 ( void ( PyDataSource:: * )
00345 ( const DataSource * ) )
00346 &PyDataSource::append,
00347 "append ( DataArray ) -> None\n"
00348 "append ( DataSource ) -> None\n"
00349 "\n"
00350 "Appends contents of DataSource or DataArray to the DataArray." )
00351
00352 .def ( "append",
00353 ( void ( PyDataSource:: * )
00354 ( const PyDataSource * ) )
00355 &PyDataSource::append )
00356
00357
00358 .def ( "__getitem__",
00359 ( numeric::array ( PyDataSource:: * )
00360 ( const std::string & ) const )
00361 &PyDataSource::columnAsNumArray,
00362 return_value_policy < return_by_value > (),
00363 "__getitem__ ( value ) -> array\n"
00364 "\n"
00365 "Returns a copy of the column as numerical array. 'value' can\n"
00366 "be either the column label or its index." )
00367
00368 .def ( "__getitem__",
00369 ( numeric::array ( PyDataSource:: * )
00370 ( unsigned int ) const )
00371 &PyDataSource::columnAsNumArray,
00372 return_value_policy < return_by_value > () )
00373
00374 .def ( "__setitem__",
00375 ( void ( PyDataSource:: * )
00376 ( const std::string &,
00377 numeric::array ) )
00378 &PyDataSource::saveColumnFromNumArray,
00379 return_value_policy < return_by_value > (),
00380 "__setitem__ ( value, array ) -> None\n"
00381 "\n"
00382 "Copies the contents of array. If `'value' is an index, then\n"
00383 "replaces the contents of the existing column. If 'value' is\n"
00384 "a label then either replaces existing column with that label\n"
00385 "or adds a new column." )
00386
00387 .def ( "__setitem__",
00388 ( void ( PyDataSource:: * )
00389 ( unsigned int,
00390 numeric::array ) )
00391 &PyDataSource::saveColumnFromNumArray,
00392 return_value_policy < return_by_value > () )
00393
00394 ;
00395 register_exception_translator<PyDataSource::StopIteration>
00396 (&PyDataSourceExceptionTranslator);
00397 }
00398
00399 }
00400 }
00401
00402 using namespace hippodraw;
00403
00404 PyDataSource::PyDataSource() {
00405 m_type = "NTuple";
00406 m_dataSource = new NTuple();
00407 }
00408
00409 PyDataSource::
00410 PyDataSource ( const std::string & name, DataSource * source )
00411 : m_type ( name ),
00412 m_dataSource ( source )
00413 {
00414 }
00415
00419 PyDataSource::
00420 PyDataSource(const std::string & dataSource)
00421 : m_type(dataSource) {
00422 if (dataSource == "ListTuple") {
00423 m_dataSource = new ListTuple();
00424 } else if (dataSource == "NTuple") {
00425 m_dataSource = new NTuple();
00426 #ifdef HAVE_NUMARRAY
00427 } else if (dataSource == "NumArrayTuple") {
00428 m_dataSource = new NumArrayTuple();
00429 #else
00430 } else if (dataSource == "NumArrayTuple") {
00431 throw std::runtime_error ("HippoDraw was not built with "
00432 "numeric Python soupport" );
00433 #endif
00434 } else {
00435 throw std::runtime_error("Invalid DataSource: " + dataSource);
00436 }
00437 }
00438
00439 PyDataSource::
00440 ~PyDataSource()
00441 {
00442 delete m_dataSource;
00443 }
00444
00445 template < typename T >
00446 void
00447 PyDataSource::
00448 copy_direct ( boost::python::numeric::array array,
00449 std::vector<double > & col )
00450 {
00451 T * data = reinterpret_cast < T * > ( num_util::data ( array ) );
00452 int size = num_util::size ( array );
00453 std::copy ( data, data+ size, back_inserter( col ) );
00454 }
00455
00456 void
00457 PyDataSource::
00458 extractVector ( boost::python::numeric::array array,
00459 std::vector<double> & col )
00460 {
00461 PyArray_TYPES type = num_util::type ( array );
00462
00463 if ( num_util::iscontiguous ( array ) &&
00464 type != PyArray_NOTYPE ) {
00465 switch ( type )
00466 {
00467 #ifdef HAVE_NUMPY
00468 case PyArray_BOOL:
00469 copy_direct < bool > ( array, col );
00470 break;
00471 #endif
00472 case PyArray_CHAR:
00473 copy_direct < char > ( array, col );
00474 break;
00475
00476 case PyArray_SHORT :
00477 copy_direct < short > ( array, col );
00478 break;
00479
00480 case PyArray_INT :
00481 copy_direct < int > ( array, col );
00482 break;
00483
00484 case PyArray_UINT :
00485 copy_direct < unsigned int > ( array, col );
00486 break;
00487 case PyArray_FLOAT :
00488 copy_direct < float > ( array, col );
00489 break;
00490 case PyArray_DOUBLE :
00491 copy_direct < double > ( array, col );
00492 break;
00493
00494 default:
00495 std::string what ( "DataArray: Array type `" );
00496 what += num_util::type2string ( type );
00497 what += "' not supported.";
00498 throw std::runtime_error ( what );
00499 break;
00500 }
00501 }
00502 else {
00503 const numeric::array & my_array = array;
00504 int rank = num_util::rank ( my_array );
00505 if ( rank < 2 ) {
00506 int size = num_util::size( my_array );
00507 col.clear();
00508 col.reserve(size);
00509 for (int i = 0; i < size; i++) {
00510 boost::python::object result = my_array[i];
00511 col.push_back( boost::python::extract<double>(result) );
00512 }
00513 }
00514 else {
00515 boost::python::object tarray = array.getflat();
00516 int size = num_util::size ( array );
00517 for ( int i = 0; i < size; i++ ) {
00518 boost::python::object result = tarray[i];
00519 col.push_back ( boost::python::extract < double > ( result ) );
00520 }
00521 }
00522 }
00523 }
00524
00525 PyDataSource *
00526 PyDataSource::
00527 getCurrentDataSource ()
00528 {
00529 PyDataSource * array = 0;
00530
00531 DataSourceController * controller = DataSourceController::instance ();
00532 DataSource * source = controller -> getCurrent ();
00533
00534 if ( source != 0 ) {
00535 NTuple * ntuple = dynamic_cast < NTuple * > ( source );
00536 if ( ntuple != 0 ) {
00537 array = new PyDataSource ( "NTuple", source );
00538 }
00539
00540 ListTuple * ltuple = dynamic_cast < ListTuple * > ( source );
00541 if ( ltuple != 0 ) {
00542 array = new PyDataSource ( "ListTuple", source );
00543 }
00544
00545 #ifdef HAVE_NUMARRAY
00546 NumArrayTuple * natuple = dynamic_cast < NumArrayTuple * > ( source );
00547 if ( natuple != 0 ) {
00548 array = new PyDataSource ( "NumArrayTuple", source );
00549 }
00550 #endif
00551
00552 #ifdef HAVE_CFITSIO
00553 FitsNTuple * fntuple = dynamic_cast < FitsNTuple * > ( source );
00554 if ( fntuple != 0 ) {
00555 array = new PyDataSource ( "FitsNTuple", source );
00556 }
00557 #endif
00558
00559 #ifdef HAVE_ROOT
00560 RootNTuple * rntuple = dynamic_cast < RootNTuple * > ( source );
00561 if ( rntuple != 0 ) {
00562 array = new PyDataSource ( "RootNTuple", source );
00563 }
00564 #endif
00565 }
00566
00567
00568 return array;
00569 }
00570
00571 unsigned int PyDataSource::columns() const {
00572 return m_dataSource->columns();
00573 }
00574
00575 unsigned int PyDataSource::rows() const {
00576 return m_dataSource->rows();
00577 }
00578
00579 const std::string & PyDataSource::getTitle() const {
00580 return m_dataSource->title();
00581 }
00582
00583 void PyDataSource::setTitle(const std::string & title) {
00584 m_dataSource->setTitle(title);
00585 }
00586
00587 void PyDataSource::setName(const std::string & name) {
00588 m_dataSource->setName(name);
00589 }
00590
00591 const std::vector<std::string> & PyDataSource::getLabels() const {
00592 return m_dataSource->getLabels();
00593 }
00594
00595 const std::vector<double> &
00596 PyDataSource::getColumn(const std::string & name) const {
00597 return m_dataSource->getColumn(name);
00598 }
00599
00600 const std::vector<double> &
00601 PyDataSource::getColumn(unsigned int index) const {
00602 return m_dataSource->getColumn(index);
00603 }
00604
00605 void
00606 PyDataSource::
00607 replaceColumn (const std::string & label,
00608 const std::vector < double > & col )
00609 {
00610 if ( m_type == "NTuple" ||
00611 m_type == "FitsNTuple" ||
00612 m_type == "RootNTuple" ) {
00613 m_dataSource -> replaceColumn ( label, col );
00614 } else if (m_type == "ListTuple") {
00615 ListTuple * nt = dynamic_cast<ListTuple *>(m_dataSource);
00616 boost::python::list seq(col);
00617 nt->replaceColumn(label, seq);
00618 } else {
00619 std::string what("Cannot replace a column of this type in a " + m_type);
00620 throw std::runtime_error(what);
00621 }
00622 }
00623
00624 void
00625 PyDataSource::
00626 replaceColumn ( unsigned int index,
00627 const std::vector < double > & col)
00628 {
00629 const std::vector<std::string> & names = m_dataSource->getLabels();
00630 if ( index < names.size() ) {
00631 replaceColumn(names[index], col);
00632 } else {
00633 std::string what ( "Invalid column index: " );
00634 what += hippodraw::String::convert ( index );
00635 throw std::runtime_error ( what );
00636 }
00637 }
00638
00639 void
00640 PyDataSource::
00641 replaceColumn ( const std::string & label,
00642 boost::python::numeric::array array)
00643 {
00644 #ifdef HAVE_NUMARRAY
00645 NumArrayTuple * nt = dynamic_cast<NumArrayTuple *>(m_dataSource);
00646 if (!nt) {
00647 std::string what("Cannot replace a column of this type in a " + m_type);
00648 throw std::runtime_error(what);
00649 }
00650 nt->replaceColumn(label, array);
00651 #else
00652 throw std::runtime_error ( "HippoDraw was not built with "
00653 "numeric Python suppport" );
00654 #endif
00655 }
00656
00657 void
00658 PyDataSource::
00659 replaceColumn ( unsigned int index,
00660 boost::python::numeric::array array )
00661 {
00662 #ifdef HAVE_NUMARRAY
00663 NumArrayTuple * nt = dynamic_cast<NumArrayTuple *>(m_dataSource);
00664 if (!nt) {
00665 std::string what("Cannot replace a column of this type in a " + m_type);
00666 throw std::runtime_error(what);
00667 }
00668 nt->replaceColumn(index, array);
00669 #else
00670 throw std::runtime_error ( "HippoDraw was not built with "
00671 "numeric Python suppport" );
00672 #endif
00673 }
00674
00675 int PyDataSource::addColumn( const std::string & label,
00676 const std::vector<double> & col ) {
00677 if (m_type == "NTuple") {
00678 NTuple * nt = dynamic_cast<NTuple *>(m_dataSource);
00679 return nt->addColumn(label, col);
00680 } else if (m_type == "ListTuple") {
00681 ListTuple * nt = dynamic_cast<ListTuple *>(m_dataSource);
00682 boost::python::list seq(col);
00683 return nt->addColumn(label, seq);
00684 } else {
00685 std::string what("Cannot add a column of this type to a " + m_type);
00686 throw std::runtime_error(what);
00687 }
00688 return m_dataSource->columns();
00689 }
00690
00691 int PyDataSource::addColumn( const std::string & label,
00692 boost::python::numeric::array array ) {
00693 #ifdef HAVE_NUMARRAY
00694 NumArrayTuple * nt = dynamic_cast<NumArrayTuple *>(m_dataSource);
00695 if (!nt) {
00696 std::string what("Cannot add a column of this type to a " + m_type);
00697 throw std::runtime_error(what);
00698 }
00699 return nt->addColumn(label, array);
00700 #else
00701 throw std::runtime_error ( "HippoDraw was not built with "
00702 "numeric Python support" );
00703 #endif
00704 }
00705
00706 void PyDataSource::clear() {
00707 m_dataSource->clear();
00708 }
00709
00710 bool PyDataSource::hasColumn(const std::string & colname) const {
00711 const std::vector<std::string> & names = getLabels();
00712 return std::find(names.begin(), names.end(), colname) != names.end();
00713 }
00714
00715 void PyDataSource::registerNTuple( const std::string & name ) {
00716 m_dataSource->setName(name);
00717 DataSourceController * controller = DataSourceController::instance();
00718 controller->registerNTuple(name, m_dataSource);
00719 }
00720
00721 std::string PyDataSource::registerNTuple() {
00722 DataSourceController * controller = DataSourceController::instance();
00723 return controller->registerNTuple(m_dataSource);
00724 }
00725
00726 boost::python::numeric::array
00727 PyDataSource::
00728 columnAsNumArray( const std::string & colname ) const
00729 {
00730 #ifdef HAVE_NUMARRAY
00731 if (m_type == "NumArrayTuple") {
00732 NumArrayTuple * nt = dynamic_cast<NumArrayTuple *>(m_dataSource);
00733 boost::python::numeric::array a = nt->getNumArray(colname);
00734 return a;
00735 }
00736
00737 #ifdef HAVE_ROOT
00738 if ( m_type == "RootNTuple" ) {
00739 QtRootNTuple * tuple = dynamic_cast < QtRootNTuple *> ( m_dataSource );
00740 boost::python::numeric::array a = tuple -> getColumnAsArray ( colname );
00741 return a;
00742 }
00743 #endif
00744
00745 typedef std::vector<double> vec;
00746 const vec & array = m_dataSource->getColumn(colname);
00747 std::vector < int > shape;
00748 m_dataSource -> fillShape ( shape, colname );
00749 numeric::array na
00750 = num_util::makeNum ( &const_cast<vec &>( array )[0], shape );
00751 return na;
00752 #else
00753 throw std::runtime_error ("HippoDraw was not built with "
00754 "numeric Python support" );
00755 #endif // HAVE_NUMARRAY
00756 }
00757
00758 boost::python::numeric::array
00759 PyDataSource::
00760 columnAsNumArray ( unsigned int index ) const {
00761 #ifdef HAVE_NUMARRAY
00762 if ( index < columns() ) {
00763 if (m_type == "NumArrayTuple") {
00764 NumArrayTuple * nt = dynamic_cast<NumArrayTuple *>(m_dataSource);
00765 return nt->getNumArray(index);
00766 }
00767 typedef std::vector<double> vec;
00768 const vec & array = m_dataSource->getColumn(index);
00769 std::vector < int > shape;
00770 m_dataSource -> fillShape ( shape, index );
00771 numeric::array na =
00772 num_util::makeNum ( &const_cast <vec &> ( array )[0], shape );
00773 return na;
00774 } else {
00775 throw StopIteration("index out-of-range");
00776 }
00777 #else
00778 throw std::runtime_error ( "HippoDraw was not built with "
00779 "numeric Python support" );
00780 #endif
00781 }
00782
00783 void
00784 PyDataSource::
00785 checkRank ( boost::python::numeric::array array )
00786 {
00787 #ifdef HAVE_NUMARRAY
00788 int rank = num_util::rank ( array );
00789 if ( rank > 1 ) {
00790 std::string what ( "DataArray: Can not add " );
00791 what += hippodraw::String::convert ( rank );
00792 what += " dimensional array\n to ";
00793 what += m_type;
00794 throw std::runtime_error ( what );
00795 }
00796 #endif
00797 }
00798
00799 void
00800 PyDataSource::
00801 saveColumn ( const std::string & label,
00802 const std::vector < double > & v,
00803 const std::vector < intptr_t > & shape )
00804 {
00805 if ( hasColumn ( label ) ) {
00806 m_dataSource -> replaceColumn ( label, v, shape );
00807 } else {
00808 m_dataSource -> addColumn ( label, v, shape );
00809 }
00810 }
00811
00812 void
00813 PyDataSource::
00814 saveColumnFromNumArray ( const std::string & label,
00815 boost::python::numeric::array array )
00816 {
00817 #ifdef HAVE_NUMARRAY
00818 PyApp::lock ();
00819 if (m_type == "NumArrayTuple") {
00820 if (hasColumn(label)) {
00821 replaceColumn(label, array);
00822 } else {
00823 addColumn(label, array);
00824 }
00825 PyApp::unlock();
00826 return;
00827 }
00828
00829 #ifdef HAVE_CFITSIO
00830 FitsNTuple * fnt = dynamic_cast < FitsNTuple * > ( m_dataSource );
00831 if ( fnt != 0 ) {
00832 std::vector < double > vec;
00833 extractVector ( array, vec );
00834
00835 const std::vector < intptr_t > shape = num_util::shape ( array );
00836 saveColumn ( label, vec, shape );
00837
00838 PyApp::unlock();
00839 return;
00840 }
00841 #endif // cfitsio
00842
00843 if (m_type == "ListTuple") {
00844 boost::python::list seq(array);
00845 ListTuple * nt = dynamic_cast<ListTuple *>(m_dataSource);
00846 if (hasColumn(label)) {
00847 nt->replaceColumn(label, seq);
00848 } else {
00849 nt->addColumn(label, seq);
00850 }
00851 PyApp::unlock();
00852 return;
00853 }
00854
00855 checkRank ( array );
00856 std::vector<double> col;
00857 extractVector(array, col);
00858
00859 if (m_type == "NTuple") {
00860 NTuple * nt = dynamic_cast<NTuple *>(m_dataSource);
00861 if (hasColumn(label)) {
00862 m_dataSource ->replaceColumn ( label, col );
00863 } else {
00864 nt->addColumn(label, col);
00865 }
00866 PyApp::unlock();
00867 return;
00868 }
00869
00870
00871 #ifdef HAVE_ROOT
00872 RootNTuple * rnt = dynamic_cast < RootNTuple * > ( m_dataSource );
00873 if ( rnt != 0 ) {
00874 if ( hasColumn ( label ) ) {
00875 m_dataSource -> replaceColumn ( label, col );
00876 } else {
00877 rnt -> addColumn ( label, col );
00878 }
00879 PyApp::unlock();
00880 return;
00881 }
00882 #endif // root
00883 PyApp::unlock();
00884
00885 throw std::runtime_error("__setitem__ not supported for " + m_type);
00886 #else
00887 throw std::runtime_error ("HippoDraw was not built with "
00888 "numeric Python support" );
00889 #endif
00890 }
00891
00894 void PyDataSource::
00895 saveColumnFromNumArray( unsigned int index,
00896 boost::python::numeric::array array )
00897 {
00898 #ifdef HAVE_NUMARRAY
00899 if ( index < columns()) {
00900
00901 if (m_type == "NumArrayTuple") {
00902 replaceColumn(index, array);
00903 return;
00904
00905 } else if (m_type == "NTuple") {
00906 checkRank ( array );
00907 std::vector<double> col;
00908 extractVector ( array, col );
00909 NTuple * nt = dynamic_cast<NTuple *>(m_dataSource);
00910 nt->replaceColumn(index, col);
00911 return;
00912
00913 } else if (m_type == "ListTuple") {
00914 boost::python::list seq(array);
00915 ListTuple * nt = dynamic_cast<ListTuple *>(m_dataSource);
00916 nt->replaceColumn(index, seq);
00917 return;
00918 }
00919 #ifdef HAVE_CFITSIO
00920 else {
00921 FitsNTuple * fnt = dynamic_cast < FitsNTuple * > ( m_dataSource );
00922 if ( fnt != 0 ) {
00923 std::vector<double> col;
00924 extractVector ( array, col );
00925 const std::vector < intptr_t > shape = num_util::shape ( array );
00926 fnt -> replaceColumn ( index, col, shape );
00927 return;
00928 }
00929 }
00930 #endif
00931 throw std::runtime_error
00932 ("__setitem__ by index is not supported for " + m_type);
00933 } else {
00934 std::string what ( "DataArray:: Attempt to save column " );
00935 what += hippodraw::String::convert ( index );
00936 what += " with ";
00937 what += hippodraw::String::convert ( columns () );
00938 what += " columns in data source";
00939 throw std::runtime_error ( what );
00940 }
00941 #else
00942 throw std::runtime_error ( "HippoDraw was not built with "
00943 "numeric Python support" );
00944 #endif
00945 }
00946
00947
00948 void
00949 PyDataSource::
00950 saveColumnFrom ( const std::string & label,
00951 const std::vector < double > & array )
00952 {
00953 if ( hasColumn ( label ) ) {
00954 m_dataSource -> replaceColumn ( label, array );
00955 }
00956 else {
00957 m_dataSource -> addColumn ( label, array );
00958 }
00959 }
00960
00961 void
00962 PyDataSource::
00963 addRow ( const std::vector < double > & row )
00964 {
00965 PyApp::lock ();
00966 try {
00967 m_dataSource -> addRow ( row );
00968 }
00969 catch ( const std::runtime_error & e ) {
00970 PyApp::unlock ();
00971 throw e;
00972 }
00973 PyApp::unlock ();
00974 }
00975
00976 void
00977 PyDataSource::
00978 append ( const DataSource * source )
00979 {
00980 PyApp::lock ();
00981 m_dataSource -> append ( source );
00982 PyApp::unlock ();
00983 }
00984 void
00985 PyDataSource::
00986 append ( const PyDataSource * source )
00987 {
00988 m_dataSource -> append ( & source -> dataSource() );
00989 }