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