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,461 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Tue Mar 26 20:16:47 2019
4
+
5
+ @author: sayala
6
+ """
7
+
8
+ from deprecated import deprecated
9
+
10
+
11
+
12
+ def _sensorupsampletocellsbyInterpolation(df, cellsy):
13
+ '''
14
+
15
+ Function for when sensorsy in the results are less than cellsy desired.
16
+ Interpolates the dataframe.
17
+
18
+ #2DO: improve interpolation with pandas. right onw it's row by row.
19
+
20
+ _sensorupsampletocellsbyInterpolation(df, cellsy)
21
+ '''
22
+
23
+ import pandas as pd
24
+ import numpy as np
25
+
26
+ sensorsy = len(df)
27
+
28
+ #2DO: Update this section to match bifacialvf
29
+ cellCenterPVM=[]
30
+ for i in range (0, cellsy):
31
+ cellCenterPVM.append((i*sensorsy/cellsy+(i+1)*sensorsy/cellsy)/2)
32
+
33
+ df2 = pd.DataFrame()
34
+ for j in range (0, len(df.keys())):
35
+ A = list(df[df.keys()[j]])
36
+ B= np.interp(cellCenterPVM, list(range(0,sensorsy)), A)
37
+ df2[df.keys()[j]]=B
38
+
39
+ return df2
40
+
41
+ def _sensorsdownsampletocellsbyAverage(df, cellsy):
42
+ '''
43
+ df = dataframe with rows indexed by number (i.e. 0 to sensorsy) where sensorsy > cellsy
44
+ cellsy = int. usually 8 or 12.
45
+
46
+ example:
47
+ F_centeraverages = _sensorsdownsampletocellsbyAverage(F, cellsy)
48
+ '''
49
+ import numpy as np
50
+ import pandas as pd
51
+
52
+ edges=len(df)-np.floor(len(df)/(cellsy))*(cellsy)
53
+ edge1=int(np.floor(edges/2))
54
+ edge2=int(edges-edge1)
55
+ A = list(range(df.index[0]+edge1, df.index[-1]-edge2+2, int(np.floor(len(df)/(cellsy)))))
56
+ B = range(0,len(A)-1,1)
57
+ C = [df.iloc[A[x]:A[x+1]].mean(axis=0) for x in B]
58
+ df_centeraverages=pd.DataFrame(C)
59
+
60
+ return df_centeraverages
61
+
62
+ def _sensorsdownsampletocellbyCenter(df, cellsy):
63
+ '''
64
+ df = dataframe with rows indexed by number (i.e. 0 to sensorsy) where sensorsy > cellsy
65
+ cellsy = int. usually 8 or 12.
66
+
67
+ example:
68
+ F_centervalues = _sensorsdownsampletocellbyCenter(F, cellsy)
69
+ '''
70
+
71
+ import numpy as np
72
+
73
+
74
+ edges=len(df)-np.floor(len(df)/(cellsy))*(cellsy)
75
+ edge1=int(np.floor(edges/2))
76
+ edge2=int(edges-edge1)
77
+ A = list(range(df.index[0]+edge1, df.index[-1]-edge2+2, int(np.floor(len(df)/(cellsy)))))
78
+ A = [int(x+(A[1]-A[0])*0.5) for x in A]
79
+ A = A[:-1]
80
+ df_centervalues=df.loc[A]
81
+ df_centervalues=df_centervalues.reset_index(drop=True)
82
+
83
+ return df_centervalues
84
+
85
+ def _setupforPVMismatch(portraitorlandscape, sensorsy, numcells=72):
86
+ r''' Sets values for calling PVMismatch, for ladscape or portrait modes and
87
+
88
+ Example:
89
+ stdpl, cellsx, cellsy = _setupforPVMismatch(portraitorlandscape='portrait', sensorsy=100):
90
+ '''
91
+
92
+ import numpy as np
93
+
94
+ # cell placement for 'portrait'.
95
+ if numcells == 72:
96
+ stdpl=np.array([[0, 23, 24, 47, 48, 71],
97
+ [1, 22, 25, 46, 49, 70],
98
+ [2, 21, 26, 45, 50, 69],
99
+ [3, 20, 27, 44, 51, 68],
100
+ [4, 19, 28, 43, 52, 67],
101
+ [5, 18, 29, 42, 53, 66],
102
+ [6, 17, 30, 41, 54, 65],
103
+ [7, 16, 31, 40, 55, 64],
104
+ [8, 15, 32, 39, 56, 63],
105
+ [9, 14, 33, 38, 57, 62],
106
+ [10, 13, 34, 37, 58, 61],
107
+ [11, 12, 35, 36, 59, 60]])
108
+
109
+ elif numcells == 96:
110
+ stdpl=np.array([[0, 23, 24, 47, 48, 71, 72, 95],
111
+ [1, 22, 25, 46, 49, 70, 73, 94],
112
+ [2, 21, 26, 45, 50, 69, 74, 93],
113
+ [3, 20, 27, 44, 51, 68, 75, 92],
114
+ [4, 19, 28, 43, 52, 67, 76, 91],
115
+ [5, 18, 29, 42, 53, 66, 77, 90],
116
+ [6, 17, 30, 41, 54, 65, 78, 89],
117
+ [7, 16, 31, 40, 55, 64, 79, 88],
118
+ [8, 15, 32, 39, 56, 63, 80, 87],
119
+ [9, 14, 33, 38, 57, 62, 81, 86],
120
+ [10, 13, 34, 37, 58, 61, 82, 85],
121
+ [11, 12, 35, 36, 59, 60, 83, 84]])
122
+ else:
123
+ print("Error. Only 72 and 96 cells modules supported at the moment. Change numcells to either of this options!")
124
+ return
125
+
126
+ if portraitorlandscape == 'landscape':
127
+ stdpl = stdpl.transpose()
128
+ elif portraitorlandscape != 'portrait':
129
+ print("Error. portraitorlandscape variable must either be 'landscape' or 'portrait'")
130
+ return
131
+
132
+ cellsx = len(stdpl[1]); cellsy = len(stdpl)
133
+
134
+ return stdpl, cellsx, cellsy
135
+
136
+
137
+ def calculatePVMismatch(pvsys, stdpl, cellsx, cellsy, Gpoat):
138
+ r''' calls PVMismatch with all the pre-generated values on bifacial_radiance
139
+
140
+ Example:
141
+ PowerAveraged, PowerDetailed = def calculatePVMismatch(pvsys, stdpl, cellsx, cellsy, Gpoat)
142
+
143
+ '''
144
+
145
+ import numpy as np
146
+
147
+ if np.mean(Gpoat) < 0.001:
148
+ PowerAveraged = 0
149
+ PowerDetailed = 0
150
+ else:
151
+ # makes the system # 1 module, in portrait mode.
152
+ G=np.array([Gpoat]).transpose()
153
+ H = np.ones([1,cellsx])
154
+ array_det = np.dot(G,H)
155
+ array_avg = np.ones([cellsy,cellsx])*np.mean(Gpoat)
156
+
157
+ # ACtually do calculations
158
+ pvsys.setSuns({0: {0: [array_avg, stdpl]}})
159
+ PowerAveraged=pvsys.Pmp
160
+
161
+ pvsys.setSuns({0: {0: [array_det, stdpl]}})
162
+ PowerDetailed=pvsys.Pmp
163
+
164
+ return PowerAveraged, PowerDetailed
165
+
166
+ def mismatch_fit3(data):
167
+ '''
168
+ Electrical mismatch calculation following Progress in PV paper
169
+ Estimating and parameterizing mismatch power loss in bifacial photovoltaic systems
170
+ Chris Deline, Silvana Ayala Pelaez,Sara MacAlpine,Carlos Olalla
171
+ https://doi.org/10.1002/pip.3259
172
+
173
+ .. deprecated:: 0.4.3
174
+ This fitted model is deprecated in favor of :func:`mismatch_fit2` which has
175
+ better agreement with the experimental data.
176
+
177
+ Parameters
178
+ ----------
179
+ data : np.ndarray, pd.Series, pd.DataFrame
180
+ Gtotal irradiance measurements. Each column is the irradiance for a module
181
+ at a specific time.
182
+
183
+ Returns
184
+ -------
185
+ fit3 : Float or pd.Series
186
+ Returns mismatch values for each module in percentage [%].
187
+
188
+ Equation: 1/(n^2*Gavg)*Sum Sum (abs(G_i - G_j))
189
+ ## Note: starting with Pandas 1.0.0 this function will not work on Series objects.
190
+ '''
191
+ import numpy as np
192
+ import pandas as pd
193
+
194
+ if type(data) == np.ndarray:
195
+ data = pd.DataFrame(data)
196
+
197
+ datac = data[~np.isnan(data)]
198
+ mad = mad_fn(datac) # (percentage)
199
+ mad2 = mad**2
200
+
201
+ fit3 = 0.054*mad + 0.068*mad2
202
+
203
+ if fit3.__len__() == 1:
204
+ if isinstance(fit3, pd.Series):
205
+ fit3 = float(fit3.iloc[0])
206
+ else:
207
+ fit3 = float(fit3)
208
+
209
+ return fit3
210
+
211
+
212
+ def mismatch_fit2(data):
213
+ '''
214
+ Electrical mismatch calculation following Progress in PV paper
215
+ Estimating and parameterizing mismatch power loss in bifacial photovoltaic systems
216
+ Chris Deline, Silvana Ayala Pelaez,Sara MacAlpine,Carlos Olalla
217
+ https://doi.org/10.1002/pip.3259
218
+
219
+ Parameters
220
+ ----------
221
+ data : np.ndarray, pd.Series, pd.DataFrame
222
+ Gtotal irradiance measurements. Each column is the irradiance for a module
223
+ at a specific time.
224
+
225
+ Returns
226
+ -------
227
+ fit2 : Float or pd.Series
228
+ Returns mismatch values for each module in percentage [%].
229
+
230
+ Equation: 1/(n^2*Gavg)*Sum Sum (abs(G_i - G_j))
231
+ ## Note: starting with Pandas 1.0.0 this function will not work on Series objects.
232
+ '''
233
+ import numpy as np
234
+ import pandas as pd
235
+
236
+ if type(data) == np.ndarray:
237
+ data = pd.DataFrame(data)
238
+
239
+ datac = data[~np.isnan(data)]
240
+ mad = mad_fn(datac) # (percentage)
241
+ mad2 = mad**2
242
+
243
+ fit2 = 0.142*mad + 0.032*mad2
244
+
245
+ if fit2.__len__() == 1:
246
+ if isinstance(fit2, pd.Series):
247
+ fit2 = float(fit2.iloc[0])
248
+ else:
249
+ fit2 = float(fit2)
250
+
251
+ return fit2
252
+
253
+
254
+ def mad_fn(data, axis='index'):
255
+ '''
256
+ Mean average deviation calculation for mismatch purposes.
257
+
258
+ Parameters
259
+ ----------
260
+ data : np.ndarray or pd.Series or pd.DataFrame
261
+ Gtotal irradiance measurements. If data is a pandas.DataFrame, one
262
+ MAD/Average is returned for each index, based on values across columns.
263
+
264
+ axis : {0 or 'index', 1 or 'columns'}, default 'index'
265
+ Calculate mean average deviation across rows (default) or columns for 2D data
266
+
267
+ * 0, or 'index' : MAD calculated across rows.
268
+ * 1, or 'columns' : MAD calculated across columns.
269
+ Returns
270
+ -------
271
+ scalar or pd.Series: return MAD / Average [%]. Scalar for a 1D array, Series for 2D.
272
+
273
+
274
+ Equation: 1/(n^2*Gavg)*Sum Sum (abs(G_i - G_j)) * 100[%]
275
+
276
+ '''
277
+ import numpy as np
278
+ import pandas as pd
279
+ def _mad_1D(data): #1D calculation of MAD
280
+ return (np.abs(np.subtract.outer(data,data)).sum()/float(data.__len__())**2 / np.mean(data))*100
281
+ if type(axis) == str:
282
+ try:
283
+ axis = {"index": 0, "rows": 0, 'columns':1}[axis]
284
+ except KeyError:
285
+ raise Exception('Incorrect index string in mad_fn. options: index, rows, columns.')
286
+
287
+ ndim = data.ndim
288
+ if ndim == 2 and axis==0:
289
+ data = data.T
290
+ # Pandas returns a notimplemented error if this is a DataFrame.
291
+ if (type(data) == pd.Series):
292
+ data = data.to_numpy()
293
+
294
+ if type(data) == pd.DataFrame:
295
+ temp = data.apply(pd.Series.to_numpy, axis=1)
296
+ return(temp.apply(_mad_1D))
297
+ elif ndim ==2: #2D array
298
+ return [_mad_1D(i) for i in data]
299
+ else:
300
+ return _mad_1D(data)
301
+
302
+
303
+ @deprecated(reason='This analysis script will be moved to its own tutorial' +\
304
+ ' file in a future release.', version='0.5.0')
305
+ def analysisIrradianceandPowerMismatch(testfolder, writefiletitle, portraitorlandscape, bififactor, numcells=72, downsamplingmethod='byCenter'):
306
+ r'''
307
+ Use this when sensorsy calculated with bifacial_radiance > cellsy
308
+
309
+ Reads and calculates power output and mismatch for each file in the
310
+ testfolder where all the bifacial_radiance irradiance results .csv are saved.
311
+ First load each file, cleans it and resamples it to the numsensors set in this function,
312
+ and then calculates irradiance mismatch and PVMismatch power output for averaged, minimum,
313
+ or detailed irradiances on each cell for the cases of A) only 12 or 8 downsmaples values are
314
+ considered (at the center of each cell), and B) 12 or 8 values are obtained from averaging
315
+ all the irradiances falling in the area of the cell (No edges or inter-cell spacing are considered
316
+ at this moment). Then it saves all the A and B irradiances, as well as the cleaned/resampled
317
+ front and rear irradiances.
318
+
319
+ Ideally sensorsy in the read data is >> 12 to give results for the irradiance mismatch in the cell.
320
+
321
+ Also ideally n
322
+
323
+ Parameters
324
+ ----------
325
+ testfolder: folder containing output .csv files for bifacial_radiance
326
+ writefiletitle: .csv title where the output results will be saved.
327
+ portraitorlandscape: 'portrait' or 'landscape', for PVMismatch input
328
+ which defines the electrical interconnects inside the module.
329
+ bififactor: bifaciality factor of the module. Max 1.0. ALL Rear irradiance values saved include the bifi-factor.
330
+ downsampling method: 1 - 'byCenter' - 2 - 'byAverage'
331
+
332
+ Example:
333
+
334
+ # User information.
335
+ import bifacial_radiance
336
+ testfolder=r'C:\Users\sayala\Documents\HPC_Scratch\EUPVSEC\HPC Tracking Results\RICHMOND\Bifacial_Radiance Results\PVPMC_0\results'
337
+ writefiletitle= r'C:\Users\sayala\Documents\HPC_Scratch\EUPVSEC\HPC Tracking Results\RICHMOND\Bifacial_Radiance Results\PVPMC_0\test_df.csv'
338
+ sensorsy=100
339
+ portraitorlandscape = 'portrait'
340
+ analysis.analysisIrradianceandPowerMismatch(testfolder, writefiletitle, portraitorlandscape, bififactor=1.0, numcells=72)
341
+
342
+ '''
343
+ from bifacial_radiance import load
344
+ import os, glob
345
+ import pandas as pd
346
+
347
+ # Default variables
348
+ numpanels=1 # 1 at the moment, necessary for the cleaning routine.
349
+ automatic=True
350
+
351
+ #loadandclean
352
+ # testfolder = r'C:\Users\sayala\Documents\HPC_Scratch\EUPVSEC\PinPV_Bifacial_Radiance_Runs\HPCResults\df4_FixedTilt\FixedTilt_Cairo_C_0.15\results'
353
+ filelist = sorted(os.listdir(testfolder))
354
+ #filelist = sorted(glob.glob(os.path.join('testfolder','*.csv')))
355
+ print('{} files in the directory'.format(filelist.__len__()))
356
+
357
+ # Check number of sensors on data.
358
+ temp = load.read1Result(os.path.join(testfolder,filelist[0]))
359
+ sensorsy = len(temp)
360
+
361
+ # Setup PVMismatch parameters
362
+ stdpl, cellsx, cellsy = _setupforPVMismatch(portraitorlandscape=portraitorlandscape, sensorsy=sensorsy, numcells=numcells)
363
+
364
+ F=pd.DataFrame()
365
+ B=pd.DataFrame()
366
+ for z in range(0, filelist.__len__()):
367
+ data=load.read1Result(os.path.join(testfolder,filelist[z]))
368
+ [frontres, backres] = load.deepcleanResult(data, sensorsy=sensorsy, numpanels=numpanels, automatic=automatic)
369
+ F[filelist[z]]=frontres
370
+ B[filelist[z]]=backres
371
+
372
+ B = B*bififactor
373
+ # Downsample routines:
374
+ if sensorsy > cellsy:
375
+ if downsamplingmethod == 'byCenter':
376
+ print("Sensors y > cellsy; Downsampling data by finding CellCenter method")
377
+ F = _sensorsdownsampletocellbyCenter(F, cellsy)
378
+ B = _sensorsdownsampletocellbyCenter(B, cellsy)
379
+ elif downsamplingmethod == 'byAverage':
380
+ print("Sensors y > cellsy; Downsampling data by Averaging data into Cells method")
381
+ F = _sensorsdownsampletocellsbyAverage(F, cellsy)
382
+ B = _sensorsdownsampletocellsbyAverage(B, cellsy)
383
+ else:
384
+ print ("Sensors y > cellsy for your module. Select a proper downsampling method ('byCenter', or 'byAverage')")
385
+ return
386
+ elif sensorsy < cellsy:
387
+ print("Sensors y < cellsy; Upsampling data by Interpolation")
388
+ F = _sensorupsampletocellsbyInterpolation(F, cellsy)
389
+ B = _sensorupsampletocellsbyInterpolation(B, cellsy)
390
+ elif sensorsy == cellsy:
391
+ print ("Same number of sensorsy and cellsy for your module.")
392
+ F = F
393
+ B = B
394
+
395
+ # Calculate POATs
396
+ Poat = F+B
397
+
398
+ # Define arrays to fill in:
399
+ Pavg_all=[]; Pdet_all=[]
400
+ Pavg_front_all=[]; Pdet_front_all=[]
401
+ colkeys = F.keys()
402
+
403
+ import pvmismatch
404
+
405
+ if cellsx*cellsy == 72:
406
+ cell_pos = pvmismatch.pvmismatch_lib.pvmodule.STD72
407
+ elif cellsx*cellsy == 96:
408
+ cell_pos = pvmismatch.pvmismatch_lib.pvmodule.STD96
409
+ else:
410
+ print("Error. Only 72 and 96 cells modules supported at the moment. Change numcells to either of this options!")
411
+ return
412
+
413
+ pvmod=pvmismatch.pvmismatch_lib.pvmodule.PVmodule(cell_pos=cell_pos)
414
+ pvsys = pvmismatch.pvsystem.PVsystem(numberStrs=1, numberMods=1, pvmods=pvmod)
415
+
416
+
417
+ # Calculate powers for each hour:
418
+ for i in range(0,len(colkeys)):
419
+ Pavg, Pdet = calculatePVMismatch(pvsys = pvsys, stdpl=stdpl, cellsx=cellsx, cellsy=cellsy, Gpoat=list(Poat[colkeys[i]]/1000))
420
+ Pavg_front, Pdet_front = calculatePVMismatch(pvsys = pvsys, stdpl = stdpl, cellsx = cellsx, cellsy = cellsy, Gpoat= list(F[colkeys[i]]/1000))
421
+ Pavg_all.append(Pavg)
422
+ Pdet_all.append(Pdet)
423
+ Pavg_front_all.append(Pavg_front)
424
+ Pdet_front_all.append(Pdet_front)
425
+
426
+ ## Rename Rows and save dataframe and outputs.
427
+ F.index='FrontIrradiance_cell_'+F.index.astype(str)
428
+ B.index='BackIrradiance_cell_'+B.index.astype(str)
429
+ Poat.index='POAT_Irradiance_cell_'+Poat.index.astype(str)
430
+
431
+ # Statistics Calculatoins
432
+ dfst=pd.DataFrame()
433
+ dfst['MAD/G_Total'] = mad_fn(Poat)
434
+ dfst['Front_MAD/G_Total'] = mad_fn(F)
435
+ dfst['MAD/G_Total**2'] = dfst['MAD/G_Total']**2
436
+ dfst['Front_MAD/G_Total**2'] = dfst['Front_MAD/G_Total']**2
437
+ dfst['poat'] = Poat.mean()
438
+ dfst['gfront'] = F.mean()
439
+ dfst['grear'] = B.mean()
440
+ dfst['bifi_ratio'] = dfst['grear']/dfst['gfront']
441
+ dfst['stdev'] = Poat.std()/ dfst['poat']
442
+ dfst.index=Poat.columns.astype(str)
443
+
444
+ # Power Calculations/Saving
445
+ Pout=pd.DataFrame()
446
+ Pout['Pavg']=Pavg_all
447
+ Pout['Pdet']=Pdet_all
448
+ Pout['Front_Pavg']=Pavg_front_all
449
+ Pout['Front_Pdet']=Pdet_front_all
450
+ Pout['Mismatch_rel'] = 100-(Pout['Pdet']*100/Pout['Pavg'])
451
+ Pout['Front_Mismatch_rel'] = 100-(Pout['Front_Pdet']*100/Pout['Front_Pavg'])
452
+ Pout.index=Poat.columns.astype(str)
453
+
454
+ ## Save CSV as one long row
455
+ df_all = pd.concat([Pout, dfst, Poat.T, F.T, B.T], axis=1)
456
+ df_all.to_csv(writefiletitle)
457
+ print("Saved Results to ", writefiletitle)
458
+
459
+
460
+
461
+