bifacial-radiance 0.5.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bifacial_radiance/HPCScripts/BasicSimulations/addNewModule.py +15 -0
- bifacial_radiance/HPCScripts/BasicSimulations/dask_on_node.sh +11 -0
- bifacial_radiance/HPCScripts/BasicSimulations/run_sbatch.sbatch +51 -0
- bifacial_radiance/HPCScripts/BasicSimulations/simulate_fixedtilt_gencumsky.py +110 -0
- bifacial_radiance/HPCScripts/BasicSimulations/simulate_fixedtilt_gendaylit.py +102 -0
- bifacial_radiance/HPCScripts/BasicSimulations/simulate_tracking_gendaylit.py +126 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/PuertoRico.py +168 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/PuertoRico_2.py +166 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/PuertoRico_Original.py +195 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/basic_module_sampling.py +154 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_B.py +162 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_Cases.py +122 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_CasesMonth.py +142 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_PRNew.py +91 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_PRNewP2.py +95 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_TreeResults.py +108 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_basic_module_sampling.py +103 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/simulate_JackHourly.py +160 -0
- bifacial_radiance/HPCScripts/Other Examples (unorganized)/simulate_improvedArray_Oct2127.py +623 -0
- bifacial_radiance/TEMP/.gitignore +4 -0
- bifacial_radiance/__init__.py +24 -0
- bifacial_radiance/data/CEC Modules.csv +16860 -0
- bifacial_radiance/data/default.ini +65 -0
- bifacial_radiance/data/falsecolor.exe +0 -0
- bifacial_radiance/data/gencumsky/License.txt +54 -0
- bifacial_radiance/data/gencumsky/Makefile +17 -0
- bifacial_radiance/data/gencumsky/README.txt +9 -0
- bifacial_radiance/data/gencumsky/Solar Irradiation Modelling.doc +0 -0
- bifacial_radiance/data/gencumsky/Sun.cpp +118 -0
- bifacial_radiance/data/gencumsky/Sun.h +45 -0
- bifacial_radiance/data/gencumsky/average_val.awk +3 -0
- bifacial_radiance/data/gencumsky/cPerezSkyModel.cpp +238 -0
- bifacial_radiance/data/gencumsky/cPerezSkyModel.h +57 -0
- bifacial_radiance/data/gencumsky/cSkyVault.cpp +536 -0
- bifacial_radiance/data/gencumsky/cSkyVault.h +86 -0
- bifacial_radiance/data/gencumsky/climateFile.cpp +312 -0
- bifacial_radiance/data/gencumsky/climateFile.h +37 -0
- bifacial_radiance/data/gencumsky/cumulative.cal +177 -0
- bifacial_radiance/data/gencumsky/cumulative.rad +14 -0
- bifacial_radiance/data/gencumsky/cumulativesky_rotated.rad +2 -0
- bifacial_radiance/data/gencumsky/gencumulativesky +0 -0
- bifacial_radiance/data/gencumsky/gencumulativesky.cpp +269 -0
- bifacial_radiance/data/gencumsky/make_gencumskyexe.py +107 -0
- bifacial_radiance/data/gencumsky/paths.h +62 -0
- bifacial_radiance/data/gencumulativesky +0 -0
- bifacial_radiance/data/gencumulativesky.exe +0 -0
- bifacial_radiance/data/ground.rad +83 -0
- bifacial_radiance/data/module.json +103 -0
- bifacial_radiance/gui.py +1696 -0
- bifacial_radiance/images/fig1_fixed_small.gif +0 -0
- bifacial_radiance/images/fig2_tracked_small.gif +0 -0
- bifacial_radiance/load.py +1156 -0
- bifacial_radiance/main.py +5673 -0
- bifacial_radiance/mismatch.py +461 -0
- bifacial_radiance/modelchain.py +299 -0
- bifacial_radiance/module.py +1427 -0
- bifacial_radiance/performance.py +466 -0
- bifacial_radiance/spectral_utils.py +555 -0
- bifacial_radiance-0.5.1.dist-info/METADATA +129 -0
- bifacial_radiance-0.5.1.dist-info/RECORD +63 -0
- bifacial_radiance-0.5.1.dist-info/WHEEL +6 -0
- bifacial_radiance-0.5.1.dist-info/licenses/LICENSE +30 -0
- bifacial_radiance-0.5.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
Created on Tue April 27 06:29:02 2021
|
|
4
|
+
|
|
5
|
+
@author: sayala
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import pvlib
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def MBD(meas, model):
|
|
14
|
+
"""
|
|
15
|
+
This function calculates the MEAN BIAS DEVIATION of measured vs. modeled
|
|
16
|
+
data and returns it as a Percentage [%].
|
|
17
|
+
|
|
18
|
+
MBD=100∙[((1⁄(m)∙∑〖(y_i-x_i)]÷[(1⁄(m)∙∑〖x_i]〗)〗)
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
meas : numeric list
|
|
23
|
+
Measured data.
|
|
24
|
+
model : numeric list
|
|
25
|
+
Modeled data
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
out : numeric
|
|
30
|
+
Percentage [%] Mean Bias Deviation between the measured and the modeled
|
|
31
|
+
data.
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
df = pd.DataFrame({'model': model, 'meas': meas})
|
|
36
|
+
# rudimentary filtering of modeled irradiance
|
|
37
|
+
df = df.dropna()
|
|
38
|
+
minirr = meas.min()
|
|
39
|
+
df = df[df.model > minirr]
|
|
40
|
+
m = df.__len__()
|
|
41
|
+
out = 100*((1/m)*sum(df.model-df.meas))/df.meas.mean()
|
|
42
|
+
return out
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def RMSE(meas, model):
|
|
46
|
+
"""
|
|
47
|
+
This function calculates the ROOT MEAN SQUARE ERROR of measured vs. modeled
|
|
48
|
+
data and returns it as a Percentage [%].
|
|
49
|
+
|
|
50
|
+
RMSD=100∙〖[(1⁄(m)∙∑▒(y_i-x_i )^2 )]〗^(1⁄2)÷[(1⁄(m)∙∑▒〖x_i]〗)
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
meas : numeric list
|
|
55
|
+
Measured data.
|
|
56
|
+
model : numeric list
|
|
57
|
+
Modeled data
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
out : numeric
|
|
62
|
+
Percentage [%] Root Mean Square Error between the measured and the
|
|
63
|
+
modeled data.
|
|
64
|
+
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
df = pd.DataFrame({'model': model, 'meas': meas})
|
|
70
|
+
df = df.dropna()
|
|
71
|
+
minirr = meas.min()
|
|
72
|
+
df = df[df.model > minirr]
|
|
73
|
+
m = df.__len__()
|
|
74
|
+
out = 100*np.sqrt(1/m*sum((df.model-df.meas)**2))/df.meas.mean()
|
|
75
|
+
return out
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# residuals absolute output (not %)
|
|
79
|
+
def MBD_abs(meas, model):
|
|
80
|
+
"""
|
|
81
|
+
This function calculates the ABSOLUTE MEAN BIAS DEVIATION of measured vs.
|
|
82
|
+
modeled data and returns it as a Percentage [%].
|
|
83
|
+
|
|
84
|
+
MBD=100∙[((1⁄(m)∙∑〖(y_i-x_i)]÷[(1⁄(m)∙∑〖x_i]〗)〗)
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
meas : numeric list
|
|
89
|
+
Measured data.
|
|
90
|
+
model : numeric list
|
|
91
|
+
Modeled data
|
|
92
|
+
|
|
93
|
+
Returns
|
|
94
|
+
-------
|
|
95
|
+
out : numeric
|
|
96
|
+
Absolute output residual of the Mean Bias Deviation between the
|
|
97
|
+
measured and the modeled data.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
df = pd.DataFrame({'model': model, 'meas': meas})
|
|
102
|
+
# rudimentary filtering of modeled irradiance
|
|
103
|
+
df = df.dropna()
|
|
104
|
+
minirr = meas.min()
|
|
105
|
+
df = df[df.model > minirr]
|
|
106
|
+
m = df.__len__()
|
|
107
|
+
out = ((1/m)*sum(df.model-df.meas))
|
|
108
|
+
return out
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def RMSE_abs(meas, model):
|
|
112
|
+
"""
|
|
113
|
+
This function calculates the ABSOLUTE ROOT MEAN SQUARE ERROR of measured
|
|
114
|
+
vs. modeled data and returns it as a Percentage [%].
|
|
115
|
+
|
|
116
|
+
RMSD=100∙〖[(1⁄(m)∙∑▒(y_i-x_i )^2 )]〗^(1⁄2)÷[(1⁄(m)∙∑▒〖x_i]〗)
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
meas : numeric list
|
|
121
|
+
Measured data.
|
|
122
|
+
model : numeric list
|
|
123
|
+
Modeled data
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
out : numeric
|
|
128
|
+
Absolute output residual of the Root Mean Square Error between the
|
|
129
|
+
measured and the modeled data.
|
|
130
|
+
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
#
|
|
134
|
+
|
|
135
|
+
df = pd.DataFrame({'model': model, 'meas': meas})
|
|
136
|
+
df = df.dropna()
|
|
137
|
+
minirr = meas.min()
|
|
138
|
+
df = df[df.model > minirr]
|
|
139
|
+
m = df.__len__()
|
|
140
|
+
out = np.sqrt(1/m*sum((df.model-df.meas)**2))
|
|
141
|
+
return out
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _cleanDataFrameResults(mattype, rearMat, Wm2Front, Wm2Back,
|
|
145
|
+
fillcleanedSensors=False):
|
|
146
|
+
|
|
147
|
+
# 2D array of values. if a row of rearMat is nan then it's single-sided and
|
|
148
|
+
# agriPV is true for that row
|
|
149
|
+
_matchAgriPV = ['sky', 'pole', 'tube', 'bar', '3267', '1540', '1540']
|
|
150
|
+
_match = ['sky', 'pole', 'tube', 'bar', 'ground', '3267', '1540']
|
|
151
|
+
matcharray = np.row_stack([_matchAgriPV if row.isna().all() else _match
|
|
152
|
+
for (n,row) in rearMat.iterrows()])
|
|
153
|
+
"""
|
|
154
|
+
if Wm2Front.size != Wm2Back.size:
|
|
155
|
+
agriPV = True
|
|
156
|
+
matchers = ['sky', 'pole', 'tube', 'bar', '3267', '1540']
|
|
157
|
+
else:
|
|
158
|
+
agriPV = False
|
|
159
|
+
matchers = ['sky', 'pole', 'tube', 'bar', 'ground', '3267', '1540']
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
maskfront = np.row_stack([row.str.contains('|'.join(matcharray[index]),
|
|
163
|
+
na=False) for (index, row) in
|
|
164
|
+
mattype.iterrows()])
|
|
165
|
+
|
|
166
|
+
Wm2Front[maskfront] = np.nan
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
maskback = np.row_stack([row.str.contains('|'.join(matcharray[index]),
|
|
170
|
+
na=False) for (index, row) in
|
|
171
|
+
rearMat.iterrows()])
|
|
172
|
+
Wm2Back[maskback] = np.nan
|
|
173
|
+
except AttributeError: # rearMat is empty
|
|
174
|
+
pass
|
|
175
|
+
|
|
176
|
+
# Filling Nans...
|
|
177
|
+
filledFront = Wm2Front.mean(axis=1)
|
|
178
|
+
|
|
179
|
+
if fillcleanedSensors:
|
|
180
|
+
frontcopy = Wm2Front.copy().interpolate(axis=1)
|
|
181
|
+
filledBack = Wm2Back.copy().interpolate(axis=1)
|
|
182
|
+
else:
|
|
183
|
+
frontcopy = Wm2Front.copy()
|
|
184
|
+
filledBack = Wm2Back.copy() # interpolate()
|
|
185
|
+
|
|
186
|
+
return filledFront, filledBack, frontcopy
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def calculatePerformance(module, csvfile=None, results=None,
|
|
190
|
+
temp_air=None, wind_speed=1, temp_cell=None,
|
|
191
|
+
CECMod2=None,
|
|
192
|
+
fillcleanedSensors=False, **kwargs):
|
|
193
|
+
'''
|
|
194
|
+
Calculate Performance and Mismatch for timestamped data. This routine requires
|
|
195
|
+
CECMod details to have been set with the module using ModuleObj.addCEC.
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
Parameters
|
|
199
|
+
----------
|
|
200
|
+
module : bifacial_radiance.module.ModuleObj
|
|
201
|
+
module object with CEC Module data as dictionary
|
|
202
|
+
csvfile : numeric list
|
|
203
|
+
Compiled Results data
|
|
204
|
+
results : numeric list
|
|
205
|
+
compiled Results data
|
|
206
|
+
temp_air : value or list
|
|
207
|
+
Air temperature for calculating module temperature
|
|
208
|
+
wind_speed : value or list
|
|
209
|
+
Wind tempreatuer for calcluating module temperature
|
|
210
|
+
temp_cell : value or list
|
|
211
|
+
Cell temperature for calculating module performance. If none, module
|
|
212
|
+
temperature is calculated using temp_air and wind_speed
|
|
213
|
+
CECMod2 : dict, optional
|
|
214
|
+
CEC Module data as dictionary, for a monofacial module to be used as
|
|
215
|
+
comparison for Bifacial Gain in Energy using only the calculated front
|
|
216
|
+
Irradiance. If none, same module as CECMod
|
|
217
|
+
is used.
|
|
218
|
+
|
|
219
|
+
Returns
|
|
220
|
+
-------
|
|
221
|
+
dfst : dataframe
|
|
222
|
+
Dataframe with the complied and calculated results for the sim, including:
|
|
223
|
+
POA_eff: mean of [(mean of clean Gfront) + clean Grear * bifaciality
|
|
224
|
+
factor]
|
|
225
|
+
Gfront_mean: mean of clean Gfront
|
|
226
|
+
Grear_mean: mean of clean Grear
|
|
227
|
+
Mismatch: mismatch calculated from the MAD distribution of
|
|
228
|
+
POA_total
|
|
229
|
+
Pout_raw: power output calculated from POA_total, considers
|
|
230
|
+
wind speed and temp_amb if in trackerdict.
|
|
231
|
+
Pout: power output considering electrical mismatch
|
|
232
|
+
BGG: Bifacial Gain in Irradiance, [Grear_mean*100*bifacialityfactor/
|
|
233
|
+
Gfront_mean]
|
|
234
|
+
BGE: Bifacial Gain in Energy, when power is calculated with CECMod2 or
|
|
235
|
+
same module but just the front irradiance as input, so that
|
|
236
|
+
[Pout-Pout_Gfront/Pout_Gfront]
|
|
237
|
+
|
|
238
|
+
'''
|
|
239
|
+
|
|
240
|
+
from bifacial_radiance import mismatch
|
|
241
|
+
|
|
242
|
+
dfst = pd.DataFrame()
|
|
243
|
+
|
|
244
|
+
if csvfile is not None:
|
|
245
|
+
data = pd.read_csv(csvfile)
|
|
246
|
+
Wm2Front = data['Wm2Front'].str.strip(
|
|
247
|
+
'[]').str.split(',', expand=True).astype(float)
|
|
248
|
+
mattype = data['mattype'].str.strip('[]').str.split(',', expand=True)
|
|
249
|
+
if 'Wm2Back' in data:
|
|
250
|
+
Wm2Back = data['Wm2Back'].str.strip(
|
|
251
|
+
'[]').str.split(',', expand=True).astype(float)
|
|
252
|
+
else:
|
|
253
|
+
Wm2Back = pd.DataFrame([0])
|
|
254
|
+
if 'rearMat' in data:
|
|
255
|
+
rearMat = data['rearMat'].str.strip('[]').str.split(',', expand=True)
|
|
256
|
+
else:
|
|
257
|
+
rearMat = pd.DataFrame([np.nan])
|
|
258
|
+
if 'timestamp' in data:
|
|
259
|
+
dfst['timestamp'] = data['timestamp']
|
|
260
|
+
if 'modNum' in data:
|
|
261
|
+
dfst['Module'] = data['modNum']
|
|
262
|
+
if 'rowNum' in data:
|
|
263
|
+
dfst['Row'] = data['rowNum']
|
|
264
|
+
if 'sceneNum' in data:
|
|
265
|
+
dfst['sceneNum'] = data['sceneNum']
|
|
266
|
+
else:
|
|
267
|
+
if results is not None:
|
|
268
|
+
results = results.loc[:,~results.columns.duplicated()]
|
|
269
|
+
Wm2Front = pd.DataFrame.from_dict(dict(zip(
|
|
270
|
+
results.index, results['Wm2Front']))).T
|
|
271
|
+
mattype = pd.DataFrame.from_dict(dict(zip(
|
|
272
|
+
results.index, results['mattype']))).T
|
|
273
|
+
if 'Wm2Back' in results:
|
|
274
|
+
Wm2Back = pd.DataFrame.from_dict(dict(zip(
|
|
275
|
+
results.index, results['Wm2Back']))).T
|
|
276
|
+
else:
|
|
277
|
+
Wm2Back = pd.DataFrame([0])
|
|
278
|
+
if 'rearMat' in results:
|
|
279
|
+
rearMat = pd.DataFrame.from_dict(dict(zip(
|
|
280
|
+
results.index, results['rearMat']))).T
|
|
281
|
+
else:
|
|
282
|
+
rearMat = pd.DataFrame([np.nan])
|
|
283
|
+
|
|
284
|
+
if 'timestamp' in results:
|
|
285
|
+
dfst['timestamp'] = results['timestamp']
|
|
286
|
+
if 'modNum' in results:
|
|
287
|
+
dfst['module'] = results['modNum']
|
|
288
|
+
if 'rowNum' in results:
|
|
289
|
+
dfst['row'] = results['rowNum']
|
|
290
|
+
if 'sceneNum' in results:
|
|
291
|
+
dfst['sceneNum'] = results['sceneNum']
|
|
292
|
+
|
|
293
|
+
else:
|
|
294
|
+
print("Data or file not passed. Ending arrayResults")
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
filledFront, filledBack, frontcopy = _cleanDataFrameResults(
|
|
298
|
+
mattype, rearMat, Wm2Front, Wm2Back,
|
|
299
|
+
fillcleanedSensors=fillcleanedSensors)
|
|
300
|
+
|
|
301
|
+
POA = filledBack.apply(lambda x: x*module.bifi + filledFront)
|
|
302
|
+
|
|
303
|
+
# Statistics Calculations
|
|
304
|
+
|
|
305
|
+
dfst['POA_eff'] = POA.mean(axis=1)
|
|
306
|
+
|
|
307
|
+
dfst['Gfront_mean'] = Wm2Front.mean(axis=1)
|
|
308
|
+
|
|
309
|
+
if len(rearMat) > 0:
|
|
310
|
+
dfst['Grear_mean'] = Wm2Back.mean(axis=1)
|
|
311
|
+
dfst['Pout_raw'] = module.calculatePerformance(
|
|
312
|
+
effective_irradiance=dfst['POA_eff'],
|
|
313
|
+
temp_air=temp_air, wind_speed=wind_speed, temp_cell=temp_cell)
|
|
314
|
+
dfst['Pout_Gfront'] = module.calculatePerformance(
|
|
315
|
+
effective_irradiance=dfst['Gfront_mean'], CECMod=CECMod2,
|
|
316
|
+
temp_air=temp_air, wind_speed=wind_speed, temp_cell=temp_cell)
|
|
317
|
+
dfst['BGG'] = dfst['Grear_mean']*100*module.bifi/dfst['Gfront_mean']
|
|
318
|
+
dfst['BGE'] = ((dfst['Pout_raw'] - dfst['Pout_Gfront']) * 100 /
|
|
319
|
+
dfst['Pout_Gfront'])
|
|
320
|
+
dfst['Mismatch'] = mismatch.mismatch_fit2(POA.T) # value in percentage [%]
|
|
321
|
+
dfst['Pout'] = dfst['Pout_raw']*(1-dfst['Mismatch']/100)
|
|
322
|
+
|
|
323
|
+
dfst['Wind Speed'] = wind_speed
|
|
324
|
+
if "dni" in kwargs:
|
|
325
|
+
dfst['DNI'] = kwargs['dni']
|
|
326
|
+
if "dhi" in kwargs:
|
|
327
|
+
dfst['DHI'] = kwargs['dhi']
|
|
328
|
+
if "ghi" in kwargs:
|
|
329
|
+
dfst['GHI'] = kwargs['ghi']
|
|
330
|
+
dfst['Wind Speed'] = wind_speed
|
|
331
|
+
|
|
332
|
+
return dfst
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def calculatePerformanceGencumsky(csvfile=None, results=None,
|
|
336
|
+
bifacialityfactor=1.0,
|
|
337
|
+
fillcleanedSensors=False):
|
|
338
|
+
'''
|
|
339
|
+
Compile calculate results for cumulative 1 axis tracking routine
|
|
340
|
+
|
|
341
|
+
Parameters
|
|
342
|
+
----------
|
|
343
|
+
csvfile : numeric list
|
|
344
|
+
Compiled Results data
|
|
345
|
+
results : numeric list
|
|
346
|
+
compiled Results data
|
|
347
|
+
agriPV : Bool
|
|
348
|
+
Turns off cleaning for ground material
|
|
349
|
+
|
|
350
|
+
Returns
|
|
351
|
+
-------
|
|
352
|
+
dfst : dataframe
|
|
353
|
+
Dataframe with the complied and calculated results for the sim,
|
|
354
|
+
including: POA_eff: Avg of [(mean of clean Gfront) + clean Grear *
|
|
355
|
+
bifaciality factor]
|
|
356
|
+
Gfront_mean: mean of clean Gfront
|
|
357
|
+
Grear_mean: mean of clean Grear
|
|
358
|
+
BGG: Bifacial Gain in Irradiance, [Grear_mean * 100 *
|
|
359
|
+
bifacialityfactor/Gfront_mean
|
|
360
|
+
|
|
361
|
+
'''
|
|
362
|
+
|
|
363
|
+
import pandas as pd
|
|
364
|
+
|
|
365
|
+
def _dict2DF(df, key):
|
|
366
|
+
return pd.DataFrame(dict([ (k,pd.Series(v))
|
|
367
|
+
for k,v in dict(zip(df.index, df[key])).items() ])).T
|
|
368
|
+
|
|
369
|
+
dfst = pd.DataFrame()
|
|
370
|
+
|
|
371
|
+
if csvfile is not None:
|
|
372
|
+
results = pd.read_csv(csvfile)
|
|
373
|
+
Wm2Front = results['Wm2Front'
|
|
374
|
+
].str.strip('[]').str.split(',',
|
|
375
|
+
expand=True).astype(float)
|
|
376
|
+
Wm2Back = results['Wm2Back'
|
|
377
|
+
].str.strip('[]').str.split(',',
|
|
378
|
+
expand=True).astype(float)
|
|
379
|
+
mattype = results['mattype'
|
|
380
|
+
].str.strip('[]').str.split(',',
|
|
381
|
+
expand=True)
|
|
382
|
+
rearMat = results['rearMat'
|
|
383
|
+
].str.strip('[]').str.split(',',
|
|
384
|
+
expand=True)
|
|
385
|
+
|
|
386
|
+
if 'modNum' in results:
|
|
387
|
+
dfst['module'] = results['modNum']
|
|
388
|
+
if 'rowNum' in results:
|
|
389
|
+
dfst['row'] = results['rowNum']
|
|
390
|
+
if 'sceneNum' in results:
|
|
391
|
+
dfst['sceneNum'] = results['sceneNum']
|
|
392
|
+
else:
|
|
393
|
+
if results is not None:
|
|
394
|
+
Wm2Front = _dict2DF(results, 'Wm2Front')
|
|
395
|
+
mattype = _dict2DF(results, 'mattype')
|
|
396
|
+
if 'Wm2Back' in results:
|
|
397
|
+
Wm2Back = _dict2DF(results,'Wm2Back')
|
|
398
|
+
else:
|
|
399
|
+
Wm2Back = pd.DataFrame([0])
|
|
400
|
+
if 'rearMat' in results:
|
|
401
|
+
rearMat = _dict2DF(results, 'rearMat')
|
|
402
|
+
else:
|
|
403
|
+
rearMat = pd.DataFrame(None)
|
|
404
|
+
|
|
405
|
+
if 'modNum' in results:
|
|
406
|
+
dfst['module'] = results['modNum']
|
|
407
|
+
if 'rowNum' in results:
|
|
408
|
+
dfst['row'] = results['rowNum']
|
|
409
|
+
if 'sceneNum' in results:
|
|
410
|
+
dfst['sceneNum'] = results['sceneNum']
|
|
411
|
+
|
|
412
|
+
else:
|
|
413
|
+
print("Data or file not passed. Ending calculatePerformanceGencumsky")
|
|
414
|
+
return
|
|
415
|
+
|
|
416
|
+
# Data gets cleaned but need to maintain same number of sensors
|
|
417
|
+
# due to adding for the various tracker angles.
|
|
418
|
+
filledFront, filledBack, frontcopy = _cleanDataFrameResults(
|
|
419
|
+
mattype, rearMat, Wm2Front, Wm2Back,
|
|
420
|
+
fillcleanedSensors=fillcleanedSensors)
|
|
421
|
+
cumFront = []
|
|
422
|
+
cumWM2 = []
|
|
423
|
+
cumBack = []
|
|
424
|
+
cumRow = []
|
|
425
|
+
cumMod = []
|
|
426
|
+
cumScene = []
|
|
427
|
+
Grear_mean = []
|
|
428
|
+
# Gfront_mean = []
|
|
429
|
+
POA_eff = []
|
|
430
|
+
|
|
431
|
+
# NOTE change 26.07.22 'row' -> 'rowNum' and 'mod' -> 'ModNumber
|
|
432
|
+
# NOTE change March 13 2024 ModNumber -> modNum
|
|
433
|
+
#for rownum in results['rowNum'].unique():
|
|
434
|
+
# for modnum in results['modNum'].unique():
|
|
435
|
+
for i, df in results.groupby(['rowNum','modNum','sceneNum']):
|
|
436
|
+
#mask = (results['rowNum'] == rownum) & (
|
|
437
|
+
# results['modNum'] == modnum)
|
|
438
|
+
cumBack.append(list(filledBack.loc[df.index].sum(axis=0, min_count=1)))
|
|
439
|
+
cumFront.append(filledFront.loc[df.index].sum(axis=0, min_count=1))
|
|
440
|
+
cumWM2.append(list(frontcopy.loc[df.index].sum(axis=0, min_count=1)))
|
|
441
|
+
cumRow.append(i[0])
|
|
442
|
+
cumMod.append(i[1])
|
|
443
|
+
cumScene.append(i[2])
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
# Maybe this would be faster by first doing the DF with the above,
|
|
447
|
+
# exploding the column and calculating.
|
|
448
|
+
POA_eff.append(list(
|
|
449
|
+
(filledBack.loc[df.index].apply(lambda x: x*bifacialityfactor +
|
|
450
|
+
filledFront.loc[df.index])).sum(axis=0)))
|
|
451
|
+
Grear_mean.append(filledBack.loc[df.index].sum(axis=0, min_count=1).mean())
|
|
452
|
+
# Gfront_mean.append(filledFront[mask].sum(axis=0).mean())
|
|
453
|
+
|
|
454
|
+
dfst = pd.DataFrame(zip(cumRow, cumMod, cumScene, cumFront, cumWM2, cumBack, Grear_mean,
|
|
455
|
+
POA_eff), columns=('rowNum', 'modNum','sceneNum', 'Gfront_mean',
|
|
456
|
+
'Wm2Front', 'Wm2Back', 'Grear_mean',
|
|
457
|
+
'POA_eff'))
|
|
458
|
+
|
|
459
|
+
dfst['BGG'] = dfst['Grear_mean']*100*bifacialityfactor/dfst['Gfront_mean']
|
|
460
|
+
|
|
461
|
+
# Reordering columns
|
|
462
|
+
cols = ['rowNum', 'modNum','sceneNum', 'BGG', 'Gfront_mean', 'Grear_mean', 'POA_eff',
|
|
463
|
+
'Wm2Front','Wm2Back']
|
|
464
|
+
dfst = dfst[cols]
|
|
465
|
+
|
|
466
|
+
return dfst
|