Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.4.0 #496

Merged
merged 96 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
51d0ebc
Updated tests to verify #486.
MicahGale Aug 13, 2024
91a5dbd
Updated isotope str to include metastable.
MicahGale Aug 13, 2024
061f683
updated space in tests for metastable space.
MicahGale Aug 13, 2024
151e8a6
fixed americium bs test.
MicahGale Aug 13, 2024
cc18df0
Handled stupid legacy edge case.
MicahGale Aug 13, 2024
c4a3f31
Added issue #486 to changelog.
MicahGale Aug 13, 2024
adaf8ac
Merge pull request #487 from idaholab/486-metastable-isotopes-are-pri…
tjlaboss Aug 14, 2024
53637c8
Made method to auto insert new materials to data_inputs.
MicahGale Aug 15, 2024
ca465fe
Updated docstrings.
MicahGale Aug 15, 2024
b1c889b
Made append method more robust.
MicahGale Aug 15, 2024
524acf0
Updated changelog with materials append feature.
MicahGale Aug 15, 2024
c4b1d0d
Wrote test system for issue #490.
MicahGale Aug 16, 2024
7550970
Separate writing function from write_to_file()
tjlaboss Aug 16, 2024
db62c4c
Non MCNP_InputFile logic in write_to_file()
tjlaboss Aug 16, 2024
6b118c6
Implement MCNP_Problem.write_problem()
tjlaboss Aug 16, 2024
8ec1a17
Reformat with black
tjlaboss Aug 16, 2024
44255c0
Rename new_problme -> file_path
tjlaboss Aug 16, 2024
78abee3
getattr(), not .get()
tjlaboss Aug 16, 2024
d0397bf
Added auto deleter.
MicahGale Aug 17, 2024
1c3d5b0
Added all deleter methods to data numbered.
MicahGale Aug 17, 2024
38013e2
Started test fixtures for data numbered objects.
MicahGale Aug 17, 2024
29900d0
Remove comments about .tell()
tjlaboss Aug 17, 2024
bc900b0
Directly create MCNP_InputFile from stream
tjlaboss Aug 17, 2024
1044fc2
Make write_to_stream() private and deprecate write_to_file()
tjlaboss Aug 17, 2024
a56f294
Improve parameter type hinting
tjlaboss Aug 17, 2024
26cfedc
Fixed sitemap URLs (#495)
MicahGale Aug 17, 2024
9fa1a96
Tested everything for thing.
MicahGale Aug 17, 2024
4315fed
Fixed new collection bugs that were found.
MicahGale Aug 17, 2024
f24cf27
Merge branch 'develop' into mat_append
MicahGale Aug 17, 2024
2da5a82
Updated docs about materials.
MicahGale Aug 17, 2024
1962c78
Merge branch 'develop' into write_to_stream
MicahGale Aug 17, 2024
b34c34b
Merge branch 'develop' into case_of_the_missing_parens
MicahGale Aug 17, 2024
d605f2a
import montepy.errors into top-level
tjlaboss Aug 18, 2024
faa9184
Move test_integration.py to pytest
tjlaboss Aug 18, 2024
883f8e4
Test new writing methods
tjlaboss Aug 18, 2024
2c21daf
Format with black
tjlaboss Aug 18, 2024
f84a3ea
Update CHANGELOG
tjlaboss Aug 18, 2024
f74b19d
Update edge case test to use write_problem()
tjlaboss Aug 18, 2024
5d661f8
Update documentation for PR #493
tjlaboss Aug 18, 2024
9968ddc
Comma without braces for multiple types
tjlaboss Aug 19, 2024
4adaf1c
use pytest.raises in test_orphaning_mt
tjlaboss Aug 19, 2024
6ef5274
Convert test_mcnp_problem.py to pytest
tjlaboss Aug 19, 2024
363c469
Test catching of writing to unwritable destination
tjlaboss Aug 19, 2024
65209fa
Un-deprecate MCNP_Problem.write_to_file()
tjlaboss Aug 19, 2024
5460cb2
Set fixture scope to "module" and format w black
tjlaboss Aug 19, 2024
91c4e63
Cover a bit more code
tjlaboss Aug 19, 2024
74d415a
Bring changelog up to standards
tjlaboss Aug 19, 2024
8d55af4
format with black, forgot to commit this
tjlaboss Aug 19, 2024
4749e95
Merge pull request #493 from idaholab/write_to_stream
tjlaboss Aug 19, 2024
478ff5c
Merge branch 'develop' into mat_append
tjlaboss Aug 19, 2024
45cb024
Git merge wasn't smart enough.
MicahGale Aug 19, 2024
9fea074
Thanks for the suggestion Word.
MicahGale Aug 19, 2024
4dd84b7
Merge pull request #488 from idaholab/mat_append
MicahGale Aug 19, 2024
93ef872
Merge branch 'develop' into case_of_the_missing_parens
MicahGale Aug 19, 2024
3c6f648
Switched to stringIO.
MicahGale Aug 19, 2024
f27a19a
Switched to write_problem
MicahGale Aug 19, 2024
382773c
Made test method less jank.
MicahGale Aug 19, 2024
36b0146
Marked what needs to be fixed.
MicahGale Aug 20, 2024
0ade822
Fixed bug with cell_modifiers being printed in comments. (#484)
MicahGale Aug 20, 2024
7d12c3f
Merge branch 'develop' into case_of_the_missing_parens
MicahGale Aug 21, 2024
7c21aa3
Added #490 to the changelog.
MicahGale Aug 21, 2024
9a97f23
Stoped hiding the shift operator.
MicahGale Aug 21, 2024
ba4bba6
Updated the right variable.
MicahGale Aug 22, 2024
3c572f0
Clarified doc strings around empty tuples.
MicahGale Aug 22, 2024
15752ae
Implemented updating syntax trees for needed parentheses.
MicahGale Aug 22, 2024
28033c1
Added Operator.GROUP for clarity.
MicahGale Aug 22, 2024
82bbcf6
Avoided accidentally overriding final parens.
MicahGale Aug 22, 2024
7f283c7
Switched test_geometry over to pytest fully.
MicahGale Aug 22, 2024
3ddecf3
removed namespace conflicts in test.
MicahGale Aug 22, 2024
7713327
Updated test to handle having a grouping operator.
MicahGale Aug 22, 2024
288da57
Tested added parens to scratch logic creation.
MicahGale Aug 22, 2024
9f0ce04
Fixed namespace typo.
MicahGale Aug 22, 2024
d824cfd
Skipped parens in tree for str.
MicahGale Aug 22, 2024
8e4bb22
Removed completed TODOs
MicahGale Aug 22, 2024
4e9599e
Added tests for generating parens.
MicahGale Aug 22, 2024
cb08869
I can conjugate.
MicahGale Aug 22, 2024
05a692d
Updated doc strings.
MicahGale Aug 22, 2024
78dfab2
Made test stricter to be word for word.
MicahGale Aug 22, 2024
46eae03
fixed list comprehension that deleted comments. Whoops.
MicahGale Aug 22, 2024
4dd50c0
Shut up test about volume changing.
MicahGale Aug 22, 2024
224593e
Upgraded black to match GHA.
MicahGale Aug 22, 2024
980a825
Merge pull request #491 from idaholab/case_of_the_missing_parens
MicahGale Aug 22, 2024
6f0f82e
Updating changelog to next version: 0.4.0
MicahGale Aug 22, 2024
1fe418e
Update test count in README
tjlaboss Aug 22, 2024
21b99f3
Update example to use write_problem()
tjlaboss Aug 22, 2024
59ede4c
General update to README.md
tjlaboss Aug 22, 2024
798eb36
Merge branch 'develop' into readme_040
tjlaboss Aug 22, 2024
77773e0
Updated tag line.
MicahGale Aug 23, 2024
acadcca
Updated link to sphinx site for SEO.
MicahGale Aug 23, 2024
e091a9e
Added hyperlinks to features.
MicahGale Aug 23, 2024
8caf905
Updated example problem to show more features.
MicahGale Aug 23, 2024
9641389
leveraged our core competencies for synergy.
MicahGale Aug 23, 2024
9313d00
Improved contributing blurb.
MicahGale Aug 23, 2024
aa9d1fe
Clarified open issues.
MicahGale Aug 23, 2024
40b1ece
Merge pull request #503 from idaholab/readme_040
MicahGale Aug 23, 2024
ed6f2d3
Fixed changelog formatting.
MicahGale Aug 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/scripts/check_sitemap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import xml.etree.ElementTree as ET
import urllib.request

NS = {"a": "http://www.sitemaps.org/schemas/sitemap/0.9"}
TOLERANCE = 0.8


def discover_urls():
tree = ET.parse("doc/build/html/sitemap.xml")
root = tree.getroot()
return [node.find("a:loc", NS).text for node in root.findall("a:url", NS)]


def test_urls(urls):
passed = 0
for url in urls:
code = 404
try:
code = urllib.request.urlopen(url).getcode()
except urllib.error.HTTPError as e:
print(url, e)
if code == 200:
passed += 1
else:
print(url, code)
if passed / len(urls) < TOLERANCE:
raise ValueError(f"Too many URLs failed")


if __name__ == "__main__":
test_urls(discover_urls())
10 changes: 3 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,7 @@ jobs:
with:
python-version: 3.12
- run: pip install . montepy[doc,build]
- uses: mathieudutour/[email protected]
name: Get next version number
id: version_num
with:
dry_run: True
github_token: ${{ secrets.GITHUB_TOKEN }}
- run: sphinx-build doc/source/ doc/build/ -W --keep-going -E
- run: sphinx-build doc/source/ doc/build/html -W --keep-going -E
name: Build site strictly
- uses: actions/upload-artifact@v4
with:
Expand All @@ -121,6 +115,8 @@ jobs:
run: |
cd doc
make linkcheck
- name: test sitemap
run: python .github/scripts/check_sitemap.py

format-test:
runs-on: ubuntu-latest
Expand Down
77 changes: 49 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![PyPI version](https://badge.fury.io/py/montepy.svg)](https://badge.fury.io/py/montepy)
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)

MontePy is a python library to read, edit, and write MCNP input files.
MontePy is the most user friendly Python library for reading, editing, and writing MCNP input files.

## Installing

Expand All @@ -24,35 +24,56 @@ see the [Installing section in the user guide](https://www.montepy.org/starting.

## User Documentation

MontePy has a [sphinx website](https://www.montepy.org/).
This has a getting started guide for users,
as well as API documentation.
There is also a developer's guide covering the design and approach of MontePy, and how to contribute.
MontePy has a website [documenting how to work with MCNP in python with MontePy](https://www.montepy.org/).
The website contains a user's guide for getting started,
a developer's guide covering the design and approach of MontePy,
instructions for contributing,
and the Python API documentation.

## Features

* Handles almost all MCNP input syntax including: message blocks, & continue, comments, etc.
* Parses Cells, surfaces, materials, and transforms very well.
* Can parse the following surfaces exactly P(X|Y|Z), C(X|Y|Z), C/(X|Y|Z) (I mean it can do PX, and PY, etc.)
* Can read in all other inputs but not understand them
* Can write out full MCNP problem even if it doesn't fully understand an input.
* Can write out the MCNP problem verbatim, and try to match the original user formatting.
* Can quickly access cells, surfaces, and materials by their numbers. For example: `cell = problem.cells[105]`.
* Can quickly update cell importances. For example `cell.importance.neutron = 2.0`.
* Has over 240 test cases right now
* Handles almost all MCNP input syntax.
* Parses Cells, Surfaces, Materials, and Transforms very well.
* Can parse all surface types except macrobody facets ([Issue #354](https://github.com/idaholab/MontePy/issues/354)).
* Can read and write out all other MCNP inputs, even if it doesn't not understand them
* Attempts to write out the MCNP problem verbatim, even matching the original user formatting. (See some of the [open issues](https://github.com/idaholab/MontePy/issues).)
* Can quickly [access cells, surfaces, and materials by their numbers](https://www.montepy.org/starting.html#collections-are-accessible-by-number). For example: `cell = problem.cells[105]`.
* Can quickly update cell parameters, [such as importances](https://www.montepy.org/starting.html#setting-cell-importances). For example `cell.importance.neutron = 2.0`.
* Can easily [create universes, and fill other cells with universes](https://www.montepy.org/starting.html#universes).
* Currently has over 430 test cases.


Quick example for renumbering all of the cells in a problem:
Here is a quick example showing multiple tasks in MontePy:

```python
import montepy
foo = montepy.read_input("foo.imcnp")
i = 9500
for cell in foo.cells:
cell.number = i
i = i + 5
# read in file
problem = montepy.read_input("foo.imcnp")

foo.write_to_file("foo_update.imcnp")
# set photon importance for multiple cells
importances = {1: 0.005,
2: 0.1,
3: 1.0,
99: 1.235
}
for cell_num, importance in importances.items():
problem.cells[cell_num].importance.photon = importance

#create a universe and fill another cell with it
universe = montepy.Universe(123)
problem.univeres.append(universe)
# add all cells with numbers between 1 and 4
universe.claim(problem.cells[1:5])
# fill cell 99 with universe 123
problem.cells[99].fill.universe = universe

# update all surfaces numbers by adding 1000 to them
for surface in problem.surfaces:
surface.number += 1000
# all cells using these surfaces will be automatically updated as well

#write out an updated file
problem.write_problem("foo_update.imcnp")

```

Expand All @@ -62,16 +83,16 @@ Here a few of the known bugs and limitations:


* Cannot handle vertical input mode.
* Does not support tallies in an easy way.
* Does not support source definition in an easy way.
* Does not support editing tallies in a user-friendly way.
* Does not support editing source definition in a user-friendly way.

## Bugs, Requests and Development

So MontePy doesn't do what you want? Right now development is done with a Just-In-Time development approach, as in features are added JIT for a developer to use them on my current projects.
If there's a feature you want add an issue here with the feature request tag.
If you want to add a feature on your own talk to Micah Gale (but still add the issue).
So MontePy doesn't do what you want?
Add an issue here with the "feature request" tag.
The system is very modular and you should be able to develop it pretty quickly.
Also read the [developer's guide](https://www.montepy.org/developing.html).
Read the [developer's guide](https://www.montepy.org/developing.html) for more details.
If you have any questions feel free to ask [@micahgale](mailto:[email protected]).


# Finally: make objects not regexes!
# Finally: make objects, not regexes!
15 changes: 15 additions & 0 deletions doc/source/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
MontePy Changelog
=================

0.4.0
--------------

**Features Added**

* Write problems to either file paths or streams (file handles) with MCNP_Problem.write_problem() (:issue:`492`).
* When adding a material to problem.materials it will also be added to problem.data_inputs, ensuring it is printed to the file (:pull:`488`).

**Bug Fixes**

* Fixed bug that didn't show metastable states for pretty printing and isotope. Also handled the case that Am-241 metstable states break convention (:issue:`486`).
* Fixed bug where cell modifiers could be made irrelevant by being added after a comment (:issue:`483`).
* Fixed bug where parentheses in cell geometry are not properly exported (:pull:`491`).


0.3.3
--------------

Expand Down
1 change: 1 addition & 0 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
html_logo = "monty.svg"

html_baseurl = "https://www.montepy.org/"
sitemap_url_scheme = "{link}"
html_extra_path = ["robots.txt"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
Expand Down
10 changes: 8 additions & 2 deletions doc/source/developing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,8 @@ SURFACE: 1005, RCC

Writing to File (Format for MCNP Input)
"""""""""""""""""""""""""""""""""""""""
MontePy (via :func:`~montepy.mcnp_problem.MCNP_Problem.write_to_file`) writes
a class to file by calling its :func:`~montepy.mcnp_object.MCNP_Object.format_for_mcnp_input` method.
MontePy (via :func:`~montepy.mcnp_problem.MCNP_Problem.write_problem`) writes
a class to file path or file handle by calling its :func:`~montepy.mcnp_object.MCNP_Object.format_for_mcnp_input` method.
This must return a list of strings that faithfully represent this objects state, and tries to replicate the user formatting.
Each string in the list represents one line in the MCNP input file to be written.

Expand Down Expand Up @@ -397,6 +397,12 @@ For example the init function for ``Cells``
def __init__(self, cells=None):
super().__init__(montepy.Cell, cells)

Collection: :class:`~montepy.numbered_object_collection.NumberedDataObjectCollection`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is a subclass of :class:`~montepy.numbered_object_collection.NumberedObjectCollection`,
which is designed for :class:`~montepy.data_inputs.data_input.DataInputAbstract` instances.
It is a wrapper that will ensure that all of its items are also in :func:`~montepy.mcnp_problem.MCNP_Problem.data_inputs`.


Numbered Object :class:`~montepy.numbered_mcnp_object.Numbered_MCNP_Object`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
18 changes: 13 additions & 5 deletions doc/source/starting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,13 @@ It will read the specified MCNP input file, and return an MontePy :class:`~monte
Writing a File
--------------

The :class:`~montepy.mcnp_problem.MCNP_Problem` object has the method :func:`~montepy.mcnp_problem.MCNP_Problem.write_to_file`, which writes the problem's current
The :class:`~montepy.mcnp_problem.MCNP_Problem` object has
the method :func:`~montepy.mcnp_problem.MCNP_Problem.write_problem`, which writes the problem's current
state as a valid MCNP input file.

>>> problem.write_to_file("bar.imcnp")
>>> problem.write_problem("bar.imcnp")

The :func:`~montepy.mcnp_problem.MCNP_Problem.write_to_file` method does take an optional argument: ``overwrite``.
The :func:`~montepy.mcnp_problem.MCNP_Problem.write_problem` method does take an optional argument: ``overwrite``.
By default if the file exists, it will not be overwritten and an error will be raised.
This can be changed by ``overwrite=True``.

Expand All @@ -97,8 +98,15 @@ This can be changed by ``overwrite=True``.
Instead of constantly having to override the same file you can add a timestamp to the output file,
or create an always unique file name with the `UUID <https://docs.python.org/3/library/uuid.html>`_ library.

The method :func:`~montepy.mcnp_problem.MCNP_Problem.write_problem`
also accepts an open file handle, stream, or other object with a ``write()`` method.

If no changes are made to the problem in MontePy the entire file will be just parroted out as it was in the original file.
>>> with open("/path/to/file", "w") as fh:
... problem.write_problem(fh)


If no changes are made to the problem in MontePy, the entire file should just be parroted out as it was in the original file
(see Issues :issue:`397` and :issue:`492`).
However any objects (e.g., two cells) that were changed (i.e., mutated) may have their formatting changed slightly.
MontePy will do its best to guess the formatting of the original value and to replicate it with the new value.
However, this may not always be possible, especially if more digits are needed to keep information (e.g., ``10`` versus ``1000``).
Expand Down Expand Up @@ -127,7 +135,7 @@ We can then open this file in MontePy, and then modify it slightly, and save it
problem = montepy.read_input("foo.imcnp")
problem.cells[1].number = 5
problem.surfaces[1].number = 1000
problem.write_to_file("bar.imcnp")
problem.write_problem("bar.imcnp")

This new file we can see is now reformatted according to MontePy's preferences for formatting::

Expand Down
1 change: 1 addition & 0 deletions montepy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from montepy.particle import Particle
from montepy.surfaces.surface_type import SurfaceType
from montepy.universe import Universe
import montepy.errors
import sys


Expand Down
8 changes: 7 additions & 1 deletion montepy/cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,7 @@ def format_for_mcnp_input(self, mcnp_version):
"""
self.validate()
self._update_values()
self._tree.check_for_graveyard_comments()
modifier_keywords = {
cls._class_prefix(): cls for cls in self._INPUTS_TO_PROPERTY.keys()
}
Expand All @@ -694,6 +695,7 @@ def cleanup_last_line(ret):
ret += node.format()
else:
printed_importance = False
final_param = next(reversed(node.nodes.values()))
for param in node.nodes.values():
if param["classifier"].prefix.value.lower() in modifier_keywords:
cls = modifier_keywords[
Expand All @@ -707,10 +709,14 @@ def cleanup_last_line(ret):
# add trailing space to comment if necessary
ret = cleanup_last_line(ret)
ret += "\n".join(
getattr(self, attr).format_for_mcnp_input(mcnp_version)
getattr(self, attr).format_for_mcnp_input(
mcnp_version, param is not final_param
)
)
else:
# add trailing space to comment if necessary
ret = cleanup_last_line(ret)
ret += param.format()
# check for accidental empty lines from subsequent cell modifiers that didn't print
ret = "\n".join([l for l in ret.splitlines() if l.strip()])
return self.wrap_string_for_mcnp(ret, mcnp_version, True)
3 changes: 2 additions & 1 deletion montepy/data_inputs/cell_modifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def _format_tree(self):
"""
return self._tree.format()

def format_for_mcnp_input(self, mcnp_version):
def format_for_mcnp_input(self, mcnp_version, has_following=False):
"""
Creates a string representation of this MCNP_Object that can be
written to file.
Expand All @@ -241,6 +241,7 @@ def format_for_mcnp_input(self, mcnp_version):
:rtype: list
"""
self.validate()
self._tree.check_for_graveyard_comments(has_following)
if not self._problem:
print_in_data_block = not self.in_cell_block
else:
Expand Down
18 changes: 16 additions & 2 deletions montepy/data_inputs/isotope.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class Isotope:

# Cl-52 Br-101 Xe-150 Os-203 Cm-251 Og-296
_BOUNDING_CURVE = [(17, 52), (35, 101), (54, 150), (76, 203), (96, 251), (118, 296)]
_STUPID_MAP = {
"95642": {"_is_metastable": False, "_meta_state": None},
"95242": {"_is_metastable": True, "_meta_state": 1},
}
"""
Points on bounding curve for determining if "valid" isotope
"""
Expand All @@ -38,6 +42,14 @@ def __init__(self, ZAID="", node=None):
self._library = ""
if node is None:
self._tree = ValueNode(self.mcnp_str(), str, PaddingNode(" "))
self._handle_stupid_legacy_stupidity()

def _handle_stupid_legacy_stupidity(self):
# TODO work on this for mat_redesign
if self.ZAID in self._STUPID_MAP:
stupid_overwrite = self._STUPID_MAP[self.ZAID]
for key, value in stupid_overwrite.items():
setattr(self, key, value)

def __parse_zaid(self):
"""
Expand Down Expand Up @@ -183,8 +195,9 @@ def mcnp_str(self):
return f"{self.ZAID}.{self.library}" if self.library else self.ZAID

def nuclide_str(self):
meta_suffix = f"m{self.meta_state}" if self.is_metastable else ""
suffix = f".{self._library}" if self._library else ""
return f"{self.element.symbol}-{self.A}{suffix}"
return f"{self.element.symbol}-{self.A}{meta_suffix}{suffix}"

def get_base_zaid(self):
"""
Expand All @@ -198,8 +211,9 @@ def get_base_zaid(self):
return self.Z * 1000 + self.A

def __str__(self):
meta_suffix = f"m{self.meta_state}" if self.is_metastable else ""
suffix = f" ({self._library})" if self._library else ""
return f"{self.element.symbol:>2}-{self.A:<3}{suffix}"
return f"{self.element.symbol:>2}-{self.A:<3}{meta_suffix:<2}{suffix}"

def __hash__(self):
return hash(self._ZAID)
Expand Down
6 changes: 5 additions & 1 deletion montepy/geometry_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ class Operator(Enum):
"""
Internal operator essentially equivalent to No-op.

This is used to properly handle parentheses while parsing.
This is used to properly handle some leaf nodes.
"""
GROUP = "()"
"""
Grouping operator that represents parentheses.
"""
7 changes: 5 additions & 2 deletions montepy/input_parser/cell_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ def geometry_term(self, p):
else:
ret.padding = p.padding
else:
ret.nodes["end_pad"] = p.padding
if "end_pad" in ret.nodes:
ret.nodes["end_pad"] += p.padding
else:
ret.nodes["end_pad"] = p.padding
return ret

@_("geometry_factor")
Expand Down Expand Up @@ -176,7 +179,7 @@ def geometry_factory(self, p):
if hasattr(p, "padding"):
for node in p.padding.nodes:
nodes["start_pad"].append(node)
return syntax_node.GeometryTree("geom parens", nodes, ">", p.geometry_expr)
return syntax_node.GeometryTree("geom parens", nodes, "()", p.geometry_expr)

# support for fill card weirdness
@_(
Expand Down
Loading