Xmipp  v3.23.11-Nereus
python_utils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: David Strelak (davidstrelak@gmail.com)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include "python_utils.h"
27 
28 namespace Python {
29 std::string print_traceback() {
30  PyObject* type;
31  PyObject* value;
32  PyObject* traceback;
33 
34  PyErr_Fetch(&type, &value, &traceback);
35  PyErr_NormalizeException(&type, &value, &traceback);
36 
37  std::string fcn = "";
38  fcn += "def get_pretty_traceback(exc_type, exc_value, exc_tb):\n";
39  fcn += " import sys, traceback\n";
40  fcn += " lines = []\n";
41  fcn += " lines = traceback.format_exception(exc_type, exc_value, exc_tb)\n";
42  fcn += " output = '\\n'.join(lines)\n";
43  fcn += " return output\n";
44 
45  PyRun_SimpleString(fcn.c_str());
46  PyObject* mod = PyImport_ImportModule("__main__");
47  PyObject* method = PyObject_GetAttrString(mod, "get_pretty_traceback");
48  PyObject* outStr = PyObject_CallObject(method, Py_BuildValue("OOO", type, value, traceback));
49  PyObject* str_exc_type = PyObject_Str(outStr); //Now a unicode
50  return PyUnicode_AsUTF8(str_exc_type);
51 }
52 
53 std::string whichPython() {
54  char path[1035];
55  FILE *fp = popen("which python", "r");
56  if (fp == NULL)
57  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot execute which python");
58  if (fgets(path, sizeof(path)-1, fp) == NULL)
59  REPORT_ERROR(ERR_UNCLASSIFIED,"Cannot find python");
60  pclose(fp);
61  return path;
62 }
63 
64 void initPython(const std::string &path) {
65 #if PY_MAJOR_VERSION >= 3
66 #if PY_MINOR_VERSION > 4
67  auto program = Py_DecodeLocale(path.c_str(), NULL);
68 #else // PY_MINOR_VERSION > 4
69  std::vector<wchar_t> tmp(path.begin(), path.end());
70  auto program = tmp.data();
71 #endif // PY_MINOR_VERSION > 4
72 #else // PY_MAJOR_VERSION >= 3
73 #error Python version >= 3 expected
74 #endif // PY_MAJOR_VERSION >= 3
75  if (nullptr == program) {
76  REPORT_ERROR(ERR_VALUE_INCORRECT, "Cannot decode the python path\n");
77  }
78  Py_SetProgramName(program);
79  Py_Initialize();
80 }
81 
82 void initPython() {
84 }
85 
87  initPython();
88  initNumpy();
89 }
90 
91 PyObject *getClassRef(const std::string &moduleName, const std::string &className) {
92  PyObject * pName = PyUnicode_FromString(moduleName.c_str());
93  PyObject * pModule = PyImport_Import(pName);
94  PyObject * pDict = PyModule_GetDict(pModule);
95  PyObject * pClass = PyDict_GetItemString(pDict, className.c_str());
96  Py_DECREF(pName);
97  Py_DECREF(pModule);
98  Py_DECREF(pDict);
99  return pClass;
100 }
101 
102 PyObject * getFunctionRef(const std::string &moduleName, const std::string &funcName) {
103  PyObject * pName = PyUnicode_FromString(moduleName.c_str());
104  PyObject * pModule = PyImport_Import(pName);
105  PyObject * pFunc = PyObject_GetAttrString(pModule, funcName.c_str());
106  Py_DECREF(pName);
107  Py_DECREF(pModule);
108  return pFunc;
109 }
110 
111 template<typename T>
112 PyObject* convertToNumpy(const MultidimArray<T> &array) {
113  npy_intp dim[3];
114  dim[0]=XSIZE(array);
115  dim[1]=YSIZE(array);
116  dim[2]=ZSIZE(array);
117  if (std::is_same<T, int>::value) {
118  return PyArray_SimpleNewFromData(3, dim, NPY_INT, array.data);
119  } else if (std::is_same<T, double>::value){
120  return PyArray_SimpleNewFromData(3, dim, NPY_DOUBLE, array.data);
121  } else {
122  REPORT_ERROR(ERR_TYPE_INCORRECT, "Not implemented");
123  }
124 }
125 
126 void initNumpy() {
127 #ifndef NUMPY_IMPORT_ARRAY_RETVAL
128 #define NUMPY_IMPORT_ARRAY_RETVAL NULL
129 #endif
130  auto init = []() -> std::nullptr_t { // explicit on purpose
131  import_array();
132  return nullptr;
133  };
134  init();
135 }
136 
137 // explicit instantiation
138 template PyObject* convertToNumpy<double>(MultidimArray<double> const&);
139 template PyObject* convertToNumpy<int>(MultidimArray<int> const&);
140 
141 } // namespace
Just to locate unclassified errors.
Definition: xmipp_error.h:192
std::string whichPython()
#define YSIZE(v)
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void initPythonAndNumpy()
template PyObject * convertToNumpy< int >(MultidimArray< int > const &)
viol type
PyObject * getFunctionRef(const std::string &moduleName, const std::string &funcName)
#define XSIZE(v)
#define ZSIZE(v)
void mod(const MultidimArray< T > &x, MultidimArray< T > &m, double y)
PyObject * getClassRef(const std::string &moduleName, const std::string &className)
PyObject * convertToNumpy(const MultidimArray< T > &array)
template PyObject * convertToNumpy< double >(MultidimArray< double > const &)
void initNumpy()
std::string print_traceback()
Incorrect type received.
Definition: xmipp_error.h:190
Incorrect value received.
Definition: xmipp_error.h:195
void initPython(const std::string &path)