Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ assignees: ''
A clear and concise description of what the bug is.

**To Reproduce**
Please provide a minimal example to reproduce the issue
Please provide a minimal example to reproduce the issue

**Expected behavior**
A clear and concise description of what you expected to happen.
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/flake8.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,3 @@ jobs:
- name: Run flake8 on changed files only
run: |
git diff origin/$GITHUB_BASE_REF HEAD -- "*.py" | flake8 --config=.flake8 --diff

24 changes: 24 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Pre-commit

on: [push, pull_request]

jobs:
pre-commit:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.13"

- name: Install pre-commit
run: |
python -m pip install --upgrade pip
pip install pre-commit

- name: Run pre-commit
run: pre-commit run --all-files
11 changes: 9 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: '^(docs/source/|tutorials_and_tools/_build/)'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
rev: v6.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
args: ["--maxkb=2000"]
- repo: https://github.com/psf/black
rev: 23.11.0
rev: 25.9.0
hooks:
- id: black
exclude: '^tutorials_and_tools/'
- repo: https://github.com/PyCQA/flake8
rev: 7.3.0 # Use the desired flake8 version
hooks:
- id: flake8
exclude: '^tutorials_and_tools/'
1 change: 0 additions & 1 deletion contributors/tobin-ford.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ agreement and sign this declaration.
Signed,

Tobin Ford https://github.com/tobin-ford

1 change: 1 addition & 0 deletions docs/source/whatsnew/releases/v0.6.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Enhancements
of parameter values for computation.
This change clarifies the distinction between retrieving raw material data and
extracting parameter values for use in calculations. (:issue:`256`, :pull:`257`)
- Update pre-commit hooks and add github workflow (:pull:`267`)


Deprecations
Expand Down
9 changes: 6 additions & 3 deletions pvdeg/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,12 @@ def calculate_jsc_from_tau_cp(

# 3. calc c.p. for emitter, depletion region, and base
cp_emitter = collection_probability(
emitter_depth, thickness=w_emitter, s=s_emitter, diffusion_length=l_emitter,
d=d_emitter
)
emitter_depth,
thickness=w_emitter,
s=s_emitter,
diffusion_length=l_emitter,
d=d_emitter,
)
cp_emitter = np.flip(cp_emitter)
emitter_depth = np.flip((-emitter_depth + np.max(emitter_depth)))

Expand Down
10 changes: 5 additions & 5 deletions pvdeg/data/DegradationDatabase.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
"value": 129,
"stdev": 3.35,
"units": "kJ/mol"
},
},
"n": {
"value": 2,
"stdev": 0,
Expand Down Expand Up @@ -241,7 +241,7 @@
"value": 128,
"stdev": 2.95,
"units": "kJ/mol"
},
},
"n": {
"value": 2,
"stdev": 0,
Expand Down Expand Up @@ -276,7 +276,7 @@
"value": 105,
"stdev": 5.45,
"units": "kJ/mol"
},
},
"n": {
"value": 2,
"stdev": 0,
Expand Down Expand Up @@ -311,7 +311,7 @@
"value": 102,
"stdev": 6.05,
"units": "kJ/mol"
},
},
"n": {
"value": 2,
"stdev": 0,
Expand Down Expand Up @@ -939,4 +939,4 @@
"p": {"value": 0.49,
"stdev": 0.22},
"Corr-E_a-P":{"value": -0.606}}
}
}
1 change: 0 additions & 1 deletion pvdeg/data/H2Opermeation.json
Original file line number Diff line number Diff line change
Expand Up @@ -513,4 +513,3 @@
"Do": { "name": "Diffusivity Prefactor", "units": "cm²/s", "value": 0.0347563378698928 }
}
}

2 changes: 1 addition & 1 deletion pvdeg/data/O2permeation.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,4 @@
"Eap": { "name": "Permeability Activation Energy", "units": "kJ/mol", "value": 39.2779774417758 },
"Po": { "name": "Permeability Prefactor", "units": "g·mm/m²/day/atm", "value": 12931378.0376762 }
}
}
}
4 changes: 2 additions & 2 deletions pvdeg/geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,8 +995,8 @@ def interpolate_analysis(
) # probably a nicer way to do this

grid_lat, grid_lon = np.mgrid[
df["latitude"].min(): df["latitude"].max(): resolution,
df["longitude"].min(): df["longitude"].max(): resolution,
df["latitude"].min() : df["latitude"].max() : resolution,
df["longitude"].min() : df["longitude"].max() : resolution,
]

grid_z = griddata(data[:, 0:2], data[:, 2], xi=(grid_lat, grid_lon), method=method)
Expand Down
4 changes: 1 addition & 3 deletions pvdeg/geospatialscenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -1080,9 +1080,7 @@ def _check_set(self, iterable, to_check: set):
iterable = set(iterable)

if not iterable.issubset(to_check):
raise ValueError(
f"All of iterable: {iterable} is not in {to_check}"
)
raise ValueError(f"All of iterable: {iterable} is not in {to_check}")

def format_geospatial_work(self):
if self.func:
Expand Down
5 changes: 3 additions & 2 deletions pvdeg/scenario.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,9 @@ def addModule(
Options : ``sol_position``, ``tilt``, ``azimuth``, ``sky_model``
"""
try:
mat_params = utilities.read_material_property(pvdeg_file=material_file,
key=material)
mat_params = utilities.read_material_property(
pvdeg_file=material_file, key=material
)

old_modules = [mod["module_name"] for mod in self.modules]
if module_name in old_modules:
Expand Down
4 changes: 1 addition & 3 deletions pvdeg/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -1531,9 +1531,7 @@ def read_material_property(
k: (
material_dict[k]["value"]
if k in material_dict and isinstance(material_dict[k], dict)
else material_dict[k]
if k in material_dict
else None
else material_dict[k] if k in material_dict else None
)
for k in parameters
}
Expand Down
8 changes: 5 additions & 3 deletions pvdeg/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,9 +237,11 @@ def get(
temp_air = weather_df["temp_air"]
dew_point = weather_df.get("dew_point")
if dew_point is None or temp_air is None:
raise ValueError('Cannot calculate "relative_humidity": one of'
'"dew_point" or "temp_air" column not found in'
'DataFrame.')
raise ValueError(
'Cannot calculate "relative_humidity": one of'
'"dew_point" or "temp_air" column not found in'
"DataFrame."
)
weather_df["relative_humidity"] = humidity.relative(temp_air, dew_point)
print(
"\r",
Expand Down
4 changes: 1 addition & 3 deletions tests/test_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ def test_edge_seal_ingress_rate():
# test calculation for constant k

water_saturation_pressure, avg_water_saturation_pressure = (
humidity.water_saturation_pressure(
PSM.get("dew_point")
)
humidity.water_saturation_pressure(PSM.get("dew_point"))
)
k = design.edge_seal_ingress_rate(avg_water_saturation_pressure)
assert k == pytest.approx(0.00096, abs=0.000005)
Expand Down
4 changes: 1 addition & 3 deletions tests/test_geospatial.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ def test_autotemplate():
func=pvdeg.humidity.module, ds_gids=GEO_WEATHER
).compute()

assert pvdeg.utilities.compare_templates(
autotemplate_result, HUMIDITY_TEMPLATE
)
assert pvdeg.utilities.compare_templates(autotemplate_result, HUMIDITY_TEMPLATE)
# custom function because we cant use equals or identical because of empty
# like values

Expand Down
61 changes: 36 additions & 25 deletions tests/test_humidity.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def test_water_saturation_pressure_mean():
weather dataframe and meta dictionary
"""
water_saturation_pressure_avg = pvdeg.humidity.water_saturation_pressure(
temp=WEATHER["temp_air"])
temp=WEATHER["temp_air"]
)
assert water_saturation_pressure_avg[1] == pytest.approx(0.47607, abs=5e-5)
assert water_saturation_pressure_avg[0][0] == pytest.approx(0.469731, abs=5e-5)
assert water_saturation_pressure_avg[0][1] == pytest.approx(0.465908, abs=5e-5)
Expand All @@ -78,7 +79,8 @@ def test_water_saturation_pressure_individual_points():
weather dataframe and meta dictionary
"""
water_saturation_pressure = pvdeg.humidity.water_saturation_pressure(
temp=WEATHER["temp_air"], average=False)
temp=WEATHER["temp_air"], average=False
)
assert water_saturation_pressure[0] == pytest.approx(0.469731, abs=5e-5)
assert water_saturation_pressure[1] == pytest.approx(0.465908, abs=5e-5)
assert water_saturation_pressure[2] == pytest.approx(0.462112, abs=5e-5)
Expand Down Expand Up @@ -106,8 +108,9 @@ def test_module():
# Check approximate equality for all columns
assert result.shape == rh_expected.shape
for col in rh_expected.columns:
np.testing.assert_allclose(result[col].values, rh_expected[col].values,
rtol=1e-3, atol=1e-3)
np.testing.assert_allclose(
result[col].values, rh_expected[col].values, rtol=1e-3, atol=1e-3
)


def test_module_basic():
Expand Down Expand Up @@ -162,14 +165,17 @@ def test_module_with_params():

def test_module_edge_cases():
"""Test pvdeg.humidity.module with edge case input (extreme weather values)."""
weather_df = pd.DataFrame({
"relative_humidity": [0, 100, 50],
"temp_air": [-20, 50, 25],
"wind_speed": [0, 10, 5],
"ghi": [0, 1000, 500],
"dni": [0, 900, 400],
"dhi": [0, 100, 100],
}, index=pd.date_range("2020-01-01", periods=3, freq="H"))
weather_df = pd.DataFrame(
{
"relative_humidity": [0, 100, 50],
"temp_air": [-20, 50, 25],
"wind_speed": [0, 10, 5],
"ghi": [0, 1000, 500],
"dni": [0, 900, 400],
"dhi": [0, 100, 100],
},
index=pd.date_range("2020-01-01", periods=3, freq="H"),
)
meta = {"latitude": 40, "longitude": -105, "altitude": 1600}
result = pvdeg.humidity.module(
weather_df,
Expand Down Expand Up @@ -203,11 +209,13 @@ def test_backsheet():
rh_ambient = pd.Series([40, 60, 80])
temp_ambient = pd.Series([20, 25, 30])
temp_module = pd.Series([25, 30, 35])
result = pvdeg.humidity.backsheet(rh_ambient,
temp_ambient,
temp_module,
backsheet_thickness=0.3,
back_encap_thickness=0.46,)
result = pvdeg.humidity.backsheet(
rh_ambient,
temp_ambient,
temp_module,
backsheet_thickness=0.3,
back_encap_thickness=0.46,
)
# Should return a pandas Series and have same length as input
assert result.tolist() == pytest.approx([24.535486, 31.149815, 38.113095], abs=1e-5)

Expand All @@ -220,8 +228,9 @@ def test_dew_yield():
wind_speed = pd.Series([1, 2, 3])
n = pd.Series([4, 5, 3])
# Call dew_yield function
result = pvdeg.humidity.dew_yield(elevation=1, dry_bulb=temp_air,
dew_point=dew_point, wind_speed=wind_speed, n=n)
result = pvdeg.humidity.dew_yield(
elevation=1, dry_bulb=temp_air, dew_point=dew_point, wind_speed=wind_speed, n=n
)
# Check result type and shape
assert result.tolist() == pytest.approx([0.332943, 0.316928, 0.358373], abs=1e-6)

Expand All @@ -231,8 +240,9 @@ def test_diffusivity_weighted_water_basic():
rh_ambient = pd.Series([50, 55, 60])
temp_ambient = pd.Series([20, 22, 24])
temp_module = pd.Series([25, 27, 29])
result = pvdeg.humidity.diffusivity_weighted_water(rh_ambient, temp_ambient,
temp_module)
result = pvdeg.humidity.diffusivity_weighted_water(
rh_ambient, temp_ambient, temp_module
)
assert result == pytest.approx(0.0009117307352906477, abs=1e-9)


Expand All @@ -244,9 +254,9 @@ def test_diffusivity_weighted_water_with_params():
So = 1.8
Eas = 16.7
Ead = 38.1
result = pvdeg.humidity.diffusivity_weighted_water(rh_ambient, temp_ambient,
temp_module, So=So, Eas=Eas,
Ead=Ead)
result = pvdeg.humidity.diffusivity_weighted_water(
rh_ambient, temp_ambient, temp_module, So=So, Eas=Eas, Ead=Ead
)
assert result == pytest.approx(0.0006841420183438176, abs=1e-9)


Expand Down Expand Up @@ -276,6 +286,7 @@ def test_ceq():

# Unit tests for backsheet_from_encap


def test_backsheet_from_encap():
rh_back_encap = pd.Series([40, 60, 80])
rh_surface_outside = pd.Series([20, 40, 60])
Expand Down Expand Up @@ -311,4 +322,4 @@ def test_back_encapsulant_water_concentration_missing_back_encap_thickness():
back_encap_thickness=None,
backsheet="W017",
backsheet_thickness=0.3,
)
)
4 changes: 2 additions & 2 deletions tutorials_and_tools/tutorials_and_tools/ASTM Live Demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@
weather_id = (33.4484, -112.0740)
weather_arg = {'api_key': NREL_API_KEY,
'email': 'user@mail.com',
'names': '2021', # tmy is another common option; right now requesting only 2021 data
'attributes': [], # grabs all. to select, could be 'air_temperature', 'dew_point', 'dhi',
'names': '2021', # tmy is another common option; right now requesting only 2021 data
'attributes': [], # grabs all. to select, could be 'air_temperature', 'dew_point', 'dhi',
# 'dni', 'ghi', 'surface_albedo', 'surface_pressure', 'wind_direction', 'wind_speed'
'map_variables': True,
'leap_day': False}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,4 @@
"qualified_function": "pvdeg.degradation.IwaVantHoff"
}
}
}
}