Skip to content

Commit 789829c

Browse files
committed
GeospatialScenario: dask client init, display dask
1 parent 2501b7f commit 789829c

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

pvdeg/geospatialscenario.py

+66-4
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,15 @@
1111
import numpy as np
1212
import matplotlib.pyplot as plt
1313
from typing import List, Union, Optional, Callable
14+
from dask.distributed import Client
1415
from IPython.display import display, HTML
1516
import cartopy.crs as ccrs
1617
import cartopy.feature as cfeature
1718

1819
from pvdeg.scenario import Scenario
1920

21+
pvdeg.geospatial.start_dask
22+
2023
class GeospatialScenario(Scenario):
2124
def __init__(
2225
self,
@@ -33,6 +36,7 @@ def __init__(
3336
meta_data: pd.DataFrame = None,
3437
func: Callable = None,
3538
template: xr.Dataset = None,
39+
dask_client: Client = None,
3640
):
3741
super().__init__(
3842
name=name,
@@ -49,6 +53,7 @@ def __init__(
4953
self.hpc = hpc
5054
self.func = func
5155
self.template = template
56+
self.dask_client = dask_client
5257
self.kdtree = None # sklearn kdtree
5358

5459
def __eq__(self, other):
@@ -57,8 +62,46 @@ def __eq__(self, other):
5762
due to larger than memory/out of memory datasets stored in
5863
GeospatialScenario.weather_data attribute.
5964
""")
60-
6165

66+
def start_dask(self, hpc=None) -> None:
67+
"""
68+
Starts a dask cluster for parallel processing.
69+
70+
Parameters
71+
----------
72+
hpc : dict
73+
Dictionary containing dask hpc settings (see examples below).
74+
Supply `None` for a default configuration.
75+
76+
Examples
77+
--------
78+
Local cluster:
79+
80+
.. code-block:: python
81+
82+
hpc = {'manager': 'local',
83+
'n_workers': 1,
84+
'threads_per_worker': 8,
85+
'memory_limit': '10GB'}
86+
87+
SLURM cluster:
88+
89+
.. code-block:: python
90+
91+
kestrel = {
92+
'manager': 'slurm',
93+
'n_jobs': 1, # Max number of nodes used for parallel processing
94+
'cores': 104,
95+
'memory': '246GB',
96+
'account': 'pvsoiling',
97+
'walltime': '4:00:00',
98+
'processes': 52,
99+
'local_directory': '/tmp/scratch',
100+
'job_extra_directives': ['-o ./logs/slurm-%j.out'],
101+
'death_timeout': 600,}
102+
"""
103+
self.dask_client = pvdeg.geospatial.start_dask()
104+
62105
# add restoring from gids functionality from nsrdb
63106
def addLocation(
64107
self,
@@ -605,12 +648,13 @@ def run(self, hpc_worker_conf: Optional[dict] = None) -> None:
605648
Only supports one function at a time. Unlike `Scenario` which supports unlimited conventional pipeline jobs.
606649
Results are stored in the `GeospatialScenario.results` attribute.
607650
608-
Creates a dask cluster or client using the hpc_worker_conf parameter.
651+
Creates a dask client if it has not been initialized previously with `GeospatialScenario.start_dask`.
609652
610653
Parameters:
611654
-----------
612655
hpc_worker_conf : dict
613656
Dictionary containing dask hpc settings (see examples below).
657+
When `None`, a default configuration is used.
614658
615659
Examples
616660
--------
@@ -639,7 +683,12 @@ def run(self, hpc_worker_conf: Optional[dict] = None) -> None:
639683
'job_extra_directives': ['-o ./logs/slurm-%j.out'],
640684
'death_timeout': 600,}
641685
"""
642-
client = pvdeg.geospatial.start_dask(hpc=hpc_worker_conf)
686+
if self.dask_client and hpc_worker_conf:
687+
raise ValueError(f"Dask Client already exists, cannot configure new client.")
688+
elif not self.dask_client:
689+
self.dask_client = pvdeg.geospatial.start_dask(hpc=hpc_worker_conf)
690+
691+
print("Dashboard:", self.dask_client.dashboard_link)
643692

644693
analysis_result = pvdeg.geospatial.analysis(
645694
weather_ds=self.weather_data,
@@ -650,7 +699,7 @@ def run(self, hpc_worker_conf: Optional[dict] = None) -> None:
650699

651700
self.results = analysis_result
652701

653-
client.shutdown()
702+
self.dask_client.shutdown()
654703

655704
def restore_result_gids(self):
656705
"""
@@ -987,6 +1036,15 @@ def format_geospatial_work(self):
9871036
<p><strong>self.template:</strong> {self.format_template()}</p>
9881037
"""
9891038

1039+
return ""
1040+
1041+
def format_dask_link(self):
1042+
if self.dask_client:
1043+
return f"""
1044+
<a href="{self.dask_client.dashboard_link}" target="_blank">{self.dask_client.dashboard_link}</a></p>
1045+
"""
1046+
return ""
1047+
9901048
def _ipython_display_(self):
9911049
file_url = f"file:///{os.path.abspath(self.path).replace(os.sep, '/')}"
9921050
html_content = f"""
@@ -1015,6 +1073,10 @@ def _ipython_display_(self):
10151073
<h3>self.meta_data</h3>
10161074
{self.format_geo_meta()}
10171075
</div>
1076+
<div>
1077+
<h3>self.dask_client</h3>
1078+
{self.format_dask_link()}
1079+
</div>
10181080
</div>
10191081
<p><i>All attributes can be accessed by the names shown above.</i></p>
10201082
<script>

0 commit comments

Comments
 (0)