LvArray
PyArray.hpp
Go to the documentation of this file.
1 /*
2  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3  * Copyright (c) 2019, Lawrence Livermore National Security, LLC.
4  *
5  * Produced at the Lawrence Livermore National Laboratory
6  *
7  * LLNL-CODE-746361
8  *
9  * All rights reserved. See COPYRIGHT for details.
10  *
11  * This file is part of the GEOSX Simulation Framework.
12  *
13  * GEOSX is a free software; you can redistribute it and/or modify it under
14  * the terms of the GNU Lesser General Public License (as published by the
15  * Free Software Foundation) version 2.1 dated February 1999.
16  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17  */
18 
23 #pragma once
24 
25 // Source includes
27 #include "numpyHelpers.hpp"
28 #include "../Array.hpp"
29 #include "../Macros.hpp"
30 #include "../limits.hpp"
31 #include "../output.hpp"
32 #include "pythonHelpers.hpp"
33 
34 // System includes
35 #include <string>
36 #include <memory>
37 #include <typeindex>
38 
39 namespace LvArray
40 {
41 namespace python
42 {
43 namespace internal
44 {
45 
51 {
52 public:
53 
57  virtual ~PyArrayWrapperBase() = default;
58 
63  virtual int getAccessLevel() const
64  { return m_accessLevel; }
65 
71  virtual void setAccessLevel( int const accessLevel, int const memorySpace ) = 0;
72 
77  virtual std::string repr() const = 0;
78 
84  virtual int ndim() const = 0;
85 
91  virtual int getSingleParameterResizeIndex() const = 0;
92 
98  virtual void setSingleParameterResizeIndex( int const dim ) const = 0;
99 
105  virtual void resize( long long const newSize ) = 0;
106 
112  virtual void resize( long long const * const newSizes ) = 0;
113 
121  virtual PyObject * toNumPy() const = 0;
122 
127  virtual std::type_index valueType() const = 0;
128 
129 protected:
130 
132  int m_accessLevel = static_cast< int >( LvArray::python::PyModify::READ_ONLY );
133 };
134 
146 template< typename T,
147  int NDIM,
148  typename PERM,
149  typename INDEX_TYPE,
150  template< typename > class BUFFER_TYPE >
151 class PyArrayWrapper final : public PyArrayWrapperBase
152 {
153 public:
154 
161  m_array( array )
162  {}
163 
165  virtual ~PyArrayWrapper() = default;
166 
168  virtual std::string repr() const final override
169  { return system::demangleType< Array< T, NDIM, PERM, INDEX_TYPE, BUFFER_TYPE > >(); }
170 
172  virtual int ndim() const final override
173  { return NDIM; }
174 
176  virtual int getSingleParameterResizeIndex() const final override
177  { return m_array.getSingleParameterResizeIndex(); }
178 
180  virtual void setSingleParameterResizeIndex( int const dim ) const final override
181  { m_array.setSingleParameterResizeIndex( dim ); }
182 
184  virtual void resize( long long const newSize ) final override
185  { m_array.resize( integerConversion< INDEX_TYPE >( newSize ) ); }
186 
188  virtual void resize( long long const * const newSizes ) final override
189  {
190  INDEX_TYPE dims[ NDIM ];
191 
192  for( int i = 0; i < NDIM; ++i )
193  { dims[ i ] = integerConversion< INDEX_TYPE >( newSizes[ i ] ); }
194 
195  m_array.resize( NDIM, dims );
196  }
197 
199  virtual void setAccessLevel( int accessLevel, int memorySpace ) final override
200  {
201  LVARRAY_UNUSED_VARIABLE( memorySpace );
202  if( accessLevel >= static_cast< int >( LvArray::python::PyModify::RESIZEABLE ) )
203  {
204  // touch
205  }
206  m_accessLevel = accessLevel;
207  }
208 
210  virtual PyObject * toNumPy() const final override
211  {
212  m_array.move( MemorySpace::host, m_accessLevel != static_cast< int >(PyModify::READ_ONLY) );
213  return toNumPyImpl();
214  };
215 
217  virtual std::type_index valueType() const final override
218  {
219  if( std::is_same< T, std::string >::value && NDIM == 1 )
220  { return std::type_index( typeid( PyObject * ) ); }
221  return std::type_index( typeid( T ) );
222  }
223 
224 private:
225 
230  template< typename _T=T >
231  std::enable_if_t< !std::is_same< _T, std::string >::value, PyObject * >
232  toNumPyImpl() const
233  {
234  return createNumPyArray( m_array.data(),
235  m_accessLevel >= static_cast< int >( LvArray::python::PyModify::MODIFIABLE ),
236  NDIM,
237  m_array.dims(),
238  m_array.strides() );
239  }
240 
246  template< typename _T=T >
247  std::enable_if_t< std::is_same< _T, std::string >::value && NDIM == 1, PyObject * >
248  toNumPyImpl() const
249  { return createPyListOfStrings( m_array.data(), integerConversion< long long >( m_array.size() ) ); }
250 
253 };
254 
260 PyObject * create( std::unique_ptr< internal::PyArrayWrapperBase > && array );
261 
262 } // namespace internal
263 
276 template< typename T,
277  int NDIM,
278  typename PERM,
279  typename INDEX_TYPE,
280  template< typename > class BUFFER_TYPE >
281 std::enable_if_t< internal::canExportToNumpy< T > || ( std::is_same< T, std::string >::value && NDIM == 1 ), PyObject * >
283 {
285  return internal::create( std::make_unique< WrapperType >( array ) );
286 }
287 
292 PyTypeObject * getPyArrayType();
293 
294 } // namespace python
295 } // namespace LvArray
#define LVARRAY_UNUSED_VARIABLE(X)
Mark X as an unused variable, used to silence compiler warnings.
Definition: Macros.hpp:51
std::enable_if_t< internal::canExportToNumpy< T >, PyObject *> create(T &value)
Create a NumPy 1D array of length 1 containing the scalar value.
Definition: numpyHelpers.hpp:147
PyObject * createPyListOfStrings(std::string const *const strptr, long long const size)
Create and return a Python list of strings from an array of std::strings. The Python strings will be ...
Definition: pythonHelpers.cpp:85
virtual std::type_index valueType() const final override
Return the type of the values stored in the Array.
Definition: PyArray.hpp:217
virtual int getSingleParameterResizeIndex() const final override
Return the single parameter resize index of the Array.
Definition: PyArray.hpp:176
PyArrayWrapper(Array< T, NDIM, PERM, INDEX_TYPE, BUFFER_TYPE > &array)
Constructor.
Definition: PyArray.hpp:159
virtual int ndim() const =0
Return the number of dimensions in the Array.
virtual void resize(long long const newSize) final override
Resize the default dimension of the Array.
Definition: PyArray.hpp:184
virtual void resize(long long const *const newSizes) final override
Resize all the dimensions of the Array.
Definition: PyArray.hpp:188
virtual std::string repr() const =0
Return a string representing to the underlying Array type.
virtual void setAccessLevel(int const accessLevel, int const memorySpace)=0
Set the access level for the Array.
Provides A virtual Python wrapper around an Array.
Definition: PyArray.hpp:50
Array< T, NDIM, PERM, INDEX_TYPE, BUFFER_TYPE > & m_array
The wrapped Array.
Definition: PyArray.hpp:252
An implements the PyArrayWrapperBase interface for a particular Array type.
Definition: PyArray.hpp:151
virtual std::string repr() const final override
Return a string representing to the underlying Array type.
Definition: PyArray.hpp:168
virtual void resize(long long const newSize)=0
Resize the default dimension of the Array.
virtual PyObject * toNumPy() const final override
Return a NumPy ndarray wrapping the Array.
Definition: PyArray.hpp:210
virtual int ndim() const final override
Return the number of dimensions in the Array.
Definition: PyArray.hpp:172
virtual int getAccessLevel() const
Return the access level for the Array.
Definition: PyArray.hpp:63
virtual std::type_index valueType() const =0
Return the type of the values stored in the Array.
std::enable_if_t< !std::is_same< _T, std::string >::value, PyObject *> toNumPyImpl() const
Create a NumPy ndarray for an Array that doesn&#39;t contain std::strings.
Definition: PyArray.hpp:232
Forward declarations of Python Objects.
virtual PyObject * toNumPy() const =0
Return a NumPy ndarray wrapping the Array.
The top level namespace.
Definition: Array.hpp:24
virtual int getSingleParameterResizeIndex() const =0
Return the single parameter resize index of the Array.
virtual void setSingleParameterResizeIndex(int const dim) const =0
Set the single parameter resize index of the Array.
Contains methods to help with conversion to python objects.
virtual ~PyArrayWrapperBase()=default
Default destructor.
PyTypeObject * getPyArrayType()
Return the Python type for the Array.
std::enable_if_t< internal::canExportToNumpy< T >||(std::is_same< T, std::string >::value &&NDIM==1), PyObject *> create(Array< T, NDIM, PERM, INDEX_TYPE, BUFFER_TYPE > &array)
Create a Python object corresponding to array.
Definition: PyArray.hpp:282
std::enable_if_t< std::is_same< _T, std::string >::value &&NDIM==1, PyObject *> toNumPyImpl() const
Create Python list of strings from a 1D Array of strings.
Definition: PyArray.hpp:248
virtual void setSingleParameterResizeIndex(int const dim) const final override
Set the single parameter resize index of the Array.
Definition: PyArray.hpp:180
virtual void setAccessLevel(int accessLevel, int memorySpace) final override
Set the access level for the Array.
Definition: PyArray.hpp:199
int m_accessLevel
If the array can be modified.
Definition: PyArray.hpp:132
std::enable_if_t< internal::canExportToNumpy< T >, PyObject *> createNumPyArray(T *const data, bool const modify, int const ndim, INDEX_TYPE const *const dimsPtr, INDEX_TYPE const *const stridesPtr)
Return a NumPy ndarray view of data.
Definition: numpyHelpers.hpp:107