OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
PyLine.h
Go to the documentation of this file.
1//
2// Python API for the Line
3//
4// Copyright (c) 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 PyOpal_PyLine_h
18
19
20#include "Lines/Sequence.h"
21#include "Lines/Line.h"
22#include "Beamlines/TBeamline.h"
24
25namespace PyOpal {
26
27// to get the inheritance from PyElement I need to make PyLine_ templated; but
28// really I only ever want to associate a PyLine_ with a TBeamline (it is a list
29// of elements in a beamline). So I typedef a PyLine class which is the
30// specialisation to PyLine_<TBeamline>.
31template <class C>
32class PyLine_; // forwards declaration of the PyLine_
34
50template <class C>
52public:
59 boost::python::object getElement(int i);
60
70 void setElement(int i, boost::python::object element);
71
77 void append(boost::python::object element);
78
84 std::string getName() const;
85
86
92 void setName(std::string name);
93
95 int getLength() const {return line.size();}
96
102 boost::python::class_<PyLine> make_class(const char* className);
103
105
106private:
108 std::vector<boost::python::object> line;
110 int wrangleIndex(int index);
111};
112
113template <>
115 std::shared_ptr<TBeamline<FlaggedElmPtr>> objectPtr = getOpalShared();
116 return objectPtr->getName();
117}
118
119template <>
121 std::shared_ptr<TBeamline<FlaggedElmPtr>> objectPtr = getOpalShared();
122 objectPtr->setName(name);
123}
124
125template<>
127 if (index >= 0) {
128 return index;
129 }
130 index = line.size()+index;
131 return index;
132}
133
134template <>
136 TBeamline<FlaggedElmPtr>* wrapped = getOpalShared().get();
137 // no constructor exists that takes a string name, but clone does, so I
138 // instantiate a line and then use clone to make a line having the correct
139 // name; duh.
140 Line lineDef;
141 Line* line = lineDef.clone(wrapped->getName());
142 line->setElement(wrapped);
143 Object* objectPtr = dynamic_cast<Object*>(line);
144 if (objectPtr == nullptr) {
145 throw OpalException("PyLine_<TBeamline<FlaggedElmPtr> >::register",
146 "Trying to register something that was not a Opal Object");
147 }
148 OpalData::getInstance()->define(objectPtr);
149}
150
151template<>
152boost::python::class_<PyLine> PyLine_<TBeamline<FlaggedElmPtr> >::make_class(const char* className) {
153 boost::python::docstring_options docop(true, true, false); // user_def, py_sig, cpp_sig
154 auto pyclass = boost::python::class_<PyLine>(className);
155 return pyclass;
156}
157
158template<>
159boost::python::object PyLine_<TBeamline<FlaggedElmPtr> >::getElement(int i) {
160 i = wrangleIndex(i);
161 try {
162 return line.at(i);
163 } catch (std::exception& exc) {
164 throw OpalException("PyLine::getElement", "Out of range");
165 }
166}
167
168template<>
169void PyLine_<TBeamline<FlaggedElmPtr> >::setElement(int i, boost::python::object pyelement) {
170 // TBeamline is implemented as a double linked list??
171 typedef TBeamline<FlaggedElmPtr> BL;
172 i = wrangleIndex(i);
173 try {
174 line.at(i) = pyelement;
175 } catch (std::exception& exc) {
176 throw OpalException("PyLine::setElement", "Failed to set element");
177 }
178 boost::python::object pyopalelement = pyelement.attr("get_opal_element")();
180 boost::python::extract<PyOpal::PyOpalObjectNS::PyOpalObject<OpalElement>& >(pyopalelement);
181 int index = 0;
182 for (BL::iterator it = object_m->begin(); it != object_m->end(); ++it) {
183 if (index == i) {
184 // 4 layers of nested inheritance template wrapper darkness
185 std::shared_ptr<OpalElement> opalElementShared = cpyelement.getOpalShared();
186 OpalElement* opalElement = opalElementShared.get();
187 if (!opalElement) {
188 throw OpalException("PyLine::setElement", "Failed to extract element");
189 }
190 opalElement->update();
191 ElementBase* elmbase = opalElement->getElement();
192 if (!elmbase) {
193 throw OpalException("PyLine::setElement", "Failed to cast element");
194 }
195 ElmPtr elmptr(elmbase);
196 FlaggedElmPtr felmptr(elmptr);
197 BL::iterator new_it = object_m->erase(it);
198 object_m->insert(new_it, felmptr);
199 return;
200 }
201 ++index;
202 }
203 throw OpalException("PyLine::getElement", "Out of range");
204}
205
206template <>
207void PyLine_<TBeamline<FlaggedElmPtr> >::append(boost::python::object pyelement) {
208 int i = line.size();
209 // first we extend the size of the python object list by 1 with dummy variables
210 line.push_back(boost::python::object());
211 FlaggedElmPtr felmptr(ElmPtr(nullptr));
212 object_m->push_back(felmptr);
213 // then we set the python object using setElement method
214 setElement(i, pyelement);
215}
216
217
218}
219#endif // PyOpal_PyLine_h
220
221/*
222OPAL Beamline insanity...
223
224There exists:
2251. Beamline is a beamline
2262. TBeamline which is another sort of beamline that inherits from Beamline
2273. BeamSequence
2284. Line which has some bindings to the UI
2295. FlaggedBeamline which has a flag to indicate the Beamline is reflected
2306. Sequence which is a list of Sequence elements whatever they are
231I struggle to understand the motivation for so many different classes.
232*/
233
const std::string name
PyLine_< TBeamline< FlaggedElmPtr > > PyLine
Definition PyLine.h:33
ElementBase * getElement() const
Return the embedded CLASSIC element.
Definition Element.h:120
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
virtual const std::string & getName() const
Get element name.
A section of a beam line.
Definition ElmPtr.h:32
A section of a beam line.
virtual void update()
Update the embedded CLASSIC element.
Definition Line.h:32
virtual Line * clone(const std::string &name)
Make clone.
Definition Line.cpp:117
std::shared_ptr< TBeamline< FlaggedElmPtr > > object_m
std::shared_ptr< TBeamline< FlaggedElmPtr > > getOpalShared()
void registerObject()
int getLength() const
Definition PyLine.h:95
void setName(std::string name)
std::vector< boost::python::object > line
Definition PyLine.h:108
int wrangleIndex(int index)
void append(boost::python::object element)
void setElement(int i, boost::python::object element)
std::string getName() const
boost::python::class_< PyLine > make_class(const char *className)
boost::python::object getElement(int i)
The base class for all OPAL exceptions.