Conversation
…azard_data_provider.py Signed-off-by: Juan Roman <jroman@arfimaconsulting.com>
Signed-off-by: Juan Roman <jroman@arfimaconsulting.com>
Signed-off-by: Juan Roman <jroman@arfimaconsulting.com>
Signed-off-by: Juan Roman <jroman@arfimaconsulting.com>
Signed-off-by: Juan Roman <jroman@arfimaconsulting.com>
|
This is work in progress. I opened this PR to spark discussion. For now, I have only implemented the new protocols that are supposed to replace SourcePaths: HazardResourceProvider and ScenarioYearResolver. To illustrate their use, I have implemented a new hazard model and a new image creator. I still haven't refactored the existing CascadingHazardDataProvider in terms of the new protocols. This is challenging because it requires generalizing the ScenarioYearResolver protocol to return linear combinations of ScenarioYear, and wire both HazardDataProviders to it. My intention is that the HazardResourceProvider and the ScenarioYearResolver should be injectable dependencies of a single/unified CascadingHazardDataProvider. The cascading provider's only job would be to handle the cascade based on geographical availability of the ordered list of resources provided by the HazardResourceProvider. For each resource, in would check "in boundness" of every lat-lon, and if positive, it would call the ScenarioYearResolver to obtain a linear combination of the resource's scenario-years with which to fulfill the requester scenario-year. Furthermore, the HazardModelFactory should pass the same ScenarioYearResolver to both the HazardModel and the ImageCreator, for consistent fetching of map data and map images. The HierarchicalZarrHazardModel is an example of this philosophy. In contrast, the current CascadingHazardDataProvider delegates some scenario resolution to CoreInventorySourcePaths, while resolving years internally to perform the linear combination. |
Main contribution:
HazardDataProvider:HierarchicalHazardDataProvider. This new provider combines the cascading logic of the existing provider with a new logic for resolving an available scenario and year to fulfill every incoming request. The provider is agnostic to the criterion used to sort the resources. Cascading is strictly geographical, the first resource having geographic coverage to fulfill a requested latitude-longitude will be used. The requested scenario-year is assigned an available scenario-year in the selected resource by aScenarioYearResolver.resolve_nearest_scenario_yearas an instance of theScenarioYearResolver. Given a requested scenario-year and a resource, it assigns the closest available scenario by radiative forcing value and the closest year. In the historical case it assigns the latest available year if the historical scenario is available. If the historical scenario is not available it assigns the lowest year from the scenario with lowest radiative forcing. In the case of a tie it assigns the scenario with the largest radiative forcing and the largest year (giving a worst case estimate). In the case of an unrecognized requested scenario it assigns the last available scenario (again trying to give a worst case estimate under the assumption that scenarios are sorted in the inventory from most optimistic to most pessimistic).A notable limitation of the current implementation is that the resolution is one-to-one, this is in contrast with the existing
CascadingHazardDataProviderthat can do one-to-many resolution at the level of years. It could be generalized to support resolution from linear combinations of available scenario years but we have intentionally kept it simple until a satisfying generalization is established.Other contributions:
To support the implementation of the new provider, we have reviewed and updated the full
HazardModellogical chain, from thePregeneratedHazardModelto theZarrReader. The main changes are:HazardDataProviderwas previously defined as an ABC, we have redefined it as a Protocol. Also, the method it must implement is now called justget_data, as opposed to the previousget_data_cascading, as the cascading nature is an implementation detail that can vary and not part of the interface. Consequently we have renamed the existingHazardDataProviderasCascadingHazardDataProvider.interpolate_yearsto be an argument of the__init__ofCascadingHazardDataProvider, since an arbitraryHazardDataProvidermight not have year interpolation as a toggleable option.PregeneratedHazardModel. Most importantly we have cleaned up the handling of the event loop to stop using the low levelthreading.Threadthat lead to brittle error propagation and replaced it with higher levelasyncioandconcurrentdirectives. We have split the previously monolithic_get_cascading_hazard_data_batchescontaining the closuresall_requestsandsingle_indicatorinto_get_hazard_data_in_batchesand_get_batch_data, and replaced closures and mutation of outer state with pure methods and a merge of the different batch results.ImageCreatorto extract common functionality and implement aResolvingImageCreatorthat uses the sameScenarioYearResolveras the hazard model.ZarrReaderto avoid duplicate and diverging checking of "in boundness". Previously this was done separately in thein_boundsmethod and inside theget_curvesmethod. There was an inconsistency in the checking of bounds in the case of "floor" interpolation that could lead to a resource being selected to fulfill a latitude-longitude after a positivein_boundscheck and thenget_curvesfailing to provide a curve, this is becausein_boundspreviously always applied pixel center offsets regardless of the selected interpolation method.