Skip to content

Panond 2 #9

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

Merged
merged 19 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions docs/sphinx/source/reference/iotools.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion docs/sphinx/source/whatsnew/v0.10.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -31,4 +35,4 @@ Requirements

Contributors
~~~~~~~~~~~~

* Connor Krening (:ghuser:`ckrening`)
5 changes: 4 additions & 1 deletion pvlib/iotools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
57 changes: 22 additions & 35 deletions pvlib/iotools/panond.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import io


def num_type(value):
def _num_type(value):
"""
Determine if a value is float, int or a string
"""
Expand All @@ -29,22 +29,22 @@ 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,
# a new method of list detection needs to be found.
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):
Expand All @@ -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
Expand All @@ -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]
Expand All @@ -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,
Expand Down Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions pvlib/tests/iotools/test_panond.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()