OPAL (Object Oriented Parallel Accelerator Library)  2024.1
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 
31 #include "Elements/OpalElement.h"
33 #include "AbstractObjects/Object.h"
34 #include "AbsBeamline/Component.h"
35 #include "Attributes/Attributes.h"
37 
38 extern Inform *gmsg;
39 
40 namespace PyOpal {
41 
66 namespace PyOpalObjectNS {
67 
68 // forward declarations
69 template <class C> class PyOpalObject;
70 template <class C> struct PyOpalObjectGetProperty;
71 template <class C> struct PyOpalObjectSetProperty;
72 
82 
84 extern std::map<AttributeType, std::string> attributeName; // defined in PyOpalObject.cpp
85 
94 struct AttributeDef {
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 
137 template <class C>
138 class PyOpalObject {
139 public:
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);
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 
292 protected:
293  static std::vector<AttributeDef> attributes;
294  static std::map<std::string, AttributeDef> pyNameToAttribute;
295  static std::string classDocstring;
296  static bool converterRegistered;
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 
331 template <class C>
332 std::map<std::string, AttributeDef> PyOpalObject<C>::pyNameToAttribute;
333 
339 template <class C>
341  std::shared_ptr<C> objectPtr = pyelement.getOpalShared();
342  objectPtr->update();
343 }
344 
345 template <class C>
346 template <class ValueType>
347 void PyOpalObject<C>::dummySet(ValueType test) {
348  (void)test; // disable Wunused-parameter
350 }
351 
352 template <class C>
353 boost::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 
377 template <class C>
378 boost::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  std::string keyStr = boost::python::extract<std::string>(key);
394  boost::python::object value = kwargs[key];
397  throw OpalException("PyOpalObject::setAttributes",
398  "Did not recognise attribute '"+keyStr+"'");
399  }
401  self.setAttribute(att.type_m, att.opalName_m, value.ptr());
402  }
403  boost::python::object obj;
404  return obj;
405 }
406 
408 template <class C>
409 struct PyOpalObjectGetProperty : boost::python::default_call_policies {
410 public:
415  PyOpalObjectGetProperty(AttributeType type, std::string opalName): type_m(type), opalName_m(opalName) {}
418 
426  template <class ArgumentPackage>
427  PyObject* postcall(ArgumentPackage const&, PyObject* result);
428 
430  static void setObject(const PyOpalObject<C>* object) {object_m = object;}
431 
432 private:
434  std::string opalName_m;
435  static const PyOpalObject<C>* object_m;
436 };
437 
439 template <class C>
440 struct PyOpalObjectSetProperty : boost::python::default_call_policies {
441 public:
446  PyOpalObjectSetProperty(AttributeType type, std::string opalName): type_m(type), opalName_m(opalName) {}
449 
457  template <class ArgumentPackage>
458  PyObject* postcall(ArgumentPackage const& args, PyObject* result);
459 
461  static void setObject(PyOpalObject<C>* object) {object_m = object;}
462 
463 private:
465  std::string opalName_m;
467 };
468 
470 
471 
472 template <class C>
474  std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
475  objectPtr->execute();
476 }
477 
478 template <class C>
480  C* wrappedC = pyobject.getOpalShared().get();
481  Object* objectPtr = dynamic_cast<Object*>(wrappedC);
482  if (objectPtr == nullptr) {
483  throw OpalException("PyOpalObject<C>::registerObject",
484  "Trying to register something that was not a Opal Object");
485  }
486  //Object* objectPtr = &(*pyobject.getOpalShared());
487  OpalData::getInstance()->define(objectPtr);
488 }
489 
490 template <class C>
491 std::string PyOpalObject<C>::getOpalName(const PyOpalObject<C>& pyobject) {
492  std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
493  return objectPtr->getOpalName();
494 }
495 
496 template <class C>
497 void PyOpalObject<C>::setOpalName(PyOpalObject<C>& pyobject, std::string name) {
498  std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
499  objectPtr->setOpalName(name);
500 }
501 
502 template <class C>
504  std::shared_ptr<C> objectPtr = pyobject.getOpalShared();
505  objectPtr->setOpalName(name);
506  if (objectPtr->getElement()) { // some OpalThings don't define an Element
507  objectPtr->getElement()->setName(name);
508  }
509 }
510 
511 template <class C>
513  std::shared_ptr<OpalElement> elementPtr =
514  std::dynamic_pointer_cast<OpalElement, C>(pyobject.getOpalShared());
515  if (elementPtr.get() == nullptr) {
516  throw OpalException("PyOpalObject<C>::getPyOpalElement",
517  "Wrapped object was not an OpalElement");
518  }
519  PyOpalObject<OpalElement> element(elementPtr);
520  boost::python::object pyelement(element);
521  return pyelement;
522 }
523 
524 
525 // defined in PyOpalElement
526 template <>
528 
529 template <class C>
530 PyOpalObject<C>::PyOpalObject() : object_m(new C) {}
531 
532 template <class C>
533 PyObject* PyOpalObject<C>::getAttribute(AttributeType type, std::string opalName) const {
534  if (!object_m) {
535  throw OpalException("PyOpalObject<C>::getRealAttribute",
536  "Object was not initialised");
537  }
538  Attribute* attribute = object_m->findAttribute(opalName);
539  if (attribute == nullptr) {
540  throw OpalException("PyOpalObject<C>::getRealAttribute",
541  "Failed to parse attribute "+opalName);
542  }
543  PyObject* pyvalue;
544  // I spent quite a bit of time trying to get this type unwinding to work
545  // using templates (so it is done at compile time). In the end I couldn't
546  // fight the template syntax and had to do it at runtime using an enum; it's
547  // not so bad - the memory footprint is smaller and, tbh, template syntax is
548  // horrible so might be easier to use.
549  switch (type) {
550  case DOUBLE:
551  {
552  double value = Attributes::getReal(*attribute);
553  pyvalue = PyFloat_FromDouble(value);
554  break;
555  }
556  case INT:
557  {
558  double value = Attributes::getReal(*attribute);
559  pyvalue = PyLong_FromDouble(value);
560  break;
561  }
562  case STRING:
563  case PREDEFINED_STRING:
564  case UPPER_CASE_STRING:
565  {
566  std::string value = Attributes::getString(*attribute);
567  pyvalue = PyUnicode_FromString(value.c_str());
568  break;
569  }
570  case BOOL:
571  {
572  bool value = Attributes::getBool(*attribute);
573  if (value) {
574  pyvalue = Py_True;
575  } else {
576  pyvalue = Py_False;
577  }
578  break;
579  }
580  case FLOAT_LIST:
581  {
582  std::vector<double> value = Attributes::getRealArray(*attribute);
583  pyvalue = PyList_New(value.size());
584  for (size_t i = 0; i < value.size(); ++i) {
585  PyList_SetItem(pyvalue, i, PyFloat_FromDouble(value[i]));
586  }
587  break;
588  }
589  case STRING_LIST:
590  {
591  std::vector<std::string> value = Attributes::getStringArray(*attribute);
592  pyvalue = PyList_New(value.size());
593  for (size_t i = 0; i < value.size(); ++i) {
594  PyList_SetItem(pyvalue, i, PyUnicode_FromString(value[i].c_str()));
595  }
596  break;
597  }
598  default:
599  {
600  throw OpalException("PyOpalObject<C>::getAttribute",
601  "Attribute type "+attributeName[type]+" not implemented");
602  }
603  }
604  Py_INCREF(pyvalue);
605  return pyvalue;
606 }
607 
608 
609 template <class C>
610 void PyOpalObject<C>::setAttribute(AttributeType type, std::string opalName, PyObject* pyvalue) {
611  if (!object_m) {
612  throw OpalException("PyOpalObject<C>::setAttribute",
613  "Element was not initialised");
614  }
615  Attribute* attribute = object_m->findAttribute(opalName);
616  if (attribute == nullptr) {
617  throw OpalException("PyOpalObject<C>::setAttribute",
618  "Failed to parse attribute "+opalName);
619  }
620  switch (type) {
621  case DOUBLE:
622  {
623  double value = PyFloat_AsDouble(pyvalue);
624  Attributes::setReal(*attribute, value);
625  break;
626  }
627  case INT:
628  {
629  double value = PyLong_AsDouble(pyvalue);
630  Attributes::setReal(*attribute, value);
631  break;
632  }
633  case STRING:
634  {
635  std::string value = PyUnicode_AsUTF8(pyvalue);
636  Attributes::setString(*attribute, value);
637  break;
638  }
639  case PREDEFINED_STRING:
640  {
641  // predefined string is a string with a list of options
642  // note that value checking never happens - method exists in
643  // src/Attributes/PredefinedString.h but requires a Statement object
644  // which seems hard to construct (Classic/Parser/Statement.h)
645  std::string value = PyUnicode_AsUTF8(pyvalue);
646  Attributes::setPredefinedString(*attribute, value);
647  break;
648  }
649  case UPPER_CASE_STRING:
650  {
651  std::string value = PyUnicode_AsUTF8(pyvalue);
652  Attributes::setUpperCaseString(*attribute, value);
653  break;
654  }
655  case BOOL:
656  {
657  bool value = PyObject_IsTrue(pyvalue);
658  Attributes::setBool(*attribute, value);
659  break;
660  }
661  case FLOAT_LIST:
662  {
663  Py_ssize_t listSize = PyList_Size(pyvalue);
664  std::vector<double> value(listSize);
665  for (Py_ssize_t i = 0; i < listSize; ++i) {
666  double value_i = PyFloat_AsDouble(PyList_GetItem(pyvalue, i));
667  value[i] = value_i;
668  }
669  Attributes::setRealArray(*attribute, value);
670  break;
671  }
672  case STRING_LIST:
673  {
674  Py_ssize_t listSize = PyList_Size(pyvalue);
675  std::vector<std::string> value(listSize);
676  for (Py_ssize_t i = 0; i < listSize; ++i) {
677  PyObject* pyvalue_i = PyList_GetItem(pyvalue, i);
678  std::string value_i = PyUnicode_AsUTF8(pyvalue_i);
679  value[i] = value_i;
680  }
681  Attributes::setStringArray(*attribute, value);
682  break;
683  }
684  default:
685  {
686  throw OpalException("PyOpalObject<C>::setAttribute",
687  "Attribute type "+attributeName[type]+" not implemented");
688  }
689  }
690 }
691 
692 template <class C>
693 PyOpalObject<C>::PyOpalObject(const PyOpalObject<C>& rhs) : object_m(rhs.object_m) {
694 }
695 
696 template <class C>
698  Attribute* attribute = object_m->findAttribute(def.opalName_m);
699  if (attribute == nullptr) {
700  throw OpalException("PyOpalObject<C>::getRealAttribute",
701  "Failed to parse attribute "+def.opalName_m);
702  }
703  std::string docString = def.pyName_m+" ("+attributeName[def.type_m]+"): "+attribute->getHelp();
704  if (def.docString_m != "") {
705  docString = def.pyName_m+" ("+attributeName[def.type_m]+"): "+def.docString_m;
706  }
707  return docString;
708 }
709 
710 template <class C>
711 boost::python::class_<PyOpalObject<C> > PyOpalObject<C>::make_generic_class(const char* className) {
712  // WARNING - boost::python is bugged so that in module initialisation,
713  // errors are not handled correctly
714  // https://github.com/boostorg/python/issues/280
715  // so if you get the attribute name wrong you get a bad error
716  // hence I do some local error handling
717  typedef boost::python::class_<PyOpalObject<C> > PyClass;
718  boost::python::docstring_options docop(true, true, false); // user_def, py_sig, cpp_sig
719  PyClass pyclass = PyClass(className);
720  try {
721  addAttributes(pyclass);
722  addGetOpalName(pyclass);
723  addSetAttributes(pyclass);
724  } catch (OpalException& exc) {
725  std::cerr << "Failed to initialise class because '" << exc.what()
726  << "'" << std::endl;
727  throw exc;
728  } catch (std::exception& exc) {
729  std::cerr << "Failed to initialise class because '" << exc.what()
730  << "'" << std::endl;
731  throw exc;
732  }
733  if (gmsg == nullptr) {
734  std::cerr <<
735  "Failed to initialise class because gmsg was not initialised.\n"
736  "PyOpal::Globals::Initialise() must be called before attempting to\n"
737  "initialise classes" << std::endl;
738  throw OpalException("PyOpalObject::make_generic_class",
739  "Globals not initialised");
740  }
741  return pyclass;
742 }
743 
744 template <class C>
745 boost::python::class_<PyOpalObject<C> > PyOpalObject<C>::make_class(const char* className) {
746  auto pyclass = make_generic_class(className);
747  addSetOpalName(pyclass);
748  return pyclass;
749 }
750 
751 template <class C>
752 boost::python::class_<PyOpalObject<C> > PyOpalObject<C>::make_element_class(const char* className) {
753  auto pyclass = make_generic_class(className);
754  addSetOpalElementName(pyclass);
755  addGetOpalElement(pyclass);
756  return pyclass;
757 }
758 
759 template <class C>
760 template <class PYCLASS>
761 void PyOpalObject<C>::addExecute(PYCLASS& pyclass) {
762  pyclass.def("execute", &PyOpalObject<C>::execute);
763 }
764 
765 template <class C>
766 template <class PYCLASS>
767 void PyOpalObject<C>::addRegister(PYCLASS& pyclass) {
768  pyclass.def("register", &PyOpalObject<C>::registerObject);
769 }
770 
771 template <class C>
772 template <class PYCLASS>
773 void PyOpalObject<C>::addGetOpalName(PYCLASS& pyclass) {
774  pyclass.def("get_opal_name", &PyOpalObject<C>::getOpalName);
775 }
776 
777 template <class C>
778 template <class PYCLASS>
779 void PyOpalObject<C>::addSetAttributes(PYCLASS& pyclass) {
780  pyclass.def("set_attributes",
781  boost::python::raw_function(&PyOpalObject<C>::setAttributes, 0)
782  );
783 }
784 
785 template <class C>
786 template <class PYCLASS>
787 void PyOpalObject<C>::addSetOpalName(PYCLASS& pyclass) {
788  pyclass.def("set_opal_name", &PyOpalObject<C>::setOpalName);
789 }
790 
791 template <class C>
792 template <class PYCLASS>
794  pyclass.def("set_opal_name", &PyOpalObject<C>::setOpalElementName);
795 }
796 
797 template <class C>
798 template <class PYCLASS>
799 void PyOpalObject<C>::addGetOpalElement(PYCLASS& pyclass) {
800  pyclass.def("get_opal_element", &PyOpalObject<C>::getPyOpalElement);
801 }
802 
803 template <class C>
804 template <class PYCLASS>
805 void PyOpalObject<C>::addGetFieldValue(PYCLASS& pyclass,
806  double distanceUnits, double timeUnits,
807  double efieldUnits, double bfieldUnits) {
808  distanceUnits_m = distanceUnits;
809  timeUnits_m = timeUnits;
810  bfieldUnits_m = bfieldUnits;
811  efieldUnits_m = efieldUnits;
812  pyclass.def("get_field_value",
814  boost::python::args("x", "y", "z", "t"),
815  getFieldValueDocString.c_str());
816 }
817 
818 template <class C>
819 template <class PYCLASS>
820 void PyOpalObject<C>::addAttributes(PYCLASS& pyclass) {
821  for (std::vector<AttributeDef>::iterator iter = attributes.begin(); iter != attributes.end(); ++iter) {
822  pyNameToAttribute[iter->pyName_m] = *iter;
823  PyOpalObjectGetProperty<C> getProp(iter->type_m, iter->opalName_m);
824  PyOpalObjectSetProperty<C> setProp(iter->type_m, iter->opalName_m);
825  std::string docString = getDocString(*iter);
826  std::string pyname = iter->pyName_m.c_str();
827  switch (iter->type_m) {
828  case DOUBLE:
829  {
830  pyclass.add_property(pyname.c_str(),
831  boost::python::make_function(&PyC::dummyGet<double>, getProp),
832  boost::python::make_function(&PyC::dummySet<double>, setProp),
833  docString.c_str()
834  );
835  break;
836  }
837  case INT:
838  {
839  pyclass.add_property(pyname.c_str(),
840  boost::python::make_function(&PyC::dummyGet<int>, getProp),
841  boost::python::make_function(&PyC::dummySet<int>, setProp),
842  docString.c_str()
843  );
844  break;
845  }
846  case STRING:
847  case PREDEFINED_STRING:
848  case UPPER_CASE_STRING:
849  {
850  pyclass.add_property(pyname.c_str(),
851  boost::python::make_function(&PyC::dummyGet<std::string>, getProp),
852  boost::python::make_function(&PyC::dummySet<std::string>, setProp),
853  docString.c_str()
854  );
855  break;
856  }
857  case BOOL:
858  {
859  pyclass.add_property(pyname.c_str(),
860  boost::python::make_function(&PyC::dummyGet<bool>, getProp),
861  boost::python::make_function(&PyC::dummySet<bool>, setProp),
862  docString.c_str()
863  );
864  break;
865  }
866  case FLOAT_LIST:
867  case STRING_LIST:
868  {
869  pyclass.add_property(pyname.c_str(),
870  boost::python::make_function(&PyC::dummyGet<boost::python::list>, getProp),
871  boost::python::make_function(&PyC::dummySet<boost::python::list>, setProp),
872  docString.c_str()
873  );
874  break;
875  }
876  default:
877  {
878  // Looks like exception handling doesn't work properly at module
879  // import time so this may not be handled politely - thrown as an
880  // unrecognised SystemError
881  throw OpalException("PyOpalObject<C>::addAttributes", "Type not implemented");
882  }
883  }
884  }
885 }
886 
887 template <class C> double PyOpalObject<C>::distanceUnits_m = 1;
888 template <class C> double PyOpalObject<C>::timeUnits_m = 1;
889 template <class C> double PyOpalObject<C>::bfieldUnits_m = 1;
890 template <class C> double PyOpalObject<C>::efieldUnits_m = 1;
891 
892 template <class C> const std::string PyOpalObject<C>::getFieldValueDocString =
893  "Get the field value at a point in the field map.\n"
894  "\n"
895  "The field lookup is performed against the last RINGDEFINITION that was\n"
896  "instantiated. This should be instantiated by calling\n"
897  "pyopal.parser.initialise_from_opal_file\n"
898  "\n"
899  "Parameters\n"
900  "----------\n"
901  "x : float\n"
902  " x position [m]\n"
903  "y : float\n"
904  " y position [m]\n"
905  "z : float\n"
906  " z position [m]\n"
907  "t: float\n"
908  " time [ns]\n"
909  "\n"
910  "Returns\n"
911  "-------\n"
912  "The function returns a tuple containing 7 values:\n"
913  "out of bounds : int\n"
914  " 1 if the event was out of the field map boundary, else 0.\n"
915  "Bx : float\n"
916  " x magnetic field [T]\n"
917  "By : float\n"
918  " y magnetic field [T]\n"
919  "Bz : float\n"
920  " z magnetic field [T]\n"
921  "Ex : float\n"
922  " x electric field [MV/m]\n"
923  "Ey : float\n"
924  " y electric field [MV/m]\n"
925  "Ez : float\n"
926  " z electric field [MV/m]\n";
927 
928 
930 
931 template <class C>
932 template <class ArgumentPackage>
933 PyObject* PyOpalObjectGetProperty<C>::postcall(ArgumentPackage const&, PyObject* result) {
934  Py_DECREF(result);
935  result = object_m->getAttribute(type_m, opalName_m);
936  return result;
937 }
938 
939 template <class C>
941 
943 
944 template <class C>
945 template <class ArgumentPackage>
946 PyObject* PyOpalObjectSetProperty<C>::postcall(ArgumentPackage const& args, PyObject* result) {
947  PyObject* value;
948  PyObject* pyObject; // this is a direct pointer to the C but I don't know how to unwrap it...
949  if (!PyArg_ParseTuple(args, "OO", &pyObject, &value)) {
950  return nullptr; // ParseTuple sets the error message
951  }
952  Py_DECREF(result);
953  object_m->setAttribute(type_m, opalName_m, value);
954  object_m = nullptr;
955  Py_RETURN_NONE;
956 }
957 
958 template <class C>
960 
961 } // PyOpalObject
962 } // PyOpal
963 
964 #endif // PyOpalObject_H
static OpalData * getInstance()
Definition: OpalData.cpp:196
void setString(Attribute &attr, const std::string &val)
Set string value.
Definition: Attributes.cpp:391
void setRealArray(Attribute &attr, const std::vector< double > &value)
Set array value.
Definition: Attributes.cpp:309
const std::string & getHelp() const
Return the help string.
Definition: Attribute.cpp:82
The base class for all OPAL objects.
Definition: Object.h:48
void setReal(Attribute &attr, double val)
Set real value.
Definition: Attributes.cpp:271
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
virtual const std::string & what() const
Return the message string for the exception.
void addExecute(PYCLASS &pyclass)
Definition: PyOpalObject.h:761
std::map< AttributeType, std::string > attributeName
void define(Object *newObject)
Define a new object.
Definition: OpalData.cpp:489
static boost::python::object setAttributes(boost::python::tuple args, boost::python::dict kwargs)
Definition: PyOpalObject.h:378
item[EANGLE] Entrance edge counterclockwise This enables to obtain skew at each point along the its radius is computed such that the reference trajectory always remains in the centre of the magnet In the body of the magnet the radius is set from the LENGTH and ANGLE attributes It is then continuously changed to be proportional to the dipole field on the reference trajectory while entering the end fields This attribute is only to be set TRUE for a non zero dipole component(Default:FALSE)\item[VARSTEP] The step size(meters) used in calculating the reference trajectory for VARRARDIUS
PyOpalObjectSetProperty(AttributeType type, std::string opalName)
Definition: PyOpalObject.h:446
static void setObject(const PyOpalObject< C > *object)
Definition: PyOpalObject.h:430
static std::map< std::string, AttributeDef > pyNameToAttribute
Definition: PyOpalObject.h:294
void setStringArray(Attribute &attr, const std::vector< std::string > &value)
Set string array value.
Definition: Attributes.cpp:524
PyObject * postcall(ArgumentPackage const &args, PyObject *result)
Definition: PyOpalObject.h:946
static const std::string getFieldValueDocString
Definition: PyOpalObject.h:327
static void execute(PyOpalObject< C > &pyobject)
Definition: PyOpalObject.h:473
boost::python::class_< PyC > make_generic_class(const char *className)
Definition: PyOpalObject.h:711
std::shared_ptr< C > getOpalShared()
Definition: PyOpalObject.h:286
std::string getDocString(AttributeDef &def)
Definition: PyOpalObject.h:697
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
Definition: Attributes.cpp:294
PyObject * getAttribute(AttributeType type, std::string opalName) const
Definition: PyOpalObject.h:533
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
Definition: LICENSE:162
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const T * find(const T table[], const std::string &name)
Look up name.
Definition: TFind.h:34
bool getBool(const Attribute &attr)
Return logical value.
Definition: Attributes.cpp:100
std::string::iterator iterator
Definition: MSLang.h:15
void update(PyOpalObjectNS::PyOpalObject< C > pyelement)
Definition: PyOpalObject.h:340
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B)
Definition: Component.cpp:99
static void setOpalElementName(PyOpalObject< C > &pyobject, std::string name)
Definition: PyOpalObject.h:503
static boost::python::object getPyOpalElement(PyOpalObject< C > &pyobject)
Definition: PyOpalObject.h:512
void setUpperCaseString(Attribute &attr, const std::string &val)
Set uppercase string value.
Definition: Attributes.cpp:456
static void registerObject(PyOpalObject< C > &pyobject)
Definition: PyOpalObject.h:479
PyObject * postcall(ArgumentPackage const &, PyObject *result)
Definition: PyOpalObject.h:933
The base class for all OPAL exceptions.
Definition: OpalException.h:28
static void setOpalName(PyOpalObject< C > &pyobject, std::string name)
Definition: PyOpalObject.h:497
void addRegister(PYCLASS &pyclass)
Definition: PyOpalObject.h:767
boost::python::class_< PyC > make_element_class(const char *className)
Definition: PyOpalObject.h:752
Definition: Inform.h:42
void addAttributes(PYCLASS &pyclass)
Definition: PyOpalObject.h:820
PyOpalObjectGetProperty(AttributeType type, std::string opalName)
Definition: PyOpalObject.h:415
void addSetOpalName(PYCLASS &pyclass)
Definition: PyOpalObject.h:787
void setPredefinedString(Attribute &attr, const std::string &val)
Set predefined string value.
Definition: Attributes.cpp:426
void setBool(Attribute &attr, bool val)
Set logical value.
Definition: Attributes.cpp:119
float result
Definition: test.py:2
PyOpalObject(std::shared_ptr< C > object)
Definition: PyOpalObject.h:144
const std::string name
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special exception
Definition: LICENSE:157
std::shared_ptr< C > getOpalShared() const
Definition: PyOpalObject.h:289
static std::vector< AttributeDef > attributes
Definition: PyOpalObject.h:293
static boost::python::object getFieldValue(PyOpalObjectNS::PyOpalObject< C > &pyobject, double x, double y, double z, double t)
Definition: PyOpalObject.h:353
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
void addGetFieldValue(PYCLASS &pyclass, double distanceUnits, double timeUnits, double bfieldUnits, double efieldUnits)
Definition: PyOpalObject.h:805
std::vector< std::string > getStringArray(const Attribute &attr)
Get string array value.
Definition: Attributes.cpp:478
boost::python::class_< PyC > make_class(const char *className)
Definition: PyOpalObject.h:745
static const PyOpalObject< C > * object_m
Definition: PyOpalObject.h:435
Interface for a single beam element.
Definition: Component.h:50
static std::string getOpalName(const PyOpalObject< C > &pyobject)
Definition: PyOpalObject.h:491
void setAttribute(AttributeType type, std::string opalName, PyObject *value)
Definition: PyOpalObject.h:610
void addSetOpalElementName(PYCLASS &pyclass)
Definition: PyOpalObject.h:793
void addSetAttributes(PYCLASS &pyclass)
Definition: PyOpalObject.h:779
void addGetOpalName(PYCLASS &pyclass)
Definition: PyOpalObject.h:773
SDDS1 &description type
Definition: test.stat:4
Inform * gmsg
Definition: Main.cpp:70
static void setObject(PyOpalObject< C > *object)
Definition: PyOpalObject.h:461
void addGetOpalElement(PYCLASS &pyclass)
Definition: PyOpalObject.h:799
A representation of an Object attribute.
Definition: Attribute.h:52