Skip to content

Commit

Permalink
Generating Spectra - Patches
Browse files Browse the repository at this point in the history
Changes to radObj.generate_spectra and associated tests. Now automatically handles metadata from the radiance object with optional parameters available for metdata and path. Existing test for generate_spectra changed to handle new structure. Two additional tests added to check for scale-albedo-nonspectral-sim and for scaled spectra/albedo.
  • Loading branch information
mcbrown042 committed Jul 20, 2022
1 parent 8b73d11 commit a63c905
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 29 deletions.
63 changes: 56 additions & 7 deletions bifacial_radiance/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2750,24 +2750,73 @@ def calculateResults(self, CECMod=None, glassglass=False, bifacialityfactor=None

return trackerdict

def generate_spectra(self, ground=None, scale_spectra=False, scale_albedo=False,
scale_albedo_nonspectral_sim=False, scale_upper_bound=2500):
def generate_spectra(self, metdata=None, simulationPath=None, groundMaterial=None, scale_spectra=False,
scale_albedo=False, scale_albedo_nonspectral_sim=False, scale_upper_bound=2500):
'''
Generate spectral irradiance files for spectral simulations using pySMARTS
Or
Generate an hourly albedo weighted by pySMARTS spectral irradiances
Parameters
----------
metdata : radianceObject.metdata, optional
DESC
simulationPath : path object or string, optional
path of current simulation directory
groundMaterial : str or (R,G,B), optional
ground material string from pySMARTS glossary or compatible
(R,G,B) tuple.
scale_spectra : boolean, default=False
Apply a simple scaling to the generated spectra. Scales by
integrated irradiance below specified upper wavelength bound
scale_albedo : boolean, default=False
Apply a scaling factor to generated spectral albedo.
Scales by mean value below specified upper wavelength bound
scale_albedo_nonspectral_sim : boolean, default=False
You intend to run a non-spectral simulation. This will scale
the albedo read from the weather file by a calculation
on measured and generated spectra and the spectral responsivity
of device (spectral responsivity currently not implemented)
scale_upper_bound : integer, optional
Sets an upper bound for the wavelength in all scaling
calculations. Limits the bounds of integration for spectral DNI,
DHI, and GHI. Limits the domain over which spectral albedo
is averaged.
Returns
-------
spectral_alb : spectral_property class
spectral_alb.data: dataframe with frequency and magnitude data.
returns as None when scale_albedo_nonspectral_sim == True
spectral_dni : spectral_property class
spectral_dni.data: dataframe with frequency and magnitude data.
spectral_dhi : spectral_property class
spectral_dhi.data: dataframe with frequency and magnitude data.
weighted_alb : pd.series
datetime-indexed series of weighted albedo values
returns as None when scale_albedo_nonspectral_sim == False
'''
if metdata == None:
metdata = self.metdata
if simulationPath == None:
simulationPath = self.path

from bifacial_radiance import spectral_utils as su
import os

spectra_path = 'spectra'
if not os.path.exists(spectra_path):
os.mkdir(spectra_path)

spectra = su.generate_spectra(self.metdata, self.path, ground=ground, spectra_folder=spectra_path,

(spectral_alb, spectral_dni, spectral_dhi, weighted_alb) = su.generate_spectra(metdata=metdata,
simulationPath=simulationPath, groundMaterial=groundMaterial, spectra_folder=spectra_path,
scale_spectra=scale_spectra, scale_albedo=scale_albedo,
scale_albedo_nonspectral_sim=scale_albedo_nonspectral_sim,
scale_upper_bound=scale_upper_bound)

if scale_albedo_nonspectral_sim:
self.metdata.albedo = spectra['weightedALB']
return spectra
self.metdata.albedo = weighted_alb.values
return (spectral_alb, spectral_dni, spectral_dhi, weighted_alb)

# End RadianceObj definition

Expand Down
25 changes: 13 additions & 12 deletions bifacial_radiance/spectral_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def spectral_albedo_smarts_SRRL(YEAR, MONTH, DAY, HOUR, ZONE,
smarts_res['Wvlgth'], interpolation='linear')


def generate_spectra(metdata, simulationPath, ground='Gravel', spectra_folder=None, scale_spectra=False,
def generate_spectra(metdata, simulationPath, groundMaterial='Gravel', spectra_folder=None, scale_spectra=False,
scale_albedo=False, scale_albedo_nonspectral_sim=False, scale_upper_bound=2500):
"""
generate spectral curve for particular material. Requires pySMARTS
Expand All @@ -240,7 +240,7 @@ def generate_spectra(metdata, simulationPath, ground='Gravel', spectra_folder=No
DESCRIPTION.
simulationPath: bifacial_radiance MetObj
path of simulation directory
ground : string, optional
groundMaterial : string, optional
type of ground material for spectral simulation. Options include:
Grass, Gravel, Snow, Seasonal etc.
The default is 'Gravel'.
Expand All @@ -264,9 +264,11 @@ def generate_spectra(metdata, simulationPath, ground='Gravel', spectra_folder=No
spectral_dni.data: dataframe with frequency and magnitude data.
spectral_dhi : spectral_property class
spectral_dhi.data: dataframe with frequency and magnitude data.
weighted_alb : pd.series
datetime-indexed series of weighted albedo values
"""

# make the datetime easily readable and indexed
dts = pd.Series(data=metdata.datetime)

Expand Down Expand Up @@ -330,18 +332,18 @@ def generate_spectra(metdata, simulationPath, ground='Gravel', spectra_folder=No
if lat < 0: winter = north
if lat > 0: winter = south

if ground == 'Seasonal':
if groundMaterial == 'Seasonal':
MONTH = metdata.datetime[idx].month
if MONTH in winter :
if alb >= 0.6:
ground = 'Snow'
groundMaterial = 'Snow'
else:
ground = 'DryGrass'
groundMaterial = 'DryGrass'
else:
ground = 'Grass'
groundMaterial = 'Grass'

# Generate base spectral albedo
spectral_alb = spectral_albedo_smarts(zen, azm, ground, min_wavelength=280)
spectral_alb = spectral_albedo_smarts(zen, azm, groundMaterial, min_wavelength=280)

# Limit albedo by upper bound wavelength
talb = spectral_alb.data[spectral_alb.data.index <= scale_upper_bound]
Expand Down Expand Up @@ -378,8 +380,7 @@ def generate_spectra(metdata, simulationPath, ground='Gravel', spectra_folder=No
walbPath = os.path.join(simulationPath,spectra_folder,'albedo_scaled_nonSpec.csv')
walb.to_csv(walbPath)
print('Weighted albedo CSV saved.')

return {'specALB':spectral_alb, 'specDNI':spectral_dni, 'specDHI':spectral_dhi,'weightedALB':walb.values}
weighted_alb = walb
return (spectral_alb, spectral_dni, spectral_dhi, weighted_alb)

#return (spectral_alb, spectral_dni, spectral_dhi)
return {'specALB':spectral_alb, 'specDNI':spectral_dni, 'specDHI':spectral_dhi}
return (spectral_alb, spectral_dni, spectral_dhi, None)
49 changes: 39 additions & 10 deletions tests/test_spectra.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,46 @@ def test_generate_spectra():
rad_obj = br.RadianceObj(name, TESTDIR)
metdata = rad_obj.readWeatherFile(MET_FILENAME,
starttime='2001-06-16',
endtime='2001-06-18',
endtime='2001-06-16',
coerce_year=2001)
idx = metdata.datetime.index(pd.to_datetime('2001-06-17 12:0:0 -7'))

(spectral_alb, spectral_dni, spectral_dhi) = br.generate_spectra(idx,
rad_obj.metdata,
material='Grass',
spectra_folder=SPECTRA_FOLDER)
assert spectral_alb.data.__len__() == 1962
assert spectral_dhi.data.index[1961] == 4000.0
assert spectral_dni.data.iloc[0,0] == 0.003805

(spectral_alb, spectral_dni, spectral_dhi, weighted_alb) = rad_obj.generate_spectra(groundMaterial='Grass')

assert spectral_alb.data.__len__() == 2002
assert spectral_dhi.data.index[2001] == 4000.0
assert spectral_dni.data.iloc[400,0] == 0.8732

def test_scale_spectra():
# test scaling of spectra and albedo
name = "_test_generate_spectra"
rad_obj = br.RadianceObj(name, TESTDIR)
metdata = rad_obj.readWeatherFile(MET_FILENAME,
starttime='2001-06-16',
endtime='2001-06-16',
coerce_year=2001)

(spectral_alb, spectral_dni, spectral_dhi, weighted_alb) = rad_obj.generate_spectra(groundMaterial='Grass',
scale_spectra=True,
scale_albedo=True)
assert spectral_alb.data.__len__() == 2002
assert spectral_dhi.data.index[2001] == 4000.0
assert (0.5074 <= spectral_dni.data.iloc[400][0] <= 0.5075)
assert spectral_dni.data.iloc[400].name == 560.0
assert weighted_alb == None

def test_nonspectral_albedo():
# test scale_albedo_nonspectral_sim
name = '_test_generate_nonspectral_albedo'
rad_obj = br.RadianceObj(name, TESTDIR)
metdata = rad_obj.readWeatherFile(MET_FILENAME,
starttime='2001-06-16',
endtime='2001-06-16',
coerce_year=2001)

weighted_alb = rad_obj.generate_spectra(groundMaterial='Grass', scale_albedo_nonspectral_sim=True)[3]

assert((weighted_alb[12] <= 0.1286) & (weighted_alb[12] >= 0.1285))
assert(len(weighted_alb) == 16)


def _other_cruft():
Expand Down

0 comments on commit a63c905

Please sign in to comment.