Skip to content

Added support for loading native object for openvdb#170

Open
spyke7 wants to merge 6 commits into
MDAnalysis:masterfrom
spyke7:grid_openvdb_native
Open

Added support for loading native object for openvdb#170
spyke7 wants to merge 6 commits into
MDAnalysis:masterfrom
spyke7:grid_openvdb_native

Conversation

@spyke7
Copy link
Copy Markdown
Contributor

@spyke7 spyke7 commented May 29, 2026

Fixes #171

Changes -

  • Made _extract_from_vdb_grid that gets the delta, origin, data type and metadata, if a native object is passed - OpenVDB.py
  • made the datatypes list global as _DATATYPES and checked for instance if a openvdb.gridbase is passed - OpenVDB.py
  • In core.py, checked if not a filename (str) is given, and called the OpenVDBField - core.py
  • Updated the tests for the _extract_from_vdb_grid - test_vdb.py

@orbeckst please have a look at this when you are free and have time.
Also, made a new section in changelog, with enhancement in it

@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

❌ Patch coverage is 90.69767% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.02%. Comparing base (5983c10) to head (099ea1a).

Files with missing lines Patch % Lines
gridData/OpenVDB.py 94.11% 1 Missing and 1 partial ⚠️
gridData/core.py 77.77% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #170      +/-   ##
==========================================
- Coverage   90.03%   90.02%   -0.02%     
==========================================
  Files           6        6              
  Lines         953      992      +39     
  Branches      126      132       +6     
==========================================
+ Hits          858      893      +35     
- Misses         58       61       +3     
- Partials       37       38       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@orbeckst
Copy link
Copy Markdown
Member

Is the objective of the PR to enable #162 for openvdb objects only or implement it for all available formats?

It's totally ok to only do it for OpenVDB, I just want to know when reviewing the PR.

Copy link
Copy Markdown
Member

@orbeckst orbeckst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great that you're starting the work on #162 . The type-selection mechanism needs to be reworked.

We also need to have a more general architecture for Grid for (1) detecting the format, (2) dispatching to the correct loader. We can decide to do this in a separate PR if for right now we're only focusing on VDB.

Comment thread CHANGELOG Outdated
Comment thread CHANGELOG Outdated
Comment thread gridData/OpenVDB.py Outdated
for key in self.vdb_grid.metadata:
try:
self.metadata[key] = self.vdb_grid[key]
except (TypeError, ValueError):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under which conditions does that fail? I am always suspicious of try/except that passes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vec3f can be one of the example. But I can create a path for a warning to be raised for this

Comment thread gridData/OpenVDB.py Outdated
self.origin = v_origin
self.delta = v_delta

dtype = np.dtype("float32")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner to set the dtype to the default in an else block of the for loop:

        for numpy_dtype, vdb_names in self._DATATYPES.items():
            name_dtype = vdb_names[0]
            ...
            if vdb_class_name == canonical_name:
                dtype = numpy_dtype
                break
        else:
             # could not find a matching dtype, use default
             dtype = np.float32

Or maybe should we use float64? @BradyAJohnston @PardhavMaradani do you have an opinion?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also log a warning if you encounter an unknown type and use the default.

Comment thread gridData/OpenVDB.py Outdated
Comment on lines +321 to +329
canonical_name = (
name_dtype.gridType
if isinstance(name_dtype, DownCastTo)
else name_dtype
)

if vdb_class_name == canonical_name:
dtype = numpy_dtype
break
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic is flawed. You are picking the first match to a value in the _DATATYPES dict and the relationship from vdb to np is many-to-one (eg FloatGrid can map back to int8, unint16, float32, ...) and the dict order is not defined so you might choose the wrong dtype.

Instead you must define an appropriate mapping from VDB to np.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, I will try to redo that

Comment thread gridData/OpenVDB.py
Comment thread gridData/OpenVDB.py Outdated
Comment on lines +333 to +335
if bbox is None or bbox[0] == bbox[1]:
self.grid = np.zeros((0, 0, 0), dtype=dtype)
return
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens here?

Possibly log a warning that you encountered an empty box with a single entry. (Is that what happened??)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically for VDB grid that has no active voxels
evalActiveVoxelBoundingBox() returns none

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the explanation. Can you add a comment to the code that explains what happens?

And issue a warning.

Comment thread gridData/core.py
Comment on lines +252 to +266
try:
# if a openvdb native grid is passed
import openvdb as vdb
if isinstance(grid, vdb.GridBase):
vdb_field = OpenVDB.OpenVDBField(grid=grid)
self.metadata = vdb_field.metadata
self._load(
grid=vdb_field.grid,
origin=vdb_field.origin,
delta=vdb_field.delta,
metadata=vdb_field.metadata,
)
return
except ImportError:
pass
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the right idea. This (together with the filename/array code below) is quite clunky. For each additional format we will need to add another try/except.

We need to come up with a more general solution, e.g., a dict-based dispatch lookup or a dispatcher function that calls the correct setup, based on the detected format.

world = native_grid.transform.indexToWorld((0, 0, 0))
assert_allclose([world[0], world[1], world[2]], g.origin, rtol=1e-5)

def test_extract_from_vdb_grid(self, grid345):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parameterize the test to try out all normally supported vdb gridtypes

assert new_vdb_grid.metadata["name"] == "new_density"
assert new_vdb_grid.grid.dtype == np.dtype("float32")
assert_allclose(new_vdb_grid.grid, data, rtol=1e-5)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also include a test that shows that file round-tripping works, e.g.,

  1. create Grid
  2. write OpenVDB
  3. read OpenVDB
  4. compare to Grid

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include a test that reads the test vdb file directly with OpenVDB first.

@orbeckst
Copy link
Copy Markdown
Member

For right now I linked this PR to the OpenVDB-only issue #171

spyke7 and others added 2 commits May 30, 2026 11:23
Co-authored-by: Oliver Beckstein <orbeckst@gmail.com>
Co-authored-by: Oliver Beckstein <orbeckst@gmail.com>
@orbeckst orbeckst mentioned this pull request May 30, 2026
4 tasks
@read-the-docs-community
Copy link
Copy Markdown

read-the-docs-community Bot commented May 30, 2026

Documentation build overview

📚 GridDataFormats | 🛠️ Build #32917981 | 📁 Comparing 099ea1a against latest (5983c10)

  🔍 Preview build  

3 files changed
± index.html
± _modules/gridData/OpenVDB.html
± _modules/gridData/core.html

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.

create Grid from openvdb grid object

2 participants