Skip to content

Support for mixed precip/noprecip input and AR order 1#544

Open
ladc wants to merge 27 commits intomasterfrom
precip-noprecip_input_fix_and_ar_order-1_fix_issue543
Open

Support for mixed precip/noprecip input and AR order 1#544
ladc wants to merge 27 commits intomasterfrom
precip-noprecip_input_fix_and_ar_order-1_fix_issue543

Conversation

@ladc
Copy link
Copy Markdown
Contributor

@ladc ladc commented Mar 27, 2026

Fix several issues in case of intermittent rainfall in the radar images:

  • Fix mixed rain/norain input frames
  • Add tests
  • Make AR1 work for regular steps
  • Add tests
  • Make AR1 work for steps blending
  • Add tests

Works towards fixing issue #543.

Reduce overall number of tests and refactor code
Add dedicated AR order parameterization
@ladc ladc force-pushed the precip-noprecip_input_fix_and_ar_order-1_fix_issue543 branch from 2e24248 to 5170768 Compare March 27, 2026 12:44
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 2, 2026

Codecov Report

❌ Patch coverage is 94.14894% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.20%. Comparing base (29a317b) to head (15caf3a).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
pysteps/utils/check_norain.py 77.27% 5 Missing ⚠️
pysteps/blending/skill_scores.py 70.00% 3 Missing ⚠️
pysteps/blending/steps.py 80.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #544      +/-   ##
==========================================
+ Coverage   83.89%   84.20%   +0.31%     
==========================================
  Files         168      170       +2     
  Lines       14678    14974     +296     
==========================================
+ Hits        12314    12609     +295     
- Misses       2364     2365       +1     
Flag Coverage Δ
unit_tests 84.20% <94.14%> (+0.31%) ⬆️

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.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@FelixE91
Copy link
Copy Markdown
Contributor

FelixE91 commented Apr 7, 2026

We consider these fixes important enough to merge them into the master branch. They can have a direct positive impact on the operation of pysteps, as they
(i) prevent some runs from crashing when mixed time steps with and without precipitation are present in the radar inputs
(ii) provide more readable and clearer error messages if the run does abort due to mixed time steps with and without precipitation in the radar inputs
The tests (pytest) are still generating numerous warnings. Most of them are unrelated to the code we added here.
The warnings from the pytest execution should be investigated as a separate issue #545

@FelixE91
Copy link
Copy Markdown
Contributor

FelixE91 commented Apr 7, 2026

The implemented solution prevents pysteps from crashing when the radar input data contains both precip and noprecip time steps.
If possible, the most recent time steps with precipitation are used, and the ar_order value is adjusted (i.e. reduced) as needed.
Otherwise, the radar input is set to an observation array without precipitation and a warning is printed. Pysteps with NWP blending will still run if rain is present in the NWP.

@FelixE91 FelixE91 marked this pull request as ready for review April 7, 2026 13:56
@dnerini dnerini requested a review from RubenImhoff April 7, 2026 20:08
@dnerini dnerini self-requested a review April 7, 2026 20:08
)

# Check all time steps for zero-precip (constant field, minimum==maximum)
zero_precip = [np.nanmin(obs) == np.nanmax(obs) for obs in precip]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do you not use the check_norain method here?

Copy link
Copy Markdown
Contributor

@FelixE91 FelixE91 Apr 8, 2026

Choose a reason for hiding this comment

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

The output differs. While check_norain returns a Boolean value for the entire array, the check here is performed for each individual timestep and returns a list of length ar_order+1. This is a simple technical check to verify whether the input array is constant for the respective timestep, which must be avoided in order to calculate the spatial correlation coefficient.
Note that check_norain is still used later in steps.py to apply the specified thresholds.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If you prefer, we could call this const_precip or so to avoid confusion?

@mats-knmi
Copy link
Copy Markdown
Contributor

We have been having these issues as well in our processing, so I hope this PR finally fixes it. To me it looks good, I just had a couple of questions. If they can be answered I can approve it.

Copy link
Copy Markdown
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.

I have tried to answer @mats-knmi's questions. Final approval for the updates of the blending and autoregression functions is still pending, most of it to enable AR-1 runs.

@RubenImhoff
Copy link
Copy Markdown
Contributor

Thanks for picking this up, great work! I will go through the changes and leave my review as well.

Regarding AR_order = 1, indeed this was not yet supported (also mentioned in the code by the way: "The order of the autoregressive model to use. Must be >= 1."). I am glad to see that we are fixing this now, too. :)

)

# Check all time steps for zero-precip/constant field (constant field, minimum==maximum)
const_precip = [np.nanmin(obs) == np.nanmax(obs) for obs in precip]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A lot of 'no_rain' cases consist of a couple of cells containing clutter. Our experience is that the autoregressive model and/or determining the correlation coefficients then also fail. So, ideally we check for that, too.

In the check_norain function, we have built in a norain_thr, which is the minimum fraction of rainy pixels, and a threshold (precip_thr). I can imagine that it would be good, and consistent, to use that here, too. If so, the function becomes more similar to the check_norain function, so we could even see if an integration of the two functions makes more sense at that point (no preference on my side).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, gotcha! That makes sense, now I understand why the check_norain method is for flexible than just checking the min and max.
As mentioned, it was a technical test here to avoid const arrays as they cause errors in the correlation coefficients.
I will modify the function to use the thresholds and check for a constant field.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Great, thanks, @FelixE91!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also in check_norain we now also have support for a window function. I am not sure how it works in this case, but we have had instances where there was precipitation outside the window function, so it passed a no_rain check, but after the window function was applied it was still a constant field so we got an error.

I am not sure if that is the case here, but imo just using the check_norain method here is slightly more robust and it should also cover the case of a constant field that you are checking for.

Do you have a specific reason why using check_norain here would be worse than what you are doing now?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I mean, I guess we can assume that a constant field exists if all precip is zero only. It woudl be very unlikely to have the same non-zero value at every pixel ;)
Since I need a list of length ar_order+1 as output, I can simply do const_precip = [check_norain(obs) for obs in precip] that should work and address @RubenImhoff 's comment, too.

"precip_thr": precip_thr,
"norain_thr": norain_thr,
# Set default window function to "tukey" to match the default in check_inputs() below
"win_fun": "tukey" if noise_kwargs is None else noise_kwargs["win_fun"],
Copy link
Copy Markdown
Contributor

@FelixE91 FelixE91 Apr 9, 2026

Choose a reason for hiding this comment

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

I was not totally sure whether this check should be for the entire domain or for the window function that is used in later noise generation.
Here I set it to match this window function ("tukey" by default).
If you think it is better to check the full domain at this point of the code, we simply delete lines 3665/3666.

"precip_thr": precip_thr,
"norain_thr": norain_thr,
# Set default window function to "tukey" to match the default in check_inputs() below
"win_fun": "tukey" if noise_kwargs is None else noise_kwargs["win_fun"],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as in blending.steps.py.
If we want to check the entire domain here, we can delete lines 1515/1516.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Precip + no-precip input time steps cause blending failure AND in general ar_order=1 causes blending failure

4 participants