Skip to content

Add exporter capabilities (refactor project) - #267

Open
krzywon wants to merge 13 commits into
refactor_24from
refactor-exporters
Open

krzywon wants to merge 13 commits into
refactor_24from
refactor-exporters

Conversation

@krzywon

@krzywon krzywon commented Nov 9, 2026

Copy link
Copy Markdown
Collaborator

This adds data exporters for ASCII, CSV, canSAS XML, and NXcanSAS formats. Similarly to the new importers, a master exporter class registers all child classes within itself, attempts to find an appropriate exporter based on the data type and file extension defined by the user and atomically written to the final file to prevent corrupt files in the case of errors.

To enable better unit tests when exporting and then reimporting a few choices were made:

  • This is built off of the 224_hdf5_errors branch to ensure the appropriate importer objects exist
  • The ascii importer can now parse units from the header

I am not adding this PR to the existing stack to allow the importers to work to be merged without this work.

krzywon and others added 13 commits November 9, 2026 04:23
…ed (#263)

- Read each loaded column from its own position; ignored columns are
  skipped and their values aren't parsed
- Add AsciiReaderParams.column_positions_included
- guess_params_from_filename keeps columns with no known unit as
  <ignore> instead of dropping them (e.g. dPhi in 4-column I vs Phi files)
- Add tests

Fixes #263
…ain exporter to eliminate unwanted unit conversion
…ed on export in order to retain the originally loaded units
…gainst legacy loaders as well as the new importers
codescene-access[bot]

This comment was marked as outdated.

@ps1401 ps1401 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I have some comments here. The PR looks good in general but given its size and the fact we're at the end of a long contributor camp I'd like to give it a second pass before approving.

one_dim.name: 2,
two_dim.name: 3,
three_dim.name: 5,
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could you check these please. Ignoring columns starting with "d" in COLUMN_ORDERS above I count 2 for one_dim, 5 for two_dim, and 5 for three_dim.

Specifically, two_dim looks like a copy of three_dim, including Qz in the required list . . .

given, from the extension of ``path``.
"""
exporters = cls.exporters()
if isinstance(name, type):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What is type in this context?

raise ExportError(f'Unknown exporter "{exporter}". Known exporters are: {known}.')
return selected
if type(self) is not Exporter:
return type(self)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm not sure what case is covered here - can you explain it for me please?

Find the columns to write. Returns the column headings (name and units) and the values of each column, in the
units given in the headings.
"""
contents = {name: quantity for name, quantity in datum._data_contents.items()}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Use of _data_contents here means that this expoter is currently only set up for SasMeasurement objects, and will not work for general SasData or SasDerivedMeasurement objects. We need to urgently clarify how all of these data objects will be used in the next hackathon and therefore how much support these exporters will need to provide.


class AsciiExporter(DelimitedTextExporter):
"""
Exporter for whitespace separated multi-column ASCII files. Supports 1D and 2D data, one dataset per file.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Add "and 3D data" here.

if np.allclose(fast_grid, fast_grid[0], equal_nan=True) and \
np.allclose(slow_grid, slow_grid[:, :1], equal_nan=True):
return shape
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This looks good, it may be worth considering if the Abscissae type as defined in the Abscissa class may help with determining whether the points lie on an appropriate grid.

Base automatically changed from 224-hdf5-errors to refactor_24 November 9, 2026 18:47

@codescene-access codescene-access Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No quality gates enabled for this code.

See analysis details in CodeScene

Quality Gate Profile: Custom Configuration
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants