20 #include "msdevstudio/MSconfig.h"
24 #include <boost/python.hpp>
41 #include "numpy/oldnumeric.h"
52 using namespace boost::python;
146 namespace hippodraw {
150 PyErr_SetString ( PyExc_StopIteration, e.
what() );
156 class_ < PyDataSource >
158 "A DataArray wraps a DataSource object so that numerical Python\n"
159 "arrays can be used as both input and output. The numerical array\n"
160 "can be either a numarray.array or Numeric.array depending on\n"
161 "how the hippo module was configured.\n"
163 "Access to the array is done like a Python list or dictionary.\n"
164 "\tarray = my_data_array [ index ] # list form\n"
165 "\tarray = my_data_array [ 'my_label' ] # dict form\n"
167 "Storage to the array is also done like a Python list or dictionary.\n"
168 "\tmy_data_array [ index ] = ... # list form\n"
169 "\tmy_data_array [ 'my_label' ] = ... # dict form\n" )
171 .def ( init < const std::string & > (
172 "DataArray ( string ) -> DataArray\n"
174 "Creates a DataArray. The string can be one of\n"
177 "\tNumArrayTuple" ) )
179 .add_property (
"columns",
180 &PyDataSource::columns )
182 .add_property (
"rows",
183 &PyDataSource::rows )
186 &PyDataSource::getCurrentDataSource,
187 return_value_policy < reference_existing_object > (),
188 "getCurrent () -> DataArray\n"
190 "Returns a DataArray that wraps the current DataSource." )
192 .staticmethod (
"getCurrent" )
195 &PyDataSource::dataSource,
196 return_value_policy < reference_existing_object > (),
197 "dataSource () -> DataSource\n"
199 "Returns reference to underlying DataSource" )
202 &PyDataSource::getTitle,
203 return_value_policy < copy_const_reference > (),
204 "getTitle () -> string\n"
206 "Returns title of the DataSource." )
209 &PyDataSource::setName,
210 "setName ( string ) -> None\n"
212 "Sets the name of the DataSource. The name should be unique\n"
213 "with one application and may appear in the Inspector panel." )
216 &PyDataSource::setTitle,
217 "setTitle ( string ) -> None\n"
219 "Sets the title of the DataSource. The title is what appears,\n"
220 "by default, at the top of a Display." )
223 &PyDataSource::getLabels,
224 return_value_policy < copy_const_reference > (),
225 "getLabels () -> list\n"
227 "Returns the list of string objects of column labels." )
231 (
const std::string &,
const std::vector<double> &) )
232 &PyDataSource::addColumn,
233 "addColumn ( string, list ) -> value\n"
234 "addColumn ( string, array ) -> value\n"
236 "Adds a column. The string will be the label of the column.\n"
237 "A copy of the list or array values will be the contents.\n"
238 "The second form is only available if HippoDraw was configured\n"
239 "with numerical Python support. Returns the new column's index." )
244 (
const std::string &, boost::python::numeric::array) )
245 &PyDataSource::addColumn )
250 (
unsigned int )
const)
251 &PyDataSource::getColumn,
252 return_value_policy < copy_const_reference> (),
253 "getColumn ( value ) -> list\n"
255 "Returns a column as list of floats. 'value' maybe either\n"
256 "the column label or its index." )
260 (
const std::string & )
const)
261 &PyDataSource::getColumn,
262 return_value_policy < copy_const_reference> () )
264 .def (
"replaceColumn",
266 (
const std::string &,
const std::vector<double> & ) )
267 &PyDataSource::replaceColumn,
268 "replaceColumn ( value, list ) -> None\n"
269 "replaceColumn ( value, array ) -> None\n"
271 "Replace column by its label or index. The second form is \n"
272 "only available if HippoDraw was configure with numerical\n"
275 .def (
"replaceColumn",
277 (
unsigned int index,
const std::vector<double> & ) )
278 &PyDataSource::replaceColumn )
281 .def (
"replaceColumn",
283 (
const std::string &, numeric::array ) )
284 &PyDataSource::replaceColumn )
286 .def (
"replaceColumn",
288 (
unsigned int index, numeric::array ) )
289 &PyDataSource::replaceColumn )
298 &PyDataSource::hasColumn,
299 "has_key ( string ) -> Boolean\n"
301 "Returns True if column with label exists.")
304 &PyDataSource::getLabels,
305 return_value_policy < copy_const_reference > (),
308 "Returns the list of column labels." )
312 &PyDataSource::registerNTuple,
313 "register ( string ) -> None\n"
314 "register ( ) -> string\n"
316 "Register the underlying DataSource with the\n"
317 "DataSourceController. The first form registers it with the\n"
318 "given name, while the second from returns a unique name\n"
319 "generated by the controller." )
323 &PyDataSource::registerNTuple )
329 .def (
"__setitem__",
330 &PyDataSource::saveColumnFrom,
331 "__setitem__ ( label, sequence ) -> None\n"
333 "Copies the contensts of the sequence. If column with label\n"
334 "already exists, replaces it, otherwise add a new column." )
337 &PyDataSource::addRow,
338 "addRow ( sequence ) -> None\n"
340 "Adds a row to the held DataSource object if supported, otherwise"
341 " throws Runtime exception." )
346 &PyDataSource::append,
347 "append ( DataArray ) -> None\n"
348 "append ( DataSource ) -> None\n"
350 "Appends contents of DataSource or DataArray to the DataArray." )
355 &PyDataSource::append )
358 .def (
"__getitem__",
360 (
const std::string & )
const )
361 &PyDataSource::columnAsNumArray,
362 return_value_policy < return_by_value > (),
363 "__getitem__ ( value ) -> array\n"
365 "Returns a copy of the column as numerical array. 'value' can\n"
366 "be either the column label or its index." )
368 .def (
"__getitem__",
370 (
unsigned int )
const )
371 &PyDataSource::columnAsNumArray,
372 return_value_policy < return_by_value > () )
374 .def (
"__setitem__",
376 (
const std::string &,
378 &PyDataSource::saveColumnFromNumArray,
379 return_value_policy < return_by_value > (),
380 "__setitem__ ( value, array ) -> None\n"
382 "Copies the contents of array. If `'value' is an index, then\n"
383 "replaces the contents of the existing column. If 'value' is\n"
384 "a label then either replaces existing column with that label\n"
385 "or adds a new column." )
387 .def (
"__setitem__",
391 &PyDataSource::saveColumnFromNumArray,
392 return_value_policy < return_by_value > () )
395 register_exception_translator<PyDataSource::StopIteration>
402 using namespace hippodraw;
404 PyDataSource::PyDataSource() {
406 m_dataSource =
new NTuple();
410 PyDataSource (
const std::string & name,
DataSource * source )
412 m_dataSource ( source )
421 : m_type(dataSource) {
422 if (dataSource ==
"ListTuple") {
424 }
else if (dataSource ==
"NTuple") {
427 }
else if (dataSource ==
"NumArrayTuple") {
430 }
else if (dataSource ==
"NumArrayTuple") {
431 throw std::runtime_error (
"HippoDraw was not built with "
432 "numeric Python soupport" );
435 throw std::runtime_error(
"Invalid DataSource: " + dataSource);
445 template <
typename T >
449 std::vector<double > & col )
453 std::copy ( data, data+ size, back_inserter( col ) );
459 std::vector<double> & col )
464 type != PyArray_NOTYPE ) {
469 copy_direct < bool > ( array, col );
473 copy_direct < char > ( array, col );
477 copy_direct < short > ( array, col );
481 copy_direct < int > ( array, col );
485 copy_direct < unsigned int > ( array, col );
488 copy_direct < float > ( array, col );
490 case PyArray_DOUBLE :
491 copy_direct < double > ( array, col );
495 std::string what (
"DataArray: Array type `" );
497 what +=
"' not supported.";
498 throw std::runtime_error ( what );
503 const numeric::array & my_array = array;
509 for (
int i = 0; i <
size; i++) {
510 boost::python::object result = my_array[i];
511 col.push_back( boost::python::extract<double>(result) );
515 boost::python::object tarray = array.getflat();
517 for (
int i = 0; i <
size; i++ ) {
518 boost::python::object result = tarray[i];
519 col.push_back ( boost::python::extract < double > ( result ) );
532 DataSource * source = controller -> getCurrent ();
547 if ( natuple != 0 ) {
554 if ( fntuple != 0 ) {
561 if ( rntuple != 0 ) {
595 const std::vector<double> &
600 const std::vector<double> &
608 const std::vector < double > & col )
610 if (
m_type ==
"NTuple" ||
612 m_type ==
"RootNTuple" ) {
614 }
else if (
m_type ==
"ListTuple") {
619 std::string what(
"Cannot replace a column of this type in a " +
m_type);
620 throw std::runtime_error(what);
627 const std::vector < double > & col)
630 if ( index < names.size() ) {
633 std::string what (
"Invalid column index: " );
635 throw std::runtime_error ( what );
642 boost::python::numeric::array array)
647 std::string what(
"Cannot replace a column of this type in a " +
m_type);
648 throw std::runtime_error(what);
652 throw std::runtime_error (
"HippoDraw was not built with "
653 "numeric Python suppport" );
660 boost::python::numeric::array array )
665 std::string what(
"Cannot replace a column of this type in a " +
m_type);
666 throw std::runtime_error(what);
670 throw std::runtime_error (
"HippoDraw was not built with "
671 "numeric Python suppport" );
676 const std::vector<double> & col ) {
680 }
else if (
m_type ==
"ListTuple") {
685 std::string what(
"Cannot add a column of this type to a " +
m_type);
686 throw std::runtime_error(what);
692 boost::python::numeric::array array ) {
696 std::string what(
"Cannot add a column of this type to a " +
m_type);
697 throw std::runtime_error(what);
701 throw std::runtime_error (
"HippoDraw was not built with "
702 "numeric Python support" );
711 const std::vector<std::string> & names =
getLabels();
712 return std::find(names.begin(), names.end(), colname) != names.end();
726 boost::python::numeric::array
731 if (
m_type ==
"NumArrayTuple") {
733 boost::python::numeric::array a = nt->
getNumArray(colname);
738 if (
m_type ==
"RootNTuple" ) {
740 boost::python::numeric::array a = tuple -> getColumnAsArray ( colname );
745 typedef std::vector<double>
vec;
747 std::vector < int >
shape;
753 throw std::runtime_error (
"HippoDraw was not built with "
754 "numeric Python support" );
755 #endif // HAVE_NUMARRAY
758 boost::python::numeric::array
763 if (
m_type ==
"NumArrayTuple") {
767 typedef std::vector<double>
vec;
769 std::vector < int >
shape;
778 throw std::runtime_error (
"HippoDraw was not built with "
779 "numeric Python support" );
790 std::string what (
"DataArray: Can not add " );
792 what +=
" dimensional array\n to ";
794 throw std::runtime_error ( what );
802 const std::vector < double > & v,
803 const std::vector < intptr_t > &
shape )
815 boost::python::numeric::array array )
819 if (
m_type ==
"NumArrayTuple") {
832 std::vector < double >
vec;
843 if (
m_type ==
"ListTuple") {
856 std::vector<double> col;
885 throw std::runtime_error(
"__setitem__ not supported for " +
m_type);
887 throw std::runtime_error (
"HippoDraw was not built with "
888 "numeric Python support" );
896 boost::python::numeric::array array )
901 if (
m_type ==
"NumArrayTuple") {
905 }
else if (
m_type ==
"NTuple") {
907 std::vector<double> col;
913 }
else if (
m_type ==
"ListTuple") {
923 std::vector<double> col;
931 throw std::runtime_error
932 (
"__setitem__ by index is not supported for " +
m_type);
934 std::string what (
"DataArray:: Attempt to save column " );
938 what +=
" columns in data source";
939 throw std::runtime_error ( what );
942 throw std::runtime_error (
"HippoDraw was not built with "
943 "numeric Python support" );
951 const std::vector < double > & array )
963 addRow (
const std::vector < double > & row )
969 catch (
const std::runtime_error & e ) {