EndfFile
- class endf_parserpy.EndfFile(filename, *, parser=None, mode='index', parsed_cache_bytes=67108864, raw_cache_bytes=67108864, on_error='mark', check_edits='eager', verify_source=False)[source]
Lazy, memory-bounded, editable view of a multi-material ENDF file.
The file is indexed on construction (see
TapeIndex). Section data is read from disk and parsed only on access and is then held in bounded caches. Materials are addressed by zero-based position:with EndfFile("tape.endf") as endf_file: material = endf_file[0] # a MaterialView section = material[3, 2] # parsed MF=3/MT=2 section material[3, 2] = section # edit it back in endf_file.export("edited.endf")
- Parameters:
filename (str or os.PathLike) – Path to the ENDF file.
parser (EndfParserBase, optional) – Engine used to parse and write sections. Defaults to
EndfParserFactory.create(select="fastest").mode ({"index", "load_raw", "parse_all"}) –
"index"(default) only builds the index."load_raw"also pre-reads section text into the raw cache;"parse_all"also parses every section. The cache budgets still apply, so these modes pre-warm the caches rather than guarantee residency.parsed_cache_bytes (int) – Budgets, in raw-text-equivalent bytes, for the parsed-section and raw-text caches.
raw_cache_bytes (int) – Budgets, in raw-text-equivalent bytes, for the parsed-section and raw-text caches.
on_error ({"raise", "mark"}) – Whether a section that fails to parse raises
SectionParseErroror is returned as aFailedSection.check_edits ({"eager", "deferred"}) – When the recipe-conformity of an edited section is checked.
"eager"(the default) renders every edited section through the parser’s writer immediately, so a malformed edit raises at the offending assignment, and a retrieved section is a read-only (frozen) view."deferred"accepts every edit, marking the section dirty, and checks conformity only atexport()/to_string()orinvalid_edits(); a retrieved section is then a live write-through view.verify_source (bool) – If true, the file’s size and mtime are checked against the index before every disk read; a change raises
StaleSourceError.
Notes
An
EndfFileis not safe for concurrent use from several threads: its caches, material list and edit overlays are plain, unguarded state, so any access racing with another is undefined. Use oneEndfFileper thread.- append_material(material, *, mat, za=None, awr=None)[source]
Append a new material to the tape.
- Parameters:
material (Mapping) – A nested
{MF: {MT: section}}mapping, as returned by an ordinaryparsefile. TheMF=0tape-head entry, if present, is ignored.mat (int) – ENDF MAT number of the new material.
za (optional) – Identifiers, used by
by_za()and the index.awr (optional) – Identifiers, used by
by_za()and the index.
- Returns:
A view of the appended material.
- Return type:
Notes
Under
check_edits="eager"every section of the appended material is render-checked immediately, exactly as a section assignment is, so a malformed section is rejected here rather than atexport()time.The
matargument must agree with the MAT number the material carries in its own records (the'MAT'key of a parsed section, or the control field of a raw section’s first line); a mismatch is rejected, since the records, not the argument, are what gets written to the tape.
- build_index(section_path, *, name=None)[source]
Build a secondary index over one or several section fields.
With a single section path – a string
"MF/MT[/field...]"– this parses that section of every material that has it, reads the value at the field path and returns a dict{value: [positions]}.With a list (or tuple) of section paths it builds a composite index instead: the key is the tuple of the values at the respective paths, in the order given, so the result is a dict
{(value0, value1, ...): [positions]}. A material is indexed only if every path resolves for it; one that lacks any of the addressed sections or fields is skipped. Paths that share anMF/MTsection have it parsed only once per material. The key shape follows the argument type: a one-element list still yields one-element-tuple keys.One section is parsed per material per distinct
MF/MT, so the cost grows with the number of materials. Withnamethe result is also stored and reachable viasecondary_indexes; because the index is keyed by tape position, a stored index is dropped whenever a material is appended, removed or reordered, and must then be rebuilt.
- by_mat(mat, *, occurrence=None)[source]
Return the material with the given MAT number.
occurrence(zero-based) selects among several materials that share a MAT number, as on a PENDF tape. Without it, a MAT number that is not unique raisesAmbiguousMaterialError.
- property cache_nbytes
The current
(raw, parsed)cache sizes in bytes.
- export(path, *, overwrite=False)[source]
Write the (possibly edited) tape to a file.
The tape is written one material at a time via a temporary file and an atomic replace, so peak memory stays bounded by a single material regardless of the tape size. Untouched sections keep their data records verbatim from disk (they are not parsed) and edited or added sections are rendered by the parser; the SEND/FEND/MEND framing and the column 76-80 sequence numbers are regenerated either way, preserving every data field byte-for-byte without making the tape byte-identical. An existing file is only overwritten when
overwrite=True. A tape from which every material has been deleted is written as its tape head (TPID) followed by the tape end (TEND).Exporting onto the file the
EndfFilewas opened from is permitted, but it leaves the in-memory structural index stale (the byte offsets of untouched sections have moved). The object is therefore invalidated: every subsequent operation raisesStaleSourceError, and the file must be re-opened with a newEndfFileto continue. Exporting to any other path leaves the object usable.
- find(*, mat=None, za=None)[source]
Return a list of materials matching every given criterion.
This is the structural lookup; a criterion left as
Noneis not applied. For lookups by a parsed section field, seequery().
- get(path)[source]
Return the material, section or field addressed by
path.pathis anEndfMaterialPathor a string of the formmaterial[/MF/MT[/field...]]. This is the explicit-method synonym ofendf_file[path]: a material-depth path yields aMaterialView, a section-depth path a section view (seeendf_parserpy.tape.views) and a field-depth path the value at that field. If the addressed section cannot be parsed aSectionParseErroris raised regardless ofon_error.
- invalid_edits()[source]
Return the edited sections that do not conform to their recipe.
Renders every edited section through the parser’s writer and returns a list of
(position, MF, MT, exception)tuples, one per edited section that fails to render; an empty list means every edit is conformant, soif not endf_file.invalid_edits()reads as “every edit is valid”. Untouched sections are written verbatim and are not checked.Under
check_edits="deferred"this is the explicit conformity check thatexport()andto_string()perform implicitly; under"eager"every edit was already checked at write time, so it is a near no-op but remains harmless to call.
- property parser
The parser engine used for sections.
- query(section_path, value=<object object>, *, predicate=None, tol=0.0)[source]
Return the materials whose section field matches.
Pass exactly one of
value(equality, withintolfor numbers) orpredicate(a callable applied to the field). Returns a list ofMaterialView.
- reorder(order)[source]
Reorder the materials of the tape.
orderis a permutation ofrange(len(self)): the material currently atorder[i]moves to positioni.
- property secondary_indexes
The named secondary indexes built by
build_index().Emptied whenever a material is appended, removed or reordered, since the indexes are keyed by tape position.
- to_string()[source]
Return the (possibly edited) tape as an ENDF-6 formatted string.
Untouched sections keep their data records verbatim from disk and edited or added sections are rendered by the parser; in both cases the SEND/FEND/MEND framing and the column 76-80 sequence numbers are regenerated, so every data field is preserved byte-for-byte but the tape is not necessarily byte-identical to the input. The result ends with a newline; use
str.splitlines()if a list of lines is needed. A tape from which every material has been deleted is written as its tape head (TPID) followed by the tape end (TEND).This necessarily builds the whole tape in memory; for a large tape, write it to a file with
export(), which is memory-bounded.
- class endf_parserpy.tape.FailedSection(exception, raw_lines, position, mf, mt)[source]
Internal placeholder for a section that could not be parsed.
When the
EndfFilewas opened withon_error="mark"a section that fails to parse is kept as aFailedSectionso that the bulk operations (query(),build_index(),export()) can skip it or write it back verbatim instead of aborting. Accessing such a section directly (endf_file[path]ormaterial[mf, mt]) raisesSectionParseError, with this object’sexceptionkept as the cause; aFailedSectionis therefore never handed back to the caller.- mf, mt
The MF/MT numbers of the section.
- Type: