diff --git a/docs/sphinx/source/reference/iotools.rst b/docs/sphinx/source/reference/iotools.rst index 7c2b08104c..8a83af75e6 100644 --- a/docs/sphinx/source/reference/iotools.rst +++ b/docs/sphinx/source/reference/iotools.rst @@ -44,6 +44,8 @@ of sources and file formats relevant to solar energy modeling. iotools.get_acis_mpe iotools.get_acis_station_data iotools.get_acis_available_stations + iotools.read_panond + iotools.parse_panond A :py:class:`~pvlib.location.Location` object may be created from metadata in some files. diff --git a/docs/sphinx/source/whatsnew/v0.10.2.rst b/docs/sphinx/source/whatsnew/v0.10.2.rst index 4b18a7fe9b..287b35c557 100644 --- a/docs/sphinx/source/whatsnew/v0.10.2.rst +++ b/docs/sphinx/source/whatsnew/v0.10.2.rst @@ -11,6 +11,10 @@ Deprecations Enhancements ~~~~~~~~~~~~ +* Added .pan/.ond reader function :py:func:'pvlib.iotools.panond' +* Added .pan/.ond reader function +:py:func:`pvlib.iotools.panond` +(:issue:`1747` ) Bug fixes @@ -31,4 +35,4 @@ Requirements Contributors ~~~~~~~~~~~~ - +* Connor Krening (:ghuser:`ckrening`) \ No newline at end of file diff --git a/pvlib/iotools/__init__.py b/pvlib/iotools/__init__.py index 2074d236b7..fa25a6abb6 100644 --- a/pvlib/iotools/__init__.py +++ b/pvlib/iotools/__init__.py @@ -27,4 +27,7 @@ from pvlib.iotools.acis import get_acis_nrcc # noqa: F401 from pvlib.iotools.acis import get_acis_mpe # noqa: F401 from pvlib.iotools.acis import get_acis_station_data # noqa: F401 -from pvlib.iotools.acis import get_acis_available_stations # noqa: F401 \ No newline at end of file +from pvlib.iotools.acis import get_acis_available_stations # noqa: F401 +from pvlib.iotools.panond import read_panond # noqa: F401 +from pvlib.iotools.panond import parse_panond # noqa: F401 +from pvlib.iotools.acis import get_acis_available_stations # noqa: F401 diff --git a/pvlib/iotools/panond.py b/pvlib/iotools/panond.py index d99e7b5a4d..06ea46d093 100644 --- a/pvlib/iotools/panond.py +++ b/pvlib/iotools/panond.py @@ -5,7 +5,7 @@ import io -def num_type(value): +def _num_type(value): """ Determine if a value is float, int or a string """ @@ -29,9 +29,9 @@ def num_type(value): return value_out -def element_type(element): +def _element_type(element): """ - Determine if an element is a list then pass to num_type() + Determine if an element is a list then pass to _num_type() """ if ',' in element: # Detect a list. # .pan/.ond don't use ',' to indicate 1000. If that changes, @@ -39,12 +39,12 @@ def element_type(element): values = element.split(',') element_out = [] for val in values: # Determine datatype of each value - element_out.append(num_type(val)) + element_out.append(_num_type(val)) return element_out else: - return num_type(element) + return _num_type(element) def parse_panond(fbuf): @@ -63,9 +63,6 @@ def parse_panond(fbuf): file. The value of datatypes are assumed during reading. The value units are the default used by PVsyst. - Raises - ------ - Notes ----- The parser is intended for use with .pan and .ond files that were created @@ -89,32 +86,31 @@ def parse_panond(fbuf): 'level1 = first level key1 = value1 - level2 = second level - key2 = value2' + key2 = value2 + level2 = second level + key3 = value3 + key4 = value4 + key5 = value5' output: - { - level1: first level - key1: value1, - level2:{ - level2: second level, - key2: value2 + level1:{ + level1: first level + key1: value1, + key2: value2, + level2:{ + level2: second level, + key3: value3, + key4: value4 + }, + key5: value5 } - } The parser takes an additional step to infer the datatype present in each value. The .pan/.ond files appear to have intentially left datatype indicators (e.g. floats have '.' decimals). However, there is still the possibility that the datatype applied from this parser is incorrect. In that event the user would need to convert to the desired datatype. - - See Also - -------- - read_panond - - References - ---------- """ comp = {} # Component dict_levels = [comp] @@ -135,7 +131,8 @@ def parse_panond(fbuf): key = line_data[0].strip() # Logical to make sure there is a value to extract if len(line_data) > 1: - value = element_type(line_data[1].strip()) + value = _element_type(line_data[1].strip()) + else: value = None # add a level to the dict. If a key/value pair triggers the new level, @@ -173,21 +170,11 @@ def read_panond(file): file. The value of datatypes are assumed during reading. The value units are the default used by PVsyst. - Raises - ------ - Notes ----- The read_panond function simply converts a file path to a file-like object, passes it to parse-panond, and returns the file content. At time of creation, tested .pan/.ond files used UTF-8 encoding. - - See Also - -------- - parse_panond - - References - ---------- """ with open(file, "r", encoding='utf-8-sig') as file: diff --git a/pvlib/tests/iotools/test_panond.py b/pvlib/tests/iotools/test_panond.py index 48c8d01bba..3e828a8903 100644 --- a/pvlib/tests/iotools/test_panond.py +++ b/pvlib/tests/iotools/test_panond.py @@ -160,12 +160,12 @@ def test_read_ond_file(): """ f_obj = io.StringIO(fn_str) ond_str = parse_panond(f_obj) - assert ond_file.keys() == ond_str.keys() + assert ond_file['PVObject_'].keys() == ond_str['PVObject_'].keys() def test_read_pan_file(): fn_file = DATA_DIR / 'ET-M772BH550GL.PAN' - ond_file = read_panond(fn_file) + pan_file = read_panond(fn_file) # expected fn_str = """PVObject_=pvModule Version=7.2 @@ -244,5 +244,5 @@ def test_read_pan_file(): End of PVObject pvModule """ f_obj = io.StringIO(fn_str) - ond_str = parse_panond(f_obj) - assert ond_file.keys() == ond_str.keys() + pan_str = parse_panond(f_obj) + assert pan_file['PVObject_'].keys() == pan_str['PVObject_'].keys()