Skip to content
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 postprocessing plugins #405

Open
wants to merge 36 commits into
base: master
Choose a base branch
from

Conversation

joeycasey87
Copy link

Added an infrastructure.py file to the postprocessing folder which should operate in the same way as the interface file does for the importers in the io folder. The postprocessor file is currently effectively empty as no postprocessor plugins have been added yet. A line has been added to the init file so that it should act similar to the init file in the io folder.

@@ -2,3 +2,4 @@
"""Methods for post-processing of forecasts."""

from . import ensemblestats
from postprocessors import *
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from postprocessors import *
from .postprocessors import *

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just wondering if "postprocessors" is a good name? sounds a bit too vague, particularly as a submodule of "postprocessing" ... can we try to be a bit more specific? perhaps use "diagnostic" instead? what do you think? @ladc ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point - "diagnostic" makes sense if we also want to add other postprocessors in the future which are not purely diagnostic (such as bias correction methods).

Copy link

codecov bot commented Jul 25, 2024

Codecov Report

Attention: Patch coverage is 93.38843% with 8 lines in your changes missing coverage. Please review.

Project coverage is 84.37%. Comparing base (9dc68c5) to head (657e56e).

Files with missing lines Patch % Lines
pysteps/postprocessing/interface.py 88.57% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #405      +/-   ##
==========================================
+ Coverage   84.23%   84.37%   +0.13%     
==========================================
  Files         160      161       +1     
  Lines       13242    13345     +103     
==========================================
+ Hits        11155    11260     +105     
+ Misses       2087     2085       -2     
Flag Coverage Δ
unit_tests 84.37% <93.38%> (+0.13%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@dnerini dnerini changed the title Added structure for the creation of postprocessing plugins Add diagnostic plugins Aug 5, 2024
@joeycasey87
Copy link
Author

Hi @dnerini, could you please review this pull request when you have the time? The extended version of the cookiecutter plugin template which can be used to create importer, diagnostic postprocessing, and nowcast plugins is nearly finished but I require the postprocessing interface to be merged to ensure that everything is behaving correctly when tested. Cheers

@ladc
Copy link
Contributor

ladc commented Aug 20, 2024

Thanks for this contribution! We discussed how to make it more generic and @joeycasey87 will try to refactor it tomorrow to allow for various kinds of post-processors including new ensemblestats and bias correction methods, for example. To be continued.

@ladc ladc changed the title Add diagnostic plugins Adapt pysteps to allow for postprocessing plugins (diagnostics and ensemblestats for now) Aug 27, 2024
@ladc ladc changed the title Adapt pysteps to allow for postprocessing plugins (diagnostics and ensemblestats for now) Adapt pysteps to allow for postprocessing plugins Aug 27, 2024
@dnerini
Copy link
Member

dnerini commented Sep 8, 2024

what's the status of this PR? should we mark it as a draft?

@ladc ladc requested a review from FelixE91 January 14, 2025 14:07
joeycasey87 and others added 14 commits January 14, 2025 15:14
Also reformatted with black. Tests were added for the get_method and diagnostics_info functions in the postprocessing interface. Tests for the discover_diagnostics function will be written once these changes have been merged as then the cookiecutter plugins can then be properly tested.
Changed the test file to match the test updated pysteps test file
These were necessary for the IO plugins, but less so for the diagnostics.
Avoid duplicate code, refactor into functions.
Also fix a small typo causing a bug: postprocessor_s_
@ladc ladc force-pushed the postprocessor_plugin branch from d9b593d to 3586f56 Compare January 14, 2025 14:17
@ladc
Copy link
Contributor

ladc commented Jan 14, 2025

Apologies for the force-push, but I have done a rebase to the latest master version. The plan is now to clean up some of the dummy code (maybe move this into test, but most likely remove it entirely), add the necessary test(s) in test_plugins_support.py and hopefully merge it into the master branch soonish, thanks in advance to @FelixE91 #nopressure

For the tests, we're now only checking the importer cookiecutter template. The new precipitation type plugin was created using the diagnostics template (I suppose), so we should add a test for this new template ( see also https://github.com/pySTEPS/pysteps/blob/e3325854dae006b1e78eb43a6d2203f2b0b71560/pysteps/tests/test_plugins_support.py#L17C1-L17C20 )

Question: do we really need a separate template for all the plugin types? (Diagnostics, ensemblestats ... which are all in fact postprocessors)? Could we have one for any kind of postprocessors? Or even better, one cookiecutter template for all kinds of plugins which could even expose multiple functions (e.g. diagnostics and visualisation)? Not urgent at all.

Felix Erdmann and others added 7 commits January 29, 2025 13:29
- should match names as in the plugin cookiecutter
- diagnostic plugins created with the cookiecutter are now correctly
recognized and implemented
- importer and diagnostic plugins correctly recognized in entry points
- cleaning: removed unused import modules
@ladc ladc force-pushed the postprocessor_plugin branch from 51f9642 to 1305e88 Compare February 25, 2025 13:41
@ladc ladc self-requested a review February 26, 2025 14:38
Copy link
Contributor

@ladc ladc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost done, some final cleanup needed. There's also still some duplicate code but that will take a bit more time to simplify.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just delete this file?

Copy link
Contributor

@FelixE91 FelixE91 Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, at least not until we change the structure. The objective was to create a structure similar to what exists for the importers with io.importers.py and for the ensemblestats with postprocessing.ensemblestats.py.
The postprocessing interface.py and __init__.py currently read from diagnostics.py to check for available pre-installed functions1 - that's consistent with the way pre-installed ensemblestats functions are loaded and similar to the io.__init__.py and io.interface.py to load pre-installed importers.

New functions found in the entry_points are added to the available methods in the methods dictionary.

The (io and postprocessing) interface also reads from the module (importers.py and ensemblestats.py|diagnostics.py, respectively) BUT it would not add the functions to the methods dictionary. Instead, they must be added explicitly to the interface.py methods dictionary (_importer_methods and _ensemblestats_methods|_diagnostics_methods, respectively) to avoid an error in the get_method() function.
This might be fixed to add pre-installed functions from the module automatically to the methods dictionary.

Footnotes

  1. At the moment there are no pre-installed diagnostics. This might change in the future, unless we always use the cookiecutter to create plugins

@ladc
Copy link
Contributor

ladc commented Feb 26, 2025

Also, by updating the cookiecutter template I just realised that we broke the standard pysteps tests, so best to merge these changes in quite fast.

@FelixE91
Copy link
Contributor

Additional tests are successful. CodeCov's getting closer to the target value. Still some work to do before we can merge into main.

Copy link
Contributor

@FelixE91 FelixE91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's decide together whether we want to merge it like this or make some of the recommended changes first. @dnerini @ladc

from pprint import pprint
import warnings

_diagnostics_methods = dict()
Copy link
Contributor

@FelixE91 FelixE91 Feb 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still a discrepancy here, as the dictionary in the io.interface is called _importer_methods, i.e. without “s” on importer. However, I would leave it as it is, as the use of plural is consistent with the module name.

difference = module_methods_set ^ interface_methods_set
if len(difference) > 0:
# print("\nIMPORTANT:")
_diff = module_methods_set - interface_methods_set
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we want to avoid differences, it should not be a problem that these lines with if len(difference) > 0 are not considered in the tests - this means that the plugin implementation works well.


import_abc_xxx("filename")
import_abc_yyy("filename")
from pysteps.io.importers import import_institution_name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should similar lines be added to test the diagnostics plugin? Or not needed here in ci?

@@ -107,7 +113,7 @@ def importers_info():

difference = available_importers ^ importers_in_the_interface
if len(difference) > 0:
print("\nIMPORTANT:")
# print("\nIMPORTANT:")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete?

"""

# Add your diagnostic_ function here AND add this method to the _diagnostics_methods
# dictionary in postprocessing.interface.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's see how we proceed with this file. I think we must keep it as mention in Originally posted by @ladc in #405 (comment)

"""
import importlib

from pysteps.postprocessing import diagnostics, ensemblestats
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codacy Static Code Analysis does not like the import of diagnostics as it isn't explicitly called. However, it is needed to add diagnostics plugins as globals()[module] in add_postprocessor() needs the diagnostics module to be imported.

@@ -65,9 +65,8 @@ commands =
# Test the pysteps plugin support
pip install cookiecutter
cookiecutter -f --no-input https://github.com/pySTEPS/cookiecutter-pysteps-plugin -o {temp_dir}/
pip install {temp_dir}/pysteps-importer-abc
pip install {temp_dir}/pysteps-importer-institution-name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We must remember to update all these default names when we further develop or simplify the cookiecutter.

Maybe we can introduce an environment variable that sets the default name? Then we would only need to change it in one place.


Interface for the postprocessing module.

Support postprocessing types:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added that we currently support these two types of postprocessing plugins.
We might need to add some tests for the ensemblestats type later.

Note that we have removed the ensemblestats type from the cookiecutter at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In review
Development

Successfully merging this pull request may close these issues.

4 participants