Reader architecture¶
pynxtools-ellips is a pynxtools reader plugin, built on pynxtools's MultiFormatReader. This page explains how the pieces fit together and, more importantly, where a new vendor format would go.
One reader, dispatched by file extension¶
EllipsometryReader (src/pynxtools_ellips/reader.py) registers as the ellips entry point. It routes input files by extension:
| Extension | Handler | What it does |
|---|---|---|
.yaml / .yml |
handle_eln_file |
Reads the ELN metadata file — both for NeXus template content (flattened via CONVERT_DICT/REPLACE_NESTED, kept on the reader unchanged from earlier versions of this plugin) and for the parser configuration (colnames/sep/skip/filename) the .dat file needs to be read at all. |
.dat |
handle_dat_file |
Parses a J.A. Woollam VASE/CompleteEASE export via WoollamParser. |
The ELN must be processed first — self.processing_order = [".yaml", ".yml", ".dat"] guarantees that regardless of the order files are passed on the command line, since the .dat file's column layout isn't self-describing and has to come from the ELN.
How the ELN is handled¶
Most pynxtools plugins route all NeXus content — ELN-sourced and instrument-file-sourced alike — through the config file's @eln/@attrs/@data tokens, with every path spelled out explicitly. pynxtools-ellips only does that for the handful of paths that come from the parsed .dat file (see below); the ELN's own content is written directly by handle_eln_file via the existing flatten_and_replace/CONVERT_DICT mechanism.
The config file and wildcards¶
config/config_woollam.json only covers what the ELN's own structure can't: the parsed measurement data, and the repeated per-angle/per-observable fields (Psi_50deg, Delta_60deg, ...). The repeated fields are added using MultiFormatReader's wildcard mechanism:
"/ENTRY[entry]/data_collection/DATA[*]": "@data:*",
"/ENTRY[entry]/data_collection/DATA[*]/@units": "degree",
"/ENTRY[entry]/data_collection/FIELDNAME_errors[*_errors]": "@data:*_errors"
EllipsometryReader.get_data_dims() returns the parser's list of field labels (["Psi_50deg", "Psi_60deg", ..., "Delta_70deg"]); for each label, pynxtools expands * in both the key and the value, so DATA[*] becomes one concrete template entry per label.
The parser¶
WoollamParser (src/pynxtools_ellips/parsers/woollam.py) subclasses a small shared base, _EllipsParser (parsers/base.py):
matches_file(file)— a cheap structural check (the acquisition-method markerVASEmethod[near the top of the file), not just an extension check._parse(file, header_config=...)— populatesself.datawith the measurement arrays and, for each per-angle/per-observable field, a{"link": ..., "shape": np.index_exp[...]}entry requesting a sliced HDF5 virtual dataset — see Learn > Application definitions for why this has to be a slice rather than the full array.post_process(eln_data)— derivesatom_typesfrom the sample's chemical formula if the ELN didn't already provide one.
If a second vendor parser is added, parsers/base.py is the contract to implement against
Adding a second vendor¶
- Add a new parser module under
parsers/, subclassing_EllipsParser. - Register its file extension in
EllipsometryReader.__init__'sself.extensions. - If its data doesn't fit the existing
config_woollam.jsonmapping, add a new config file and a way to select it in the reader. - Add real vendor example data under
examples/<vendor>/, following the pattern in Tutorial > Convert your first ellipsometry dataset.