OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
PyOpalObject.h
Go to the documentation of this file.
1//
2// Python API for PolynomialCoefficient (part of the multidimensional polynomial fitting routines)
3//
4// Copyright (c) 2008-2023, Chris Rogers, STFC Rutherford Appleton Laboratory, Didcot, UK
5//
6// This file is part of OPAL.
7//
8// OPAL is free software: you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12//
13// You should have received a copy of the GNU General Public License
14// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
15//
16
17#ifndef PyOpalObject_H
18#define PyOpalObject_H
19
20#include <Python.h>
21#include <structmember.h>
22
23#include <memory>
24#include <exception>
25#include <iostream>
26#include <boost/python.hpp>
27#include <boost/noncopyable.hpp>
28#include <boost/mpl/front.hpp>
29
37
38extern Inform *gmsg;
39
40namespace PyOpal {
41
66namespace PyOpalObjectNS {
67
68// forward declarations
69template <class C> class PyOpalObject;
70template <class C> struct PyOpalObjectGetProperty;
71template <class C> struct PyOpalObjectSetProperty;
72
82
84extern std::map<AttributeType, std::string> attributeName; // defined in PyOpalObject.cpp
85
95 std::string opalName_m;
96 std::string pyName_m;
97 std::string docString_m;
99 // could also add a "read only" flag as some attributes are read only
100};
101
137template <class C>
139public:
140 typedef PyOpalObject<C> PyC; // for convenience
142 inline PyOpalObject();
144 PyOpalObject(std::shared_ptr<C> object) : object_m(object) {}
146 PyOpalObject(const PyOpalObject<C>& rhs);
148 virtual ~PyOpalObject() = default;
149
156 inline boost::python::class_<PyC> make_class(const char* className);
157
163 inline boost::python::class_<PyC> make_element_class(const char* className);
164
165
171 inline boost::python::class_<PyC> make_generic_class(const char* className);
172
173
176 template <class PYCLASS>
177 void addAttributes(PYCLASS& pyclass);
178
181 template <class PYCLASS>
182 void addExecute(PYCLASS& pyclass);
183
187 template <class PYCLASS>
188 void addRegister(PYCLASS& pyclass);
189
193 template <class PYCLASS>
194 void addGetOpalName(PYCLASS& pyclass);
195
199 template <class PYCLASS>
200 void addSetAttributes(PYCLASS& pyclass);
201
205 template <class PYCLASS>
206 void addSetOpalName(PYCLASS& pyclass);
207
212 template <class PYCLASS>
213 void addSetOpalElementName(PYCLASS& pyclass);
214
223 template <class PYCLASS>
224 void addGetOpalElement(PYCLASS& pyclass);
225
244 template <class PYCLASS>
245 void addGetFieldValue(PYCLASS& pyclass,
246 double distanceUnits, double timeUnits,
247 double bfieldUnits, double efieldUnits);
248
252 template <class ValueType>
253 ValueType dummyGet() const {PyOpalObjectGetProperty<C>::setObject(this); return ValueType();}
254
258 virtual void doSetup() {}
259
263 template <class ValueType>
264 inline void dummySet(ValueType test);
265
274 PyObject* getAttribute(AttributeType type, std::string opalName) const;
275
283 void setAttribute(AttributeType type, std::string opalName, PyObject* value);
284
286 std::shared_ptr<C> getOpalShared() {return object_m;}
287
289 std::shared_ptr<C> getOpalShared() const {return object_m;}
290
291
292protected:
293 static std::vector<AttributeDef> attributes;
294 static std::map<std::string, AttributeDef> pyNameToAttribute;
295 static std::string classDocstring;
297 std::shared_ptr<C> object_m;
300 std::string getDocString(AttributeDef& def);
302 static boost::python::object getFieldValue(
304 double x, double y, double z, double t);
306 static std::string getOpalName(const PyOpalObject<C>& pyobject);
308 static void setOpalName(PyOpalObject<C>& pyobject, std::string name);
311 static void setOpalElementName(PyOpalObject<C>& pyobject, std::string name);
313 static void execute(PyOpalObject<C>& pyobject);
315 static void registerObject(PyOpalObject<C>& pyobject);
317 static boost::python::object getPyOpalElement(PyOpalObject<C>& pyobject);
320 static boost::python::object setAttributes(boost::python::tuple args,
321 boost::python::dict kwargs);
322 // unit definitions for getFieldValue method
323 static double distanceUnits_m;
324 static double timeUnits_m;
325 static double bfieldUnits_m;
326 static double efieldUnits_m;
327 static const std::string getFieldValueDocString;
328};
329
331template <class C>
332std::map<std::string, AttributeDef> PyOpalObject<C>::pyNameToAttribute;
333
339template <class C>
341 std::shared_ptr<C> objectPtr = pyelement.getOpalShared();
342 objectPtr->update();
343}
344
345template <class C>
346template <class ValueType>
347void PyOpalObject<C>::dummySet(ValueType test) {
348 (void)test; // disable Wunused-parameter
350}
351
352template <class C>
353boost::python::object PyOpalObject<C>::getFieldValue(
355 double x, double y, double z, double t) {
356 std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
357 objectPtr->update();
358 pyobject.doSetup();
359 ElementBase* element = objectPtr->getElement();
360 Component* component = dynamic_cast<Component*>(element);
361 if (component == nullptr) {
362 throw OpalException("PyElement<C>::getFieldValue",
363 "Failed to deduce Component from ElementBase.");
364 }
365 Vector_t R({x*distanceUnits_m, y*distanceUnits_m, z*distanceUnits_m});
366 Vector_t P({0.0, 0.0, 0.0});
367 Vector_t B;
368 Vector_t E;
369 t *= timeUnits_m;
370 bool outOfBounds = component->apply(R, P, t, E, B);
371 return boost::python::make_tuple(outOfBounds,
372 B[0]*bfieldUnits_m, B[1]*bfieldUnits_m, B[2]*bfieldUnits_m,
373 E[0]*efieldUnits_m, E[1]*efieldUnits_m, E[2]*efieldUnits_m);
374}
375
377template <class C>
378boost::python::object PyOpalObject<C>::setAttributes(boost::python::tuple args,
379 boost::python::dict kwargs) {
380 if (boost::python::len(args) == 0) {
381 throw OpalException("PyOpalObject::setAttributes",
382 "Did not find class instance (i.e. 'self') when calling "
383 "set_attributes");
384 } else if (boost::python::len(args) > 1) {
385 throw OpalException("PyOpalObject::setAttributes",
386 "set_attributes cannot take any non-keyword args (except the class"
387 " instance");
388 }
389 PyOpalObject<C> self = boost::python::extract<PyOpalObject<C> >(args[0]);
390 boost::python::list key_list = kwargs.keys();
391 for (boost::python::ssize_t i = 0; i < boost::python::len(key_list); ++i) {
392 boost::python::object key = key_list[i];
393 boost::python::object keyObjStr = boost::python::str(key);
394 boost::python::extract<const char*> keyExtract(keyObjStr);
395 if (!keyExtract.check()) {
396 throw OpalException("PyOpalObject::setAttributes",
397 "Attribute key is not convertible to string");
398 }
399 std::string keyStr(keyExtract());
400 boost::python::object value = kwargs[key];
401 if (PyOpalObject<C>::pyNameToAttribute.find(keyStr) ==
403 throw OpalException("PyOpalObject::setAttributes",
404 "Did not recognise attribute '"+keyStr+"'");
405 }
407 self.setAttribute(att.type_m, att.opalName_m, value.ptr());
408 }
409 boost::python::object obj;
410 return obj;
411}
412
414template <class C>
415struct PyOpalObjectGetProperty : boost::python::default_call_policies {
416public:
421 PyOpalObjectGetProperty(AttributeType type, std::string opalName): type_m(type), opalName_m(opalName) {}
424
432 template <class ArgumentPackage>
433 PyObject* postcall(ArgumentPackage const&, PyObject* result);
434
436 static void setObject(const PyOpalObject<C>* object) {object_m = object;}
437
438private:
440 std::string opalName_m;
442};
443
445template <class C>
446struct PyOpalObjectSetProperty : boost::python::default_call_policies {
447public:
452 PyOpalObjectSetProperty(AttributeType type, std::string opalName): type_m(type), opalName_m(opalName) {}
455
463 template <class ArgumentPackage>
464 PyObject* postcall(ArgumentPackage const& args, PyObject* result);
465
467 static void setObject(PyOpalObject<C>* object) {object_m = object;}
468
469private:
471 std::string opalName_m;
473};
474
476
477
478template <class C>
480 std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
481 objectPtr->execute();
482}
483
484template <class C>
486 C* wrappedC = pyobject.getOpalShared().get();
487 Object* objectPtr = dynamic_cast<Object*>(wrappedC);
488 if (objectPtr == nullptr) {
489 throw OpalException("PyOpalObject<C>::registerObject",
490 "Trying to register something that was not a Opal Object");
491 }
492 //Object* objectPtr = &(*pyobject.getOpalShared());
493 OpalData::getInstance()->define(objectPtr);
494}
495
496template <class C>
497std::string PyOpalObject<C>::getOpalName(const PyOpalObject<C>& pyobject) {
498 std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
499 return objectPtr->getOpalName();
500}
501
502template <class C>
504 std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
505 objectPtr->setOpalName(name);
506}
507
508template <class C>
510 std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
511 objectPtr->setOpalName(name);
512 if (objectPtr->getElement()) { // some OpalThings don't define an Element
513 objectPtr->getElement()->setName(name);
514 }
515}
516
517template <class C>
519 std::shared_ptr<OpalElement> elementPtr =
520 std::dynamic_pointer_cast<OpalElement, C>(pyobject.getOpalShared());
521 if (elementPtr.get() == nullptr) {
522 throw OpalException("PyOpalObject<C>::getPyOpalElement",
523 "Wrapped object was not an OpalElement");
524 }
525 PyOpalObject<OpalElement> element(elementPtr);
526 boost::python::object pyelement(element);
527 return pyelement;
528}
529
530
531// defined in PyOpalElement
532template <>
534
535template <class C>
536PyOpalObject<C>::PyOpalObject() : object_m(new C) {}
537
538template <class C>
539PyObject* PyOpalObject<C>::getAttribute(AttributeType type, std::string opalName) const {
540 if (!object_m) {
541 throw OpalException("PyOpalObject<C>::getRealAttribute",
542 "Object was not initialised");
543 }
544 Attribute* attribute = object_m->findAttribute(opalName);
545 if (attribute == nullptr) {
546 throw OpalException("PyOpalObject<C>::getRealAttribute",
547 "Failed to parse attribute "+opalName);
548 }
549 PyObject* pyvalue;
550 // I spent quite a bit of time trying to get this type unwinding to work
551 // using templates (so it is done at compile time). In the end I couldn't
552 // fight the template syntax and had to do it at runtime using an enum; it's
553 // not so bad - the memory footprint is smaller and, tbh, template syntax is
554 // horrible so might be easier to use.
555 switch (type) {
556 case DOUBLE:
557 {
558 double value = Attributes::getReal(*attribute);
559 pyvalue = PyFloat_FromDouble(value);
560 break;
561 }
562 case INT:
563 {
564 double value = Attributes::getReal(*attribute);
565 pyvalue = PyLong_FromDouble(value);
566 break;
567 }
568 case STRING:
571 {
572 std::string value = Attributes::getString(*attribute);
573 pyvalue = PyUnicode_FromString(value.c_str());
574 break;
575 }
576 case BOOL:
577 {
578 bool value = Attributes::getBool(*attribute);
579 if (value) {
580 pyvalue = Py_True;
581 } else {
582 pyvalue = Py_False;
583 }
584 break;
585 }
586 case FLOAT_LIST:
587 {
588 std::vector<double> value = Attributes::getRealArray(*attribute);
589 pyvalue = PyList_New(value.size());
590 for (size_t i = 0; i < value.size(); ++i) {
591 PyList_SetItem(pyvalue, i, PyFloat_FromDouble(value[i]));
592 }
593 break;
594 }
595 case STRING_LIST:
596 {
597 std::vector<std::string> value = Attributes::getStringArray(*attribute);
598 pyvalue = PyList_New(value.size());
599 for (size_t i = 0; i < value.size(); ++i) {
600 PyList_SetItem(pyvalue, i, PyUnicode_FromString(value[i].c_str()));
601 }
602 break;
603 }
604 default:
605 {
606 throw OpalException("PyOpalObject<C>::getAttribute",
607 "Attribute type "+attributeName[type]+" not implemented");
608 }
609 }
610 Py_INCREF(pyvalue);
611 return pyvalue;
612}
613
614
615template <class C>
616void PyOpalObject<C>::setAttribute(AttributeType type, std::string opalName, PyObject* pyvalue) {
617 if (!object_m) {
618 throw OpalException("PyOpalObject<C>::setAttribute",
619 "Element was not initialised");
620 }
621 Attribute* attribute = object_m->findAttribute(opalName);
622 if (attribute == nullptr) {
623 throw OpalException("PyOpalObject<C>::setAttribute",
624 "Failed to parse attribute "+opalName);
625 }
626 switch (type) {
627 case DOUBLE:
628 {
629 double value = PyFloat_AsDouble(pyvalue);
630 Attributes::setReal(*attribute, value);
631 break;
632 }
633 case INT:
634 {
635 double value = PyLong_AsDouble(pyvalue);
636 Attributes::setReal(*attribute, value);
637 break;
638 }
639 case STRING:
640 {
641 std::string value = PyUnicode_AsUTF8(pyvalue);
642 Attributes::setString(*attribute, value);
643 break;
644 }
646 {
647 // predefined string is a string with a list of options
648 // note that value checking never happens - method exists in
649 // src/Attributes/PredefinedString.h but requires a Statement object
650 // which seems hard to construct (Classic/Parser/Statement.h)
651 std::string value = PyUnicode_AsUTF8(pyvalue);
652 Attributes::setPredefinedString(*attribute, value);
653 break;
654 }
656 {
657 std::string value = PyUnicode_AsUTF8(pyvalue);
658 Attributes::setUpperCaseString(*attribute, value);
659 break;
660 }
661 case BOOL:
662 {
663 bool value = PyObject_IsTrue(pyvalue);
664 Attributes::setBool(*attribute, value);
665 break;
666 }
667 case FLOAT_LIST:
668 {
669 Py_ssize_t listSize = PyList_Size(pyvalue);
670 std::vector<double> value(listSize);
671 for (Py_ssize_t i = 0; i < listSize; ++i) {
672 double value_i = PyFloat_AsDouble(PyList_GetItem(pyvalue, i));
673 value[i] = value_i;
674 }
675 Attributes::setRealArray(*attribute, value);
676 break;
677 }
678 case STRING_LIST:
679 {
680 Py_ssize_t listSize = PyList_Size(pyvalue);
681 std::vector<std::string> value(listSize);
682 for (Py_ssize_t i = 0; i < listSize; ++i) {
683 PyObject* pyvalue_i = PyList_GetItem(pyvalue, i);
684 std::string value_i = PyUnicode_AsUTF8(pyvalue_i);
685 value[i] = value_i;
686 }
687 Attributes::setStringArray(*attribute, value);
688 break;
689 }
690 default:
691 {
692 throw OpalException("PyOpalObject<C>::setAttribute",
693 "Attribute type "+attributeName[type]+" not implemented");
694 }
695 }
696}
697
698template <class C>
699PyOpalObject<C>::PyOpalObject(const PyOpalObject<C>& rhs) : object_m(rhs.object_m) {
700}
701
702template <class C>
704 Attribute* attribute = object_m->findAttribute(def.opalName_m);
705 if (attribute == nullptr) {
706 throw OpalException("PyOpalObject<C>::getRealAttribute",
707 "Failed to parse attribute "+def.opalName_m);
708 }
709 std::string docString = def.pyName_m+" ("+attributeName[def.type_m]+"): "+attribute->getHelp();
710 if (def.docString_m != "") {
711 docString = def.pyName_m+" ("+attributeName[def.type_m]+"): "+def.docString_m;
712 }
713 return docString;
714}
715
716template <class C>
717boost::python::class_<PyOpalObject<C> > PyOpalObject<C>::make_generic_class(const char* className) {
718 // WARNING - boost::python is bugged so that in module initialisation,
719 // errors are not handled correctly
720 // https://github.com/boostorg/python/issues/280
721 // so if you get the attribute name wrong you get a bad error
722 // hence I do some local error handling
723 typedef boost::python::class_<PyOpalObject<C> > PyClass;
724 boost::python::docstring_options docop(true, true, false); // user_def, py_sig, cpp_sig
725 PyClass pyclass = PyClass(className);
726 try {
727 addAttributes(pyclass);
728 addGetOpalName(pyclass);
729 addSetAttributes(pyclass);
730 } catch (OpalException& exc) {
731 std::cerr << "Failed to initialise class because '" << exc.what()
732 << "'" << std::endl;
733 throw exc;
734 } catch (std::exception& exc) {
735 std::cerr << "Failed to initialise class because '" << exc.what()
736 << "'" << std::endl;
737 throw exc;
738 }
739 if (gmsg == nullptr) {
740 std::cerr <<
741 "Failed to initialise class because gmsg was not initialised.\n"
742 "PyOpal::Globals::Initialise() must be called before attempting to\n"
743 "initialise classes" << std::endl;
744 throw OpalException("PyOpalObject::make_generic_class",
745 "Globals not initialised");
746 }
747 return pyclass;
748}
749
750template <class C>
751boost::python::class_<PyOpalObject<C> > PyOpalObject<C>::make_class(const char* className) {
752 auto pyclass = make_generic_class(className);
753 addSetOpalName(pyclass);
754 return pyclass;
755}
756
757template <class C>
758boost::python::class_<PyOpalObject<C> > PyOpalObject<C>::make_element_class(const char* className) {
759 auto pyclass = make_generic_class(className);
760 addSetOpalElementName(pyclass);
761 addGetOpalElement(pyclass);
762 return pyclass;
763}
764
765template <class C>
766template <class PYCLASS>
767void PyOpalObject<C>::addExecute(PYCLASS& pyclass) {
768 pyclass.def("execute", &PyOpalObject<C>::execute);
769}
770
771template <class C>
772template <class PYCLASS>
773void PyOpalObject<C>::addRegister(PYCLASS& pyclass) {
774 pyclass.def("register", &PyOpalObject<C>::registerObject);
775}
776
777template <class C>
778template <class PYCLASS>
779void PyOpalObject<C>::addGetOpalName(PYCLASS& pyclass) {
780 pyclass.def("get_opal_name", &PyOpalObject<C>::getOpalName);
781}
782
783template <class C>
784template <class PYCLASS>
785void PyOpalObject<C>::addSetAttributes(PYCLASS& pyclass) {
786 pyclass.def("set_attributes",
787 boost::python::raw_function(&PyOpalObject<C>::setAttributes, 0)
788 );
789}
790
791template <class C>
792template <class PYCLASS>
793void PyOpalObject<C>::addSetOpalName(PYCLASS& pyclass) {
794 pyclass.def("set_opal_name", &PyOpalObject<C>::setOpalName);
795}
796
797template <class C>
798template <class PYCLASS>
800 pyclass.def("set_opal_name", &PyOpalObject<C>::setOpalElementName);
801}
802
803template <class C>
804template <class PYCLASS>
806 pyclass.def("get_opal_element", &PyOpalObject<C>::getPyOpalElement);
807}
808
809template <class C>
810template <class PYCLASS>
812 double distanceUnits, double timeUnits,
813 double efieldUnits, double bfieldUnits) {
814 distanceUnits_m = distanceUnits;
815 timeUnits_m = timeUnits;
816 bfieldUnits_m = bfieldUnits;
817 efieldUnits_m = efieldUnits;
818 pyclass.def("get_field_value",
820 boost::python::args("x", "y", "z", "t"),
821 getFieldValueDocString.c_str());
822}
823
824template <class C>
825template <class PYCLASS>
826void PyOpalObject<C>::addAttributes(PYCLASS& pyclass) {
827 for (std::vector<AttributeDef>::iterator iter = attributes.begin(); iter != attributes.end(); ++iter) {
828 pyNameToAttribute[iter->pyName_m] = *iter;
829 PyOpalObjectGetProperty<C> getProp(iter->type_m, iter->opalName_m);
830 PyOpalObjectSetProperty<C> setProp(iter->type_m, iter->opalName_m);
831 std::string docString = getDocString(*iter);
832 std::string pyname = iter->pyName_m.c_str();
833 switch (iter->type_m) {
834 case DOUBLE:
835 {
836 pyclass.add_property(pyname.c_str(),
837 boost::python::make_function(&PyC::dummyGet<double>, getProp),
838 boost::python::make_function(&PyC::dummySet<double>, setProp),
839 docString.c_str()
840 );
841 break;
842 }
843 case INT:
844 {
845 pyclass.add_property(pyname.c_str(),
846 boost::python::make_function(&PyC::dummyGet<int>, getProp),
847 boost::python::make_function(&PyC::dummySet<int>, setProp),
848 docString.c_str()
849 );
850 break;
851 }
852 case STRING:
855 {
856 pyclass.add_property(pyname.c_str(),
857 boost::python::make_function(&PyC::dummyGet<std::string>, getProp),
858 boost::python::make_function(&PyC::dummySet<std::string>, setProp),
859 docString.c_str()
860 );
861 break;
862 }
863 case BOOL:
864 {
865 pyclass.add_property(pyname.c_str(),
866 boost::python::make_function(&PyC::dummyGet<bool>, getProp),
867 boost::python::make_function(&PyC::dummySet<bool>, setProp),
868 docString.c_str()
869 );
870 break;
871 }
872 case FLOAT_LIST:
873 case STRING_LIST:
874 {
875 pyclass.add_property(pyname.c_str(),
876 boost::python::make_function(&PyC::dummyGet<boost::python::list>, getProp),
877 boost::python::make_function(&PyC::dummySet<boost::python::list>, setProp),
878 docString.c_str()
879 );
880 break;
881 }
882 default:
883 {
884 // Looks like exception handling doesn't work properly at module
885 // import time so this may not be handled politely - thrown as an
886 // unrecognised SystemError
887 throw OpalException("PyOpalObject<C>::addAttributes", "Type not implemented");
888 }
889 }
890 }
891}
892
893template <class C> double PyOpalObject<C>::distanceUnits_m = 1;
894template <class C> double PyOpalObject<C>::timeUnits_m = 1;
895template <class C> double PyOpalObject<C>::bfieldUnits_m = 1;
896template <class C> double PyOpalObject<C>::efieldUnits_m = 1;
897
898template <class C> const std::string PyOpalObject<C>::getFieldValueDocString =
899 "Get the field value at a point in the field map.\n"
900 "\n"
901 "The field lookup is performed against the last RINGDEFINITION that was\n"
902 "instantiated. This should be instantiated by calling\n"
903 "pyopal.parser.initialise_from_opal_file\n"
904 "\n"
905 "Parameters\n"
906 "----------\n"
907 "x : float\n"
908 " x position [m]\n"
909 "y : float\n"
910 " y position [m]\n"
911 "z : float\n"
912 " z position [m]\n"
913 "t: float\n"
914 " time [ns]\n"
915 "\n"
916 "Returns\n"
917 "-------\n"
918 "The function returns a tuple containing 7 values:\n"
919 "out of bounds : int\n"
920 " 1 if the event was out of the field map boundary, else 0.\n"
921 "Bx : float\n"
922 " x magnetic field [T]\n"
923 "By : float\n"
924 " y magnetic field [T]\n"
925 "Bz : float\n"
926 " z magnetic field [T]\n"
927 "Ex : float\n"
928 " x electric field [MV/m]\n"
929 "Ey : float\n"
930 " y electric field [MV/m]\n"
931 "Ez : float\n"
932 " z electric field [MV/m]\n";
933
934
936
937template <class C>
938template <class ArgumentPackage>
939PyObject* PyOpalObjectGetProperty<C>::postcall(ArgumentPackage const&, PyObject* result) {
940 Py_DECREF(result);
941 result = object_m->getAttribute(type_m, opalName_m);
942 return result;
943}
944
945template <class C>
947
949
950template <class C>
951template <class ArgumentPackage>
952PyObject* PyOpalObjectSetProperty<C>::postcall(ArgumentPackage const& args, PyObject* result) {
953 PyObject* value;
954 PyObject* pyObject; // this is a direct pointer to the C but I don't know how to unwrap it...
955 if (!PyArg_ParseTuple(args, "OO", &pyObject, &value)) {
956 return nullptr; // ParseTuple sets the error message
957 }
958 Py_DECREF(result);
959 object_m->setAttribute(type_m, opalName_m, value);
960 object_m = nullptr;
961 Py_RETURN_NONE;
962}
963
964template <class C>
966
967} // PyOpalObject
968} // PyOpal
969
970#endif // PyOpalObject_H
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
Inform * gmsg
Definition Main.cpp:69
Inform * gmsg
Definition Main.cpp:69
const std::string name
double getReal(const Attribute &attr)
Return real value.
void setRealArray(Attribute &attr, const std::vector< double > &value)
Set array value.
void setBool(Attribute &attr, bool val)
Set logical value.
void setUpperCaseString(Attribute &attr, const std::string &val)
Set uppercase string value.
void setString(Attribute &attr, const std::string &val)
Set string value.
bool getBool(const Attribute &attr)
Return logical value.
void setReal(Attribute &attr, double val)
Set real value.
void setStringArray(Attribute &attr, const std::vector< std::string > &value)
Set string array value.
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
std::vector< std::string > getStringArray(const Attribute &attr)
Get string array value.
void setPredefinedString(Attribute &attr, const std::string &val)
Set predefined string value.
std::string getString(const Attribute &attr)
Get string value.
std::map< AttributeType, std::string > attributeName
void update(PyOpalObjectNS::PyOpalObject< C > pyelement)
A representation of an Object attribute.
Definition Attribute.h:52
const std::string & getHelp() const
Return the help string.
Definition Attribute.cpp:82
The base class for all OPAL objects.
Definition Object.h:48
static OpalData * getInstance()
Definition OpalData.cpp:196
void define(Object *newObject)
Define a new object.
Definition OpalData.cpp:489
Interface for a single beam element.
Definition Component.h:50
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B)
Definition Component.cpp:99
void addRegister(PYCLASS &pyclass)
void addGetOpalName(PYCLASS &pyclass)
static std::string getOpalName(const PyOpalObject< C > &pyobject)
void addSetOpalName(PYCLASS &pyclass)
static std::vector< AttributeDef > attributes
static void registerObject(PyOpalObject< C > &pyobject)
void addAttributes(PYCLASS &pyclass)
void addGetOpalElement(PYCLASS &pyclass)
static std::map< std::string, AttributeDef > pyNameToAttribute
static boost::python::object setAttributes(boost::python::tuple args, boost::python::dict kwargs)
void addSetOpalElementName(PYCLASS &pyclass)
boost::python::class_< PyC > make_generic_class(const char *className)
void addGetFieldValue(PYCLASS &pyclass, double distanceUnits, double timeUnits, double bfieldUnits, double efieldUnits)
std::string getDocString(AttributeDef &def)
PyOpalObject(std::shared_ptr< C > object)
static boost::python::object getFieldValue(PyOpalObjectNS::PyOpalObject< C > &pyobject, double x, double y, double z, double t)
static boost::python::object getPyOpalElement(PyOpalObject< C > &pyobject)
static void setOpalElementName(PyOpalObject< C > &pyobject, std::string name)
void addSetAttributes(PYCLASS &pyclass)
std::shared_ptr< C > getOpalShared()
PyObject * getAttribute(AttributeType type, std::string opalName) const
boost::python::class_< PyC > make_class(const char *className)
static void execute(PyOpalObject< C > &pyobject)
boost::python::class_< PyC > make_element_class(const char *className)
void addExecute(PYCLASS &pyclass)
static const std::string getFieldValueDocString
std::shared_ptr< C > getOpalShared() const
static void setOpalName(PyOpalObject< C > &pyobject, std::string name)
void setAttribute(AttributeType type, std::string opalName, PyObject *value)
static void setObject(const PyOpalObject< C > *object)
static const PyOpalObject< C > * object_m
PyObject * postcall(ArgumentPackage const &, PyObject *result)
PyOpalObjectGetProperty(AttributeType type, std::string opalName)
static void setObject(PyOpalObject< C > *object)
PyObject * postcall(ArgumentPackage const &args, PyObject *result)
PyOpalObjectSetProperty(AttributeType type, std::string opalName)
The base class for all OPAL exceptions.
virtual const std::string & what() const
Return the message string for the exception.