Repository: NREL/bifacial_radiance

Issue:
Development tests are failing
First two are failing in all env's.  Second two only fail in upgrade-strategy Eager.

FAILED tests/test_bifacial_radiance.py::test_SingleModule_HPC - AssertionError: assert 'groundplane' == 'a0.0.a0.test'
FAILED tests/test_performance.py::test_calculatePerformance - UnboundLocalError: cannot access local variable 'CECMod1' where it is not associated with a value
FAILED tests/test_spectra.py::test_scale_spectra - AttributeError: module 'scipy.integrate' has no attribute 'trapz'
FAILED tests/test_spectra.py::test_nonspectral_albedo - AttributeError: module 'scipy.integrate' has no attribute 'trapz'

Discussion:

Patch:
diff --git a/bifacial_radiance/main.py b/bifacial_radiance/main.py
index 574ca27..aa58a58 100644
--- a/bifacial_radiance/main.py
+++ b/bifacial_radiance/main.py
@@ -3002,11 +3002,11 @@ class SceneObj:
                     f'{nMods}modsx{nRows}rows_origin{originx},{originy}.rad' )
         
         if self.hpc:
-            text += f'"{os.path.join(os.getcwd(), self.modulefile)}"' 
-            radfile = os.path.join(os.getcwd(), 'objects', filename) 
+            text += f'"{os.path.join(os.getcwd(), self.modulefile)}"'
+            radfile = os.path.join(os.getcwd(), 'objects', filename)
         else:
-            text += os.path.join(self.modulefile)
-            radfile = os.path.join('objects',filename ) 
+            text += f'"{os.path.join(self.modulefile)}"'
+            radfile = os.path.join('objects',filename)
 
         # py2 and 3 compatible: binary write, encode text first
         with open(radfile, 'wb') as f:
@@ -3214,10 +3214,10 @@ class MetObj:
                     sunup['minutedelta']= int(interval.seconds/2/60) # default sun angle 30 minutes before timestamp
                     # vector update of minutedelta at sunrise
                     sunrisemask = sunup.index.hour-1==sunup['sunrise'].dt.hour
-                    sunup['minutedelta'].mask(sunrisemask,np.floor((60-(sunup['sunrise'].dt.minute))/2),inplace=True)
+                    sunup['minutedelta'] = sunup['minutedelta'].mask(sunrisemask,np.floor((60-(sunup['sunrise'].dt.minute))/2))
                     # vector update of minutedelta at sunset
                     sunsetmask = sunup.index.hour-1==sunup['sunset'].dt.hour
-                    sunup['minutedelta'].mask(sunsetmask,np.floor((60-(sunup['sunset'].dt.minute))/2),inplace=True)
+                    sunup['minutedelta'] = sunup['minutedelta'].mask(sunsetmask,np.floor((60-(sunup['sunset'].dt.minute))/2))
                     # save corrected timestamp
                     sunup['corrected_timestamp'] = sunup.index-pd.to_timedelta(sunup['minutedelta'], unit='m')
         
@@ -3228,10 +3228,10 @@ class MetObj:
                     sunup['minutedelta']= int(interval.seconds/2/60) # default sun angle 30 minutes after timestamp
                     # vector update of minutedelta at sunrise
                     sunrisemask = sunup.index.hour==sunup['sunrise'].dt.hour
-                    sunup['minutedelta'].mask(sunrisemask,np.ceil((60+sunup['sunrise'].dt.minute)/2),inplace=True)
+                    sunup['minutedelta'] = sunup['minutedelta'].mask(sunrisemask,np.ceil((60+sunup['sunrise'].dt.minute)/2))
                     # vector update of minutedelta at sunset
                     sunsetmask = sunup.index.hour==sunup['sunset'].dt.hour
-                    sunup['minutedelta'].mask(sunsetmask,np.ceil((60+sunup['sunset'].dt.minute)/2),inplace=True)
+                    sunup['minutedelta'] = sunup['minutedelta'].mask(sunsetmask,np.ceil((60+sunup['sunset'].dt.minute)/2))
                     # save corrected timestamp
                     sunup['corrected_timestamp'] = sunup.index+pd.to_timedelta(sunup['minutedelta'], unit='m')
                 else: raise ValueError('Error: invalid weather label passed. Valid inputs: right, left or center')
diff --git a/bifacial_radiance/performance.py b/bifacial_radiance/performance.py
index d1e0d14..d7d41fc 100644
--- a/bifacial_radiance/performance.py
+++ b/bifacial_radiance/performance.py
@@ -6,7 +6,7 @@ Created on Tue April 27 06:29:02 2021
 """
 
 import pvlib
-
+import pandas as pd
 
 def calculatePerformance(effective_irradiance, CECMod, temp_air=None, wind_speed=1, temp_cell=None,  glassglass=False):
     '''
@@ -50,17 +50,27 @@ def calculatePerformance(effective_irradiance, CECMod, temp_air=None, wind_speed
             
         temp_cell = pvlib.temperature.sapm_cell(effective_irradiance, temp_air, wind_speed, 
                                                 temp_model_params['a'], temp_model_params['b'], temp_model_params['deltaT'])
-
+        
+    if isinstance(CECMod, pd.DataFrame):
+        #CECMod.to_pickle("CECMod.pkl")  
+        if len(CECMod) == 1:
+            CECMod1 = CECMod.iloc[0] 
+        else: 
+            print("More than one Module passed. Error, using 1st one")
+            CECMod1 = CECMod.iloc[0] 
+    else:
+        CECMod1 = CECMod
+        
     IL, I0, Rs, Rsh, nNsVth = pvlib.pvsystem.calcparams_cec(
         effective_irradiance=effective_irradiance,
         temp_cell=temp_cell,
-        alpha_sc=float(CECMod.alpha_sc),
-        a_ref=float(CECMod.a_ref),
-        I_L_ref=float(CECMod.I_L_ref),
-        I_o_ref=float(CECMod.I_o_ref),
-        R_sh_ref=float(CECMod.R_sh_ref),
-        R_s=float(CECMod.R_s),
-        Adjust=float(CECMod.Adjust)
+        alpha_sc=float(CECMod1.alpha_sc),
+        a_ref=float(CECMod1.a_ref),
+        I_L_ref=float(CECMod1.I_L_ref),
+        I_o_ref=float(CECMod1.I_o_ref),
+        R_sh_ref=float(CECMod1.R_sh_ref),
+        R_s=float(CECMod1.R_s),
+        Adjust=float(CECMod1.Adjust)
         )
     
     IVcurve_info = pvlib.pvsystem.singlediode(


Test patch:
diff --git a/tests/test_bifacial_radiance.py b/tests/test_bifacial_radiance.py
index 3c4e2a3..5524d6d 100644
--- a/tests/test_bifacial_radiance.py
+++ b/tests/test_bifacial_radiance.py
@@ -146,7 +146,7 @@ def test_Radiance_1axis_gendaylit_modelchains():
     #V 0.2.5 fixed the gcr passed to set1axis. (since gcr was not being passd to set1axis, gcr was default 0.33 default). 
     assert(np.mean(demo2.Wm2Front) == pytest.approx(205.0, 0.01) ) # was 214 in v0.2.3  # was 205 in early v0.2.4  
     assert(np.mean(demo2.Wm2Back) == pytest.approx(43.0, 0.1) )
-    assert demo2.trackerdict['2001-01-01_1100']['scene'].text.__len__() == 132
+    assert demo2.trackerdict['2001-01-01_1100']['scene'].text.__len__() == 134
     assert demo2.trackerdict['2001-01-01_1100']['scene'].text[23:28] == " 2.0 "
     demo2.exportTrackerDict(savefile = 'results\exportedTrackerDict.csv', reindex=True)
 
@@ -267,7 +267,7 @@ def test_SceneObj_makeSceneNxR_lowtilt():
                                 'sx_xinc': 0.0, 'sx_yinc':0.0, 'sx_zinc':0.0})
                         # zstart was 0.01 and zinc was 0 in v0.2.2
     #assert scene.text == '!xform -rz -90 -t -0.795 0.475 0 -rx 10 -t 0 0 0.2 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -15.9 -4.5 0 -rz 0 objects\\simple_panel.rad'
-    assert scene.text[0:116] == '!xform -rx 10 -t 0 0 0.2824828843917919 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -14.4 -4.5 0 -rz 0 -t 0 0 0 objects' #linux has different directory structure and will error here.
+    assert scene.text[0:117] == '!xform -rx 10 -t 0 0 0.2824828843917919 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -14.4 -4.5 0 -rz 0 -t 0 0 0 "objects' #linux has different directory structure and will error here.
 
 def test_SceneObj_makeSceneNxR_hightilt():
     # test _makeSceneNxR(tilt, height, pitch, orientation = None, azimuth = 180, nMods = 20, nRows = 7, radname = None)
@@ -311,7 +311,7 @@ def test_SceneObj_makeSceneNxR_hightilt():
                             'zinc': 0.08609923976848174, 'zstart': 0.28567662150674106,
                             'sx_xinc': 0.0, 'sx_yinc':0.0, 'sx_zinc':0.0})
     #assert scene.text == '!xform -rz -90 -t -0.795 0.475 0 -rx 65 -t 0 0 0.2 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -15.9 -4.5 0 -rz 91 objects\\simple_panel.rad'
-    assert scene.text[0:117] == '!xform -rx 65 -t 0 0 0.6304961988424087 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -14.4 -4.5 0 -rz 91 -t 0 0 0 objects'
+    assert scene.text[0:118] == '!xform -rx 65 -t 0 0 0.6304961988424087 -a 20 -t 1.6 0 0 -a 7 -t 0 1.5 0 -i 1 -t -14.4 -4.5 0 -rz 91 -t 0 0 0 "objects'
     
 
  
diff --git a/tests/test_performance.py b/tests/test_performance.py
index cc5bfb8..72b4ece 100644
--- a/tests/test_performance.py
+++ b/tests/test_performance.py
@@ -50,6 +50,13 @@ def test_calculatePerformance():
     p_mp_tamb = bifacial_radiance.performance.calculatePerformance(s1, CECMod=CECMod, 
                                                             temp_air=s3, wind_speed=1, glassglass=True)
     assert p_mp_tamb[0] == pytest.approx(190.4431, abs=.0001)
+    # test passing CECMod as a DF
+    
+    p_mp_celltemp2 = bifacial_radiance.performance.calculatePerformance(s1, pd.DataFrame([CECMod]), 
+                                                            temp_cell=s2)
+    p_mp_celltemp3 = bifacial_radiance.performance.calculatePerformance(s1, pd.DataFrame([CECMod, CECMod]), 
+                                                            temp_cell=s2)
+    assert p_mp_celltemp3.all()==p_mp_celltemp2.all()==p_mp_celltemp.all()
 
 def test_MBD():
     from bifacial_radiance import performance