Skip to content

Commit 209376e

Browse files
authored
ModelChainResult.__repr__ (#1236)
* initial __repr__ for ModelChainResult * fix timezone handling * working on it * working now * jettison that space * whatsnew * inline comments * shorten it up * test, add ModelChain.__repr__ test also * remove unneeded decorator
1 parent 14041cc commit 209376e

File tree

3 files changed

+92
-11
lines changed

3 files changed

+92
-11
lines changed

docs/sphinx/source/whatsnew/v0.10.0.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Enhancements
3131
~~~~~~~~~~~~
3232
* Added `map_variables` parameter to :py:func:`pvlib.iotools.read_srml`
3333
and :py:func:`pvlib.iotools.read_srml_month_from_solardat` (:pull:`1773`)
34+
* Improved `ModelChainResult.__repr__` (:pull:`1236`)
35+
3436

3537
Bug fixes
3638
~~~~~~~~~
@@ -55,3 +57,5 @@ Contributors
5557
~~~~~~~~~~~~
5658
* Taos Transue (:ghuser:`reepoi`)
5759
* Adam R. Jensen (:ghuser:`AdamRJensen`)
60+
* Cliff Hansen (:ghuser:`cwhanse`)
61+

pvlib/modelchain.py

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,33 @@ def get_orientation(strategy, **kwargs):
253253
return surface_tilt, surface_azimuth
254254

255255

256+
def _getmcattr(self, attr):
257+
"""
258+
Helper for __repr__ methods, needed to avoid recursion in property
259+
lookups
260+
"""
261+
out = getattr(self, attr)
262+
try:
263+
out = out.__name__
264+
except AttributeError:
265+
pass
266+
return out
267+
268+
269+
def _mcr_repr(obj):
270+
'''
271+
Helper for ModelChainResult.__repr__
272+
'''
273+
if isinstance(obj, tuple):
274+
return "Tuple (" + ", ".join([_mcr_repr(o) for o in obj]) + ")"
275+
if isinstance(obj, pd.DataFrame):
276+
return "DataFrame ({} rows x {} columns)".format(*obj.shape)
277+
if isinstance(obj, pd.Series):
278+
return "Series (length {})".format(len(obj))
279+
# scalar, None, other?
280+
return repr(obj)
281+
282+
256283
# Type for fields that vary between arrays
257284
T = TypeVar('T')
258285

@@ -384,6 +411,33 @@ def __setattr__(self, key, value):
384411
value = self._result_type(value)
385412
super().__setattr__(key, value)
386413

414+
def __repr__(self):
415+
mc_attrs = dir(self)
416+
417+
def _head(obj):
418+
try:
419+
return obj[:3]
420+
except:
421+
return obj
422+
423+
if type(self.dc) is tuple:
424+
num_arrays = len(self.dc)
425+
else:
426+
num_arrays = 1
427+
428+
desc1 = ('=== ModelChainResult === \n')
429+
desc2 = (f'Number of Arrays: {num_arrays} \n')
430+
attr = 'times'
431+
desc3 = ('times (first 3)\n' +
432+
f'{_head(_getmcattr(self, attr))}' +
433+
'\n')
434+
lines = []
435+
for attr in mc_attrs:
436+
if not (attr.startswith('_') or attr=='times'):
437+
lines.append(f' {attr}: ' + _mcr_repr(getattr(self, attr)))
438+
desc4 = '\n'.join(lines)
439+
return (desc1 + desc2 + desc3 + desc4)
440+
387441

388442
class ModelChain:
389443
"""
@@ -650,18 +704,8 @@ def __repr__(self):
650704
'airmass_model', 'dc_model', 'ac_model', 'aoi_model',
651705
'spectral_model', 'temperature_model', 'losses_model'
652706
]
653-
654-
def getmcattr(self, attr):
655-
"""needed to avoid recursion in property lookups"""
656-
out = getattr(self, attr)
657-
try:
658-
out = out.__name__
659-
except AttributeError:
660-
pass
661-
return out
662-
663707
return ('ModelChain: \n ' + '\n '.join(
664-
f'{attr}: {getmcattr(self, attr)}' for attr in attrs))
708+
f'{attr}: {_getmcattr(self, attr)}' for attr in attrs))
665709

666710
@property
667711
def dc_model(self):

pvlib/tests/test_modelchain.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,3 +1987,36 @@ def test__irrad_for_celltemp():
19871987
assert len(poa) == 2
19881988
assert_series_equal(poa[0], effect_irrad)
19891989
assert_series_equal(poa[1], effect_irrad)
1990+
1991+
1992+
def test_ModelChain___repr__(sapm_dc_snl_ac_system, location):
1993+
1994+
mc = ModelChain(sapm_dc_snl_ac_system, location,
1995+
name='my mc')
1996+
1997+
expected = '\n'.join([
1998+
'ModelChain: ',
1999+
' name: my mc',
2000+
' clearsky_model: ineichen',
2001+
' transposition_model: haydavies',
2002+
' solar_position_method: nrel_numpy',
2003+
' airmass_model: kastenyoung1989',
2004+
' dc_model: sapm',
2005+
' ac_model: sandia_inverter',
2006+
' aoi_model: sapm_aoi_loss',
2007+
' spectral_model: sapm_spectral_loss',
2008+
' temperature_model: sapm_temp',
2009+
' losses_model: no_extra_losses'
2010+
])
2011+
2012+
assert mc.__repr__() == expected
2013+
2014+
2015+
def test_ModelChainResult___repr__(sapm_dc_snl_ac_system, location, weather):
2016+
mc = ModelChain(sapm_dc_snl_ac_system, location)
2017+
mc.run_model(weather)
2018+
mcres = mc.results.__repr__()
2019+
mc_attrs = dir(mc.results)
2020+
mc_attrs = [a for a in mc_attrs if not a.startswith('_')]
2021+
assert all([a in mcres for a in mc_attrs])
2022+

0 commit comments

Comments
 (0)