Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

flumpy: Zero-data-copy bridge between flex and numpy #377

Merged
merged 5 commits into from Jul 6, 2021

Conversation

ndevenish
Copy link
Collaborator

This adds the module dxtbx.flumpy and primarily the functions flumpy.to_numpy and flumpy.from_numpy. These will convert:

  • A python flex object to a numpy array object of the same dtype, but which is pointing to the internal memory of the flex array.
  • A numpy object matching the type of the flex array (if available), but where the numpy object is referencing the internal memory of the flex object.

And exposes flex arrays as a generic PEP3118 buffer protocol object, Scuffer. This exposes the flex array in a way that anything that understands this protocol can access the structured memory. This means numpy, but also things like Cython will accept buffers directly. Currently this is only one-way, it doesn't read generic buffer objects into flex but should be simple enough.

Referencing the internal memory means that no memory needs to be copied, and changes to one object will be reflected in the other. The numpy array holds a reference to the flex object, ensuring memory lifetime, and if cctbx/cctbx_project#618 is merged, the flex objects will hold an internal reference to the numpy object.

Alongside the standard data types, flex.vec2* and flex.vec3* will be converted to Nx...x2 and Nx...x3 numpy arrays, and flex.mat3* will be converted to Nx....x3x3 numpy objects. vec2*, vec3* and mat3* can also be converted from numpy to flex arrays, but currently require the use of flumpy.vec_from_numpy (and an Nx[2,3] sized numpy array), or flumpy.mat3_from_numpy (and either a Nx9 or Nx3x3 numpy array).

The data types that aren't wrapped are flex.std_string and flex.sym_mat3_double, which don't linearly map to memory.

Usage example:

import numpy as np
import scitbx.array_family.flex as flex
import dxtbx.flumpy as flumpy

flex_obj = flex.int(10)
as_numpy = flumpy.to_numpy(flex_obj)

# >>> as_numpy
# array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32)

as_numpy[3] = 42

# >>> flex_obj[3]
# 42

np_origin = np.array([1,2,3,4])
as_flex = flumpy.from_numpy(np_origin)
as_flex[0] = 99

# >>> np_origin
# array([99,  2,  3,  4])

The new functions in dxtbx.flumpy allow you to convert flex→numpy and
numpy→flex without copying memory. This means that altering one will alter
the other.
@ndevenish ndevenish marked this pull request as ready for review June 7, 2021 14:39
@ndevenish
Copy link
Collaborator Author

The tests are expected to fail at this stage because it doesn't have cctbx/cctbx_project#618

error: cannot dynamic_cast '& other' (of type 'class scitbx::af::sharing_handle*') to type 'class numpy_sharing_handle*' (source type is not polymorphic)

@ndevenish
Copy link
Collaborator Author

This can't be merged until cctbx-base 2021.6 is released.

@codecov
Copy link

codecov bot commented Jul 5, 2021

Codecov Report

Merging #377 (f2f4a9a) into main (0cc3c65) will increase coverage by 0.41%.
The diff coverage is 96.46%.

❗ Current head f2f4a9a differs from pull request most recent head 5684943. Consider uploading reports for the commit 5684943 to get more accurate results

@@            Coverage Diff             @@
##             main     #377      +/-   ##
==========================================
+ Coverage   64.18%   64.60%   +0.41%     
==========================================
  Files         175      177       +2     
  Lines       15043    15241     +198     
  Branches     2051     2067      +16     
==========================================
+ Hits         9656     9847     +191     
- Misses       4846     4852       +6     
- Partials      541      542       +1     

@ndevenish ndevenish merged commit 2946991 into cctbx:main Jul 6, 2021
@ndevenish ndevenish deleted the flumpy branch July 6, 2021 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants