Skip to content

Commit a93fdd8

Browse files
committed
outp: refactored output
1 parent 167768f commit a93fdd8

21 files changed

Lines changed: 2523 additions & 753 deletions

src/pymcnp/Outp.py

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import re
12
import typing
23

4+
import pandas
5+
6+
from . import outp
37
from .utils import types
48
from .utils import errors
59
from .utils import _object
@@ -10,27 +14,50 @@ class Outp(_object.McnpFile):
1014
Represents OUTP files.
1115
1216
Attributes:
13-
lines: OUTP lines.
17+
header: OUPT header.
18+
blocks: OUTP tables.
19+
footer: OUTP footer.
1420
"""
1521

16-
def __init__(self, lines: types.Tuple[types.String]):
22+
_REGEX = re.compile(
23+
rf'({outp.Header._REGEX.pattern[2:-2]})'
24+
r'([\s\S]*)'
25+
rf'({outp.Footer._REGEX.pattern[2:-2]})'
26+
)
27+
28+
def __init__(
29+
self,
30+
header: outp.Header,
31+
blocks: types.Tuple[outp.Block],
32+
footer: outp.Footer,
33+
):
1734
"""
1835
Initializes ``Outp``.
1936
2037
Parameters:
21-
lines: OUTP lines.
38+
header: OUPT header.
39+
blocks: OUTP tables.
40+
footer: OUTP footer.
2241
2342
Raises:
24-
OutpError: SEMANTICS_OUTP.
43+
OutpError: SEMANTICS_TABLE.
2544
"""
2645

27-
if lines is None or None in lines:
28-
raise errors.OutpError(errors.OutpCode.SEMANTICS_OUTP, lines)
46+
if header is None:
47+
raise errors.OutpError(errors.OutpCode.SEMANTICS_TABLE, header)
48+
49+
if blocks is None or None in blocks:
50+
raise errors.OutpError(errors.OutpCode.SEMANTICS_TABLE, blocks)
2951

30-
self.lines: typing.Final[types.Tuple[types.String]] = lines
52+
if footer is None:
53+
raise errors.OutpError(errors.OutpCode.SEMANTICS_TABLE, footer)
3154

32-
@classmethod
33-
def from_mcnp(cls, source: str):
55+
self.header: typing.Final[outp.Header] = header
56+
self.blocks: typing.Final[types.Tuple[outp.Block]] = blocks
57+
self.footer: typing.Final[outp.Footer] = footer
58+
59+
@staticmethod
60+
def from_mcnp(source: str):
3461
"""
3562
Generates ``Outp`` from OUTP.
3663
@@ -41,9 +68,38 @@ def from_mcnp(cls, source: str):
4168
``Outp``.
4269
"""
4370

44-
lines = types.Tuple(map(lambda line: types.String(line), source.split('\n')))
71+
tokens = Outp._REGEX.match(source)
72+
73+
if not tokens:
74+
raise errors.OutpError(errors.OutpCode.SYNTAX_TABLE, source)
75+
76+
offset = 0
77+
header = outp.Header.from_mcnp(tokens[1 + offset])
78+
offset += outp.Header._REGEX.groups
79+
80+
blocks = []
81+
for subsource in outp.Block._REGEX.finditer(tokens[2 + offset]):
82+
for subclass in outp.Block.__subclasses__():
83+
try:
84+
if block := subclass.from_mcnp(subsource[0]):
85+
break
86+
else:
87+
continue
88+
except Exception:
89+
continue
90+
else:
91+
raise errors.OutpError(errors.OutpCode.SYNTAX_TABLE, source)
92+
93+
blocks.append(block)
4594

46-
return cls(lines)
95+
blocks = types.Tuple(blocks)
96+
footer = outp.Footer.from_mcnp(tokens[3 + offset])
97+
98+
return Outp(
99+
header,
100+
blocks,
101+
footer,
102+
)
47103

48104
def to_mcnp(self):
49105
"""
@@ -53,4 +109,32 @@ def to_mcnp(self):
53109
OUTP for ``Outp``.
54110
"""
55111

56-
return '\n'.join(line for line in self.lines)
112+
return f"{self.header}\n{"\n".join(map(str, self.blocks))}{self.footer}"
113+
114+
def to_dataframe(self):
115+
"""
116+
Generates ``pandas.DataFrame`` from ``Outp``.
117+
118+
Returns:
119+
Tuple of ``pandas.DataFrame``.
120+
"""
121+
122+
tallynps1 = {}
123+
tallynps2 = {}
124+
tallynps4 = {}
125+
126+
for block in self.blocks:
127+
if isinstance(block, outp.TallyNps1):
128+
tallynps1[block.tally] = block
129+
elif isinstance(block, outp.TallyNps2):
130+
tallynps2[block.tally] = block
131+
elif isinstance(block, outp.TallyNps4):
132+
tallynps4[block.tally] = block
133+
else:
134+
continue
135+
136+
return (
137+
pandas.DataFrame(tallynps1),
138+
pandas.DataFrame(tallynps2),
139+
pandas.DataFrame(tallynps4),
140+
)

0 commit comments

Comments
 (0)