From 757265b09009906a648842b5ffd2f6aacb93f6e9 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sat, 5 Oct 2024 06:36:40 -0600 Subject: [PATCH 1/7] 0.5.0 deprecation warning in radianceObj.Wm2Front, Wm2Back and load.loadtrackerdict --- bifacial_radiance/TEMP/.gitignore | 4 ---- bifacial_radiance/load.py | 7 ++++++- bifacial_radiance/main.py | 35 +++++++++++++++++++++++-------- 3 files changed, 32 insertions(+), 14 deletions(-) delete mode 100644 bifacial_radiance/TEMP/.gitignore diff --git a/bifacial_radiance/TEMP/.gitignore b/bifacial_radiance/TEMP/.gitignore deleted file mode 100644 index 86d0cb27..00000000 --- a/bifacial_radiance/TEMP/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/bifacial_radiance/load.py b/bifacial_radiance/load.py index 5814bd72..504ceeac 100644 --- a/bifacial_radiance/load.py +++ b/bifacial_radiance/load.py @@ -245,9 +245,14 @@ def loadTrackerDict(trackerdict, fileprefix=None): ``finalkey`` (last index file in directory) """ - + # TODO: get this module working import re, os import numpy as np + + print('Warning: loadTrackerDict has not been updated to the new v0.5.0' +\ + ' dictionary structure and is currently incomplete. Please' +\ + ' reach out at github.com/NREL/bifacial_radiance/issues if' +\ + ' this is functionality you need.\n') # get list of filenames in \results\ filelist = sorted(os.listdir('results')) diff --git a/bifacial_radiance/main.py b/bifacial_radiance/main.py index 6d6b81f2..4d146b92 100644 --- a/bifacial_radiance/main.py +++ b/bifacial_radiance/main.py @@ -60,7 +60,7 @@ import pandas as pd import numpy as np import warnings - +from deprecated import deprecated global DATA_PATH # path to data files including module.json. Global context @@ -374,9 +374,30 @@ def results(self): return getResults(self.trackerdict, self.cumulativesky) + @property + @deprecated(reason='RadianceObj.Wm2Front has been abandoned'+\ + ' Please use values recorded in ' + + ' AnalysisObj.Wm2Front or RadianceObj.results.', + version='0.5.0' + ) + def Wm2Front(self): + return None + + @property + @deprecated(reason='RadianceObj.Wm2Back has been abandoned'+\ + ' Please use values recorded in ' + + ' AnalysisObj.Wm2Back or RadianceObj.results.', + version='0.5.0' + ) + def Wm2Back(self): + return None + + def __repr__(self): #return str(self.__dict__) - return str(type(self)) + ' : ' + str({key: self.__dict__[key] for key in self.columns if (key != 'trackerdict') & (key != 'results') }) + return str(type(self)) + ' : ' + str({key: self.__dict__[key] + for key in self.columns if key not in ('trackerdict', 'results', 'Wm2Front','Wm2Back') }) + def __init__(self, name=None, path=None, hpc=False): ''' initialize RadianceObj with path of Radiance materials and objects, @@ -405,11 +426,6 @@ def __init__(self, name=None, path=None, hpc=False): #self.radfiles = [] # scene rad files for oconv, compiled from self.scenes self.scenes = [] # array of scenefiles to be compiled self.octfile = [] #octfile name for analysis - self.Wm2Front = 0 # cumulative tabulation of front W/m2 - self.Wm2Back = 0 # cumulative tabulation of rear W/m2 - self.backRatio = 0 # ratio of rear / front Wm2 - #self.nMods = None # number of modules per row - #self.nRows = None # number of rows per scene self.hpc = hpc # HPC simulation is being run. Some read/write functions are modified self.compiledResults = pd.DataFrame(None) # DataFrame of cumulative results, output from self.calculatePerformance1axis() @@ -669,6 +685,7 @@ def exportTrackerDict(self, trackerdict=None, # loadtrackerdict not updated to match new trackerdict configuration + @deprecated(version='0.5.0') def loadtrackerdict(self, trackerdict=None, fileprefix=None): """ Use :py:class:`bifacial_radiance.load._loadtrackerdict` @@ -684,8 +701,8 @@ def loadtrackerdict(self, trackerdict=None, fileprefix=None): if trackerdict is None: trackerdict = self.trackerdict (trackerdict, totaldict) = loadTrackerDict(trackerdict, fileprefix) - self.Wm2Front = totaldict['Wm2Front'] - self.Wm2Back = totaldict['Wm2Back'] + #self.Wm2Front = totaldict['Wm2Front'] + #self.Wm2Back = totaldict['Wm2Back'] def returnOctFiles(self): """ From 2ebc9590839a81f80b704c24eb96b7c90814e4a7 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sun, 6 Oct 2024 15:57:54 -0600 Subject: [PATCH 2/7] deprecation warning for deepcleanResult, RadianceObj.Wm2Front and Wm2Back. add TrackerDict class that just warns for TrackerDict[key]['scene']. Fixes #556 --- bifacial_radiance/load.py | 12 ++++++- bifacial_radiance/main.py | 47 ++++++++------------------ bifacial_radiance/mismatch.py | 5 +-- docs/sphinx/source/whatsnew/v0.5.0.rst | 2 ++ tests/test_bifacial_radiance.py | 5 ++- tests/test_load.py | 8 ++++- 6 files changed, 41 insertions(+), 38 deletions(-) diff --git a/bifacial_radiance/load.py b/bifacial_radiance/load.py index 504ceeac..2c18a292 100644 --- a/bifacial_radiance/load.py +++ b/bifacial_radiance/load.py @@ -7,6 +7,8 @@ TEMP folder in bifacial_radiance \\ bifacial_radiance """ +from deprecated import deprecated + ''' DEPRECATED - doesn't work with python3 def load_inputvariablesfile(inputfile): """ @@ -464,7 +466,11 @@ def _exportTrackerDict(trackerdict, savefile, cumulativesky=False, reindex=False D4join.to_csv(savefile4) return - + + +@deprecated(reason='load.deepcleanResult has been abandoned'+\ + ' Please use load.cleanResult instead', + version='0.5.0') def deepcleanResult(resultsDict, sensorsy, numpanels, automatic=True): """ Cleans results file read by read1Result. If automatic = False, user is @@ -473,6 +479,10 @@ def deepcleanResult(resultsDict, sensorsy, numpanels, automatic=True): If you pass in results from a file with only _Front or _Back parameters, only the corresponding Frontresults or Backresults will be returned. + .. deprecated:: 0.5.0 + This cleaning routine is deprecated in favor of :func:`cleanResult` which + is more stable + Parameters ----------- sensorsy : int diff --git a/bifacial_radiance/main.py b/bifacial_radiance/main.py index 4d146b92..9fcc0344 100644 --- a/bifacial_radiance/main.py +++ b/bifacial_radiance/main.py @@ -378,8 +378,7 @@ def results(self): @deprecated(reason='RadianceObj.Wm2Front has been abandoned'+\ ' Please use values recorded in ' + ' AnalysisObj.Wm2Front or RadianceObj.results.', - version='0.5.0' - ) + version='0.5.0' ) def Wm2Front(self): return None @@ -387,8 +386,7 @@ def Wm2Front(self): @deprecated(reason='RadianceObj.Wm2Back has been abandoned'+\ ' Please use values recorded in ' + ' AnalysisObj.Wm2Back or RadianceObj.results.', - version='0.5.0' - ) + version='0.5.0') def Wm2Back(self): return None @@ -746,30 +744,6 @@ def returnMaterialFiles(self, material_path=None): self.materialfiles = materialfilelist return materialfilelist - ''' - def getResults(self, trackerdict=None): #DEPRECATED IN FAVOR OF self.results - """ - Iterate over trackerdict and return irradiance results - following analysis1axis runs - - Parameters - ---------- - trackerdict : dict, optional - trackerdict, after analysis1axis has been run - - Returns - ------- - results : Pandas.DataFrame - dataframe containing irradiance scan results. - - """ - from bifacial_radiance.load import getResults - - if trackerdict is None: - trackerdict = self.trackerdict - - return getResults(trackerdict, self.cumulativesky) - ''' def sceneNames(self, scenes=None): if scenes is None: scenes = self.scenes @@ -2111,7 +2085,7 @@ def gendaylit1axis(self, metdata=None, trackerdict=None, startdate=None, print('Creating ~%d skyfiles. '%(len(trackerdict.keys()))) count = 0 # counter to get number of skyfiles created, just for giggles - trackerdict2={} + trackerdict2=TrackerDict({}) #for i in range(0, len(trackerdict.keys())): for key in trackerdict.keys(): time_target = pd.to_datetime(key, format="%Y-%m-%d_%H%M").tz_localize(int(self.metdata.timezone*3600)) @@ -4190,11 +4164,11 @@ def _set1axis(self, azimuth=180, limit_angle=45, angledelta=None, #times = [str(i)[5:-12].replace('-','_').replace(' ','_') for i in self.datetime] times = [i.strftime('%Y-%m-%d_%H%M') for i in self.datetime] #trackerdict = dict.fromkeys(times) - trackerdict = {} + trackerdict = TrackerDict({}) for i,time in enumerate(times) : # remove NaN tracker theta from trackerdict if (self.ghi[i] > 0) & (~np.isnan(self.tracker_theta[i])): - trackerdict[time] = { + trackerdict[time] = TrackerDict({ 'surf_azm':self.surface_azimuth[i], 'surf_tilt':self.surface_tilt[i], 'theta':self.tracker_theta[i], @@ -4203,7 +4177,7 @@ def _set1axis(self, azimuth=180, limit_angle=45, angledelta=None, 'dhi':self.dhi[i], 'temp_air':self.temp_air[i], 'wind_speed':self.wind_speed[i] - } + }) return trackerdict @@ -4347,7 +4321,7 @@ def _makeTrackerCSV(self, theta_list, trackingdata): trackerdict = dict.fromkeys(theta_list) for theta in sorted(trackerdict): - trackerdict[theta] = {} + trackerdict[theta] = TrackerDict({}) csvfile = os.path.join('EPWs', '1axis_{}.csv'.format(theta)) tempdata = trackingdata[trackingdata['theta_round'] == theta] @@ -5604,3 +5578,10 @@ def quickExample(testfolder=None): return analysis +class TrackerDict(dict): + def __getitem__(self, key): + if key == 'scene': + warnings.warn('Key `scene` deprecated. Please use the new key: `scenes` '+\ + 'which returns a list of SceneObj rather than a single SceneObj', DeprecationWarning) + return super().__getitem__('scenes') + return super().__getitem__(key) diff --git a/bifacial_radiance/mismatch.py b/bifacial_radiance/mismatch.py index 2def94f8..5371b187 100644 --- a/bifacial_radiance/mismatch.py +++ b/bifacial_radiance/mismatch.py @@ -5,7 +5,7 @@ @author: sayala """ -#from load import * +from deprecated import deprecated @@ -300,7 +300,8 @@ def _mad_1D(data): #1D calculation of MAD return _mad_1D(data) - +@deprecated(reason='This analysis script will be moved to its own tutorial' +\ + ' file in a future release.', version='0.5.0') def analysisIrradianceandPowerMismatch(testfolder, writefiletitle, portraitorlandscape, bififactor, numcells=72, downsamplingmethod='byCenter'): r''' Use this when sensorsy calculated with bifacial_radiance > cellsy diff --git a/docs/sphinx/source/whatsnew/v0.5.0.rst b/docs/sphinx/source/whatsnew/v0.5.0.rst index 691efb65..2ed4e8f2 100644 --- a/docs/sphinx/source/whatsnew/v0.5.0.rst +++ b/docs/sphinx/source/whatsnew/v0.5.0.rst @@ -11,10 +11,12 @@ Deprecations * :py:class:`~bifacial_radiance.RadianceObj.makeScene1axis`.`appendtoScene` is deprecated in favor of :py:class:`~bifacial_radiance.makeScene1axis`.`customtext` * `Wm2Front` and `Wm2Back` are no longer attributes of :py:class:`~bifacial_radiance.RadianceObj` object. Results are now tracked in :py:class:`~bifacial_radiance.AnalysisObj.results` and :py:class:`~bifacial_radiance.RadianceObj.results` for trackerDict simulations. + API Changes ~~~~~~~~~~~~ * Final irradiance and performance data are stored in: :py:class:`~bifacial_radiance.AnalysisObj.results` and :py:class:`~bifacial_radiance.RadianceObj.results`. * Results generated with the above can be saved with the :py:class:`~bifacial_radiance.RadianceObj.exportTrackerDict`, which saves an Hourly, Monthly and Yearly .csvs in the results folder. +* `trackerdict['key']['scene']` has been renamed `trackerdict['key']['scenes']` and now returns a list of SceneObjs. * NSRDB weather data can now be loaded using :py:class:`~bifacial_radiance.RadianceObj.NSRDBWeatherData`. * :py:class:`~bifacial_radiance.AnalysisObj.analysis` updated to allow single (front-only) scans in support of AgriPV modeling. Pass `None` to `backscan` for single-sided scan. (:pull:`499`) * :py:class:`~bifacial_radiance.makeScene`.`append` added to allow multiple scenes to be attached to a single RadianceObj. Default: False (over-write the scene). (:pull:`487`) diff --git a/tests/test_bifacial_radiance.py b/tests/test_bifacial_radiance.py index 2fd4c187..7566b125 100644 --- a/tests/test_bifacial_radiance.py +++ b/tests/test_bifacial_radiance.py @@ -156,7 +156,9 @@ def test_Radiance_1axis_gendaylit_modelchains(): #V 0.2.5 fixed the gcr passed to set1axis. (since gcr was not being passd to set1axis, gcr was default 0.33 default). assert(demo2.compiledResults.Gfront_mean[0] == pytest.approx(205.0, 0.01) ) # was 214 in v0.2.3 # was 205 in early v0.2.4 assert(demo2.compiledResults.Grear_mean[0] == pytest.approx(43.0, 0.1) ) - assert demo2.trackerdict['2001-01-01_1100']['scenes'][0].text.__len__() == 134 + # test that trackerdict['scene'] is deprecated + with pytest.warns(DeprecationWarning): + assert demo2.trackerdict['2001-01-01_1100']['scene'][0].text.__len__() == 134 assert demo2.trackerdict['2001-01-01_1100']['scenes'][0].text[23:28] == " 2.0 " demo2.exportTrackerDict(savefile = 'results\exportedTrackerDict.csv', reindex=True) # Run groundscan @@ -165,6 +167,7 @@ def test_Radiance_1axis_gendaylit_modelchains(): assert results_ground.sensorsground == 56 assert results_ground.mattype[0] == 'groundplane' + """ def test_RadianceObj_1axis_gendaylit_end_to_end(): name = "_test_1axis_gendaylit_end_to_end" diff --git a/tests/test_load.py b/tests/test_load.py index b97e9fef..9c71b6d1 100644 --- a/tests/test_load.py +++ b/tests/test_load.py @@ -42,7 +42,13 @@ def test_load_trackerdict(): trackerdict = demo.set1axis(cumulativesky = False) print(trackerdict) demo.loadtrackerdict(trackerdict,fileprefix = 'test_') - assert demo.Wm2Front[0] == pytest.approx(166.3, abs = 0.01) + # test that Wm2Front is deprecated + with pytest.warns(DeprecationWarning): + demo.Wm2Front + with pytest.warns(DeprecationWarning): + demo.Wm2Back + #assert demo.Wm2Front[0] == pytest.approx(166.3, abs = 0.01) + def test_cleanResult(): # example of setting NaN's when the scan intersects undesired material From 350813fb0f56d13368c1eebee02694ff04c8dd21 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sun, 6 Oct 2024 16:00:47 -0600 Subject: [PATCH 3/7] add deprecated module to setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index dc0bdacb..e535195e 100644 --- a/setup.py +++ b/setup.py @@ -101,6 +101,7 @@ 'pyradiance', 'scipy > 1.6.0', 'tqdm', + 'deprecated', ], # List additional groups of dependencies here (e.g. development From 8da06e805441bf150be71b49a7e17663cebe9c57 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sun, 6 Oct 2024 16:08:00 -0600 Subject: [PATCH 4/7] update calculatePerformanceGencumsky to labels Whm2Front and Whm2Back. Fixes #498 --- bifacial_radiance/main.py | 5 +++-- bifacial_radiance/performance.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bifacial_radiance/main.py b/bifacial_radiance/main.py index 9fcc0344..6efd2e90 100644 --- a/bifacial_radiance/main.py +++ b/bifacial_radiance/main.py @@ -3126,7 +3126,7 @@ def _printRow(analysisobj, key): - else: + else: #cumulative analysis if module is None: for key in keys: # loop over trackerdict to find first available module try: @@ -3139,7 +3139,8 @@ def _printRow(analysisobj, key): module_local = module self.compiledResults = performance.calculatePerformanceGencumsky(results=self.results, bifacialityfactor=module_local.bifi, - fillcleanedSensors=False) + fillcleanedSensors=False).rename( + columns={'Wm2Front':'Whm2Front', 'Wm2Back':'Whm2Back'}) self.compiledResults.to_csv(os.path.join('results', 'Cumulative_Results.csv'), float_format='%0.3f', index=False) diff --git a/bifacial_radiance/performance.py b/bifacial_radiance/performance.py index e0a378e9..417c8ff3 100644 --- a/bifacial_radiance/performance.py +++ b/bifacial_radiance/performance.py @@ -453,14 +453,14 @@ def _dict2DF(df, key): dfst = pd.DataFrame(zip(cumRow, cumMod, cumScene, cumFront, cumWM2, cumBack, Grear_mean, POA_eff), columns=('rowNum', 'modNum','sceneNum', 'Gfront_mean', - 'Wm2Front', 'Wm2Back', 'Grear_mean', + 'Whm2Front', 'Whm2Back', 'Grear_mean', 'POA_eff')) dfst['BGG'] = dfst['Grear_mean']*100*bifacialityfactor/dfst['Gfront_mean'] # Reordering columns cols = ['rowNum', 'modNum','sceneNum', 'BGG', 'Gfront_mean', 'Grear_mean', 'POA_eff', - 'Wm2Front','Wm2Back'] + 'Whm2Front','Whm2Back'] dfst = dfst[cols] return dfst From 75c4877750f879b77c7873ab730db248a52f91f5 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sun, 6 Oct 2024 16:19:45 -0600 Subject: [PATCH 5/7] weird path not found errors? --- bifacial_radiance/main.py | 3 +-- tests/test_load.py | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bifacial_radiance/main.py b/bifacial_radiance/main.py index 6efd2e90..25e231d7 100644 --- a/bifacial_radiance/main.py +++ b/bifacial_radiance/main.py @@ -3139,8 +3139,7 @@ def _printRow(analysisobj, key): module_local = module self.compiledResults = performance.calculatePerformanceGencumsky(results=self.results, bifacialityfactor=module_local.bifi, - fillcleanedSensors=False).rename( - columns={'Wm2Front':'Whm2Front', 'Wm2Back':'Whm2Back'}) + fillcleanedSensors=False) self.compiledResults.to_csv(os.path.join('results', 'Cumulative_Results.csv'), float_format='%0.3f', index=False) diff --git a/tests/test_load.py b/tests/test_load.py index 9c71b6d1..03287723 100644 --- a/tests/test_load.py +++ b/tests/test_load.py @@ -97,9 +97,11 @@ def test_gh126_raise_OSError(): def test_gh127_abspath(): """RadianceObj path must be absolute""" - testpath = os.path.abspath(os.path.dirname(__file__)) - projpath = os.path.dirname(testpath) + #testpath = os.path.abspath(os.path.dirname(__file__)) + #projpath = os.path.dirname(testpath) + projpath = os.path.dirname(TESTDIR) temp_path = os.path.join(projpath, 'bifacial_radiance', 'TEMP') + print(temp_path) demo = bifacial_radiance.RadianceObj(name='test', path=temp_path) os.path.isabs(demo.path) From f10dd4dcda2f676756af3bb0fe5357a73e01af03 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sun, 6 Oct 2024 16:46:49 -0600 Subject: [PATCH 6/7] Try indexing the directory differently.. revert Whm2 labeling in compiledResults. Not sure we want to do that.. --- bifacial_radiance/performance.py | 4 ++-- tests/test_load.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/bifacial_radiance/performance.py b/bifacial_radiance/performance.py index 417c8ff3..e0a378e9 100644 --- a/bifacial_radiance/performance.py +++ b/bifacial_radiance/performance.py @@ -453,14 +453,14 @@ def _dict2DF(df, key): dfst = pd.DataFrame(zip(cumRow, cumMod, cumScene, cumFront, cumWM2, cumBack, Grear_mean, POA_eff), columns=('rowNum', 'modNum','sceneNum', 'Gfront_mean', - 'Whm2Front', 'Whm2Back', 'Grear_mean', + 'Wm2Front', 'Wm2Back', 'Grear_mean', 'POA_eff')) dfst['BGG'] = dfst['Grear_mean']*100*bifacialityfactor/dfst['Gfront_mean'] # Reordering columns cols = ['rowNum', 'modNum','sceneNum', 'BGG', 'Gfront_mean', 'Grear_mean', 'POA_eff', - 'Whm2Front','Whm2Back'] + 'Wm2Front','Wm2Back'] dfst = dfst[cols] return dfst diff --git a/tests/test_load.py b/tests/test_load.py index 03287723..648fb930 100644 --- a/tests/test_load.py +++ b/tests/test_load.py @@ -97,9 +97,10 @@ def test_gh126_raise_OSError(): def test_gh127_abspath(): """RadianceObj path must be absolute""" + from pathlib import Path #testpath = os.path.abspath(os.path.dirname(__file__)) - #projpath = os.path.dirname(testpath) - projpath = os.path.dirname(TESTDIR) + projpath = Path(TESTDIR).parent + #projpath = os.path.dirname(TESTDIR) temp_path = os.path.join(projpath, 'bifacial_radiance', 'TEMP') print(temp_path) demo = bifacial_radiance.RadianceObj(name='test', path=temp_path) From 1945f656e082c55ee2a3c67e695ee11241548ad1 Mon Sep 17 00:00:00 2001 From: cdeline Date: Sun, 6 Oct 2024 18:59:52 -0600 Subject: [PATCH 7/7] Reverted accidental .gitignore deletion and test_load changes. --- bifacial_radiance/TEMP/.gitignore | 4 ++++ tests/test_load.py | 7 ++----- 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 bifacial_radiance/TEMP/.gitignore diff --git a/bifacial_radiance/TEMP/.gitignore b/bifacial_radiance/TEMP/.gitignore new file mode 100644 index 00000000..86d0cb27 --- /dev/null +++ b/bifacial_radiance/TEMP/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/tests/test_load.py b/tests/test_load.py index 648fb930..9c71b6d1 100644 --- a/tests/test_load.py +++ b/tests/test_load.py @@ -97,12 +97,9 @@ def test_gh126_raise_OSError(): def test_gh127_abspath(): """RadianceObj path must be absolute""" - from pathlib import Path - #testpath = os.path.abspath(os.path.dirname(__file__)) - projpath = Path(TESTDIR).parent - #projpath = os.path.dirname(TESTDIR) + testpath = os.path.abspath(os.path.dirname(__file__)) + projpath = os.path.dirname(testpath) temp_path = os.path.join(projpath, 'bifacial_radiance', 'TEMP') - print(temp_path) demo = bifacial_radiance.RadianceObj(name='test', path=temp_path) os.path.isabs(demo.path)