PVNet 3.0.29__tar.gz → 3.0.35__tar.gz

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 (54) hide show
  1. {pvnet-3.0.29 → pvnet-3.0.35}/PKG-INFO +19 -10
  2. {pvnet-3.0.29 → pvnet-3.0.35}/PVNet.egg-info/PKG-INFO +19 -10
  3. {pvnet-3.0.29 → pvnet-3.0.35}/PVNet.egg-info/SOURCES.txt +1 -5
  4. {pvnet-3.0.29 → pvnet-3.0.35}/PVNet.egg-info/requires.txt +13 -0
  5. {pvnet-3.0.29 → pvnet-3.0.35}/PVNet.egg-info/top_level.txt +0 -1
  6. {pvnet-3.0.29 → pvnet-3.0.35}/README.md +6 -6
  7. pvnet-3.0.35/pvnet/__init__.py +2 -0
  8. pvnet-3.0.35/pvnet/load_model.py +70 -0
  9. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/utils.py +3 -26
  10. pvnet-3.0.35/pyproject.toml +88 -0
  11. pvnet-3.0.29/pvnet/__init__.py +0 -2
  12. pvnet-3.0.29/pyproject.toml +0 -28
  13. pvnet-3.0.29/requirements-dev.txt +0 -8
  14. pvnet-3.0.29/requirements.txt +0 -27
  15. pvnet-3.0.29/setup.py +0 -33
  16. pvnet-3.0.29/tests/__init__.py +0 -0
  17. pvnet-3.0.29/tests/conftest.py +0 -305
  18. {pvnet-3.0.29 → pvnet-3.0.35}/LICENSE +0 -0
  19. {pvnet-3.0.29 → pvnet-3.0.35}/MANIFEST.in +0 -0
  20. {pvnet-3.0.29 → pvnet-3.0.35}/PVNet.egg-info/dependency_links.txt +0 -0
  21. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/callbacks.py +0 -0
  22. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/data/__init__.py +0 -0
  23. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/data/base.py +0 -0
  24. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/data/datamodule.py +0 -0
  25. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/data/pv_site_datamodule.py +0 -0
  26. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/data/utils.py +0 -0
  27. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/data/wind_datamodule.py +0 -0
  28. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/__init__.py +0 -0
  29. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/base_model.py +0 -0
  30. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/baseline/__init__.py +0 -0
  31. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/baseline/last_value.py +0 -0
  32. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/baseline/single_value.py +0 -0
  33. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/ensemble.py +0 -0
  34. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/__init__.py +0 -0
  35. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/basic_blocks.py +0 -0
  36. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/encoders/__init__.py +0 -0
  37. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/encoders/basic_blocks.py +0 -0
  38. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/encoders/encoders2d.py +0 -0
  39. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/encoders/encoders3d.py +0 -0
  40. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/encoders/encodersRNN.py +0 -0
  41. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/linear_networks/__init__.py +0 -0
  42. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/linear_networks/basic_blocks.py +0 -0
  43. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/linear_networks/networks.py +0 -0
  44. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/multimodal.py +0 -0
  45. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/multimodal_base.py +0 -0
  46. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/site_encoders/__init__.py +0 -0
  47. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/site_encoders/basic_blocks.py +0 -0
  48. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/site_encoders/encoders.py +0 -0
  49. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/multimodal/unimodal_teacher.py +0 -0
  50. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/models/utils.py +0 -0
  51. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/optimizers.py +0 -0
  52. {pvnet-3.0.29 → pvnet-3.0.35}/pvnet/training.py +0 -0
  53. {pvnet-3.0.29 → pvnet-3.0.35}/setup.cfg +0 -0
  54. {pvnet-3.0.29 → pvnet-3.0.35}/tests/test_end2end.py +0 -0
@@ -1,10 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PVNet
3
- Version: 3.0.29
3
+ Version: 3.0.35
4
4
  Summary: PVNet
5
- Author: Peter Dudfield
6
- Author-email: info@openclimatefix.org
7
- License: MIT
5
+ Author-email: Peter Dudfield <info@openclimatefix.org>
8
6
  Description-Content-Type: text/markdown
9
7
  License-File: LICENSE
10
8
  Requires-Dist: ocf_datapipes>=3.3.6
@@ -33,9 +31,20 @@ Requires-Dist: python-dotenv
33
31
  Requires-Dist: hydra-optuna-sweeper
34
32
  Requires-Dist: rich
35
33
  Requires-Dist: gcsfs
34
+ Provides-Extra: dev
35
+ Requires-Dist: pvlive-api; extra == "dev"
36
+ Requires-Dist: black; extra == "dev"
37
+ Requires-Dist: flake8; extra == "dev"
38
+ Requires-Dist: isort; extra == "dev"
39
+ Requires-Dist: mypy; extra == "dev"
40
+ Requires-Dist: pre-commit; extra == "dev"
41
+ Requires-Dist: pytest; extra == "dev"
42
+ Requires-Dist: pytest-cov; extra == "dev"
36
43
  Provides-Extra: all-models
37
44
  Requires-Dist: pytorch-tabnet; extra == "all-models"
38
45
  Requires-Dist: efficientnet_pytorch; extra == "all-models"
46
+ Provides-Extra: all
47
+ Requires-Dist: PVNet[all_models,dev]; extra == "all"
39
48
 
40
49
  # PVNet 2.1
41
50
 
@@ -70,7 +79,7 @@ Some slightly more structured notes on deliberate experiments we have performed
70
79
  ```bash
71
80
  git clone https://github.com/openclimatefix/PVNet.git
72
81
  cd PVNet
73
- pip install -r requirements.txt
82
+ pip install .
74
83
  ```
75
84
 
76
85
  The commit history is extensive. To save download time, use a depth of 1:
@@ -88,7 +97,7 @@ pip install -e .
88
97
  ### Additional development dependencies
89
98
 
90
99
  ```bash
91
- pip install -r requirements-dev.txt
100
+ pip install ".[dev]"
92
101
  ```
93
102
 
94
103
 
@@ -140,7 +149,7 @@ conda create -n ocf_datapipes python=3.10
140
149
  Then go inside the ocf_datapipes repo to add packages
141
150
 
142
151
  ```bash
143
- pip install -r requirements.txt -r requirements-dev.txt
152
+ pip install ".[dev]"
144
153
  ```
145
154
 
146
155
  Then exit this environment, and enter back into the pvnet conda environment and install ocf_datapies in editable mode (-e). This means the package is directly linked to the source code in the ocf_datapies repo.
@@ -184,7 +193,7 @@ For this example we will be using the `streamed_batches.yaml` config. Like befor
184
193
 
185
194
  This should be given the whole path to the config on your local machine, such as for our example it should be changed to:
186
195
 
187
- `configuration: "/FULL-PATH-TO-REPO/PVNet/configs/datamodule/configuration/gcp_configuration.yaml"
196
+ `configuration: "/FULL-PATH-TO-REPO/PVNet/configs/datamodule/configuration/gcp_configuration.yaml"`
188
197
  `
189
198
 
190
199
  Where `FULL-PATH-TO-REPO` represent the whole path to the PVNet repo on your local machine.
@@ -209,14 +218,14 @@ gcloud auth login
209
218
 
210
219
  For files stored in multiple locations they can be added as list. For example from the gcp_configuration.yaml file we can change from satellite data stored on a bucket:
211
220
 
212
- ```
221
+ ```yaml
213
222
  satellite:
214
223
  satellite_zarr_path: gs://solar-pv-nowcasting-data/satellite/EUMETSAT/SEVIRI_RSS/v4/2020_nonhrv.zarr
215
224
  ```
216
225
 
217
226
  To satellite data hosted by Google:
218
227
 
219
- ```
228
+ ```yaml
220
229
  satellite:
221
230
  satellite_zarr_paths:
222
231
  - "gs://public-datasets-eumetsat-solar-forecasting/satellite/EUMETSAT/SEVIRI_RSS/v4/2020_nonhrv.zarr"
@@ -1,10 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PVNet
3
- Version: 3.0.29
3
+ Version: 3.0.35
4
4
  Summary: PVNet
5
- Author: Peter Dudfield
6
- Author-email: info@openclimatefix.org
7
- License: MIT
5
+ Author-email: Peter Dudfield <info@openclimatefix.org>
8
6
  Description-Content-Type: text/markdown
9
7
  License-File: LICENSE
10
8
  Requires-Dist: ocf_datapipes>=3.3.6
@@ -33,9 +31,20 @@ Requires-Dist: python-dotenv
33
31
  Requires-Dist: hydra-optuna-sweeper
34
32
  Requires-Dist: rich
35
33
  Requires-Dist: gcsfs
34
+ Provides-Extra: dev
35
+ Requires-Dist: pvlive-api; extra == "dev"
36
+ Requires-Dist: black; extra == "dev"
37
+ Requires-Dist: flake8; extra == "dev"
38
+ Requires-Dist: isort; extra == "dev"
39
+ Requires-Dist: mypy; extra == "dev"
40
+ Requires-Dist: pre-commit; extra == "dev"
41
+ Requires-Dist: pytest; extra == "dev"
42
+ Requires-Dist: pytest-cov; extra == "dev"
36
43
  Provides-Extra: all-models
37
44
  Requires-Dist: pytorch-tabnet; extra == "all-models"
38
45
  Requires-Dist: efficientnet_pytorch; extra == "all-models"
46
+ Provides-Extra: all
47
+ Requires-Dist: PVNet[all_models,dev]; extra == "all"
39
48
 
40
49
  # PVNet 2.1
41
50
 
@@ -70,7 +79,7 @@ Some slightly more structured notes on deliberate experiments we have performed
70
79
  ```bash
71
80
  git clone https://github.com/openclimatefix/PVNet.git
72
81
  cd PVNet
73
- pip install -r requirements.txt
82
+ pip install .
74
83
  ```
75
84
 
76
85
  The commit history is extensive. To save download time, use a depth of 1:
@@ -88,7 +97,7 @@ pip install -e .
88
97
  ### Additional development dependencies
89
98
 
90
99
  ```bash
91
- pip install -r requirements-dev.txt
100
+ pip install ".[dev]"
92
101
  ```
93
102
 
94
103
 
@@ -140,7 +149,7 @@ conda create -n ocf_datapipes python=3.10
140
149
  Then go inside the ocf_datapipes repo to add packages
141
150
 
142
151
  ```bash
143
- pip install -r requirements.txt -r requirements-dev.txt
152
+ pip install ".[dev]"
144
153
  ```
145
154
 
146
155
  Then exit this environment, and enter back into the pvnet conda environment and install ocf_datapies in editable mode (-e). This means the package is directly linked to the source code in the ocf_datapies repo.
@@ -184,7 +193,7 @@ For this example we will be using the `streamed_batches.yaml` config. Like befor
184
193
 
185
194
  This should be given the whole path to the config on your local machine, such as for our example it should be changed to:
186
195
 
187
- `configuration: "/FULL-PATH-TO-REPO/PVNet/configs/datamodule/configuration/gcp_configuration.yaml"
196
+ `configuration: "/FULL-PATH-TO-REPO/PVNet/configs/datamodule/configuration/gcp_configuration.yaml"`
188
197
  `
189
198
 
190
199
  Where `FULL-PATH-TO-REPO` represent the whole path to the PVNet repo on your local machine.
@@ -209,14 +218,14 @@ gcloud auth login
209
218
 
210
219
  For files stored in multiple locations they can be added as list. For example from the gcp_configuration.yaml file we can change from satellite data stored on a bucket:
211
220
 
212
- ```
221
+ ```yaml
213
222
  satellite:
214
223
  satellite_zarr_path: gs://solar-pv-nowcasting-data/satellite/EUMETSAT/SEVIRI_RSS/v4/2020_nonhrv.zarr
215
224
  ```
216
225
 
217
226
  To satellite data hosted by Google:
218
227
 
219
- ```
228
+ ```yaml
220
229
  satellite:
221
230
  satellite_zarr_paths:
222
231
  - "gs://public-datasets-eumetsat-solar-forecasting/satellite/EUMETSAT/SEVIRI_RSS/v4/2020_nonhrv.zarr"
@@ -2,9 +2,6 @@ LICENSE
2
2
  MANIFEST.in
3
3
  README.md
4
4
  pyproject.toml
5
- requirements-dev.txt
6
- requirements.txt
7
- setup.py
8
5
  PVNet.egg-info/PKG-INFO
9
6
  PVNet.egg-info/SOURCES.txt
10
7
  PVNet.egg-info/dependency_links.txt
@@ -12,6 +9,7 @@ PVNet.egg-info/requires.txt
12
9
  PVNet.egg-info/top_level.txt
13
10
  pvnet/__init__.py
14
11
  pvnet/callbacks.py
12
+ pvnet/load_model.py
15
13
  pvnet/optimizers.py
16
14
  pvnet/training.py
17
15
  pvnet/utils.py
@@ -44,6 +42,4 @@ pvnet/models/multimodal/linear_networks/networks.py
44
42
  pvnet/models/multimodal/site_encoders/__init__.py
45
43
  pvnet/models/multimodal/site_encoders/basic_blocks.py
46
44
  pvnet/models/multimodal/site_encoders/encoders.py
47
- tests/__init__.py
48
- tests/conftest.py
49
45
  tests/test_end2end.py
@@ -25,6 +25,19 @@ hydra-optuna-sweeper
25
25
  rich
26
26
  gcsfs
27
27
 
28
+ [all]
29
+ PVNet[all_models,dev]
30
+
28
31
  [all_models]
29
32
  pytorch-tabnet
30
33
  efficientnet_pytorch
34
+
35
+ [dev]
36
+ pvlive-api
37
+ black
38
+ flake8
39
+ isort
40
+ mypy
41
+ pre-commit
42
+ pytest
43
+ pytest-cov
@@ -1,2 +1 @@
1
1
  pvnet
2
- tests
@@ -31,7 +31,7 @@ Some slightly more structured notes on deliberate experiments we have performed
31
31
  ```bash
32
32
  git clone https://github.com/openclimatefix/PVNet.git
33
33
  cd PVNet
34
- pip install -r requirements.txt
34
+ pip install .
35
35
  ```
36
36
 
37
37
  The commit history is extensive. To save download time, use a depth of 1:
@@ -49,7 +49,7 @@ pip install -e .
49
49
  ### Additional development dependencies
50
50
 
51
51
  ```bash
52
- pip install -r requirements-dev.txt
52
+ pip install ".[dev]"
53
53
  ```
54
54
 
55
55
 
@@ -101,7 +101,7 @@ conda create -n ocf_datapipes python=3.10
101
101
  Then go inside the ocf_datapipes repo to add packages
102
102
 
103
103
  ```bash
104
- pip install -r requirements.txt -r requirements-dev.txt
104
+ pip install ".[dev]"
105
105
  ```
106
106
 
107
107
  Then exit this environment, and enter back into the pvnet conda environment and install ocf_datapies in editable mode (-e). This means the package is directly linked to the source code in the ocf_datapies repo.
@@ -145,7 +145,7 @@ For this example we will be using the `streamed_batches.yaml` config. Like befor
145
145
 
146
146
  This should be given the whole path to the config on your local machine, such as for our example it should be changed to:
147
147
 
148
- `configuration: "/FULL-PATH-TO-REPO/PVNet/configs/datamodule/configuration/gcp_configuration.yaml"
148
+ `configuration: "/FULL-PATH-TO-REPO/PVNet/configs/datamodule/configuration/gcp_configuration.yaml"`
149
149
  `
150
150
 
151
151
  Where `FULL-PATH-TO-REPO` represent the whole path to the PVNet repo on your local machine.
@@ -170,14 +170,14 @@ gcloud auth login
170
170
 
171
171
  For files stored in multiple locations they can be added as list. For example from the gcp_configuration.yaml file we can change from satellite data stored on a bucket:
172
172
 
173
- ```
173
+ ```yaml
174
174
  satellite:
175
175
  satellite_zarr_path: gs://solar-pv-nowcasting-data/satellite/EUMETSAT/SEVIRI_RSS/v4/2020_nonhrv.zarr
176
176
  ```
177
177
 
178
178
  To satellite data hosted by Google:
179
179
 
180
- ```
180
+ ```yaml
181
181
  satellite:
182
182
  satellite_zarr_paths:
183
183
  - "gs://public-datasets-eumetsat-solar-forecasting/satellite/EUMETSAT/SEVIRI_RSS/v4/2020_nonhrv.zarr"
@@ -0,0 +1,2 @@
1
+ """PVNet"""
2
+ __version__ = "3.0.35"
@@ -0,0 +1,70 @@
1
+ """ Load a model from its checkpoint directory """
2
+ import glob
3
+ import os
4
+
5
+ import hydra
6
+ import torch
7
+ from pyaml_env import parse_config
8
+
9
+ from pvnet.models.ensemble import Ensemble
10
+ from pvnet.models.multimodal.unimodal_teacher import Model as UMTModel
11
+
12
+
13
+ def get_model_from_checkpoints(
14
+ checkpoint_dir_paths: list[str],
15
+ val_best: bool = True,
16
+ ):
17
+ """Load a model from its checkpoint directory"""
18
+ is_ensemble = len(checkpoint_dir_paths) > 1
19
+
20
+ model_configs = []
21
+ models = []
22
+ data_configs = []
23
+
24
+ for path in checkpoint_dir_paths:
25
+ # Load the model
26
+ model_config = parse_config(f"{path}/model_config.yaml")
27
+
28
+ model = hydra.utils.instantiate(model_config)
29
+
30
+ if val_best:
31
+ # Only one epoch (best) saved per model
32
+ files = glob.glob(f"{path}/epoch*.ckpt")
33
+ if len(files) != 1:
34
+ raise ValueError(
35
+ f"Found {len(files)} checkpoints @ {path}/epoch*.ckpt. Expected one."
36
+ )
37
+ checkpoint = torch.load(files[0], map_location="cpu")
38
+ else:
39
+ checkpoint = torch.load(f"{path}/last.ckpt", map_location="cpu")
40
+
41
+ model.load_state_dict(state_dict=checkpoint["state_dict"])
42
+
43
+ if isinstance(model, UMTModel):
44
+ model, model_config = model.convert_to_multimodal_model(model_config)
45
+
46
+ # Check for data config
47
+ data_config = f"{path}/data_config.yaml"
48
+
49
+ if os.path.isfile(data_config):
50
+ data_configs.append(data_config)
51
+ else:
52
+ data_configs.append(None)
53
+
54
+ model_configs.append(model_config)
55
+ models.append(model)
56
+
57
+ if is_ensemble:
58
+ model_config = {
59
+ "_target_": "pvnet.models.ensemble.Ensemble",
60
+ "model_list": model_configs,
61
+ }
62
+ model = Ensemble(model_list=models)
63
+ data_config = data_configs[0]
64
+
65
+ else:
66
+ model_config = model_configs[0]
67
+ model = models[0]
68
+ data_config = data_configs[0]
69
+
70
+ return model, model_config, data_config
@@ -1,6 +1,5 @@
1
1
  """Utils"""
2
2
  import logging
3
- import os
4
3
  import warnings
5
4
  from collections.abc import Sequence
6
5
  from typing import Optional
@@ -13,7 +12,6 @@ import pylab
13
12
  import rich.syntax
14
13
  import rich.tree
15
14
  import xarray as xr
16
- import yaml
17
15
  from lightning.pytorch.loggers import Logger
18
16
  from lightning.pytorch.utilities import rank_zero_only
19
17
  from ocf_datapipes.batch import BatchKey
@@ -21,26 +19,6 @@ from ocf_datapipes.utils import Location
21
19
  from ocf_datapipes.utils.geospatial import osgb_to_lon_lat
22
20
  from omegaconf import DictConfig, OmegaConf
23
21
 
24
- import pvnet
25
-
26
-
27
- def load_config(config_file):
28
- """
29
- Open yam configruation file, and get rid eof '_target_' line
30
- """
31
-
32
- # get full path of config file
33
- path = os.path.dirname(pvnet.__file__)
34
- config_file = f"{path}/../{config_file}"
35
-
36
- with open(config_file) as cfg:
37
- config = yaml.load(cfg, Loader=yaml.FullLoader)
38
-
39
- if "_target_" in config.keys():
40
- config.pop("_target_") # This is only for Hydra
41
-
42
- return config
43
-
44
22
 
45
23
  def get_logger(name=__name__, level=logging.INFO) -> logging.Logger:
46
24
  """Initializes multi-GPU-friendly python logger."""
@@ -236,11 +214,10 @@ def finish(
236
214
  """Makes sure everything closed properly."""
237
215
 
238
216
  # without this sweeps with wandb logger might crash!
239
- for logger in loggers:
240
- if isinstance(logger, pl.loggers.wandb.WandbLogger):
241
- import wandb
217
+ if any([isinstance(logger, pl.loggers.wandb.WandbLogger) for logger in loggers]):
218
+ import wandb
242
219
 
243
- wandb.finish()
220
+ wandb.finish()
244
221
 
245
222
 
246
223
  def plot_batch_forecasts(
@@ -0,0 +1,88 @@
1
+ [project]
2
+ name="PVNet"
3
+ description = "PVNet"
4
+ authors = [{name="Peter Dudfield", email="info@openclimatefix.org"}]
5
+ dynamic = ["version", "readme"]
6
+ license={file="LICENCE"}
7
+
8
+ dependencies = [
9
+ "ocf_datapipes>=3.3.6",
10
+ "ocf_ml_metrics>=0.0.11",
11
+ "numpy",
12
+ "pandas",
13
+ "matplotlib",
14
+ "xarray",
15
+ "ipykernel",
16
+ "h5netcdf",
17
+ "torch>=2.0.0",
18
+ "lightning>=2.0.1",
19
+ "torchvision",
20
+ "pytest",
21
+ "pytest-cov",
22
+ "typer",
23
+ "sqlalchemy",
24
+ "fsspec[s3]",
25
+ "wandb",
26
+ "huggingface-hub",
27
+ "tensorboard",
28
+ "tqdm",
29
+ "omegaconf",
30
+ "hydra-core",
31
+ "python-dotenv",
32
+ "hydra-optuna-sweeper",
33
+ "rich",
34
+ "gcsfs",# gcsfs is only needed when getting data from Google Cloud Storage
35
+ ]
36
+
37
+ [tool.setuptools.dynamic]
38
+ version = {attr = "pvnet.__version__"}
39
+ readme = {file = "README.md", content-type = "text/markdown"}
40
+
41
+ [tool.setuptools.package-dir]
42
+ "pvnet" = "pvnet"
43
+
44
+ [project.optional-dependencies]
45
+ dev=[
46
+ "pvlive-api",
47
+ "black",
48
+ "flake8",
49
+ "isort",
50
+ "mypy",
51
+ "pre-commit",
52
+ "pytest",
53
+ "pytest-cov",
54
+ ]
55
+ all_models=[
56
+ "pytorch-tabnet",
57
+ "efficientnet_pytorch"
58
+ ]
59
+ all=["PVNet[dev,all_models]"]
60
+
61
+ [tool.mypy]
62
+ exclude = [
63
+ "^tests/",
64
+ ]
65
+ disallow_untyped_defs = true
66
+ disallow_any_unimported = true
67
+ no_implicit_optional = true
68
+ check_untyped_defs = true
69
+ warn_return_any = true
70
+ warn_unused_ignores = true
71
+ show_error_codes = true
72
+ warn_unreachable = true
73
+
74
+ [[tool.mypy.overrides]]
75
+ module = [
76
+ ]
77
+ ignore_missing_imports = true
78
+
79
+ [tool.pytest.ini_options]
80
+ minversion = "6.0"
81
+ addopts = "-ra -q"
82
+ testpaths = [
83
+ "tests",
84
+ ]
85
+
86
+ [tool.ruff]
87
+ line-length = 100
88
+ exclude = [".ipynb_checkpoints", "tests", "configs.example"]
@@ -1,2 +0,0 @@
1
- """PVNet"""
2
- __version__ = "3.0.29"
@@ -1,28 +0,0 @@
1
- [tool.mypy]
2
- exclude = [
3
- "^tests/",
4
- ]
5
- disallow_untyped_defs = true
6
- disallow_any_unimported = true
7
- no_implicit_optional = true
8
- check_untyped_defs = true
9
- warn_return_any = true
10
- warn_unused_ignores = true
11
- show_error_codes = true
12
- warn_unreachable = true
13
-
14
- [[tool.mypy.overrides]]
15
- module = [
16
- ]
17
- ignore_missing_imports = true
18
-
19
- [tool.pytest.ini_options]
20
- minversion = "6.0"
21
- addopts = "-ra -q"
22
- testpaths = [
23
- "tests",
24
- ]
25
-
26
- [tool.ruff]
27
- line-length = 100
28
- exclude = [".ipynb_checkpoints", "tests", "configs.example"]
@@ -1,8 +0,0 @@
1
- pvlive-api @ git+https://github.com/SheffieldSolar/PV_Live-API
2
- black
3
- flake8
4
- isort
5
- mypy
6
- pre-commit
7
- pytest
8
- pytest-cov
@@ -1,27 +0,0 @@
1
- ocf_datapipes>=3.3.6
2
- ocf_ml_metrics>=0.0.11
3
- numpy
4
- pandas
5
- matplotlib
6
- xarray
7
- ipykernel
8
- h5netcdf
9
- torch>=2.0.0
10
- lightning>=2.0.1
11
- torchvision
12
- pytest
13
- pytest-cov
14
- typer
15
- sqlalchemy
16
- fsspec[s3]
17
- wandb
18
- huggingface-hub
19
- tensorboard
20
- tqdm
21
- omegaconf
22
- hydra-core
23
- python-dotenv
24
- hydra-optuna-sweeper
25
- rich
26
- # gcsfs is only needed when getting data from Google Cloud Storage
27
- gcsfs
pvnet-3.0.29/setup.py DELETED
@@ -1,33 +0,0 @@
1
- """ Usual setup file for package """
2
- # read the contents of your README file
3
- from pathlib import Path
4
-
5
- from setuptools import find_packages, setup
6
-
7
- this_directory = Path(__file__).parent
8
- long_description = (this_directory / "README.md").read_text()
9
- install_requires = (this_directory / "requirements.txt").read_text().splitlines()
10
- extras_require = {"all_models": ["pytorch-tabnet", "efficientnet_pytorch"]}
11
-
12
- with open("pvnet/__init__.py") as f:
13
- for line in f:
14
- if line.startswith("__version__"):
15
- _, _, version = line.replace("'", "").split()
16
- version = version.replace('"', "")
17
-
18
-
19
- setup(
20
- name="PVNet",
21
- version=version,
22
- license="MIT",
23
- description="PVNet",
24
- author="Peter Dudfield",
25
- author_email="info@openclimatefix.org",
26
- company="Open Climate Fix Ltd",
27
- install_requires=install_requires,
28
- extras_require=extras_require,
29
- long_description=long_description,
30
- long_description_content_type="text/markdown",
31
- include_package_data=True,
32
- packages=find_packages(),
33
- )
File without changes
@@ -1,305 +0,0 @@
1
- import os
2
- import glob
3
- import tempfile
4
-
5
- import pytest
6
- import pandas as pd
7
- import numpy as np
8
- import xarray as xr
9
- import torch
10
- import hydra
11
-
12
- from ocf_datapipes.batch import BatchKey
13
- from datetime import timedelta
14
-
15
- import pvnet
16
- from pvnet.data.datamodule import DataModule
17
- from pvnet.data.wind_datamodule import WindDataModule
18
-
19
- import pvnet.models.multimodal.encoders.encoders3d
20
- import pvnet.models.multimodal.linear_networks.networks
21
- import pvnet.models.multimodal.site_encoders.encoders
22
- from pvnet.models.multimodal.multimodal import Model
23
-
24
-
25
- xr.set_options(keep_attrs=True)
26
-
27
-
28
- def time_before_present(dt: timedelta):
29
- return pd.Timestamp.now(tz=None) - dt
30
-
31
-
32
- @pytest.fixture
33
- def nwp_data():
34
- # Load dataset which only contains coordinates, but no data
35
- ds = xr.open_zarr(
36
- f"{os.path.dirname(os.path.abspath(__file__))}/test_data/sample_data/nwp_shell.zarr"
37
- )
38
-
39
- # Last init time was at least 2 hours ago and hour to 3-hour interval
40
- t0_datetime_utc = time_before_present(timedelta(hours=2)).floor(timedelta(hours=3))
41
- ds.init_time.values[:] = pd.date_range(
42
- t0_datetime_utc - timedelta(hours=3 * (len(ds.init_time) - 1)),
43
- t0_datetime_utc,
44
- freq=timedelta(hours=3),
45
- )
46
-
47
- # This is important to avoid saving errors
48
- for v in list(ds.coords.keys()):
49
- if ds.coords[v].dtype == object:
50
- ds[v].encoding.clear()
51
-
52
- for v in list(ds.variables.keys()):
53
- if ds[v].dtype == object:
54
- ds[v].encoding.clear()
55
-
56
- # Add data to dataset
57
- ds["UKV"] = xr.DataArray(
58
- np.zeros([len(ds[c]) for c in ds.coords]),
59
- coords=ds.coords,
60
- )
61
-
62
- # Add stored attributes to DataArray
63
- ds.UKV.attrs = ds.attrs["_data_attrs"]
64
- del ds.attrs["_data_attrs"]
65
-
66
- return ds
67
-
68
-
69
- @pytest.fixture()
70
- def sat_data():
71
- # Load dataset which only contains coordinates, but no data
72
- ds = xr.open_zarr(
73
- f"{os.path.dirname(os.path.abspath(__file__))}/test_data/sample_data/non_hrv_shell.zarr"
74
- )
75
-
76
- # Change times so they lead up to present. Delayed by at most 1 hour
77
- t0_datetime_utc = time_before_present(timedelta(minutes=0)).floor(timedelta(minutes=30))
78
- t0_datetime_utc = t0_datetime_utc - timedelta(minutes=30)
79
- ds.time.values[:] = pd.date_range(
80
- t0_datetime_utc - timedelta(minutes=5 * (len(ds.time) - 1)),
81
- t0_datetime_utc,
82
- freq=timedelta(minutes=5),
83
- )
84
-
85
- # Add data to dataset
86
- ds["data"] = xr.DataArray(
87
- np.zeros([len(ds[c]) for c in ds.coords]),
88
- coords=ds.coords,
89
- )
90
-
91
- # Add stored attributes to DataArray
92
- ds.data.attrs = ds.attrs["_data_attrs"]
93
- del ds.attrs["_data_attrs"]
94
-
95
- return ds
96
-
97
-
98
- @pytest.fixture()
99
- def sample_train_val_datamodule():
100
- # duplicate the sample batcnes for more training/val data
101
- n_duplicates = 10
102
-
103
- with tempfile.TemporaryDirectory() as tmpdirname:
104
- os.makedirs(f"{tmpdirname}/train")
105
- os.makedirs(f"{tmpdirname}/val")
106
-
107
- file_n = 0
108
-
109
- for file in glob.glob("tests/test_data/sample_batches/train/*.pt"):
110
- batch = torch.load(file)
111
-
112
- for i in range(n_duplicates):
113
- # Save fopr both train and val
114
- torch.save(batch, f"{tmpdirname}/train/{file_n:06}.pt")
115
- torch.save(batch, f"{tmpdirname}/val/{file_n:06}.pt")
116
-
117
- file_n += 1
118
-
119
- dm = DataModule(
120
- configuration=None,
121
- batch_size=2,
122
- num_workers=0,
123
- prefetch_factor=None,
124
- train_period=[None, None],
125
- val_period=[None, None],
126
- test_period=[None, None],
127
- batch_dir=f"{tmpdirname}",
128
- )
129
- yield dm
130
-
131
-
132
- @pytest.fixture()
133
- def sample_datamodule():
134
- dm = DataModule(
135
- configuration=None,
136
- batch_size=2,
137
- num_workers=0,
138
- prefetch_factor=None,
139
- train_period=[None, None],
140
- val_period=[None, None],
141
- test_period=[None, None],
142
- batch_dir="tests/test_data/sample_batches",
143
- )
144
- return dm
145
-
146
-
147
- @pytest.fixture()
148
- def sample_batch(sample_datamodule):
149
- batch = next(iter(sample_datamodule.train_dataloader()))
150
- return batch
151
-
152
-
153
- @pytest.fixture()
154
- def sample_satellite_batch(sample_batch):
155
- sat_image = sample_batch[BatchKey.satellite_actual]
156
- return torch.swapaxes(sat_image, 1, 2)
157
-
158
-
159
- @pytest.fixture()
160
- def sample_pv_batch(sample_batch):
161
- pv_data = sample_batch[BatchKey.pv]
162
- return pv_data
163
-
164
-
165
- @pytest.fixture()
166
- def sample_wind_batch():
167
- dm = WindDataModule(
168
- configuration=None,
169
- batch_size=2,
170
- num_workers=0,
171
- prefetch_factor=None,
172
- train_period=[None, None],
173
- val_period=[None, None],
174
- test_period=[None, None],
175
- batch_dir="tests/test_data/sample_wind_batches",
176
- )
177
- batch = next(iter(dm.train_dataloader()))
178
- return batch
179
-
180
-
181
- @pytest.fixture()
182
- def model_minutes_kwargs():
183
- kwargs = dict(
184
- forecast_minutes=480,
185
- history_minutes=120,
186
- )
187
- return kwargs
188
-
189
-
190
- @pytest.fixture()
191
- def encoder_model_kwargs():
192
- # Used to test encoder model on satellite data
193
- kwargs = dict(
194
- sequence_length=(90 - 30) // 5 + 1,
195
- image_size_pixels=24,
196
- in_channels=11,
197
- out_features=128,
198
- )
199
- return kwargs
200
-
201
-
202
- @pytest.fixture()
203
- def site_encoder_model_kwargs():
204
- # Used to test site encoder model on PV data
205
- kwargs = dict(
206
- sequence_length=180 // 5 + 1,
207
- num_sites=349,
208
- out_features=128,
209
- )
210
- return kwargs
211
-
212
-
213
- @pytest.fixture()
214
- def site_encoder_sensor_model_kwargs():
215
- # Used to test site encoder model on PV data
216
- kwargs = dict(
217
- sequence_length=180 // 5 + 1,
218
- num_sites=26,
219
- out_features=128,
220
- num_channels=23,
221
- target_key_to_use="wind",
222
- input_key_to_use="sensor",
223
- )
224
- return kwargs
225
-
226
-
227
- @pytest.fixture()
228
- def raw_multimodal_model_kwargs(model_minutes_kwargs):
229
- kwargs = dict(
230
- sat_encoder=dict(
231
- _target_=pvnet.models.multimodal.encoders.encoders3d.DefaultPVNet,
232
- _partial_=True,
233
- in_channels=11,
234
- out_features=128,
235
- number_of_conv3d_layers=6,
236
- conv3d_channels=32,
237
- image_size_pixels=24,
238
- ),
239
- nwp_encoders_dict={
240
- "ukv": dict(
241
- _target_=pvnet.models.multimodal.encoders.encoders3d.DefaultPVNet,
242
- _partial_=True,
243
- in_channels=2,
244
- out_features=128,
245
- number_of_conv3d_layers=6,
246
- conv3d_channels=32,
247
- image_size_pixels=24,
248
- ),
249
- },
250
- add_image_embedding_channel=True,
251
- pv_encoder=dict(
252
- _target_=pvnet.models.multimodal.site_encoders.encoders.SingleAttentionNetwork,
253
- _partial_=True,
254
- num_sites=349,
255
- out_features=40,
256
- num_heads=4,
257
- kdim=40,
258
- id_embed_dim=20,
259
- ),
260
- output_network=dict(
261
- _target_=pvnet.models.multimodal.linear_networks.networks.ResFCNet2,
262
- _partial_=True,
263
- fc_hidden_features=128,
264
- n_res_blocks=6,
265
- res_block_layers=2,
266
- dropout_frac=0.0,
267
- ),
268
- embedding_dim=16,
269
- include_sun=True,
270
- include_gsp_yield_history=True,
271
- sat_history_minutes=90,
272
- nwp_history_minutes={"ukv": 120},
273
- nwp_forecast_minutes={"ukv": 480},
274
- pv_history_minutes=180,
275
- min_sat_delay_minutes=30,
276
- )
277
-
278
- kwargs.update(model_minutes_kwargs)
279
-
280
- return kwargs
281
-
282
-
283
- @pytest.fixture()
284
- def multimodal_model_kwargs(raw_multimodal_model_kwargs):
285
- return hydra.utils.instantiate(raw_multimodal_model_kwargs)
286
-
287
-
288
- @pytest.fixture()
289
- def multimodal_model(multimodal_model_kwargs):
290
- model = Model(**multimodal_model_kwargs)
291
- return model
292
-
293
-
294
- @pytest.fixture()
295
- def multimodal_quantile_model(multimodal_model_kwargs):
296
- model = Model(output_quantiles=[0.1, 0.5, 0.9], **multimodal_model_kwargs)
297
- return model
298
-
299
-
300
- @pytest.fixture()
301
- def multimodal_weighted_quantile_model(multimodal_model_kwargs):
302
- model = Model(
303
- output_quantiles=[0.1, 0.5, 0.9], **multimodal_model_kwargs, use_weighted_loss=True
304
- )
305
- return model
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes