-
Notifications
You must be signed in to change notification settings - Fork 172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adapt pysteps to allow for nowcast plugins. #418
base: master
Are you sure you want to change the base?
Changes from 16 commits
08de598
f26bef5
ab1b082
08ea3cd
bcb7ba9
6f36867
24d6c41
3f5d31a
b37ce1d
cd36341
0cd6aa2
b9dc46d
a8a401f
d50b78c
998d076
aa81fe8
54e2dd8
4b12402
c063be5
c790b02
ac9f65e
45070d4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
"""Implementations of deterministic and ensemble nowcasting methods.""" | ||
|
||
from pysteps.nowcasts.interface import get_method | ||
from pysteps.nowcasts.interface import * | ||
|
||
try: | ||
from dgmr_module_plugin import dgmr | ||
except ImportError: | ||
dgmr = None | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,9 @@ | |
get_method | ||
""" | ||
|
||
from pprint import pprint | ||
from pysteps import nowcasts | ||
import importlib | ||
from pysteps.extrapolation.interface import eulerian_persistence | ||
from pysteps.nowcasts import ( | ||
anvil, | ||
|
@@ -39,7 +42,10 @@ | |
steps, | ||
sseps, | ||
) | ||
|
||
from pysteps.nowcasts import lagrangian_probability | ||
import os | ||
|
||
|
||
_nowcast_methods = dict() | ||
_nowcast_methods["anvil"] = anvil.forecast | ||
|
@@ -54,6 +60,97 @@ | |
_nowcast_methods["steps"] = steps.forecast | ||
|
||
|
||
def discover_nowcasts(): | ||
""" | ||
Search for installed nowcasts plugins in the entrypoint 'pysteps.plugin.nowcasts' | ||
|
||
The nowcasts method found are added to the `pysteps.nowcasts.interface_nowcasts_methods` | ||
dictionary containing the available nowcasts_methods. | ||
""" | ||
|
||
# The pkg resources needs to be reload to detect new packages installed during | ||
# the execution of the python application. For example, when the plugins are | ||
# installed during the tests | ||
import pkg_resources | ||
|
||
importlib.reload(pkg_resources) | ||
entry_points = list( | ||
pkg_resources.iter_entry_points(group="pysteps.plugins.nowcasts", name=None) | ||
) | ||
if not entry_points: | ||
print("No entry points found in 'pysteps.plugins.nowcasts'.") | ||
return | ||
|
||
for entry_point in pkg_resources.iter_entry_points( | ||
group="pysteps.plugins.nowcasts", name=None | ||
): | ||
_module = entry_point.load() | ||
nowcast_module_name = entry_point.name | ||
|
||
if nowcast_module_name not in _nowcast_methods: | ||
_nowcast_methods[nowcast_module_name] = _module | ||
|
||
else: | ||
RuntimeWarning( | ||
f"The Nowcasts methode '{nowcast_module_name}' is already available in" | ||
"'pysteps.nowcasts._nowcasts_methods'.\n" | ||
f"Skipping {entry_point.module_name}:{'.'.join(entry_point.attrs)}" | ||
) | ||
if hasattr(nowcasts, nowcast_module_name): | ||
RuntimeWarning( | ||
f"The nowcasts method '{nowcast_module_name}' is already an attribute" | ||
"of 'pysteps.nowcasts'.\n" | ||
f"Skipping {entry_point.module_name}:{'.'.join(entry_point.attrs)}" | ||
) | ||
else: | ||
setattr(nowcasts, nowcast_module_name, _module) | ||
|
||
|
||
def nowcasts_info(): | ||
"""Print all the available importers.""" | ||
|
||
# nowcasts methods available in the `nowcasts` package | ||
available_nowcasts = [ | ||
attr.split(".")[0] | ||
for attr in os.listdir(" ".join(nowcasts.__path__)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Loickemajou Is there a more elegant way to detect all the nowcast methods that doesn't use os.listdir? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @ladc, for the remark. I will take time to look into alternative approaches and see if I can find a more elegant way to achieve this. |
||
if not attr.startswith("__") and attr != "interface.py" | ||
] | ||
print("\nMethods available in the pysteps.nowcasts") | ||
pprint(available_nowcasts) | ||
# nowcasts declared in the pysteps.nowcast interface | ||
|
||
nowcasts_in_the_interface = [f for f in _nowcast_methods.keys()] | ||
|
||
print("\nMethods available in the pysteps.nowcasts.get_method interface") | ||
pprint([(short_name, f.__name__) for short_name, f in _nowcast_methods.items()]) | ||
|
||
# Let's use sets to find out if there are importers present in the importer module | ||
# but not declared in the interface, and viceversa. | ||
available_nowcasts = set(available_nowcasts) | ||
nowcasts_in_the_interface = set(nowcasts_in_the_interface) | ||
|
||
difference = available_nowcasts ^ nowcasts_in_the_interface | ||
if len(difference) > 0: | ||
print("\nIMPORTANT:") | ||
_diff = available_nowcasts - nowcasts_in_the_interface | ||
if len(_diff) > 0: | ||
print( | ||
"\nIMPORTANT:\nThe following importers are available in pysteps.nowcasts module " | ||
"but not in the pysteps.nowcasts.get_method interface" | ||
) | ||
pprint(_diff) | ||
_diff = nowcasts_in_the_interface - available_nowcasts | ||
if len(_diff) > 0: | ||
print( | ||
"\nWARNING:\n" | ||
"The following importers are available in the pysteps.nowcasts.get_method " | ||
"interface but not in the pysteps.nowcasts module" | ||
) | ||
pprint(_diff) | ||
|
||
return available_nowcasts, nowcasts_in_the_interface | ||
|
||
|
||
def get_method(name): | ||
""" | ||
Return a callable function for computing nowcasts. | ||
|
@@ -90,6 +187,11 @@ | |
| sseps | short-space ensemble prediction system (SSEPS). | | ||
| | Essentially, this is a localization of STEPS | | ||
+-----------------+-------------------------------------------------------+ | ||
| dgmr | a deep generative model for the probabilistic . | | ||
dnerini marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| | nowcasting of precipitation from radar developed by | | ||
| | researchers from DeepMind | | ||
+-----------------+-------------------------------------------------------+ | ||
|
||
""" | ||
if isinstance(name, str): | ||
name = name.lower() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why this block? the dgmr plugin, if installed, will be discovered below in
discover_nowcasts()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I see, is it because the function is called
forecast
and it should be added to a module nameddgmr
? https://github.com/pySTEPS/pysteps-dgmr-nowcasts/blob/c8903bfa689951c555cfb275fb2100e36a683e40/setup.py#L86There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, in the get_method, actually when the plugin is installed, the dgmr is discovered by pysteps and it is possible to
dgmr=get_method('dgmr').
Though is not quite a nice way, included this block so that when the plugin is installed we could called it directly by doing
from pysteps.nowcasts import dgmr.
Had no idea on how to do that differently and will be very delighted to have some suggestions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you removed that part, @Loickemajou , does it mean that you found an alternative solution?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @dnerini
I have removed the conflicting dependencies and model weights to ensure that they do not interfere with PySTEPS during execution.
However, I have not yet found an alternative solution and would appreciate any suggestions or insights you might have to help improve the integration process.