This is related to #516 (closed) and dependent on #624 (closed). I don't want to try to make a merge branch until #624 (closed) is merged so I just link to my dev fork instead. It can only cause mayhem if I start sticking this stuff in #624 (closed) branch or try to make a new branch that is dependent on the #624 (closed) branch!
I think this is the right thing for a "Line" object as defined in src/Lines/Line.h, but looking at the src/Elements/OpalBeamline.h I don't understand how the two relate. There is a spaghetti-hell of templates and inheritance to fight through. Anyway, I will try to get some tracking going and probably it will become obvious.
I started working my way through the TRACK command. I have python API stubs for TrackCmd, TrackRun, Beam, FieldSolver - I was trying to do enough that I could get it to build and run.
I changed PyElement (which wraps an OpalElement) to be PyOpalObject (Which wraps an OPAL Object). This enables wrapping of non-elements e.g. actions and things like track, distribution, etc. I didn't quite finish - PyLine still requires objects of type OpalElement and is itself a PyElement. This means it is no longer compatible with the VerticalFFAMagnet element (so test_line.py throws an exception). WIP.
Nb: I tried implementing a PyElement by inheritance from PyOpalObject but I didn't find it easy - I got terribly lost in template syntax. In the end I found it better to add a few extra functions that enable to specify what additional methods the PyOpalObject should see, e.g. field elements should have a get_field_value method.
Python methods like execute are implemented as a static C++ member function that takes a PyOpalObject as the first argument. It is not a direct method (making a method would mean doing inheritance + templates = pain). It's a bit weird, there might be a way to do inheritance properly but I couldn't see my way through it all. The upshot is that on python side we can define our C++ objects to have various properties e.g. VerticalFFAMagnet has a get_field_value method, PyTrackCmd has a execute method, etc. But the type information is not quite well-preserved (I can't check to see if PyTrackCmd inherits from some PyAction class). On the other hand, some OpalElements have a field and some don't so there is maybe a benefit to doing it this way - no point in asking what is the field on a PROBE object.
I haven't got tracking working yet - I got some way through. I will be away July 23rd through to August 1st. Sorry!
-Jobs-
Code:
finish implementing some of the objects e.g. Distribution has no Python API yet. See if we can actually track a particle through a field.
implement array attributes
something to think about - can we autodetect attribute type (rather than manually specifying). Already in PyOpalObject I use an instance to get the "docstrings" on each attribute, in principle at the same time I could detect the attribute type (Real, String, etc).
I wonder if it would make sense to split the PyOpalObject into methods that act on instances of PyOpalObject; and the bits which define what methods can be called. The latter is more like a factory object.
sweep for style guide
clean up comments
tests
clean up docstrings
implement a tool to automatically generate documentation
Concerning the last point, tool to generate documentation. For pyOPALTools we use Sphinx (see http://amas.web.psi.ch/docs/pyOPALTools/), and I can help to set that up.
Just to update - I now have a minimal working example for tracking. My aim is to do some code clean up and testing and push to the master over the next couple of months.
Rather than make a new branch, I started pushing to #624 (closed) (which never got merged).
Update now - I have a clean version pushed to trunk, with "minimal worked example" of tracking. Not quite there yet, I am still getting a segmentation fault from the tracking - looks like the field lookup is not quite right. Couple of items still todo as well.
I marked the merge request as ready. Couple of things to consider:
Just remember this is a first go at getting tracking working. I have not checked/implemented anything against OPAL-T and many other things simply don't work. I also don't check whether OPAL can cope with e.g. calling Track twice; I have seen occasional memory issues here (segv), but I think for now it is out of scope.
What I am really interested in is the framework. If there are missing things or problems those are harder to back out of later on.
Have a look at test/opal_src/PyOpal/PyObjects/test_track_run.py
But the main aim was to get the API sorted out. Some of the items in that python object are not fully functional (in particular I only implemented Distribution type=fromfile)