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

Feature/add missing jrc flood impact functions #111

Merged
merged 13 commits into from
Oct 31, 2024

Conversation

aleeciu
Copy link
Collaborator

@aleeciu aleeciu commented Feb 6, 2024

This PR adds the missing flood impact fucntions from the JRC publications. The current implementation only uses the "residential buildings" functions, and this PR adds those from the five more categories (or sectors as tjey are called here) available in the JRC report, i.e., commercial buildings, industrial buildings, transport, infrastructure and agriculture. To do that, I had to slightly adjust the code as one can no longer only choose the region, but both the region and a sector.

@aleeciu aleeciu requested review from zeliest and peanutfun February 6, 2024 09:39
@@ -35,116 +35,114 @@ def test_flood_imp_func_set(self):

def test_region_Africa(self):
Copy link
Member

Choose a reason for hiding this comment

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

Would it not be simpler to have tests that loop through the allowed parameters and all methods? This class just stores data, so this is what should be tested. Also, a test for when wrong parameters are used would be good. This makes the test more complete, and also shorter.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I used the backbone structure of the already existing tests and adapted them to the changes of provided by this new PR. If you think tests are poorly written, I would open a new PR which rewrites them.

Copy link
Member

Choose a reason for hiding this comment

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

That would be a good idea. The code base is constantly improving, and thus copying older, less mature code is suboptimal going forward.

@chahank
Copy link
Member

chahank commented Apr 29, 2024

@aleeciu : could you please provide a timeline to finish this PR?

@aleeciu
Copy link
Collaborator Author

aleeciu commented May 3, 2024

Apologies, I replied quite timely in fact, but I did not realize I had to click on "send the review" in order for my comment to be visible. Anyway, here you really find me in line with comments on tests in CLIMADA-project/climada_python#734 : I am surprised about the request because the logic I followed is just the one already in the module so I find writing better tests very very important but simply beyond scope, and increasing scope is how one never gets things done :-)

@aleeciu
Copy link
Collaborator Author

aleeciu commented Aug 7, 2024

I added tests looping through all possible combinations while catching wrong combinations. I also added test for wrong value assignments. In my view this is all it was asked in the review. Please let me know.

Copy link
Member

@chahank chahank left a comment

Choose a reason for hiding this comment

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

Excellent! Please just update the code to use init methods properly.

For future pull request it might be beneficial to write new quality code following the guidelines instead of copying legacy code.

Please also update the CHANGELOG file so that these changes are recorded for the next release.

Otherwise, concerning the current style of the methods with various if/else statements, I would appreciate confirmation from @emanuel-schmid that it is fine to leave it as is.

Comment on lines 114 to 123
impf = cls()
impf.name = f"Flood {region} JRC {sector.capitalize()} noPAA"
impf.continent = f"{region}"
impf.id = impf_id
impf.mdd = impf_values
impf.mdr = impf_values
impf.intensity = np.array([0., 0.05, 0.5, 1., 1.5, 2., 3., 4., 5., 6., 12.])
impf.paa = np.ones(len(impf.intensity))

return impf
Copy link
Member

Choose a reason for hiding this comment

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

Please use the init of the class properly. The init variables are:

        id: Union[str, int] = "",
        intensity: Optional[np.ndarray] = None,
        mdd: Optional[np.ndarray] = None,
        paa: Optional[np.ndarray] = None,
        continent: str = ''
        name: str = ""

So, the code should be 

return cls(
    id = impf_id,
    mdd = impf_values,
    paa = np.ones(len(intensity)),
    intensity = intensity,
    name = name,
    continent=continent
)

Copy link
Member

Choose a reason for hiding this comment

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

Also, ImpactFunc does not have an attribute .mdr. Please make sure to remove this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

removed

Comment on lines +93 to +110
if sector == 'residential':
impf_values, impf_id = from_jrc_impf_residential(region)

elif sector == 'industrial':
impf_values, impf_id = from_jrc_impf_industrial(region)

elif sector == 'commercial':
impf_values, impf_id = from_jrc_impf_commercial(region)

elif sector == 'transport':
impf_values, impf_id = from_jrc_impf_transport(region)

elif sector == 'infrastructure':
impf_values, impf_id = from_jrc_impf_infrastructure(region)

elif sector == 'agriculture':
impf_values, impf_id = from_jrc_impf_agriculture(region)

Copy link
Member

Choose a reason for hiding this comment

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

Long chains of if and else statements are to be avoided. For future work please use a dataclass or similar.


def flood_imp_func_set(sector="residential"):
"""Builds impact function set for river flood, using standard files. By default, it reads
functions for the residential sector"""

impf_set = ImpactFuncSet()
Copy link
Member

Choose a reason for hiding this comment

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

Please use a proper initialization. Something like:

impf_Set = ImapctFuncSet([
impf_africa,
impf_asia,
...
])

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

adjusted as suggested

"Use ImpfRiverFlood.from_region_sector instead.")
self.__dict__ = ImpfRiverFlood.from_jrc_region_sector("SouthAmerica", *args, **kwargs).__dict__

def from_jrc_impf_residential(region):
Copy link
Member

Choose a reason for hiding this comment

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

This would probably have been much better solved with a dataclass. However, I am not sure it is worth the effort now. @emanuel-schmid what do you think?

@aleeciu
Copy link
Collaborator Author

aleeciu commented Sep 16, 2024

Excellent! Please just update the code to use init methods properly.

For future pull request it might be beneficial to write new quality code following the guidelines instead of copying legacy code.

Please also update the CHANGELOG file so that these changes are recorded for the next release.

Otherwise, concerning the current style of the methods with various if/else statements, I would appreciate confirmation from @emanuel-schmid that it is fine to leave it as is.

Thanks a lot. An update:

  • I will change the method initiation
  • Concerning legacy code and following guidelines: I must say I read the guidelines but, unless I am reading the wrong ones, they are much less descriptive than what you say they are :-)
  • Waiting for @emanuel-schmid to give green light on current status or refactoring is needed

@emanuel-schmid
Copy link
Contributor

Actually no, I couldn't overcome myself and give green light. 😬
Instead I committed some beautifications. Please have a look @aleeciu. If you think it's still ok, you're welcome to merge.

@aleeciu
Copy link
Collaborator Author

aleeciu commented Oct 29, 2024

I committed a couple of changes to address the remaining issues from @chahank . Thanks @emanuel-schmid for your beautfications :-)

I would merge if it wasn't for these test errors, which are however - I think - unrelated to this PR? At least I don't have them when I run tests locally.

Feel free to merge or let me know how I can fix these tests failures.

Thanks for your review.

@emanuel-schmid
Copy link
Contributor

@aleeciu the failing test is actually related to this pr: before there were 86 lines covered and 16 missed, now there are 79 lines covered and 15 missed, which is a slightly lower ratio. Just because you made the code denser, so to say. 🤷
We can safely ignore it.

@emanuel-schmid emanuel-schmid merged commit 2a6837e into develop Oct 31, 2024
9 of 11 checks passed
@emanuel-schmid emanuel-schmid deleted the feature/add-missing-JRC-flood-impact-functions branch October 31, 2024 10:14
@emanuel-schmid emanuel-schmid restored the feature/add-missing-JRC-flood-impact-functions branch November 1, 2024 15:46
@emanuel-schmid
Copy link
Contributor

@aleciu can you please fix the failing integration test: climada_petals.test.test_flood_integr.TestRiverFlood.test_full_impact and submit a new PR?

One problem is the DEMO exposures has 3 for each impf_RF value, while the ids from flood_imp_func_set() has id's [11, 21, 31, 41, 51, 61].

The other problem is that the result differs significantlly:

test_flood_integr.py", line 80, in test_full_impact
    self.assertAlmostEqual(imp.at_event[0], 226839.72426476143)
AssertionError: 188191.9029567669 != 226839.72426476143 within 7 places (38647.82130799454 difference)

@aleeciu
Copy link
Collaborator Author

aleeciu commented Dec 13, 2024

I opened a new PR #153

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.

3 participants