Skip to content

Commit

Permalink
Merge branch 'multi_sceneObjs' of https://github.com/NREL/bifacial_ra…
Browse files Browse the repository at this point in the history
…diance into multi_sceneObjs
  • Loading branch information
cdeline committed Nov 10, 2023
2 parents a97f89d + 90f8f80 commit 4ce1a54
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 90 deletions.
105 changes: 53 additions & 52 deletions bifacial_radiance/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ def _exportTrackerDict(trackerdict, savefile, reindex=False, monthlyyearly=False
# add trackerdict Results (not all simulations will have results)
try:
results = pd.concat([df(data=value['Results'],index=[key]*len(value['Results'])) for (key,value) in trackerdict.items()])
results = results[['rowWanted','modWanted','Wm2Front','Wm2Back']]
results = results[['rowWanted','modWanted','sceneNum','Wm2Front','Wm2Back']]
d = results.join(d)
except KeyError:
pass
Expand All @@ -357,57 +357,58 @@ def _exportTrackerDict(trackerdict, savefile, reindex=False, monthlyyearly=False
D4join = pd.DataFrame()
for rownum in d['rowWanted'].unique():
for modnum in d['modWanted'].unique():
mask = (d['rowWanted']==rownum) & (d['modWanted']==modnum)
print(modnum)
# Gfront_mean.append(filledFront[mask].sum(axis=0).mean())
D2 = d[mask].copy()
D2['timestamp'] = pd.to_datetime(D2['measdatetime'], format="%Y-%m-%d_%H%M")
D2 = D2.set_index('timestamp')
# D2 = D2.set_index(D2['timestamp'])

# Determine if data is sub-hourly
if len(D2) > 1:
if (D2.index[1]-D2.index[0]).total_seconds() / 60 < 60.0:
# Subhourly to hourly data averages, doesn't sum
# So we get average hourly irradiance as well as Wh on
# results of power.
D2b = D2.copy()
D2b = D2b.groupby(pd.PeriodIndex(D2b.index, freq="H")).mean().reset_index()
D2b['BGG'] = D2b['Grear_mean']*100/D2b['Gfront_mean']
D2b['BGE'] = (D2b['Pout']-D2b['Pout_Gfront'])*100/D2b['Pout']
D2b['Mismatch'] = (D2b['Pout_raw']-D2b['Pout'])*100/D2b['Pout_raw']
D2b['rowWanted'] = rownum
D2b['modWanted'] = modnum
D2b.drop(columns=['theta', 'surf_tilt', 'surf_azm'], inplace=True)
D2b=D2b.reset_index()
D2join = pd.concat([D2join, D2b], ignore_index=True, sort=False)

D3 = D2.groupby(pd.PeriodIndex(D2.index, freq="M")).sum().reset_index()
D3['BGG'] = D3['Grear_mean']*100/D3['Gfront_mean']
D3['BGE'] = (D3['Pout']-D3['Pout_Gfront'])*100/D3['Pout']
D3['Mismatch'] = (D3['Pout_raw']-D3['Pout'])*100/D3['Pout_raw']
D3['rowWanted'] = rownum
D3['modWanted'] = modnum
D3m = D2.groupby(pd.PeriodIndex(D2.index, freq="M")).mean().reset_index()
D3['temp_air'] = D3m['temp_air']
D3['wind_speed'] = D3m['wind_speed']
D3.drop(columns=['theta', 'surf_tilt', 'surf_azm'], inplace=True)

D4 = D2.groupby(pd.PeriodIndex(D2.index, freq="Y")).sum().reset_index()
D4['BGG'] = D4['Grear_mean']*100/D4['Gfront_mean']
D4['BGE'] = (D4['Pout']-D4['Pout_Gfront'])*100/D4['Pout']
D4['Mismatch'] = (D4['Pout_raw']-D4['Pout'])*100/D4['Pout_raw']
D4['rowWanted'] = rownum
D4['modWanted'] = modnum
D4m = D2.groupby(pd.PeriodIndex(D2.index, freq="Y")).mean().reset_index()
D4['temp_air'] = D4m['temp_air']
D4['wind_speed'] = D4m['wind_speed']
D4.drop(columns=['theta', 'surf_tilt', 'surf_azm'], inplace=True)

D3=D3.reset_index()
D4=D4.reset_index()
D3join = pd.concat([D3join, D3], ignore_index=True, sort=False)
D4join = pd.concat([D4join, D4], ignore_index=True, sort=False)
for sceneNum in d['sceneNum'].unique():#TODO: is sceneNum iteration required here?
mask = (d['rowWanted']==rownum) & (d['modWanted']==modnum) & (d['sceneNum']==sceneNum)
print(modnum)
# Gfront_mean.append(filledFront[mask].sum(axis=0).mean())
D2 = d[mask].copy()
D2['timestamp'] = pd.to_datetime(D2['measdatetime'], format="%Y-%m-%d_%H%M")
D2 = D2.set_index('timestamp')
# D2 = D2.set_index(D2['timestamp'])

# Determine if data is sub-hourly
if len(D2) > 1:
if (D2.index[1]-D2.index[0]).total_seconds() / 60 < 60.0:
# Subhourly to hourly data averages, doesn't sum
# So we get average hourly irradiance as well as Wh on
# results of power.
D2b = D2.copy()
D2b = D2b.groupby(pd.PeriodIndex(D2b.index, freq="H")).mean().reset_index()
D2b['BGG'] = D2b['Grear_mean']*100/D2b['Gfront_mean']
D2b['BGE'] = (D2b['Pout']-D2b['Pout_Gfront'])*100/D2b['Pout']
D2b['Mismatch'] = (D2b['Pout_raw']-D2b['Pout'])*100/D2b['Pout_raw']
D2b['rowWanted'] = rownum
D2b['modWanted'] = modnum
D2b.drop(columns=['theta', 'surf_tilt', 'surf_azm'], inplace=True)
D2b=D2b.reset_index()
D2join = pd.concat([D2join, D2b], ignore_index=True, sort=False)

D3 = D2.groupby(pd.PeriodIndex(D2.index, freq="M")).sum().reset_index()
D3['BGG'] = D3['Grear_mean']*100/D3['Gfront_mean']
D3['BGE'] = (D3['Pout']-D3['Pout_Gfront'])*100/D3['Pout']
D3['Mismatch'] = (D3['Pout_raw']-D3['Pout'])*100/D3['Pout_raw']
D3['rowWanted'] = rownum
D3['modWanted'] = modnum
D3m = D2.groupby(pd.PeriodIndex(D2.index, freq="M")).mean().reset_index()
D3['temp_air'] = D3m['temp_air']
D3['wind_speed'] = D3m['wind_speed']
D3.drop(columns=['theta', 'surf_tilt', 'surf_azm'], inplace=True)

D4 = D2.groupby(pd.PeriodIndex(D2.index, freq="Y")).sum().reset_index()
D4['BGG'] = D4['Grear_mean']*100/D4['Gfront_mean']
D4['BGE'] = (D4['Pout']-D4['Pout_Gfront'])*100/D4['Pout']
D4['Mismatch'] = (D4['Pout_raw']-D4['Pout'])*100/D4['Pout_raw']
D4['rowWanted'] = rownum
D4['modWanted'] = modnum
D4m = D2.groupby(pd.PeriodIndex(D2.index, freq="Y")).mean().reset_index()
D4['temp_air'] = D4m['temp_air']
D4['wind_speed'] = D4m['wind_speed']
D4.drop(columns=['theta', 'surf_tilt', 'surf_azm'], inplace=True)

D3=D3.reset_index()
D4=D4.reset_index()
D3join = pd.concat([D3join, D3], ignore_index=True, sort=False)
D4join = pd.concat([D4join, D4], ignore_index=True, sort=False)

savefile2 = savefile[:-4]+'_Hourly.csv'
savefile3 = savefile[:-4]+'_Monthly.csv'
Expand Down
78 changes: 51 additions & 27 deletions bifacial_radiance/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ def getfilelist(self):

return self.materialfiles + self.skyfiles + self._getradfiles()

def _getradfiles(self):
def _getradfiles(self, scenelist=None):
"""
iterate over self.scenes to get the radfiles
Expand All @@ -433,10 +433,15 @@ def _getradfiles(self):
None.
"""
if scenelist is None:
scenelist = self.scenes
a = []
for scene in self.scenes:
for f in scene.radfiles:
a.append(f)
for scene in scenelist:
if type(scene.radfiles) == list:
for f in scene.radfiles:
a.append(f)
else:
a.append(scene.radfiles)
return a

def save(self, savefile=None):
Expand Down Expand Up @@ -662,8 +667,9 @@ def returnMaterialFiles(self, material_path=None):
self.materialfiles = materialfilelist
return materialfilelist

def sceneNames(self):
return [scene.name for scene in self.scenes]
def sceneNames(self, scenes=None):
if scenes is None: scenes = self.scenes
return [scene.name for scene in scenes]

def setGround(self, material=None, material_file=None):
"""
Expand Down Expand Up @@ -2191,8 +2197,8 @@ def makeOct1axis(self, trackerdict=None, singleindex=None, customname=None):

print('\nMaking {} octfiles in root directory.'.format(indexlist.__len__()))
for index in sorted(indexlist): # run through either entire key list of trackerdict, or just a single value
try:
filelist = self.materialfiles + [trackerdict[index]['skyfile'], trackerdict[index]['radfile']]
try: #TODO: check if this works
filelist = self.materialfiles + [trackerdict[index]['skyfile']] + self._getradfiles(trackerdict[index]['scenes'])
octname = '1axis_%s%s'%(index, customname)
trackerdict[index]['octfile'] = self.makeOct(filelist, octname)
except KeyError as e:
Expand Down Expand Up @@ -2579,8 +2585,6 @@ def makeScene1axis(self, trackerdict=None, module=None, sceneDict=None,
--------
trackerdict
Append the following keys
'radfile'
directory where .rad scene file is stored
'scene'
SceneObj for each tracker theta
'clearance_height'
Expand Down Expand Up @@ -2660,7 +2664,7 @@ def makeScene1axis(self, trackerdict=None, module=None, sceneDict=None,
if cumulativesky is True: # cumulativesky workflow
print('\nMaking .rad files for cumulativesky 1-axis workflow')
for theta in trackerdict:
scene = SceneObj(module)
scene = SceneObj(module, hpc=self.hpc)
if trackerdict[theta]['surf_azm'] >= 180:
trackerdict[theta]['surf_azm'] = trackerdict[theta]['surf_azm']-180
trackerdict[theta]['surf_tilt'] = trackerdict[theta]['surf_tilt']*-1
Expand Down Expand Up @@ -2693,16 +2697,22 @@ def makeScene1axis(self, trackerdict=None, module=None, sceneDict=None,

radfile = scene._makeSceneNxR(sceneDict=sceneDict2,
radname=radname)
trackerdict[theta]['radfile'] = radfile
trackerdict[theta]['scene'] = scene
#trackerdict[theta]['radfile'] = radfile
# TODO: determine radfiles dynamically from scenes
try:
name=f"Scene{trackerdict[theta]['scenes'].__len__()}"
scene.name = name
trackerdict[theta]['scenes'].append(scene)
except KeyError: #either KeyError or maybe IndexError?
trackerdict[theta]['scenes'] = [scene]

print('{} Radfiles created in /objects/'.format(trackerdict.__len__()))

else: #gendaylit workflow
print('\nMaking ~%s .rad files for gendaylit 1-axis workflow (this takes a minute..)' % (len(trackerdict)))
count = 0
for time in trackerdict:
scene = SceneObj(module)
scene = SceneObj(module, hpc=self.hpc)

if trackerdict[time]['surf_azm'] >= 180:
trackerdict[time]['surf_azm'] = trackerdict[time]['surf_azm']-180
Expand Down Expand Up @@ -2737,15 +2747,23 @@ def makeScene1axis(self, trackerdict=None, module=None, sceneDict=None,

radfile = scene._makeSceneNxR(sceneDict=sceneDict2,
radname=radname)
trackerdict[time]['radfile'] = radfile
trackerdict[time]['scene'] = scene

#trackerdict[time]['radfile'] = radfile
# TODO: determine radfiles dynamically from scenes
try:
name=f"Scene{trackerdict[time]['scenes'].__len__()}"
scene.name = name
trackerdict[time]['scenes'].append(scene)
except KeyError: #either KeyError or maybe IndexError?
trackerdict[time]['scenes'] = [scene]
count+=1
print('{} Radfiles created in /objects/'.format(count))


if appendtoScene is not None:
for key in trackerdict:
self.appendtoScene(trackerdict[key]['radfile'], customObject = appendtoScene)
#TODO: test if this actually works
self.appendtoScene(trackerdict[key]['scenes'][0].radfiles, customObject = appendtoScene)

self.trackerdict = trackerdict
#self.nMods = sceneDict['nMods'] #assign nMods and nRows to RadianceObj
Expand All @@ -2759,7 +2777,7 @@ def analysis1axis(self, trackerdict=None, singleindex=None, accuracy='low',
customname=None, modWanted=None, rowWanted=None,
sensorsy=9, sensorsx=1,
modscanfront = None, modscanback = None, relative=False,
debug=False ):
debug=False, sceneNum=0 ):
"""
Loop through trackerdict and runs linescans for each scene and scan in there.
Expand Down Expand Up @@ -2808,6 +2826,8 @@ def analysis1axis(self, trackerdict=None, singleindex=None, accuracy='low',
Default is absolute value (relative=False)
debug : Bool
Activates internal printing of the function to help debugging.
sceneNum : int
Index of the scene number in the list of scenes per trackerdict. default 0
Returns
Expand Down Expand Up @@ -2841,9 +2861,9 @@ def analysis1axis(self, trackerdict=None, singleindex=None, accuracy='low',
trackerkeys = [singleindex]

if modWanted == None:
modWanted = round(trackerdict[trackerkeys[0]]['scene'].sceneDict['nMods'] / 1.99)
modWanted = round(trackerdict[trackerkeys[0]]['scenes'][sceneNum].sceneDict['nMods'] / 1.99)
if rowWanted == None:
rowWanted = round(trackerdict[trackerkeys[0]]['scene'].sceneDict['nRows'] / 1.99)
rowWanted = round(trackerdict[trackerkeys[0]]['scenes'][sceneNum].sceneDict['nRows'] / 1.99)


#frontWm2 = 0 # container for tracking front irradiance across module chord. Dynamically size based on first analysis run
Expand All @@ -2852,7 +2872,7 @@ def analysis1axis(self, trackerdict=None, singleindex=None, accuracy='low',
for index in trackerkeys: # either full list of trackerdict keys, or single index
name = '1axis_%s%s'%(index,customname)
octfile = trackerdict[index]['octfile']
scene = trackerdict[index]['scene']
scene = trackerdict[index]['scenes'][sceneNum]
if not trackerdict[index].get('Results'):
trackerdict[index]['Results'] = []
if octfile is None:
Expand All @@ -2863,7 +2883,7 @@ def analysis1axis(self, trackerdict=None, singleindex=None, accuracy='low',

row_mod_pairs = list(itertools.product(rowWanted,modWanted))
for (r,m) in row_mod_pairs:
Results = {'rowWanted':r,'modWanted':m}
Results = {'rowWanted':r,'modWanted':m, 'sceneNum':sceneNum}
if customname: Results['customname'] = customname
try: # look for missing data
analysis = AnalysisObj(octfile,name)
Expand Down Expand Up @@ -2904,7 +2924,8 @@ def calculateResults(self, CECMod=None, glassglass=False, bifacialityfactor=None
considering electrical mismatch, using
PVLib. Cell temperature is calculated
TODO: move into AnalysisObj?
TODO: move into AnalysisObj so it works on a specific scene!!! Or
alternatively run multiple times, enabling to select a specific sceneNum...
Parameters
----------
Expand Down Expand Up @@ -2946,8 +2967,9 @@ def calculateResults(self, CECMod=None, glassglass=False, bifacialityfactor=None
keys = list(trackerdict.keys())

# Search for module object bifaciality
# TODO: move into analysisObj so it works on a specific scene and can iterate over them.
if bifacialityfactor is None:
bifacialityfactor = trackerdict[keys[0]]['scene'].module.bifi
bifacialityfactor = trackerdict[keys[0]]['scenes'][0].module.bifi
print("Bifaciality factor of module stored is ", bifacialityfactor)
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1``34
# TODO IMPORTANT: ADD CUMULATIVE CHEck AND WHOLE OTHER PROCESSING OPTION
Expand All @@ -2965,6 +2987,7 @@ def calculateResults(self, CECMod=None, glassglass=False, bifacialityfactor=None
frontMat = []
rowWanted = []
modWanted = []
sceneNum = []
keys_all = []
dni = []
dhi = []
Expand All @@ -2978,7 +3001,8 @@ def calculateResults(self, CECMod=None, glassglass=False, bifacialityfactor=None
frontMat.append(row_mod['AnalysisObj'].mattype)
rearMat.append(row_mod['AnalysisObj'].rearMat)
rowWanted.append(row_mod['AnalysisObj'].rowWanted)
modWanted.append(row_mod['AnalysisObj'].modWanted)
modWanted.append(row_mod['AnalysisObj'].modWanted)
sceneNum.append(row_mod['sceneNum'])
if self.cumulativesky is False:
temp_air.append(trackerdict[key]['temp_air'])
wind_speed.append(trackerdict[key]['wind_speed'])
Expand All @@ -2988,9 +3012,9 @@ def calculateResults(self, CECMod=None, glassglass=False, bifacialityfactor=None

# trackerdict[key]['effective_irradiance'] = eff_irrad

data= pd.DataFrame(zip(keys_all, rowWanted, modWanted,
data= pd.DataFrame(zip(keys_all, rowWanted, modWanted, sceneNum,
Wm2Front, Wm2Back, frontMat, rearMat),
columns=('timestamp', 'rowNum','ModNumber',
columns=('timestamp', 'rowNum','ModNumber', 'sceneNum',
'Wm2Front', 'Wm2Back', 'mattype',
'rearMat'))

Expand Down
8 changes: 4 additions & 4 deletions bifacial_radiance/modelchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,11 @@ def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=N
if simulationParamsDict.get('saveImage'):
if hasattr(demo, 'trackerdict'):
bestkey = _getDesiredIndex(demo.trackerdict)
scene = demo.trackerdict[bestkey]['scene']
scene = demo.trackerdict[bestkey]['scenes'][0] #TODO: select which sceneNum chosen?
imagefilename = f'scene_{bestkey}'
viewfile = None # just use default value for now. Improve later..
elif hasattr(demo, 'scene'):
scene = demo.scene
elif hasattr(demo, 'scenes'):
scene = demo.scenes[0]
viewfile = None # just use default value for now. Improve later..
imagefilename = 'scene0'
try:
Expand Down Expand Up @@ -287,7 +287,7 @@ def _getDesiredIndex(trackerdict):

df = pd.DataFrame.from_dict(trackerdict, orient='index')
try:
df = df[df['scene'].notna()]
df = df[df['scenes'].notna()]
except KeyError:
print('Error in _getDesiredIndex - trackerdict has no scene defined.')
return df.index[-1]
Expand Down
Loading

0 comments on commit 4ce1a54

Please sign in to comment.