openPMD-api
Numpy.hpp
1 /* Copyright 2018-2020 Axel Huebl
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser 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  * openPMD-api 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 and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 #pragma once
22 
23 #include <pybind11/pybind11.h>
24 #include <pybind11/stl.h>
25 #include <pybind11/numpy.h>
26 
27 #include "openPMD/Datatype.hpp"
28 
29 #include <string>
30 #include <exception>
31 
32 
33 namespace openPMD
34 {
35  inline Datatype
36  dtype_from_numpy( pybind11::dtype const dt )
37  {
38  // ref: https://docs.scipy.org/doc/numpy/user/basics.types.html
39  // ref: https://github.com/numpy/numpy/issues/10678#issuecomment-369363551
40  if( dt.is(pybind11::dtype("b")) )
41  return Datatype::CHAR;
42  else if( dt.is(pybind11::dtype("B")) )
43  return Datatype::UCHAR;
44  else if( dt.is(pybind11::dtype("short")) )
45  return Datatype::SHORT;
46  else if( dt.is(pybind11::dtype("intc")) )
47  return Datatype::INT;
48  else if( dt.is(pybind11::dtype("int_")) )
49  return Datatype::LONG;
50  else if( dt.is(pybind11::dtype("longlong")) )
51  return Datatype::LONGLONG;
52  else if( dt.is(pybind11::dtype("ushort")) )
53  return Datatype::USHORT;
54  else if( dt.is(pybind11::dtype("uintc")) )
55  return Datatype::UINT;
56  else if( dt.is(pybind11::dtype("uint")) )
57  return Datatype::ULONG;
58  else if( dt.is(pybind11::dtype("ulonglong")) )
59  return Datatype::ULONGLONG;
60  else if( dt.is(pybind11::dtype("longdouble")) )
61  return Datatype::LONG_DOUBLE;
62  else if( dt.is(pybind11::dtype("double")) )
63  return Datatype::DOUBLE;
64  else if( dt.is(pybind11::dtype("single")) )
65  return Datatype::FLOAT;
66  else if( dt.is(pybind11::dtype("bool")) )
67  return Datatype::BOOL;
68  else
69  throw std::runtime_error("Datatype '...' not known in 'dtype_from_numpy'!"); // _s.format(dt)
70  }
71 
74  inline Datatype
75  dtype_from_bufferformat( std::string const & fmt )
76  {
77  using DT = Datatype;
78 
79  // refs:
80  // https://docs.scipy.org/doc/numpy-1.15.0/reference/arrays.interface.html
81  // https://docs.python.org/3/library/struct.html#format-characters
82  // std::cout << " scalar type '" << buf.format << "'" << std::endl;
83  // typestring: encoding + type + number of bytes
84  if( fmt.find("?") != std::string::npos )
85  return DT::BOOL;
86  else if( fmt.find("b") != std::string::npos )
87  return DT::CHAR;
88  else if( fmt.find("h") != std::string::npos )
89  return DT::SHORT;
90  else if( fmt.find("i") != std::string::npos )
91  return DT::INT;
92  else if( fmt.find("l") != std::string::npos )
93  return DT::LONG;
94  else if( fmt.find("q") != std::string::npos )
95  return DT::LONGLONG;
96  else if( fmt.find("B") != std::string::npos )
97  return DT::UCHAR;
98  else if( fmt.find("H") != std::string::npos )
99  return DT::USHORT;
100  else if( fmt.find("I") != std::string::npos )
101  return DT::UINT;
102  else if( fmt.find("L") != std::string::npos )
103  return DT::ULONG;
104  else if( fmt.find("Q") != std::string::npos )
105  return DT::ULONGLONG;
106  else if( fmt.find("f") != std::string::npos )
107  return DT::FLOAT;
108  else if( fmt.find("d") != std::string::npos )
109  return DT::DOUBLE;
110  else if( fmt.find("g") != std::string::npos )
111  return DT::LONG_DOUBLE;
112  else
113  throw std::runtime_error("dtype_from_bufferformat: Unknown "
114  "Python type '" + fmt + "'");
115  }
116 
117  inline pybind11::dtype
118  dtype_to_numpy( Datatype const dt )
119  {
120  using DT = Datatype;
121  switch( dt )
122  {
123  case DT::CHAR:
124  case DT::VEC_CHAR:
125  case DT::STRING:
126  case DT::VEC_STRING:
127  return pybind11::dtype("b");
128  break;
129  case DT::UCHAR:
130  case DT::VEC_UCHAR:
131  return pybind11::dtype("B");
132  break;
133  // case DT::SCHAR:
134  // case DT::VEC_SCHAR:
135  // pybind11::dtype("b");
136  // break;
137  case DT::SHORT:
138  case DT::VEC_SHORT:
139  return pybind11::dtype("short");
140  break;
141  case DT::INT:
142  case DT::VEC_INT:
143  return pybind11::dtype("intc");
144  break;
145  case DT::LONG:
146  case DT::VEC_LONG:
147  return pybind11::dtype("int_");
148  break;
149  case DT::LONGLONG:
150  case DT::VEC_LONGLONG:
151  return pybind11::dtype("longlong");
152  break;
153  case DT::USHORT:
154  case DT::VEC_USHORT:
155  return pybind11::dtype("ushort");
156  break;
157  case DT::UINT:
158  case DT::VEC_UINT:
159  return pybind11::dtype("uintc");
160  break;
161  case DT::ULONG:
162  case DT::VEC_ULONG:
163  return pybind11::dtype("uint");
164  break;
165  case DT::ULONGLONG:
166  case DT::VEC_ULONGLONG:
167  return pybind11::dtype("ulonglong");
168  break;
169  case DT::FLOAT:
170  case DT::VEC_FLOAT:
171  return pybind11::dtype("single");
172  break;
173  case DT::DOUBLE:
174  case DT::VEC_DOUBLE:
175  case DT::ARR_DBL_7:
176  return pybind11::dtype("double");
177  break;
178  case DT::LONG_DOUBLE:
179  case DT::VEC_LONG_DOUBLE:
180  return pybind11::dtype("longdouble");
181  break;
182  case DT::BOOL:
183  return pybind11::dtype("bool"); // also "?"
184  break;
185  case DT::DATATYPE:
186  case DT::UNDEFINED:
187  default:
188  throw std::runtime_error("dtype_to_numpy: Invalid Datatype '{...}'!"); // _s.format(dt)
189  break;
190  }
191  }
192 } // namespace openPMD
Datatype dtype_from_bufferformat(std::string const &fmt)
Return openPMD::Datatype from py::buffer_info::format.
Definition: Numpy.hpp:75
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:38
Public definitions of openPMD-api.
Definition: Date.cpp:28