Skip to content

Ncem lazy loading #526 - #529

Open
matao1984 wants to merge 5 commits into
hyperspy:mainfrom
matao1984:ncem_lazy
Open

matao1984 wants to merge 5 commits into
hyperspy:mainfrom
matao1984:ncem_lazy

Conversation

@matao1984

Copy link
Copy Markdown
Contributor

Description of the change

Modified the _read_dataset() function in _emd_ncem.py to take lazy options, instead of always eagerly reading the dataset by assigning data = dataset[:]. All tests passed.

Progress of the PR

  • [ x] Change implemented (can be split into several points),
  • update docstring (if appropriate),
  • update user guide (if appropriate),
  • [ x] add a changelog entry in the upcoming_changes folder (see upcoming_changes/README.rst),
  • Check formatting of the changelog entry (and eventual user guide changes) in the docs/readthedocs.org:rosettasciio build of this PR (link in github checks)
  • add tests,
  • [x ] ready for review.

Comment thread rsciio/emd/_emd_ncem.py Fixed
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.44444% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 88.83%. Comparing base (3dc027a) to head (790d3df).
⚠️ Report is 29 commits behind head on main.

Files with missing lines Patch % Lines
rsciio/emd/_emd_ncem.py 94.44% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #529      +/-   ##
==========================================
- Coverage   88.85%   88.83%   -0.03%     
==========================================
  Files         113      113              
  Lines       13090    13152      +62     
  Branches     2421     2433      +12     
==========================================
+ Hits        11631    11683      +52     
- Misses        914      922       +8     
- Partials      545      547       +2     

☔ View full report in Codecov by Harness.
📢 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.

@ericpre
ericpre requested a review from Copilot July 1, 2026 18:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.

Enables NCEM EMD reading to support true lazy-loading by allowing _read_dataset() to return an h5py-backed object instead of eagerly materializing dataset[:].

Changes:

  • Add a lazy option to _read_dataset() and propagate it through the NCEM data reading paths.
  • Update dask wrapping code paths to pass lazy=self.lazy.
  • Add an upcoming_changes entry documenting the fix.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
upcoming_changes/526.bugfix.rst Documents the NCEM lazy-loading behavior change.
rsciio/emd/_emd_ncem.py Adds lazy support to _read_dataset() and updates callers (numpy/dask paths).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rsciio/emd/_emd_ncem.py
Comment on lines 250 to 252
data_list = [
da.from_array(*self._read_dataset(d)) for d in dataset_list
da.from_array(*self._read_dataset(d, lazy=self.lazy))
]
Comment thread rsciio/emd/_emd_ncem.py Outdated

data_list = [
da.from_array(*self._read_dataset(d)) for d in dataset_list
da.from_array(*self._read_dataset(d, lazy=self.lazy))
Comment thread rsciio/emd/_emd_ncem.py
import dask.array as da

data = da.from_array(*self._read_dataset(d))
data = da.from_array(*self._read_dataset(d, lazy=self.lazy))
Comment thread rsciio/emd/_emd_ncem.py Outdated

data_list = [
da.from_array(*self._read_dataset(d)) for d in dataset_list
da.from_array(*self._read_dataset(d, lazy=self.lazy))
Comment thread rsciio/emd/_emd_ncem.py
import dask.array as da

data = da.from_array(*self._read_dataset(d))
data = da.from_array(*self._read_dataset(d, lazy=self.lazy))
Comment thread upcoming_changes/526.bugfix.rst Outdated
@@ -0,0 +1 @@
Modified _emd_ncem.py to correctly handle lazy loading of ncem data by avoiding eager dataset reads. No newline at end of file

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread rsciio/emd/_emd_ncem.py
Comment on lines 250 to 252
data_list = [
da.from_array(*self._read_dataset(d)) for d in dataset_list
da.from_array(*self._read_dataset(d, lazy=self.lazy))
]
Comment thread rsciio/emd/_emd_ncem.py
Comment on lines 245 to 256
if len(dataset_list) > 1:
# Squeeze the data only when
if self.lazy:
import dask.array as da

data_list = [
da.from_array(*self._read_dataset(d)) for d in dataset_list
da.from_array(*self._read_dataset(d, lazy=self.lazy))
]
if transpose_required:
data_list = [da.transpose(d) for d in data_list]
data = da.stack(data_list)
data = da.squeeze(data)
@ericpre

ericpre commented Jul 13, 2026

Copy link
Copy Markdown
Member

Most of the co-pilot review comments sound sensible and would need to be addressed.

For py4DSTEM files, parse the calibration information under [root]/metadatabundle/calibration
Updated test files to use a new py4DSTEM file with multiple datasets
Comment thread rsciio/tests/test_emd_ncem.py Dismissed
@matao1984

Copy link
Copy Markdown
Contributor Author

Sorry for being late. In the new commitment, I have:

  • Fixed the bug for file containing multiple datasets
  • Added some lines to look for [root]/metadatabundle/calibration key to include the calibration information into the original_metadata
  • Added a new file "py4DSTEM_size2x3x4x5_bf20x30.h5" containing a 4D dataset of 2x3x4x5 and also a 2D image of shape 20x30 for testing
  • Updated the test code to check the length, shape, axes, etc.

All tests passed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 5 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

upcoming_changes/526.bugfix.rst:1

  • The news fragment should be written for users (per upcoming_changes/README.rst) rather than referencing internal module names. Consider describing the user-visible behavior change (lazy loading) instead of “Modified _emd_ncem.py”.
Modified _emd_ncem.py to correctly handle lazy loading of ncem data by avoiding eager dataset reads.

rsciio/tests/test_emd_ncem.py:118

  • lazy is parametrized but not passed to file_reader, so this test only exercises the eager code path and won’t catch regressions in lazy loading. It also mutates signals while iterating and can raise an unhelpful UnboundLocalError if the 4D signal isn’t found.
def test_py4dstem(lazy):
    filename = TEST_DATA_PATH / "py4DSTEM_size2x3x4x5_bf20x30.h5"
    signals = file_reader(filename)
    assert len(signals) == 2

rsciio/emd/_emd_ncem.py:419

  • This block eagerly reads every dataset under metadatabundle/calibration into memory (value[()]) even when self.lazy is True. If any calibration entries are large arrays, this undermines the memory benefits of lazy loading and can add significant IO during metadata parsing.
            calibration = {}
            for key, value in calibration_group.items():
                if isinstance(value, h5py.Dataset):
                    calibration[key] = value[()]
            om.update({"calibration": calibration})

@matao1984

Copy link
Copy Markdown
Contributor Author

Copilot comments 1 and 2 are addressed. 3 is less of a concern because those strings are short.

@matao1984

Copy link
Copy Markdown
Contributor Author

@ericpre Sorry it has been a busy summer — is there anything I have to do with this one?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants