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.
Files changed (63) hide show
  1. bifacial_radiance/HPCScripts/BasicSimulations/addNewModule.py +15 -0
  2. bifacial_radiance/HPCScripts/BasicSimulations/dask_on_node.sh +11 -0
  3. bifacial_radiance/HPCScripts/BasicSimulations/run_sbatch.sbatch +51 -0
  4. bifacial_radiance/HPCScripts/BasicSimulations/simulate_fixedtilt_gencumsky.py +110 -0
  5. bifacial_radiance/HPCScripts/BasicSimulations/simulate_fixedtilt_gendaylit.py +102 -0
  6. bifacial_radiance/HPCScripts/BasicSimulations/simulate_tracking_gendaylit.py +126 -0
  7. bifacial_radiance/HPCScripts/Other Examples (unorganized)/PuertoRico.py +168 -0
  8. bifacial_radiance/HPCScripts/Other Examples (unorganized)/PuertoRico_2.py +166 -0
  9. bifacial_radiance/HPCScripts/Other Examples (unorganized)/PuertoRico_Original.py +195 -0
  10. bifacial_radiance/HPCScripts/Other Examples (unorganized)/basic_module_sampling.py +154 -0
  11. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_B.py +162 -0
  12. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_Cases.py +122 -0
  13. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_CasesMonth.py +142 -0
  14. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_PRNew.py +91 -0
  15. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_PRNewP2.py +95 -0
  16. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_TreeResults.py +108 -0
  17. bifacial_radiance/HPCScripts/Other Examples (unorganized)/compile_basic_module_sampling.py +103 -0
  18. bifacial_radiance/HPCScripts/Other Examples (unorganized)/simulate_JackHourly.py +160 -0
  19. bifacial_radiance/HPCScripts/Other Examples (unorganized)/simulate_improvedArray_Oct2127.py +623 -0
  20. bifacial_radiance/TEMP/.gitignore +4 -0
  21. bifacial_radiance/__init__.py +24 -0
  22. bifacial_radiance/data/CEC Modules.csv +16860 -0
  23. bifacial_radiance/data/default.ini +65 -0
  24. bifacial_radiance/data/falsecolor.exe +0 -0
  25. bifacial_radiance/data/gencumsky/License.txt +54 -0
  26. bifacial_radiance/data/gencumsky/Makefile +17 -0
  27. bifacial_radiance/data/gencumsky/README.txt +9 -0
  28. bifacial_radiance/data/gencumsky/Solar Irradiation Modelling.doc +0 -0
  29. bifacial_radiance/data/gencumsky/Sun.cpp +118 -0
  30. bifacial_radiance/data/gencumsky/Sun.h +45 -0
  31. bifacial_radiance/data/gencumsky/average_val.awk +3 -0
  32. bifacial_radiance/data/gencumsky/cPerezSkyModel.cpp +238 -0
  33. bifacial_radiance/data/gencumsky/cPerezSkyModel.h +57 -0
  34. bifacial_radiance/data/gencumsky/cSkyVault.cpp +536 -0
  35. bifacial_radiance/data/gencumsky/cSkyVault.h +86 -0
  36. bifacial_radiance/data/gencumsky/climateFile.cpp +312 -0
  37. bifacial_radiance/data/gencumsky/climateFile.h +37 -0
  38. bifacial_radiance/data/gencumsky/cumulative.cal +177 -0
  39. bifacial_radiance/data/gencumsky/cumulative.rad +14 -0
  40. bifacial_radiance/data/gencumsky/cumulativesky_rotated.rad +2 -0
  41. bifacial_radiance/data/gencumsky/gencumulativesky +0 -0
  42. bifacial_radiance/data/gencumsky/gencumulativesky.cpp +269 -0
  43. bifacial_radiance/data/gencumsky/make_gencumskyexe.py +107 -0
  44. bifacial_radiance/data/gencumsky/paths.h +62 -0
  45. bifacial_radiance/data/gencumulativesky +0 -0
  46. bifacial_radiance/data/gencumulativesky.exe +0 -0
  47. bifacial_radiance/data/ground.rad +83 -0
  48. bifacial_radiance/data/module.json +103 -0
  49. bifacial_radiance/gui.py +1696 -0
  50. bifacial_radiance/images/fig1_fixed_small.gif +0 -0
  51. bifacial_radiance/images/fig2_tracked_small.gif +0 -0
  52. bifacial_radiance/load.py +1156 -0
  53. bifacial_radiance/main.py +5673 -0
  54. bifacial_radiance/mismatch.py +461 -0
  55. bifacial_radiance/modelchain.py +299 -0
  56. bifacial_radiance/module.py +1427 -0
  57. bifacial_radiance/performance.py +466 -0
  58. bifacial_radiance/spectral_utils.py +555 -0
  59. bifacial_radiance-0.5.1.dist-info/METADATA +129 -0
  60. bifacial_radiance-0.5.1.dist-info/RECORD +63 -0
  61. bifacial_radiance-0.5.1.dist-info/WHEEL +6 -0
  62. bifacial_radiance-0.5.1.dist-info/licenses/LICENSE +30 -0
  63. 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