/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus * * MAUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MAUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MAUS. If not, see . * */ #ifndef _SRC_PY_CPP_PYPHASESPACEVECTOR_HH_ #define _SRC_PY_CPP_PYPHASESPACEVECTOR_HH_ // These ifdefs are required to avoid cpp compiler warning #ifdef _POSIX_C_SOURCE #undef _POSIX_C_SOURCE #endif #ifdef _XOPEN_SOURCE #undef _XOPEN_SOURCE #endif #include #ifdef MAUS_PYPHASESPACEVECTOR_CC namespace MAUS { class PhaseSpaceVector; // note this is just in MAUS namespace /** Methods for the PyPhaseSpaceVector object */ namespace PyPhaseSpaceVector { /** PyPhaseSpaceVector is the python implementation of the C++ PhaseSpaceVector */ typedef struct { PyObject_HEAD; PhaseSpaceVector* psv; } PyPhaseSpaceVector; /** @namespace C_API defines functions that can be accessed by other C libraries * * To access these functions, you must call import_PyPhaseSpaceVector() * (otherwise you will get segmentation fault) */ namespace C_API { /** Create a new empty PyPhaseSpaceVector (psv is NULL) * * \returns NULL on failure or the object on success. Caller owns the returned * object */ static PyObject* create_empty_vector(); /** Return the C++ PhaseSpaceVector associated with a PyPhaseSpaceVector * * \param py_psv PyPhaseSpaceVector* cast as a PyObject*. Python representation * of the phase space vector. * * \returns NULL on failure or the object on success. PyPhaseSpaceVector still * owns the memory allocated to PhaseSpaceVector. */ static PhaseSpaceVector* get_phase_space_vector(PyObject* py_psv); /** Set the C++ phase space vector associated with a PyPhaseSpaceVector * * \param py_psv PyPhaseSpaceVector* cast as a PyObject*. Python representation * of the phase space vector * \param psv C++ representation of the phase space vector. PyPhaseSpaceVector * takes ownership of the memory allocated to psv * * \returns 0 on failure, 1 on success */ static int set_phase_space_vector(PyObject* py_psv, PhaseSpaceVector* psv); } // ~~~~~~~~~~~~~~~~~~~~ PyPhaseSpaceVector private methods ~~~~~~~~~~~~~~~~~~~~~ // most are available as native python functions /** _alloc allocates memory for PyPhaseSpaceVector * * @param type - pointer to a PyPhaseSpaceVectorType object, as defined in * PyPhaseSpaceVectorType.cc * * returns a PyPhaseSpaceVector* (cast as a PyObject*); caller owns this memory */ static PyObject *_alloc(PyTypeObject *type, Py_ssize_t nitems); /** _init initialises an allocated PyPhaseSpaceVector object * * @param self an initialised PyPhaseSpaceVector* cast as a PyObject*; caller * owns this memory * @param args not used * @param kwds accepts t, energy, x, px, y, py keywords; see python docstring * * @returns 0 on success; -1 on failure */ static int _init(PyObject* self, PyObject *args, PyObject *kwds); /** deallocate memory * * @params self an initialised PyPhaseSpaceVector*; memory will be freed by * this function */ static void _free(PyPhaseSpaceVector * self); /** Initialise phase_space_vector module * * This is called by import phase_space_vector; it initialises the * PhaseSpaceVector type allowing user to construct and call methods on * PhaseSpaceVector objects */ PyMODINIT_FUNC initphase_space_vector(void); /** get time t [ns] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds not used * * @returns a PyObject float containing time t */ static PyObject* get_t(PyObject* self, PyObject *args, PyObject *kwds); /** get energy E [MeV] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds not used * * @returns a PyObject float containing energy E */ static PyObject* get_energy(PyObject* self, PyObject *args, PyObject *kwds); /** get x (horizontal) position [mm] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds not used * * @returns a PyObject float containing position x */ static PyObject* get_x(PyObject* self, PyObject *args, PyObject *kwds); /** get px (horizontal component of momentum) [MeV/c] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds not used * * @returns a PyObject float containing momentum px */ static PyObject* get_px(PyObject* self, PyObject *args, PyObject *kwds); /** get y (vertical position) [mm] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds not used * * @returns a PyObject float containing position y */ static PyObject* get_y(PyObject* self, PyObject *args, PyObject *kwds); /** get py (vertical component of momentum) [MeV/c] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds not used * * @returns a PyObject float containing momentum py */ static PyObject* get_py(PyObject* self, PyObject *args, PyObject *kwds); /** set t (time) [ns] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds accepts keyword value (float) * * @returns None */ static PyObject* set_t(PyObject* self, PyObject *args, PyObject *kwds); /** set E (energy) [MeV/c] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds accepts keyword value (float) * * @returns None */ static PyObject* set_energy(PyObject* self, PyObject *args, PyObject *kwds); /** set x (horizontal position) [mm] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds accepts keyword value (float) * * @returns None */ static PyObject* set_x(PyObject* self, PyObject *args, PyObject *kwds); /** set px (horizontal component of momentum) [MeV/c] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds accepts keyword value (float) * * @returns None */ static PyObject* set_px(PyObject* self, PyObject *args, PyObject *kwds); /** set y (vertical position) [mm] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds accepts keyword value (float) * * @returns None */ static PyObject* set_y(PyObject* self, PyObject *args, PyObject *kwds); /** set py (vertical component of momentum) [MeV/c] * * @params self a PyPhaseSpaceVector * @params args not used * @params kwds accepts keyword value (float) * * @returns None */ static PyObject* set_py(PyObject* self, PyObject *args, PyObject *kwds); /** Template for get functions */ static PyObject* get(PyObject* self, double (PhaseSpaceVector::*get_function)() const); /** Template for set functions */ static PyObject* set(PyObject* self, PyObject *args, PyObject *kwds, void (PhaseSpaceVector::*set_function)(double value)); /** Return a python string describing the phase space vector * * Returns string formatted like a python list with contents: * time [ns], energy [MeV], x [mm], px [MeV/c], y [mm], py [MeV/c] */ static PyObject* _str(PyObject * self); } } #else // ifdef MAUS_PYPHASESPACEVECTOR_CC /** MAUS::PyOpticsModel::PyPhaseSpaceVector C API objects * * Because of the way python does share libraries, we have to explicitly import * C functions via the Python API, which is done at import time. This mimics * the functions in MAUS::PyPhaseSpaceVector. Full documentation is found * there. * * Hacky implementation of public keyword in C++ */ namespace MAUS { namespace PyPhaseSpaceVector { /** import the PyPhaseSpaceVector C_API * * Make the functions in C_API namespace available to other C modules. * Functions will be in namespace MAUS::PyPhaseSpaceVector. * * @returns 0 if the import fails; return 1 if it is a success */ int import_PyPhaseSpaceVector(); int (*set_phase_space_vector)(PyObject* py_psv, PhaseSpaceVector* psv) = NULL; PhaseSpaceVector* (*get_phase_space_vector)(PyObject* py_psv) = NULL; PyObject* (*create_empty_vector)() = NULL; } } int MAUS::PyPhaseSpaceVector::import_PyPhaseSpaceVector() { PyObject* psv_module = PyImport_ImportModule("maus_cpp.phase_space_vector"); if (psv_module == NULL) { return 0; } else { PyObject *psv_dict = PyModule_GetDict(psv_module); PyObject* gpsv_c_api = PyDict_GetItemString(psv_dict, "C_API_GET_PHASE_SPACE_VECTOR"); void* gpsv_void = reinterpret_cast(PyCObject_AsVoidPtr(gpsv_c_api)); PyPhaseSpaceVector::get_phase_space_vector = reinterpret_cast(gpsv_void); PyObject* spsv_c_api = PyDict_GetItemString(psv_dict, "C_API_SET_PHASE_SPACE_VECTOR"); void* spsv_void = reinterpret_cast(PyCObject_AsVoidPtr(spsv_c_api)); PyPhaseSpaceVector::set_phase_space_vector = reinterpret_cast(spsv_void); PyObject* cev_c_api = PyDict_GetItemString(psv_dict, "C_API_CREATE_EMPTY_VECTOR"); void* cev_void = reinterpret_cast(PyCObject_AsVoidPtr(cev_c_api)); PyPhaseSpaceVector::create_empty_vector = reinterpret_cast(cev_void); if ((create_empty_vector == NULL) || (set_phase_space_vector == NULL) || (get_phase_space_vector == NULL)) return 0; } return 1; } #endif // #ifdef MAUS_PYPHASESPACEVECTOR_CC #endif // _SRC_PY_CPP_PYPHASESPACEVECTOR_HH_