From 28d40c0e114a2ae8621744f22dcafc705326dad1 Mon Sep 17 00:00:00 2001 From: cdeline Date: Thu, 5 Sep 2024 17:02:56 -0600 Subject: [PATCH] Make a nice __repr__ for MetObj class. fixes #471. --- bifacial_radiance/main.py | 40 +++++++++++++++++++++++++++++---- bifacial_radiance/module.py | 3 ++- tests/test_bifacial_radiance.py | 4 ++-- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/bifacial_radiance/main.py b/bifacial_radiance/main.py index 81949ea7..d6a44a78 100644 --- a/bifacial_radiance/main.py +++ b/bifacial_radiance/main.py @@ -328,7 +328,6 @@ class SuperClass: def __repr__(self): return str({key: self.__dict__[key] for key in self.columns}) #return str(self.__dict__) - @property def columns(self): return [attr for attr in dir(self) if not (attr.startswith('_') or attr.startswith('methods') @@ -2833,7 +2832,7 @@ def _makeGroundString(self, index=0, cumulativesky=False): -class SceneObj: +class SceneObj(SuperClass): ''' Scene information including PV module type, bifaciality, array info pv module orientation defaults: Azimuth = 180 (south) @@ -2855,7 +2854,7 @@ class SceneObj: ''' def __repr__(self): - return str(self.__dict__) + return 'SceneObj:\n'+str({key: self.__dict__[key] for key in self.columns}) def __init__(self, module=None, name=None): ''' initialize SceneObj ''' @@ -3155,6 +3154,28 @@ class MetObj(SuperClass): SAM and PVSyst use left-labeled interval data and NSRDB uses centered. """ + @property + def tmydata(self): + keys = ['ghi', 'dhi', 'dni', 'albedo', 'dewpoint', 'pressure', + 'temp_air', 'wind_speed', 'meastracker_angle', 'tracker_theta', + 'surface_tilt', 'surface_azimuth'] + return pd.DataFrame({key:self.__dict__.get(key, None) for key in keys }, + index = self.__dict__['datetime']).dropna(axis=1) + + @property + def metadata(self): + keys = ['latitude', 'longitude', 'elevation', 'timezone', 'city', 'label', + 'timezone'] + return {key:self.__dict__.get(key, None) for key in keys} + + def __repr__(self): + # return metadata and tmydata stats... + import io + buf = io.StringIO() + self.tmydata.info(memory_usage=False, buf=buf) + tmyinfo = buf.getvalue() + buf.close() + return f'\nMetObj.metadata:\n {self.metadata}\nMetObj.tmydata:\n {tmyinfo}\n' def __init__(self, tmydata, metadata, label = 'right'): @@ -3595,7 +3616,18 @@ class AnalysisObj(SuperClass): Analysis class for performing raytrace to obtain irradiance measurements at the array, as well plotting and reporting results. """ - + def __printval__(self, attr): + try: + t = type(getattr(self,attr, None)[0]) + except TypeError: + t = None + if t is float: + return np.array(getattr(self,attr)).round(3).tolist() + else: + return getattr(self,attr) + + def __repr__(self): + return 'AnalysisObj:\n' + str({key: self.__printval__(key) for key in self.columns}) def __init__(self, octfile=None, name=None, hpc=False): """ Initialize AnalysisObj by pointing to the octfile. Scan information diff --git a/bifacial_radiance/module.py b/bifacial_radiance/module.py index fc615a18..2504ff99 100644 --- a/bifacial_radiance/module.py +++ b/bifacial_radiance/module.py @@ -27,7 +27,8 @@ class ModuleObj(SuperClass): Pass this object into makeScene or makeScene1axis. """ - + def __repr__(self): + return 'ModuleObj:\n' + str(self.getDataDict()) def __init__(self, name=None, x=None, y=None, z=None, bifi=1, modulefile=None, text=None, customtext='', xgap=0.01, ygap=0.0, zgap=0.1, numpanels=1, rewriteModulefile=True, cellModule=None, diff --git a/tests/test_bifacial_radiance.py b/tests/test_bifacial_radiance.py index 2bad7492..0b114fd0 100644 --- a/tests/test_bifacial_radiance.py +++ b/tests/test_bifacial_radiance.py @@ -48,7 +48,7 @@ def test_RadianceObj_set1axis(): # test set1axis. requires metdata for boulder. name = "_test_set1axis" demo = bifacial_radiance.RadianceObj(name) - assert str(demo)[-16:-2]==name #this depends on the insertion order of the dictionary repr of demo - may not be consistent + assert len(str(demo)) > 300 # Make sure something is printed out here for demo.__repr__ #try: # epwfile = demo.getEPW(lat=40.01667, lon=-105.25) # From EPW: {N 40° 1'} {W 105° 15'} #except: # adding an except in case the internet connection in the lab forbids the epw donwload. @@ -322,7 +322,7 @@ def test_AnalysisObj_linePtsMake3D(): linepts = analysis._linePtsMake3D(0,0,0,1,1,1,0,0,0,1,2,3,'0 1 0') assert linepts == '0 0 0 0 1 0 \r1 1 1 0 1 0 \r0 0 0 0 1 0 \r1 1 1 0 1 0 \r0 0 0 0 1 0 \r1 1 1 0 1 0 \r' # v2.5.0 new linepts because now x and z also increase not only y. #assert linepts == '0 0 0 0 1 0 \r0 1 0 0 1 0 \r0 0 1 0 1 0 \r0 1 1 0 1 0 \r0 0 2 0 1 0 \r0 1 2 0 1 0 \r' - assert str(analysis)[12:16]=='None' + assert str(analysis)[-5:-1]=='None' # this depends on the order of the dict. but generally aligns with 'octfile' in alphabetical order.. def test_gendaylit2manual():