Skip to content

Discussion: what to do when we have 'negative' hazard #1257

Description

@ChrisFairless

We often do drought modelling, where drought indices (intensity) are usually given as negative values where larger values are stronger droughts.

Therefore the impact functions we use have a domain of hazard intensities of (e.g.) [-4, 0], and define a monotonically decreasing impact function – here's an example:

Image

CLIMADA seems to be mostly ok with this (to my surprise – I dimly remember some guardrails against decreasing functions? Or a reason not to have a function of this form?).

However it fails silently when applying measures to the impact function – if your measure transforms the function's intensity, (new_intensity = a * old_intensity + b) CLIMADA makes sure that the the resulting intensity doesn't drop below zero. The issue is that it doesn't tell you you're doing this, and it only shows up when someone is presenting their results to you and for some reason their promising drought adaptation measures have negative benefits. (I've copied the code snippet where this happens at the end of this Issue).

I think this needs to be flagged to the user at least. And I assume this will be relevant in the new Measures classes as well. @spjuhel – maybe you've already handled it.

I've seen this dealt with in two ways:

  • modify the source code locally to make sure intensities remain below zero when haz == "DR"
  • multiply both the hazard and the impact function intensities by -1 for the analysis, and then they all behave nicely.

Neither are very useful to newer users who won't know something is wrong.

The same behaviour would happen if the user is modelling negative impacts if their measure adjusts the impact function's mean damage degree, since they are also enforced to be >= 0 (see code at end).

I don't see an obvious workaround that can anticipate all the edge case impact functions that some sickos might bring. Maybe an option to turn off this behaviour and make it the user's responsibility?

But for now, I suggest that CLIMADA warn the user when it makes this adjustment, so it's at least not completely invisible.

Thoughts?

Big thanks to Dhiraj Gyawali @dhiraj172 for his discussions on the topic!

The relevant code is here:
https://github.com/CLIMADA-project/climada_python/blob/18d684939b1201a50f841cffb35ecdd9dca100f7/climada/entity/measures/base.py#L394C1-L406C14

        new_imp_set = copy.deepcopy(imp_set)
        for imp_fun in new_imp_set.get_func(self.haz_type):
            LOGGER.debug("Transforming impact functions.")
            imp_fun.intensity = np.maximum(
                imp_fun.intensity * self.hazard_inten_imp[0] - self.hazard_inten_imp[1],
                0.0,
            )
            imp_fun.mdd = np.maximum(
                imp_fun.mdd * self.mdd_impact[0] + self.mdd_impact[1], 0.0
            )
            imp_fun.paa = np.maximum(
                imp_fun.paa * self.paa_impact[0] + self.paa_impact[1], 0.0
            )

Activity

  1. self-assigned this
    on Feb 26, 2026
  2. chahank commented on Feb 27, 2026

    @chahank
    Member

    Excellent remark @ChrisFairless and @dhiraj172 . This is one of the reasons that we are completely rebuilding the measures and adaptation option appraisal modules. In the next version, the sure will have complete control over how the measure acts. This makes it slightly more involved in the use, but avoids the kind of pitfalls described above.

    We should also consider the case when the intensities, impacts or impact functions cover both positive and negative value ranges (e.g., temperatures in Celsius and productivity+loss).

    @spjuhel : we should make sure that the trajectory and adaptation option appraisal modules do never implicitly assume positive intensities and/or impact functions.

    @ValentinGebhart : I think the interpolation/extrapolation of the return periods might currently assume positive values. Could you maybe check and adjust if possible?

  3. ValentinGebhart commented on Feb 27, 2026

    @ValentinGebhart
    Collaborator

    Interesting example, thanks for bringing it up! In principle, the inter/extrapolation should also work with negative internsity or impact values. Problems might arise are when:

    • we filter impacts with a threshold (0 by default) before interpolation. The threshold can be adapted by the user though.
    • we transform impact or intensity values to the log scale before interpolation (current default). This can also be adapted by the user.

    So I would say that it should work if the user provides the correct kwargs to the functions. Is this enough or should we add further warnings/behaviour?

  4. chahank commented on Feb 27, 2026

    @chahank
    Member

    Great! Maybe we can add an example in the tutorial?

  5. ValentinGebhart commented on Mar 2, 2026

    @ValentinGebhart
    Collaborator

    Quick follow up to exceednace frequency with negative values:
    When computing return periods, we sort the impact values in descending order before computing exceedance frequencies. In Chris' example above, we would rather like to sort in ascending order (more negative is stronger hazard), but I assume that we do not want to hardcode this whenever the hazard intensities are negative. So it would have to be an optional parameter to any exceedance frequency computation. Do we want this?

  6. ChrisFairless commented on Mar 3, 2026

    @ChrisFairless
    CollaboratorAuthor

    For negative hazard intenstities, this is fine, since we're calculating just with impacts and event frequencies, not hazards.

    For negative impacts I think we can probably leave it as it is: I don't know of a use case where negative impacts are are the top of the exceedance curve rather than the bottom, and it's not worth preparing for that until we see it.

    However an example somewhere illustrating your points above and the appropriate kwargs would be super nice, although not urgent.

  7. ValentinGebhart commented on Apr 23, 2026

    @ValentinGebhart
    Collaborator

    @chahank @ChrisFairless
    For examples of how to adapt kwargs in local exceedance computations when handling negative values, and the addition of an option to change the ordering of intensity values, see #1285. Some instructions and examples are added to the last section of the local exceedance tutorial.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions