Gyoto
GyotoPython.h
Go to the documentation of this file.
1 /*
2  Copyright 2015-2016, 2022 Thibaut Paumard
3 
4  This file is part of Gyoto.
5 
6  Gyoto is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Gyoto is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Gyoto. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
89 #ifndef __GyotoPython_H_
90 #define __GyotoPython_H_
91 #include <GyotoSpectrum.h>
92 #include <GyotoMetric.h>
93 #include <GyotoStandardAstrobj.h>
94 #include <GyotoThinDisk.h>
95 #include <GyotoProperty.h>
96 #include <GyotoValue.h>
97 #include <GyotoScreen.h>
98 #include <GyotoFactoryMessenger.h>
99 #include <Python.h>
100 
101 namespace Gyoto {
107  namespace Python {
108  class Base;
109  template <class O> class Object;
112 
114  PyObject * PyInstance_GetMethod(PyObject* pInstance, const char *name);
115 
117  PyObject * PyImport_Gyoto();
118 
120  void PyInstance_SetThis(PyObject * pInstance,
121  PyObject * pNew,
122  void * ptr);
123 
125  bool PyCallable_HasVarArg(PyObject * pMethod);
126 
128  PyObject * PyModule_NewFromPythonCode(const char * code);
129 
131  PyObject * pGyotoSpectrum() ;
133  PyObject * pGyotoMetric() ;
135  PyObject * pGyotoStandardAstrobj() ;
137  PyObject * pGyotoThinDisk() ;
138  }
139  namespace Spectrum {
140  class Python;
141  }
142  namespace Metric {
143  class Python;
144  }
145  namespace Astrobj {
150  namespace Python {
151  class Standard;
152  class ThinDisk;
153  }
154  }
155 }
156 
193  protected:
200  std::string module_;
201 
206  std::string inline_module_;
207 
213  std::string class_;
214 
222  std::vector<double> parameters_;
223 
227  PyObject * pModule_;
228 
232  PyObject * pInstance_;
233 
237  PyObject * pProperties_;
238 
242  PyObject * pSet_;
243 
247  PyObject * pGet_;
248 
249  public:
250  Base();
251  Base(const Base&);
252  ~Base();
253 
254  virtual std::string module() const ;
255  virtual std::string inlineModule() const ;
256 
265  virtual void module(const std::string&);
266 
275  virtual void inlineModule(const std::string&);
276 
278  virtual std::string klass() const ;
279 
293  virtual void klass(const std::string& c);
294 
296  virtual std::vector<double> parameters() const;
303  virtual void parameters(const std::vector<double>&);
304 
305  virtual bool hasPythonProperty(std::string const &key) const ;
306  virtual void setPythonProperty(std::string const &key, Value val);
307  virtual Value getPythonProperty(std::string const &key) const;
308  virtual int pythonPropertyType(std::string const &key) const;
309 
310 };
311 
318 template <class O>
320  : public O, public Gyoto::Python::Base
321 {
322 public:
323  Object() : O(), Gyoto::Python::Base() {}
324  Object(const Object& o) : O(o), Base(o) {}
325  virtual ~Object() {};
326 
327  using O::set;
328 
329  virtual void set(std::string const &key, Value val) {
330  GYOTO_DEBUG_EXPR(key);
331  GYOTO_DEBUG_EXPR(val.type);
332  if (hasPythonProperty(key)) {
333  GYOTO_DEBUG << "Python key " << key << " exists" << std::endl;
334  setPythonProperty(key, val);
335  } else {
336  GYOTO_DEBUG << "Python key " << key << " does not exist" << std::endl;
337  O::set(key, val);
338  }
339  }
340 
341  virtual void set(Property const &p, Value val){
342  std::string key=p.name;
343  GYOTO_DEBUG_EXPR(key);
344  if (!hasPythonProperty(key)) {
345  GYOTO_DEBUG << "calling Generic::set" << std::endl;
346  O::set(p, val);
347  return;
348  }
349  setPythonProperty(key, val);
350  }
351 
352  virtual void set(Property const &p, Value val, std::string const &unit) {
354  if (hasPythonProperty(p.name)) {
355  GYOTO_DEBUG << "Python key " << p.name << " exists" << std::endl;
356  if (unit!="") GYOTO_ERROR("units not implemented");
357  setPythonProperty(p.name, val);
358  } else {
359  GYOTO_DEBUG << "Python key " << p.name << " does not exist" << std::endl;
360  O::set(p, val, unit);
361  }
362  }
363 
364  using O::get;
365 
366  virtual Value get(std::string const &key) const {
367  GYOTO_DEBUG_EXPR(key);
368  if (!hasPythonProperty(key)) {
369  GYOTO_DEBUG << "calling Generic::get" << std::endl;
370  return O::get(key);
371  }
372  return getPythonProperty(key);
373  }
374 
375  Value get(Property const &p,
376  std::string const &unit) const {
377  if (!hasPythonProperty(p.name)) {
378  GYOTO_DEBUG << "calling Generic::get" << std::endl;
379  return O::get(p, unit);
380  }
381  return getPythonProperty(p.name);
382  }
383 
384  Value get(Property const &p) const {
385  if (!hasPythonProperty(p.name)) {
386  GYOTO_DEBUG << "calling Generic::get" << std::endl;
387  return O::get(p);
388  }
389  return getPythonProperty(p.name);
390  }
391 
392  using O::setParameter;
393 
394  virtual int setParameter(std::string name, std::string content, std::string unit) {
395  GYOTO_DEBUG_EXPR(name);
396  GYOTO_DEBUG_EXPR(content);
397  GYOTO_DEBUG_EXPR(unit);
398  if (hasPythonProperty(name)) {
399  Property p(NULL);
400  p.name=name;
401  p.type=pythonPropertyType(name);
402  GYOTO_DEBUG << "Calling setParameter(p, name, content, unit)" << std::endl;
403  setParameter(p, name, content, unit);
404  return 0;
405  }
406  return O::setParameter(name, content, unit);
407  }
408 
409  virtual void fillElement(Gyoto::FactoryMessenger *fmp) const {
410  O::fillElement(fmp);
411  if (pProperties_) {
412  Py_ssize_t pos=0;
413  PyObject *pKey, *pVal;
414  while (PyDict_Next(pProperties_, &pos, &pKey, &pVal)) {
415  std::string key=PyUnicode_AsUTF8(pKey);
416  std::string stype=PyUnicode_AsUTF8(pVal);
418  const Property p (key, type);
419  this->fillProperty(fmp, p);
420  }
421  }
422  }
423 
424 
425  void setParameters(Gyoto::FactoryMessenger *fmp) {
426  std::string name="", content="", unit="";
427  FactoryMessenger * child = NULL;
428  if (fmp)
429  while (fmp->getNextParameter(&name, &content, &unit)) {
430  GYOTO_DEBUG << "Setting '" << name << "' to '" << content
431  << "' (unit='"<<unit<<"')" << std::endl;
432  const Property * prop =NULL;
433  bool need_delete= false;
434  if (hasPythonProperty(name)) {
435  need_delete=true;
436  prop = new Property(name, pythonPropertyType(name));
437  } else {
438  need_delete=false;
439  prop = this->property(name);
440  }
441  if (!prop) {;
442  GYOTO_DEBUG << "'" << name << "' not found, calling setParameter()"
443  << std::endl;
444  // The specific setParameter() implementation may well know
445  // this entity
446  setParameter(name, content, unit);
447  } else {
448  GYOTO_DEBUG << "'" << name << "' found "<< std::endl;
449  std::vector<std::string> plugins;
450  switch (prop->type) {
451  case Property::metric_t:
452  set(*prop, fmp->metric());
453  break;
454  case Property::astrobj_t:
455  set(*prop, fmp->astrobj());
456  break;
457  case Property::screen_t:
458  set(*prop, fmp->screen());
459  break;
461  content = fmp -> getAttribute("kind");
462  child = fmp -> getChild();
463  plugins = Gyoto::split(fmp -> getAttribute("plugin"), ",");
464  set(*prop, (*Spectrum::getSubcontractor(content, plugins))(child, plugins) );
465  delete child;
466  break;
468  content = fmp -> getAttribute("kind");
469  child = fmp -> getChild();
470  plugins = Gyoto::split(fmp -> getAttribute("plugin"), ",");
471  set(*prop, (*Spectrometer::getSubcontractor(content, plugins))(child, plugins) );
472  delete child;
473  break;
475  content = fmp->fullPath(content);
476  // no 'break;' here, we need to proceed
477  default:
478  setParameter(*prop, name, content, unit);
479  break;
480  }
481  }
482  if (need_delete) delete prop;
483  }
484  GYOTO_DEBUG << "Done processing parameters" << std::endl;
485  }
486 };
487 
502  : public Gyoto::Python::Object<Gyoto::Spectrum::Generic>
503 {
505  protected:
506 
513  PyObject * pCall_;
514 
518  PyObject * pIntegrate_;
519 
538 
539  public:
542 
543  Python();
544 
545  Python(const Python&);
546 
547  virtual Python * clone() const;
548 
549  ~Python();
550 
551  // For some reason we need to implement the bunch although only one
552  // is non-trivial
553  virtual std::string module() const ;
554  virtual void module(const std::string&);
555  virtual std::string inlineModule() const ;
556  virtual void inlineModule(const std::string&);
557  virtual std::string klass() const ;
558  virtual void klass(const std::string&);
559  virtual std::vector<double> parameters() const;
560  virtual void parameters(const std::vector<double>&);
561 
562  virtual double operator()(double nu) const;
563  virtual double operator()(double nu, double opacity, double ds) const;
564 
565  virtual double integrate(double nu1, double nu2) ;
566 
567 };
568 
569 
589  : public Gyoto::Python::Object<Gyoto::Metric::Generic>
590 {
592 
593  private:
594  // Variables to cache Python objects:
598  PyObject * pGmunu_;
599 
603  PyObject * pChristoffel_;
604 
608  PyObject * pGetRmb_;
609 
613  PyObject * pGetRms_;
614 
618  PyObject * pGetSpecificAngularMomentum_;
619 
623  PyObject * pGetPotential_;
624 
628  PyObject * pIsStopCondition_;
629 
633  PyObject * pCircularVelocity_;
634 
635  public:
638  Python();
639  Python(const Python&);
640  ~Python();
641  virtual Python* clone() const ;
642 
643  // Accessors for the Gyoto::Property members:
644  // Those are mere wrappers arround Generic::coordKind(), useful for
645  // declaring a boolen property using the macro GYOTO_PROPERTY_BOOL:
646  void spherical(bool);
647  bool spherical() const;
648  virtual std::string module() const ;
649  virtual void module(const std::string&);
650  virtual std::string inlineModule() const ;
651  virtual void inlineModule(const std::string&);
652  virtual std::string klass() const ;
653  virtual void klass(const std::string&);
654  virtual std::vector<double> parameters() const;
655  virtual void parameters(const std::vector<double>&);
657  virtual void mass(double m);
658 
659  // The minimal Gyoto::Metric API:
660  void gmunu(double g[4][4], const double * x) const ;
661  int christoffel(double dst[4][4][4], const double * x) const ;
662 
663  // Little more
664  double getRmb() const;
665  double getRms() const;
666  double getSpecificAngularMomentum(double rr) const;
667  double getPotential(double const pos[4], double l_cst) const;
668  int isStopCondition(double const coord[8]) const;
669  void circularVelocity(double const pos[4], double vel[4],
670  double dir=1.) const ;
671 
672 };
673 
684  : public Gyoto::Python::Object<Gyoto::Astrobj::Standard>
685 {
687 
688  private:
689  PyObject *pEmission_, *pIntegrateEmission_, *pTransmission_, *pCall_,
690  *pGetVelocity_, *pGiveDelta_;
691  bool pEmission_overloaded_, pIntegrateEmission_overloaded_;
692 
693  public:
696 
697  /* Birth and Death*/
698  Standard();
699  Standard(const Standard&);
701  Standard* clone() const;
702 
703  /* Astrobj::Generic API */
704  virtual double emission(double nu_em, double dsem, state_t const &coord_ph,
705  double const coord_obj[8]=NULL) const ;
706 
707  virtual void emission(double Inu[], double const nu_em[], size_t nbnu,
708  double dsem, state_t const &coord_ph,
709  double const coord_obj[8]=NULL) const ;
710 
711  virtual double integrateEmission(double nu1, double nu2, double dsem,
712  state_t const &c_ph, double const c_obj[8]=NULL) const;
713 
714  virtual void integrateEmission(double * I, double const * boundaries,
715  size_t const * chaninds, size_t nbnu,
716  double dsem, state_t const &cph, double const *co) const;
717 
718  virtual double transmission(double nuem, double dsem, state_t const &cph, double const *co) const ;
719 
720  /* Astrobj::Standard API */
721  virtual double operator()(double const coord[4]) ;
722  virtual void getVelocity(double const pos[4], double vel[4]) ;
723  virtual double giveDelta(double coord[8]);
724 
725  /* Python::Base */
726  virtual std::string module() const ;
727  virtual void module(const std::string&);
728  virtual std::string inlineModule() const ;
729  virtual void inlineModule(const std::string&);
730  virtual std::string klass() const ;
731  virtual void klass(const std::string&);
732  virtual std::vector<double> parameters() const;
733  virtual void parameters(const std::vector<double>&);
734  virtual double criticalValue() const ;
735  virtual void criticalValue(double) ;
736 
737 };
738 
749  : public Gyoto::Python::Object<Gyoto::Astrobj::ThinDisk>
750 {
752 
753  private:
754  PyObject *pEmission_, *pIntegrateEmission_, *pTransmission_, *pCall_,
755  *pGetVelocity_, *pGiveDelta_;
756  bool pEmission_overloaded_, pIntegrateEmission_overloaded_;
757 
758  public:
761 
762  /* Birth and Death*/
763  ThinDisk();
764  ThinDisk(const ThinDisk&);
766  ThinDisk* clone() const;
767 
768  /* Astrobj::Generic API */
769  virtual double emission(double nu_em, double dsem, state_t const &coord_ph,
770  double const coord_obj[8]=NULL) const ;
771 
772  virtual void emission(double Inu[], double const nu_em[], size_t nbnu,
773  double dsem, state_t const &coord_ph,
774  double const coord_obj[8]=NULL) const ;
775 
776  virtual double integrateEmission(double nu1, double nu2, double dsem,
777  state_t const &c_ph, double const c_obj[8]=NULL) const;
778 
779  virtual void integrateEmission(double * I, double const * boundaries,
780  size_t const * chaninds, size_t nbnu,
781  double dsem, state_t const &cph, double const *co) const;
782 
783  virtual double transmission(double nuem, double dsem, state_t const &cph ,double const *co) const ;
784 
785  /* Astrobj::ThinDisk API */
786  virtual double operator()(double const coord[4]) ;
787  virtual void getVelocity(double const pos[4], double vel[4]) ;
788 
789  /* Python::Base */
790  virtual std::string module() const ;
791  virtual void module(const std::string&);
792  virtual std::string inlineModule() const ;
793  virtual void inlineModule(const std::string&);
794  virtual std::string klass() const ;
795  virtual void klass(const std::string&);
796  virtual std::vector<double> parameters() const;
797  virtual void parameters(const std::vector<double>&);
798 
799 };
800 
801 
802 #endif
#define GYOTO_DEBUG
Display debug message (in debug mode)
Definition: GyotoDefs.h:341
#define GYOTO_DEBUG_EXPR(a)
Output expression value in debug mode.
Definition: GyotoDefs.h:280
#define GYOTO_ERROR(msg)
Throw a Gyoto::Error nicely.
Definition: GyotoError.h:196
Factory / SmartPointee::Subcontractor_t interface.
Base class for metric description.
#define GYOTO_OBJECT_THREAD_SAFETY
Declare virtual bool isThreadSafe() const.
Definition: GyotoObject.h:99
#define GYOTO_OBJECT
Declare class::properties and class::getProperties()
Definition: GyotoObject.h:84
Introspectable properties.
Description of the observer screen.
Spectrum of a simple object (e.g. Star)
Astronomical objects defined bya a potential/distance.
Geometrically thin disks and rings.
Introspectable value.
Coding a Gyoto::Astrobj::Standard in Python.
Definition: GyotoPython.h:685
Coding a Gyoto::Astrobj::ThinDisk in Python.
Definition: GyotoPython.h:750
Factory / SmartPointee::Subcontractor_t interface.
Definition: GyotoFactoryMessenger.h:92
SmartPointer< Metric::Generic > metric()
Build and get the Metric described in this XML file.
std::string fullPath(std::string relpath)
Transform path into full path specification.
SmartPointer< Screen > screen()
Build and get the Screen described in this XML file.
int getNextParameter(std::string *name, std::string *content, std::string *unit=NULL)
Get name and value of next parameter.
SmartPointer< Astrobj::Generic > astrobj()
Build and get the Astrobj described in this XML file.
double mass() const
Get mass used in unitLength()
Metric coded in Python.
Definition: GyotoPython.h:590
Property that can be set and got using standard methods.
Definition: GyotoProperty.h:608
static type_e typeFromString(std::string stype)
Get Property::type_e value from name.
type_e
Possible type of a Property instance.
Definition: GyotoProperty.h:616
@ metric_t
Type is Gyoto::SmartPointer<Gyoto::Metric::Generic>
Definition: GyotoProperty.h:644
@ astrobj_t
Type is Gyoto::SmartPointer<Gyoto::Astrobj::Generic>
Definition: GyotoProperty.h:648
@ filename_t
Type is std::string and holds a file name.
Definition: GyotoProperty.h:638
@ spectrometer_t
Type is Gyoto::SmartPointer<Gyoto::Spectrometer::Generic>
Definition: GyotoProperty.h:652
@ spectrum_t
Type is Gyoto::SmartPointer<Gyoto::Spectrum::Generic>
Definition: GyotoProperty.h:650
@ screen_t
Type is Gyoto::SmartPointer<Gyoto::Screen::Generic>
Definition: GyotoProperty.h:646
std::string name
Name of this instance.
Definition: GyotoProperty.h:663
int type
Type of this instance.
Definition: GyotoProperty.h:670
Base class for classes in the Python plug-in.
Definition: GyotoPython.h:192
virtual std::vector< double > parameters() const
Retrieve parameters_.
virtual void inlineModule(const std::string &)
Set inline_module_ and import the Python module.
virtual void module(const std::string &)
Set module_ and import the Python module.
std::string class_
Name of the Python class that we want to expose.
Definition: GyotoPython.h:213
PyObject * pGet_
Reference to the (optional) Get method.
Definition: GyotoPython.h:247
virtual std::string inlineModule() const
Return inline_module_.
PyObject * pProperties_
Reference to the properties member.
Definition: GyotoPython.h:237
std::string module_
Name of the Python module that holds the class.
Definition: GyotoPython.h:200
virtual std::string klass() const
Retrieve class_.
PyObject * pSet_
Reference to the (optional) Set method.
Definition: GyotoPython.h:242
virtual std::string module() const
Return module_.
std::vector< double > parameters_
Parameters that this class needs.
Definition: GyotoPython.h:222
PyObject * pInstance_
Reference to the python instance once it has been instantiated.
Definition: GyotoPython.h:232
virtual void klass(const std::string &c)
Set class_ and instantiate the Python class.
virtual void parameters(const std::vector< double > &)
Set parameters_ and send them to pInstance_.
std::string inline_module_
Python source code for module that holds the class.
Definition: GyotoPython.h:206
PyObject * pModule_
Reference to the python module once it has been loaded.
Definition: GyotoPython.h:227
Class template to implement parts of the Gyoto::Object API.
Definition: GyotoPython.h:321
Pointers performing reference counting.
Definition: GyotoSmartPointer.h:135
Loader for Python classes implementing the Spectrum interface.
Definition: GyotoPython.h:503
PyObject * pCall_
Reference to ___call__.
Definition: GyotoPython.h:513
virtual std::string inlineModule() const
Return inline_module_.
bool pCall_overloaded_
Whether call is overloaded.
Definition: GyotoPython.h:537
virtual std::string klass() const
Retrieve class_.
virtual Python * clone() const
Cloner.
virtual std::string module() const
Return module_.
virtual std::vector< double > parameters() const
Retrieve parameters_.
virtual double integrate(double nu1, double nu2)
Integrate optically thick I_nu.
PyObject * pIntegrate_
Reference to the (optional) integrate method.
Definition: GyotoPython.h:518
Container for the value of a Property.
Definition: GyotoValue.h:60
int type
Type of this instance.
Definition: GyotoValue.h:72
PyObject * pGyotoMetric()
Get reference to the Metric constructor in the gyoto Python extension.
PyObject * pGyotoStandardAstrobj()
Get reference to the StandardAstrobj constructor in the gyoto Python extension.
PyObject * PyInstance_GetMethod(PyObject *pInstance, const char *name)
Return new reference to method, or NULL if method not found.
PyObject * pGyotoSpectrum()
Get reference to the Spectrum constructor in the gyoto Python extension.
PyObject * PyModule_NewFromPythonCode(const char *code)
Create module from Python source code in a C string.
void PyInstance_SetThis(PyObject *pInstance, PyObject *pNew, void *ptr)
Set "this" attribute in instance.
PyObject * PyObject_FromGyotoValue(const Gyoto::Value &)
Convert Gyoto Value to Python Object.
bool PyCallable_HasVarArg(PyObject *pMethod)
Check whether method accepts the varargs argument.
PyObject * pGyotoThinDisk()
Get reference to the ThinDisk constructor in the gyoto Python extension.
PyObject * PyImport_Gyoto()
Return refernce to the gyoto module, or NULL.
Gyoto::Spectrometer::Subcontractor_t * getSubcontractor(std::string name, std::vector< std::string > &plugins, int errmode=0)
Query the Spectrometer register.
Gyoto::Spectrum::Subcontractor_t * getSubcontractor(std::string name, std::vector< std::string > &plugins, int errmode=0)
Query the Spectrum register.
Namespace for the Gyoto library.
Definition: GyotoAstrobj.h:44
std::vector< std::string > split(std::string const &src, std::string const &delim)
Split string.