• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NREL / bifacial_radiance / 9194573527

22 May 2024 03:56PM UTC coverage: 70.326% (+0.06%) from 70.268%
9194573527

push

github

cdeline
Fix pytests

3728 of 5301 relevant lines covered (70.33%)

1.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.34
/bifacial_radiance/modelchain.py
1
# -*- coding: utf-8 -*-
2
"""
2✔
3
Created on Sat Sep 11 15:48:21 2021
4

5
@author: sayala
6
"""
7

8
# -*- coding: utf-8 -*-
9
"""
2✔
10
Created on Thu Apr 25 16:39:39 2019
11

12
@author: sayala
13
"""
14

15
#import bifacial_radiance
16
#from   bifacial_radiance.config import *
17
#import os
18

19
# DATA_PATH = bifacial_radiance.main.DATA_PATH  # directory with module.json etc.
20

21
def _append_dicts(x, y):
2✔
22
    """python2 compatible way to append 2 dictionaries
23
    """
24
    z = x.copy()   # start with x's keys and values
2✔
25
    z.update(y)    # modifies z with y's keys and values & returns None
2✔
26
    return z
2✔
27

28
def runModelChain(simulationParamsDict, sceneParamsDict, timeControlParamsDict=None, 
2✔
29
                  moduleParamsDict=None, trackingParamsDict=None, torquetubeParamsDict=None, 
30
                  analysisParamsDict=None, cellModuleDict=None, CECModParamsDict=None, 
31
                  frameParamsDict=None, omegaParamsDict=None, pilesParamsDict=None):
32
    """
33
    This calls config.py values, which are arranged into dictionaries,
34
    and runs all the respective processes based on the variables in the config.py.
35
 
36
    To import the variables from a .ini file, use::
37
        
38
        (simulationParamsDict, sceneParamsDict, timeControlParamsDict, moduleParamsDict, 
39
         trackingParamsDict,torquetubeParamsDict,analysisParamsDict,cellModuleDict) = 
40
        bifacial_radiance.load.readconfigurationinputfile(inifile)
41
    
42
    """
43
    
44
    import bifacial_radiance
2✔
45
    import os
2✔
46
    import numpy as np
2✔
47
    import pandas as pd
2✔
48
    
49
    print("\nNew bifacial_radiance simulation starting. ")
2✔
50
    print("Version: ", bifacial_radiance.__version__)
2✔
51
    
52
    if not simulationParamsDict.get('testfolder'):
2✔
53
        simulationParamsDict['testfolder'] = bifacial_radiance.main._interactive_directory(
×
54
            title='Select or create an empty directory for the Radiance tree')
55

56
    testfolder = simulationParamsDict['testfolder']
2✔
57
    demo = bifacial_radiance.RadianceObj(
2✔
58
        simulationParamsDict['simulationname'], path=testfolder)  # Create a RadianceObj 'object'
59

60
    # Save INIFILE in folder
61
    inifilename = os.path.join(
2✔
62
        simulationParamsDict['testfolder'],  'simulation.ini')
63
    bifacial_radiance.load.savedictionariestoConfigurationIniFile(simulationParamsDict, sceneParamsDict, timeControlParamsDict,
2✔
64
                                                                  moduleParamsDict, trackingParamsDict, torquetubeParamsDict, analysisParamsDict, 
65
                                                                  cellModuleDict, CECModParamsDict, 
66
                                                                  frameParamsDict, omegaParamsDict, pilesParamsDict,
67
                                                                  inifilename)
68
    # re-load configuration file to make sure all booleans are converted
69
    (simulationParamsDict, sceneParamsDict, timeControlParamsDict, 
2✔
70
     moduleParamsDict, trackingParamsDict,torquetubeParamsDict,
71
     analysisParamsDict,cellModuleDict, CECModParamsDict, frameParamsDict, 
72
     omegaParamsDict, pilesParamsDict ) = \
73
        bifacial_radiance.load.readconfigurationinputfile(inifilename)
74
    
75
    # Load weatherfile
76

77
    if simulationParamsDict['getEPW']:
2✔
78
        simulationParamsDict['weatherFile'] = demo.getEPW(
×
79
            simulationParamsDict['latitude'], simulationParamsDict['longitude'])  # pull EPW data for any global lat/lon
80
  
81
    if simulationParamsDict['selectTimes']: 
2✔
82
        starttime = timeControlParamsDict['starttime'] 
2✔
83
        endtime = timeControlParamsDict['endtime'] 
2✔
84
    else: # read in full TMY file
85
        starttime = None; endtime=None
×
86
    
87
    if 'coerce_year' in simulationParamsDict:
2✔
88
        coerce_year = simulationParamsDict['coerce_year']
2✔
89
    else:
90
        coerce_year = None
2✔
91
    
92
    if 'weatherFileType' in simulationParamsDict:
2✔
93
        source = simulationParamsDict['weatherFileType']
×
94
        print("Weather file of type ", source, " passed.")
×
95
    else:
96
        source = None
2✔
97

98
    print('Reading weather file {}'.format(simulationParamsDict['weatherFile']))
2✔
99
    metdata = demo.readWeatherFile(simulationParamsDict['weatherFile'],
2✔
100
                                   starttime=starttime, endtime=endtime, 
101
                                   coerce_year=coerce_year, source=source)
102
    
103
    # input albedo number or material name like 'concrete'.  To see options, run this without any input.
104
    demo.setGround(sceneParamsDict['albedo'])
2✔
105
    analysis = None  # initialize default analysis return value to none.
2✔
106

107
    A = demo.printModules()
2✔
108
    
109
    #cellLeveLParams are none by default.
110
    cellModule = None 
2✔
111
    try:
2✔
112
        if simulationParamsDict['cellLevelModule']:
2✔
113
            cellModule = cellModuleDict
×
114
    except: pass
×
115
    
116
    
117
    """
2✔
118
    if not torquetubeParamsDict:
119
        #kwargs = {**torquetubeParamsDict, **moduleParamsDict} #Py3 Only
120
        torquetubeParamsDict = {}
121
    torquetubeParamsDict['axisofrotation'] = simulationParamsDict[
122
                                         'axisofrotationTorqueTube']
123
    """
124
    kwargs = moduleParamsDict
2✔
125
    
126
    if torquetubeParamsDict:
2✔
127
        if not 'visible' in torquetubeParamsDict:
2✔
128
            torquetubeParamsDict['visible'] = simulationParamsDict['torqueTube']
2✔
129
        if 'axisofrotationTorqueTube' in simulationParamsDict:
2✔
130
            torquetubeParamsDict['axisofrotation'] = simulationParamsDict[
2✔
131
                                         'axisofrotationTorqueTube']
132
        
133
    if simulationParamsDict['moduletype'] in A:
2✔
134
        if simulationParamsDict['rewriteModule'] is True:
2✔
135
            
136
            module = demo.makeModule(name=simulationParamsDict['moduletype'],
2✔
137
                                         tubeParams=torquetubeParamsDict,
138
                                         cellModule=cellModule, 
139
                                         frameParams=frameParamsDict,
140
                                         omegaParams=omegaParamsDict, **kwargs)
141

142
        print("\nUsing Pre-determined Module Type: %s " %
2✔
143
              simulationParamsDict['moduletype'])
144
    else:
145
        module = demo.makeModule(name=simulationParamsDict['moduletype'],
×
146
                                     tubeParams=torquetubeParamsDict,
147
                                         frameParams=frameParamsDict,
148
                                         omegaParams=omegaParamsDict,
149
                                     cellModule=cellModule, **kwargs)
150

151
    # module CEC params
152
    if CECModParamsDict:
2✔
153
        module.addCEC(pd.DataFrame(CECModParamsDict, index=[0]))
2✔
154

155
    customObject = None
2✔
156

157
    if "customObject" in sceneParamsDict:
2✔
158
        if sceneParamsDict["customObject"] is not None:
×
159
            if sceneParamsDict["customObject"] != '':
×
160
                customObject = sceneParamsDict['customObject']
×
161
                print("Custom Object Found, will be added to all Scenes.")
×
162
                
163
    if 'gcr' not in sceneParamsDict:  # didn't get gcr passed - need to calculate it
2✔
164
        sceneParamsDict['gcr'] = module.sceney / \
2✔
165
            sceneParamsDict['pitch']
166

167
    if simulationParamsDict['tracking'] == False and simulationParamsDict['cumulativeSky'] == True:
2✔
168
    # Fixed gencumsky condition
169
        scene = demo.makeScene(module=simulationParamsDict['moduletype'], 
2✔
170
                               sceneDict=sceneParamsDict, customtext=customObject)
171
        demo.genCumSky(demo.gencumsky_metfile)  
2✔
172
        
173
        if pilesParamsDict:
2✔
174
            demo.addPiles(spacingPiles=pilesParamsDict['spacingPiles'], 
×
175
                          pile_lenx=pilesParamsDict['pile_lenx'], 
176
                          pile_leny=pilesParamsDict['pile_leny'],
177
                          pile_height=pilesParamsDict['pile_height'])
178
            
179
        octfile = demo.makeOct(demo.getfilelist())
2✔
180
        analysis = bifacial_radiance.AnalysisObj(octfile, demo.name)
2✔
181
        frontscan, backscan = analysis.moduleAnalysis(scene, analysisParamsDict['modWanted'],
2✔
182
                                                      analysisParamsDict['rowWanted'],
183
                                                      analysisParamsDict['sensorsy'])
184
        analysis.analysis(octfile, demo.name, frontscan, backscan)
2✔
185
        print('Bifacial ratio yearly average:  %0.3f' %
2✔
186
              (np.mean(analysis.Wm2Back) / np.mean(analysis.Wm2Front)))
187

188

189
    else:
190
    # Run everything through TrackerDict.    
191

192
        if simulationParamsDict['tracking'] == False:
2✔
193
            trackerdict = demo.set1axis(metdata, 
2✔
194
                                        cumulativesky=simulationParamsDict["cumulativeSky"],
195
                                        fixed_tilt_angle=sceneParamsDict['tilt'],
196
                                        azimuth=sceneParamsDict['azimuth']) 
197
        else:
198
            trackerdict = demo.set1axis(metdata, gcr=sceneParamsDict['gcr'],
2✔
199
                                        azimuth=sceneParamsDict['axis_azimuth'],
200
                                        limit_angle=trackingParamsDict['limit_angle'],
201
                                        angledelta=trackingParamsDict['angle_delta'],
202
                                        backtrack=trackingParamsDict['backtrack'],
203
                                        cumulativesky=simulationParamsDict["cumulativeSky"])
204
            
205

206

207
        if simulationParamsDict['cumulativeSky']:
2✔
208
            trackerdict = demo.genCumSky1axis(trackerdict=trackerdict)
×
209
        else:           
210
            trackerdict = demo.gendaylit1axis()                
2✔
211

212
        trackerdict = demo.makeScene1axis(trackerdict=trackerdict,
2✔
213
                                          module=simulationParamsDict['moduletype'],
214
                                          sceneDict=sceneParamsDict,
215
                                          cumulativesky=simulationParamsDict['cumulativeSky'], customtext=customObject)
216

217
        trackerdict = demo.makeOct1axis(trackerdict=trackerdict)
2✔
218

219
        trackerdict = demo.analysis1axis(trackerdict=trackerdict,
2✔
220
                                         modWanted=analysisParamsDict['modWanted'],
221
                                         rowWanted=analysisParamsDict['rowWanted'],
222
                                         sensorsy=analysisParamsDict['sensorsy'])
223
        
224
        # TODO: Chris, not all functions were saving/returning analysis before. 
225
               # It is also not a very good return as it will only include the last key
226
               # in teh trackerdict for this, but that is what we had before.
227
               # I would consider removing analysis as a return and modifying
228
               # the way teh ini_highAzimuth py test works.
229
               # What was before:         
230
               # analysis = trackerdict[time]['AnalysisObj']
231

232
        # TODO: this is only returning the first AnalysisObj for the trackerdict entry.
233
        #  check this for more complicated scenarios with multiple AnalysisObjs...
234
        # analysis = demo.trackerdict[list(demo.trackerdict.keys())[-1]]['AnalysisObj'][0]
235
        
236

237

238
            
239
            
240
        if not simulationParamsDict['cumulativeSky']:
2✔
241

242
            print("\n--> Calculating Performance values")
2✔
243
            
244
            """
2✔
245
            #CEC Module
246
            if CECModParamsDict:
247
                CECMod = pd.DataFrame(CECModParamsDict, index=[0])
248
            else:
249
                CECMod = None
250
            """
251
            demo.calculateResults1axis()
2✔
252
            demo.exportTrackerDict(savefile=os.path.join('results','Final_Results.csv'),reindex=False)
2✔
253

254
    # Save example image files
255
    #print(simulationParamsDict)
256
    if simulationParamsDict.get('saveImage'):
2✔
257
        if hasattr(demo, 'trackerdict'):
2✔
258
            bestkey = _getDesiredIndex(demo.trackerdict)
2✔
259
            scene = demo.trackerdict[bestkey]['scenes'][0] #TODO: select which sceneNum chosen?
2✔
260
            imagefilename = f'scene_{bestkey}'
2✔
261
            viewfile = None # just use default value for now. Improve later..
2✔
262
        elif hasattr(demo, 'scenes'):
×
263
            scene = demo.scenes[0]
×
264
            viewfile = None # just use default value for now. Improve later..
×
265
            imagefilename = 'scene0'
×
266
        try:
2✔
267
            print("\nSaving scene and module .hdr to images/")
2✔
268
            scene.saveImage(filename=imagefilename, view=viewfile)
2✔
269
            #analysis.makeFalseColor('side.vp')
270
            scene.module.saveImage()
2✔
271
        except:
×
272
            print("Failed to make image")        
×
273

274
    print("Finished! ")
2✔
275
    return demo, analysis
2✔
276

277
def _getDesiredIndex(trackerdict):
2✔
278
    """
279
    Identify 'optimal' best key of trackerdict to use for visualizations.
280

281
    Parameters
282
    ----------
283
    trackerdict : final trackerdict
284

285
    Returns
286
    -------
287
    bestkey
288
    
289
    viewfile
290

291
    """
292
    import pandas as pd
2✔
293
    
294
    df = pd.DataFrame.from_dict(trackerdict, orient='index')
2✔
295
    try:
2✔
296
        df = df[df['scenes'].notna()] 
2✔
297
    except KeyError:
×
298
        print('Error in _getDesiredIndex - trackerdict has no scene defined.')
×
299
        return df.index[-1]
×
300
    # try to find an index close to 25 degree tilt
301
    try:
2✔
302
        df['objective_fn'] = abs(df.surf_tilt - 25) # choose an index closest to 25 tilt with 
2✔
303
        bestkey = df['objective_fn'].idxmin()
2✔
304
    except:
×
305
        bestkey = df.index[-1]  # default to last index
×
306

307
    return bestkey
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc