diff --git a/pypact/__init__.py b/pypact/__init__.py index ebb110f..a813cd5 100644 --- a/pypact/__init__.py +++ b/pypact/__init__.py @@ -62,7 +62,3 @@ # utilities from pypact.util.exceptions import PypactException from pypact.util.loglevels import * - - -# This makes importing slow, keep it seperate -#import pypact.analysis diff --git a/pypact/input/filesfile.py b/pypact/input/filesfile.py index 589cefb..cef874d 100644 --- a/pypact/input/filesfile.py +++ b/pypact/input/filesfile.py @@ -2,9 +2,21 @@ from pypact.util.decorators import freeze_it from pypact.util.jsonserializable import JSONSerializable -from pypact.util.exceptions import PypactDeserializeException +from pypact.util.exceptions import PypactDeserializeException, PypactException from pypact.util.file import file_exists, dir_exists -from pypact.library.projectiles import * +from pypact.library.projectiles import ( + PROJECTILE_NEUTRON, + PROJECTILE_DEUTERON, + PROJECTILE_PROTON, + PROJECTILE_ALPHA, + PROJECTILE_GAMMA, + VALID_PROJECTILES, + VALID_PROJECTILE_NAMES, + VALID_PROJECTILE_SYMBOLS, + get_projectile_name, + get_projectile_symbol, + get_projectile_value +) # represents a null entry string NULL_ENTRY = "null" diff --git a/pypact/input/inputdata.py b/pypact/input/inputdata.py index 9a7ba58..1d0422c 100644 --- a/pypact/input/inputdata.py +++ b/pypact/input/inputdata.py @@ -4,8 +4,16 @@ from pypact.util.exceptions import PypactOutOfRangeException from pypact.util.exceptions import PypactInvalidOptionException from pypact.util.exceptions import PypactIncompatibleOptionException +from pypact.util.exceptions import PypactUnphysicalValueException from pypact.util.jsonserializable import JSONSerializable -from pypact.util.loglevels import * +from pypact.util.loglevels import ( + LOG_SEVERITY_FATAL, + LOG_SEVERITY_ERROR, + LOG_SEVERITY_WARNING, + LOG_SEVERITY_INFO, + LOG_SEVERITY_DEBUG, + LOG_SEVERITY_TRACE +) from pypact.library.projectiles import PROJECTILE_NEUTRON, VALID_PROJECTILES from pypact.input.keywords import CONTROL_KEYWORDS, INIT_KEYWORDS, INVENTORY_KEYWORDS diff --git a/pypact/library/reactionlib.py b/pypact/library/reactionlib.py index 0741e03..c6c263d 100644 --- a/pypact/library/reactionlib.py +++ b/pypact/library/reactionlib.py @@ -1,4 +1,4 @@ -from .projectiles import * +from .projectiles import PROJECTILE_NEUTRON, get_projectile_symbol REACTION_DICTIONARY = { 1: 'total', diff --git a/pypact/output/nuclide.py b/pypact/output/nuclide.py index c3ea979..8846e46 100644 --- a/pypact/output/nuclide.py +++ b/pypact/output/nuclide.py @@ -5,6 +5,10 @@ NUCLIDE_IGNORES = ['\n', '|', '>', '&', '?', '#'] +# Constants for parsing nuclide identifiers +ELEMENT_SYMBOL_LENGTH = 2 +ISOTOPE_NUMBER_LENGTH = 3 + @freeze_it class Nuclide(JSONSerializable): @@ -30,10 +34,12 @@ def __init__(self): @property def name(self): + """Returns the nuclide name as a string (e.g., 'Fe56', 'Co60m').""" return f"{self.element}{self.isotope}{self.state}" @property def zai(self): + """Returns the ZAI (Z*10000 + A*10 + I) identifier for this nuclide.""" return get_zai(self.name) def fispact_deserialize(self, linedump, column_headers): @@ -49,11 +55,11 @@ def fispact_deserialize(self, linedump, column_headers): # turn the line into a list strings = line.split() - # first 2 characters are the symbol - # next 3 characters are the symbol - # last character is the symbol - symbollength = 2 - isotopelength = 3 + # first 2 characters are the element symbol + # next 3 characters are the isotope number + # last character (if alpha) is the state + symbollength = ELEMENT_SYMBOL_LENGTH + isotopelength = ISOTOPE_NUMBER_LENGTH if len(strings[0]) > symbollength: isotope = strings[0][symbollength:] strings[0] = strings[0][:symbollength] @@ -98,6 +104,13 @@ def get_entry(header_name): def index_containing_substring(the_list, substring): + """ + Find the index of the first list element containing a substring. + + :param the_list: List of strings to search + :param substring: Substring to find + :return: Index of first matching element, or -1 if not found + """ for i, s in enumerate(the_list): if substring in s: return i diff --git a/pypact/util/file.py b/pypact/util/file.py index 17b94a8..673c0e4 100644 --- a/pypact/util/file.py +++ b/pypact/util/file.py @@ -1,42 +1,46 @@ import os.path +from typing import List -# Returns the content of the file as a string -def content_as_str(filename): +def content_as_str(filename: str) -> List[str]: + """Returns the content of the file as a list of strings (one per line).""" with open(filename, 'r') as file: data = file.readlines() return data -# Returns the content of the file as a string, and removes new lines. -def content_as_str_noreturn(filename): +def content_as_str_noreturn(filename: str) -> str: + """Returns the content of the file as a string, and removes new lines.""" with open(filename, 'r') as file: data = file.read().replace('\n', '') return data -# checks if file exists -def file_exists(filename): +def file_exists(filename: str) -> bool: + """Checks if file exists.""" return os.path.isfile(filename) -# checks if directory exists -def dir_exists(filename): +def dir_exists(filename: str) -> bool: + """Checks if directory exists.""" return os.path.isdir(filename) -def file_remove(filename): +def file_remove(filename: str) -> None: + """Removes file if it exists.""" if file_exists(filename): os.remove(filename) -def get_filename_ext(filename): +def get_filename_ext(filename: str) -> str: + """Gets the file extension from filename.""" return os.path.basename(os.path.splitext(filename)[-1]) -def str_in_file(filename, string): +def str_in_file(filename: str, string: str) -> bool: + """Checks if a string exists in the file.""" if file_exists(filename): with open(filename) as file: return string in file.read() @@ -44,9 +48,13 @@ def str_in_file(filename, string): return False -# note that regardless of the flag 'ignore_empty_lines' value, -# the last line is always ignored -def nr_of_lines(filename, ignore_empty_lines=False): +def nr_of_lines(filename: str, ignore_empty_lines: bool = False) -> int: + """ + Returns the number of lines in a file. + + Note that regardless of the flag 'ignore_empty_lines' value, + the last line is always ignored. + """ with open(filename) as file: if ignore_empty_lines: return len([i for i in file if i[:-1]]) diff --git a/pypact/util/lines.py b/pypact/util/lines.py index 8433c01..c28262d 100644 --- a/pypact/util/lines.py +++ b/pypact/util/lines.py @@ -1,7 +1,8 @@ +from typing import List, Tuple, Optional from pypact.util.numerical import is_float, get_float -def line_indices(lines, tag): +def line_indices(lines: List[str], tag: str) -> List[int]: """ :param lines: Must be a list of strings representing each line @@ -12,7 +13,7 @@ def line_indices(lines, tag): return [l for l in range(len(lines)) if tag in lines[l]] -def strings_from_line(line, linetag, ignoretags=[], endtag=''): +def strings_from_line(line: str, linetag: str, ignoretags: Optional[List[str]] = None, endtag: str = '') -> List[str]: """ :param line: The string representing a line @@ -22,6 +23,9 @@ def strings_from_line(line, linetag, ignoretags=[], endtag=''): :return: A list of strings, without spaces or carriage returns, of string after the linetag """ + if ignoretags is None: + ignoretags = [] + startindex = line.find(linetag) if startindex < 0: return [] @@ -42,7 +46,7 @@ def strings_from_line(line, linetag, ignoretags=[], endtag=''): return strings -def join_strings_from_line(line, linetag, ignoretags=[], endtag=''): +def join_strings_from_line(line: str, linetag: str, ignoretags: Optional[List[str]] = None, endtag: str = '') -> str: """ :param line: The string representing a line @@ -57,13 +61,13 @@ def join_strings_from_line(line, linetag, ignoretags=[], endtag=''): return ' '.join(strings) -def first_value_from_line(line, linetag, ignoretags=[]): +def first_value_from_line(line: str, linetag: str, ignoretags: Optional[List[str]] = None) -> float: """ :param line: The string representing a line :param linetag: The tag to find in the line :param ignoretags: The list of strings to ignore - :return: The first value, float, after the tag. Returns NaN if no value found. + :return: The first value, float, after the tag. Returns 0.0 if no value found. """ strings = strings_from_line(line, linetag, ignoretags) @@ -81,7 +85,7 @@ def first_value_from_line(line, linetag, ignoretags=[]): return nan -def first_occurrence(lines, tag): +def first_occurrence(lines: List[str], tag: str) -> Tuple[int, str]: """ :param lines: A list of strings representing each line @@ -92,7 +96,7 @@ def first_occurrence(lines, tag): return next_occurrence(lines, tag, 0) -def last_occurrence(lines, tag): +def last_occurrence(lines: List[str], tag: str) -> Tuple[int, str]: """ :param lines: A list of strings representing each line @@ -109,7 +113,7 @@ def last_occurrence(lines, tag): return -1, '' -def next_occurrence(lines, tag, startindex=0): +def next_occurrence(lines: List[str], tag: str, startindex: int = 0) -> Tuple[int, str]: """ :param lines: A list of strings representing each line diff --git a/pypact/util/numerical.py b/pypact/util/numerical.py index 44d1641..48673e1 100644 --- a/pypact/util/numerical.py +++ b/pypact/util/numerical.py @@ -1,6 +1,8 @@ +from typing import Union, Callable + nan = float('NaN') -def are_values_the_same(value1, value2, rel_tol, abs_tol=0.0): +def are_values_the_same(value1: float, value2: float, rel_tol: float, abs_tol: float = 0.0) -> bool: """ Use math.isclose algorithm, it is better than numpy.isclose method. See https://github.com/numpy/numpy/issues/10161 for more on the discussion @@ -9,7 +11,7 @@ def are_values_the_same(value1, value2, rel_tol, abs_tol=0.0): return abs(value1 - value2) <= max(rel_tol * max(abs(value1), abs(value2)), abs_tol) -def get_float(value): +def get_float(value: Union[str, int, float]) -> Union[float, str]: """ Gets the floating point value from a string Will allow for fortran style floats, i.e -2.34321-308 @@ -21,7 +23,7 @@ def get_float(value): return _getfortranfloat(value) -def _istradiationalfloat(value): +def _istradiationalfloat(value: Union[str, int, float]) -> bool: """ Checks if the string can be converted to a floating point value Does not allow for fortran style floats, i.e -2.34321-308 @@ -33,7 +35,7 @@ def _istradiationalfloat(value): except ValueError: return False -def is_float(value): +def is_float(value: Union[str, int, float]) -> bool: """ Checks if the string can be converted to a floating point value Will allow for fortran style floats, i.e -2.34321-308 @@ -43,21 +45,21 @@ def is_float(value): return _istradiationalfloat(value) or _isfortranfloat(value) return False -def _isfortranfloat(value): +def _isfortranfloat(value: Union[str, int, float]) -> bool: passfunc = lambda sign, esign, parts: True failfunc = lambda: False return _fortranfloat(value, passfunc, failfunc) -def _getfortranfloat(value): +def _getfortranfloat(value: Union[str, int, float]) -> Union[float, str]: passfunc = lambda sign, esign, parts: float(sign + parts[0] + 'E' + esign + parts[1]) failfunc = lambda: "nan" return _fortranfloat(value, passfunc, failfunc) -def _fortranfloat(value, passfunc, failfunc): +def _fortranfloat(value: Union[str, int, float], passfunc: Callable, failfunc: Callable) -> Union[bool, float, str]: # could be 2.3 # 2.3e+10 # -2.3e+10 diff --git a/pypact/util/propertyfinder.py b/pypact/util/propertyfinder.py index d238a4c..0449b31 100644 --- a/pypact/util/propertyfinder.py +++ b/pypact/util/propertyfinder.py @@ -1,4 +1,9 @@ -from pypact.util.lines import * +from pypact.util.lines import ( + first_occurrence, + last_occurrence, + join_strings_from_line, + first_value_from_line +) def get(datadump, headertag, starttag, endtag='', findfirst=True, ignores=[], asstring=True):