Skip to content

Commit

Permalink
Replace analysisObj.getResults() with results property
Browse files Browse the repository at this point in the history
  • Loading branch information
cdeline committed Sep 9, 2024
1 parent 1e945f5 commit 251da4b
Show file tree
Hide file tree
Showing 14 changed files with 74 additions and 71 deletions.
24 changes: 7 additions & 17 deletions bifacial_radiance/data/module.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,35 +63,25 @@
"zgap": 0.1
},
"test": {
"bifi": 0.8,
"bifi": 1,
"glass": false,
"modulefile": "objects\\test.rad",
"modulematerial": "black",
"numpanels": 1,
"offsetfromaxis": 0,
"scenex": 1.01,
"sceney": 2.0,
"scenex": 1.6,
"sceney": 0.95,
"scenez": 0.1,
"text": "! genbox black test 1 2 0.02 | xform -t -0.5 -1.0 0 -a 1 -t 0 2.0 0",
"x": 1,
"text": "! genbox black test 1.59 0.95 0.02 | xform -t -0.795 -0.475 0 -a 1 -t 0 0.95 0",
"x": 1.59,
"xgap": 0.01,
"y": 2,
"y": 0.95,
"ygap": 0.0,
"z": 0.02,
"zgap": 0.1
},
"test-module": {
"CECMod": {
"Adjust": "22.9092",
"I_L_ref": "6.05373",
"I_o_ref": "8.36043e-11",
"R_s": "0.30812",
"R_sh_ref": "500.069",
"a_ref": "2.57764",
"alpha_sc": "0.00373527",
"name": "SunPower SPR-E19-310-COM"
},
"bifi": 0.9,
"bifi": 1,
"glass": false,
"modulefile": "objects\\test-module.rad",
"modulematerial": "black",
Expand Down
4 changes: 1 addition & 3 deletions bifacial_radiance/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,7 @@ def _printRow(analysisobj, key):
else:
keyname = 'timestamp'
return pd.concat([pd.DataFrame({keyname:key},index=[0]),
analysisobj.getResults(),
analysisobj.power_data
], axis=1)
analysisobj.results], axis=1)

for key in trackerdict:
try:
Expand Down
55 changes: 32 additions & 23 deletions bifacial_radiance/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2800,8 +2800,9 @@ def analysis1axis(self, trackerdict=None, singleindex=None, accuracy='low',
for each timestamp:
trackerdict.key.'AnalysisObj' : analysis object for this tracker theta
to get a dictionary of results, run :py:class:`bifacial_radiance.AnalysisObj`.getResults
:py:class:`bifacial_radiance.AnalysisObj`.getResults returns the following keys:
to get a dictionary of results, run :py:class:`bifacial_radiance.AnalysisObj`.results
:py:class:`bifacial_radiance.AnalysisObj`.results returns the following df:
'name', 'modNum', 'rowNum', 'sceneNum', 'x','y','z', 'mattype', 'rearMat',
'Wm2Front' : np.array of front Wm-2 irradiances, len=sensorsy_back
'Wm2Back' : np.array of rear Wm-2 irradiances, len=sensorsy_back
'backRatio' : np.array of rear irradiance ratios, len=sensorsy_back
Expand Down Expand Up @@ -2928,8 +2929,8 @@ def analysis1axisground(self, trackerdict=None, singleindex=None, accuracy='low'
for each timestamp:
trackerdict.key.'AnalysisObj' : analysis object for this tracker theta
to get a dictionary of results, run :py:class:`bifacial_radiance.AnalysisObj`.getResults
:py:class:`bifacial_radiance.AnalysisObj`.getResults returns the following keys:
to get a dictionary of results, run :py:class:`bifacial_radiance.AnalysisObj`.results
:py:class:`bifacial_radiance.AnalysisObj`.results returns the following keys:
'Wm2Ground' : np.array of Wm-2 irradiances along the ground, len=sensorsground
'sensorsground' : int of number of ground scan points
Expand Down Expand Up @@ -3052,9 +3053,7 @@ def _printRow(analysisobj, key):
else:
keyname = 'timestamp'
return pd.concat([pd.DataFrame({keyname:key},index=[0]),
analysisobj.getResults(),
analysisobj.power_data
], axis=1)
analysisobj.results], axis=1)



Expand Down Expand Up @@ -3084,7 +3083,7 @@ def _printRow(analysisobj, key):
module_local = trackerdict[key]['scenes'][analysis.sceneNum].module
else:
module_local = module
power_data = analysis.calculatePerformance(meteo_data=meteo_data,
analysis.calculatePerformance(meteo_data=meteo_data,
module=module_local,
cumulativesky=self.cumulativesky,
CECMod2=CECMod2,
Expand Down Expand Up @@ -4346,8 +4345,26 @@ def _makeTrackerCSV(self, theta_list, trackingdata):
class AnalysisObj(SuperClass):
"""
Analysis class for performing raytrace to obtain irradiance measurements
at the array, as well plotting and reporting results.
at the array, as well as plotting and reporting results.
"""
@property
def results(self):
"""
go through the AnalysisObj and return a DF of irradiance result keys.
"""
try:
keylist = ['rowWanted', 'modWanted', 'sceneNum', 'name', 'x', 'y','z',
'Wm2Front', 'Wm2Back', 'Wm2Ground', 'backRatio', 'mattype', 'rearMat' ]
resultdict = {k: v for k, v in self.__dict__.items() if k in keylist}
results = pd.DataFrame.from_dict(resultdict, orient='index').T.rename(
columns={'modWanted':'modNum', 'rowWanted':'rowNum'})
if getattr(self, 'power_data', None) is not None:
return pd.concat([results, self.power_data], axis=1)
else:
return results
except AttributeError:
return None

def __printval__(self, attr):
try:
t = getattr(self,attr, None)[0]
Expand All @@ -4359,7 +4376,7 @@ def __printval__(self, attr):
return getattr(self,attr)

def __repr__(self):
return str(type(self)) + ' : ' + str({key: self.__printval__(key) for key in self.columns})
return str(type(self)) + ' : ' + str({key: self.__printval__(key) for key in self.columns if key != 'results'})
def __init__(self, octfile=None, name=None, hpc=False):
"""
Initialize AnalysisObj by pointing to the octfile. Scan information
Expand All @@ -4384,25 +4401,17 @@ def __init__(self, octfile=None, name=None, hpc=False):
self.rowWanted = None
self.sceneNum = 0 # should this be 0 or None by default??
self.power_data = None # results from self.calculatePerformance() stored here



"""
def getResults(self): ### REPLACED BY `results` PROPERTY
def getResults(self):
"""
go through the AnalysisObj and return a dict of irradiance result keys.
Returns
-------
Results : dict. irradiance scan results
"""
#TODO (optional?) Merge power_data to returned values??
keylist = ['rowWanted', 'modWanted', 'sceneNum', 'name', 'x', 'y','z',
'Wm2Front', 'Wm2Back', 'Wm2Ground', 'backRatio', 'mattype', 'rearMat' ]
resultdict = {k: v for k, v in self.__dict__.items() if k in keylist}
return pd.DataFrame.from_dict(resultdict, orient='index').T.rename(
columns={'modWanted':'modNum', 'rowWanted':'rowNum'})

"""


def makeImage(self, viewfile, octfile=None, name=None):
Expand Down Expand Up @@ -5476,14 +5485,14 @@ def calculatePerformance(self, meteo_data, cumulativesky, module,
raise TypeError('ModuleObj input required for AnalysisObj.calculatePerformance. '+\
f'type passed: {type(module)}')

self.power_data = performance.calculatePerformance(module=module, results=self.getResults(),
self.power_data = performance.calculatePerformance(module=module, results=self.results,
CECMod2=CECMod2, agriPV=agriPV,
**meteo_data)

else:
# TODO HERE: SUM all keys for rows that have the same rowWanted/modWanted

self.power_data = performance.calculatePerformanceGencumsky(results=self.getResults(),
self.power_data = performance.calculatePerformanceGencumsky(results=self.results,
agriPV=agriPV)
#results.to_csv(os.path.join('results', 'Cumulative_Results.csv'))

Expand Down
4 changes: 2 additions & 2 deletions docs/sphinx/source/whatsnew/v0.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Deprecations

API Changes
~~~~~~~~~~~~
* A new function can now be called to compile results and report out final irradiance and performance data: :py:class:`~bifacial_radiance.RadianceObj.getResults`.
* A new function can now be called to compile results and report out final irradiance and performance data: :py:class:`~bifacial_radiance.AnalysisObj.results` and :py:class:`~bifacial_radiance.RadianceObj.getResults`.
* 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.
* 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`)
Expand All @@ -59,7 +59,7 @@ Enhancements
* New function :py:class:`~bifacial_radiance.AnalysisObj.calculatePerformance` and :py:class:`~bifacial_radiance.ModuleObj.calculatePerformance` to call CEC performance calculation from within the AnalysisObj
* New function :py:class:`~bifacial_radiance.RadianceObj.calculatePerformance1axis` to call CEC performance calculation for every entry of a trackerdict
* :py:class:`~bifacial_radiance.AnalysisObj` has new attribute `power_data` to store CEC performance data
* :py:class:`~bifacial_radiance.AnalysisObj` has new function `getResults` to bundle and return irradiance scan results in dataframe form.
* :py:class:`~bifacial_radiance.AnalysisObj` has new property `results` to bundle and return irradiance scan results in dataframe form.
* :py:class:`~bifacial_radiance.AnalysisObj` has new function `groundAnalysis` to run a ground scan under the row-row pitch of the scene to support AgriPV applications. (:pull:`499`)
* :py:class:`~bifacial_radiance.RadianceObj` has new function `analysis1axisground` to run a ground scan under the row-row pitch of the scene for 1-axis tracked scenes. (:pull:`499`)
* :py:class:`~bifacial_radiance.RadianceObj` has new intermediate function `readWeatherData` which can take raw metdata time series and metadata dict to generate a :py:class:`~bifacial_radiance.MetObj`. Useful for e.g. bringing in raw NSRDB data. (:pull:`496`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,7 @@
"\n",
"<div class=\"alert alert-warning\">\n",
"Important: If you have torquetubes and y-gap values, make sure you clean your results.\n",
"</div>\n",
""
"</div>\n"
]
},
{
Expand Down Expand Up @@ -1311,7 +1310,7 @@
"metadata": {},
"outputs": [],
"source": [
"res = demo.calculateResults(bifacialityfactor=1.0)"
"res = demo.calculatePerformance1axis()"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@
# In[21]:


res = demo.calculateResults(bifacialityfactor=1.0)
res = demo.calculatePerformance1axis()


# In[22]:
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/3 - Single Axis Tracking Hourly.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@
"source": [
"demo.makeOct1axis(singleindex='2021-01-13_0800')\n",
"results = demo.analysis1axis(singleindex='2021-01-13_0800')\n",
"temp = results['2021-01-13_0800']['AnalysisObj'][0].getResults()\n",
"temp = results['2021-01-13_0800']['AnalysisObj'][0].results\n",
"print('\\n\\nHourly bifi gain: {:0.3}'.format(sum(temp['Wm2Back'][0]) / sum(temp['Wm2Front'][0])))"
]
},
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/3 - Single Axis Tracking Hourly.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@

demo.makeOct1axis(singleindex='2021-01-13_0800')
results = demo.analysis1axis(singleindex='2021-01-13_0800')
temp = results['2021-01-13_0800']['AnalysisObj'][0].getResults()
temp = results['2021-01-13_0800']['AnalysisObj'][0].results
print('\n\nHourly bifi gain: {:0.3}'.format(sum(temp['Wm2Back'][0]) / sum(temp['Wm2Front'][0])))


Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/4 - Debugging with Custom Objects.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.9.13"
}
},
"nbformat": 4,
Expand Down
31 changes: 16 additions & 15 deletions docs/tutorials/4 - Debugging with Custom Objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@
# </div>
#

# In[4]:
# In[5]:


# Some tracking parameters that won't be needed after getting this angle:
axis_azimuth = 180
axis_tilt = 0
limit_angle = 60
backtrack = True
tilt = demo.getSingleTimestampTrackerAngle(metdata, timestamp, gcr, axis_azimuth, axis_tilt,limit_angle, backtrack)
tilt = demo.getSingleTimestampTrackerAngle(timeindex=timestamp, gcr=gcr, azimuth=axis_azimuth, axis_tilt=axis_tilt, limit_angle=limit_angle, backtrack=backtrack)

print ("\n NEW Calculated Tilt: %s " % tilt)

Expand All @@ -158,7 +158,7 @@

# ## 5. Making the Module & the Scene, Visualize and run Analysis

# In[5]:
# In[6]:


# Making module with all the variables
Expand All @@ -185,7 +185,8 @@
# ***rvu -vf views\front.vp -e .01 -pe 0.02 -vp -2 -12 14.5 tutorial_4.oct****
#

# In[6]:
# In[ ]:



## Comment the line below to run rvu from the Jupyter notebook instead of your terminal.
Expand All @@ -196,7 +197,7 @@

# And then proceed happily with your analysis:

# In[7]:
# In[ ]:


analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) # return an analysis object including the scan dimensions for back irradiance
Expand All @@ -218,7 +219,7 @@
# Although we could calculate a bifacial ratio average at this point, this value would be misleading, since some of the sensors generated will fall on the torque tube, the sky, and/or the ground since we have torquetube and ygap in the scene. To calculate the real bifacial ratio average, we must use the clean routines.
#

# In[8]:
# In[ ]:


resultFile='results/irr_tutorial_4.csv'
Expand All @@ -227,7 +228,7 @@
results_loaded


# In[9]:
# In[ ]:


print("Looking at only 1 sensor in the middle -- position 100 out of the 200 sensors sampled:")
Expand All @@ -238,28 +239,27 @@
#
# This might take some time in the current version.

# In[10]:
# In[ ]:


# Cleaning Results:
# remove invalid materials and sets the irradiance values to NaN
clean_results = bifacial_radiance.load.cleanResult(results_loaded)


# In[11]:
# In[ ]:


print("Sampling the same location as before to see what the results are now:")
clean_results.loc[100]


# In[12]:
# In[ ]:


print('CORRECT Annual bifacial ratio average: %0.3f' %( clean_results['Wm2Back'].sum() / clean_results['Wm2Front'].sum() ))

print ("\n(If we had not done the cleaning routine, the bifacial ratio would have been ", \
"calculated to %0.3f <-- THIS VALUE IS WRONG)" %( sum(analysis.Wm2Back) / sum(analysis.Wm2Front) ))
print ("\n(If we had not done the cleaning routine, the bifacial ratio would have been ", "calculated to %0.3f <-- THIS VALUE IS WRONG)" %( sum(analysis.Wm2Back) / sum(analysis.Wm2Front) ))


# <a id='step7'></a>
Expand All @@ -275,7 +275,7 @@
# Its sides are going to be 0.5x0.5x0.5 m
# and We are going to leave its bottom surface coincident with the plane z=0, but going to center on X and Y.

# In[13]:
# In[ ]:


name='MyMarker'
Expand All @@ -289,7 +289,7 @@
#
# I am passing a rotation 0 because xform has to have something (I think) otherwise it gets confused.

# In[14]:
# In[ ]:


demo.appendtoScene(scene.radfiles, customObject, '!xform -rz 0')
Expand All @@ -301,7 +301,8 @@
#
# At this point you should be able to go into a command window (cmd.exe) and check the geometry, and the marker should be there.

# In[15]:
# In[ ]:



## Comment the line below to run rvu from the Jupyter notebook instead of your terminal.
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/5 - Bifacial Carports and Canopies.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.9.13"
}
},
"nbformat": 4,
Expand Down
Loading

0 comments on commit 251da4b

Please sign in to comment.