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

t.rast.aggregate: Adjustments to temporally weighted aggregation #1799

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

fkroeber
Copy link

Until now, t.rast.aggregate provides diffrent sampling methods to select rasters for each time interval which subsequently are aggregated to the specified granularity using the specified method (in turn being handed over to r.series internally). Unfortunately, the present range of sampling methods only allow for complete in-/exclusion of single rasters during the aggregation procedure. This PR aims at enhancing t.rast.aggregate in a way that allows for weighted aggregations based on weighting factors representing the temporal overlap between the input rasters and the output rasters (see below). Therefore, a new sampling method called "relates" is introduced and a weighting flag (w) defined.

@veroandreo
Copy link
Contributor

This addition sounds really cool :) Would you mind providing a reproducible example to test it?

Copy link
Member

@wenzeslaus wenzeslaus left a comment

Choose a reason for hiding this comment

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

Generally, this looks good!

I noticed couple of issues with the code. Some seem to related to some recent updates. Maybe just a better sync to the master branch is needed.

An example in the HTML manual page would be nice. A test would be great too. Most of temporal framework has a good test coverage, so it would be good to keep that. Creating a test data might be simpler than creating a meaningful example (although that would certainly be great too).

Comment on lines 323 to 327
try:
for map_layer in granule.overlaps:
set_list.add(map_layer)
except:
pass
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be similar to the code above, but it is written in a completely different style. Any reason not to follow the above style? Additionally, the try-except is unclear as it is written now since it is a bare except. See Flake8: ./temporal/aggregation.py:326:13: E722 do not use bare 'except' (also in CI).

string = name
weight = aggregation_weights[i]
file.write("%s|%f\n" % (string, weight))
file.close()
Copy link
Member

Choose a reason for hiding this comment

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

The file.close() call is duplicated in the branches and does not need to be. Since you are rewriting most of the file code here, do you want to just use with statement avoiding the need for explicit close() call?

temporal/t.rast.aggregate/t.rast.aggregate.py Outdated Show resolved Hide resolved
temporal/t.rast.aggregate/t.rast.aggregate.py Outdated Show resolved Hide resolved
Comment on lines 353 to 358
if None in t_granule_contained or None in t_granule:
aggregation_weights.append(0)
else:
overlap_abs = min(t_granule[1], t_granule_contained[1]) - max(
t_granule[0], t_granule_contained[0]
)
Copy link
Member

Choose a reason for hiding this comment

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

(In-code) comments for these lines would be appreciated. Easier to review, easier to maintain when the intention is documented.

python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
temporal/t.rast.aggregate/t.rast.aggregate.py Outdated Show resolved Hide resolved
temporal/t.rast.aggregate/t.rast.aggregate.py Outdated Show resolved Hide resolved
temporal/t.rast.aggregate/t.rast.aggregate.py Outdated Show resolved Hide resolved
temporal/t.rast.aggregate/t.rast.aggregate.py Outdated Show resolved Hide resolved
@neteler
Copy link
Member

neteler commented Nov 30, 2021

To be fixed:

Run flake8 --count --statistics --show-source --jobs=$(nproc) .
./python/grass/temporal/aggregation.py:326:13: E722 do not use bare 'except'
            except:
            ^
./python/grass/temporal/aggregation.py:331:13: E722 do not use bare 'except'
            except:
            ^
./python/grass/temporal/aggregation.py:336:13: E722 do not use bare 'except'
            except:
            ^
./python/grass/temporal/aggregation.py:341:13: E722 do not use bare 'except'
            except:
            ^
./python/grass/temporal/aggregation.py:346:13: E722 do not use bare 'except'
            except:
            ^
5     E722 do not use bare 'except'
5
Error: Process completed with exit code 1.

@neteler neteler added the enhancement New feature or request label Nov 30, 2021
@griembauer griembauer mentioned this pull request Dec 3, 2021
@griembauer
Copy link
Contributor

Hi @wenzeslaus, we finally implemented the requested changes (some code restructuring & commenting, an example in the .html, added a test). Could you re-review? Thanks!

@neteler neteler added this to the 8.0.1 milestone Dec 9, 2021
@wenzeslaus wenzeslaus modified the milestones: 8.0.1, 8.0.2 Feb 23, 2022
Copy link
Member

@wenzeslaus wenzeslaus left a comment

Choose a reason for hiding this comment

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

As far as the code is concerned, there are only some smaller tweaks remaining.

The conflict is just in the documentation and should be simple to fix.

I'm puzzled how test_aggregation_absolute.py was not failing before, but thanks for fixing it.

python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
t_rast_list = SimpleModule("t.rast.list", input="B", flags="u").run()
rasters = [
item
for item in t_rast_list.outputs.stdout.split(os.linesep)
Copy link
Member

Choose a reason for hiding this comment

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

There is splitlines for these cases (which actually behaves as expected unlike os.linesep here). (For future reference, see #2258, hopefully more straightforward.)

@wenzeslaus
Copy link
Member

Binder link for anyone who wants to test this.

@veroandreo
Copy link
Contributor

Binder link for anyone who wants to test this.

After the merge with main, the link does not work. Use this one instead: https://mybinder.org/v2/gh/fkroeber/grass/t.rast.aggregate?urlpath=lab%2Ftree%2Fdoc%2Fnotebooks%2Fbasic_example.ipynb

I tested by adapting the example in the html:

gs.parse_command("g.region", raster="elevation", flags="pg")
for map in range(12):
    gs.run_command("r.surf.random", output="map"+"_"+str(map))
gs.run_command("t.create", type="strds", temporaltype="absolute", output="temperature_weekly", title="Weekly Temperature", description="Test dataset with weekly temperature")
gs.run_command("t.register", flags="i", type="raster", input="temperature_weekly", maps="map_0,map_1,map_2,map_3,map_4,map_5,map_6,map_7,map_8,map_9,map_10,map_11", start="2021-05-01", increment="1 weeks")
gs.parse_command("t.rast.list", input="temperature_weekly", columns="name,start_time,end_time,min,max")
gs.run_command("t.rast.aggregate", input="temperature_weekly", output="temperature_10daily_weighted", basename="tendaily_temp_weighted", method="average", granularity="10 days", sampling="related", flags="w")
gs.parse_command("t.rast.list", input="temperature_10daily_weighted", columns="name,start_time,end_time,min,max")

the aggregation seems to work fine, but it's difficult to say if the weighting also works... Maybe a more intuitive example with r.mapcalc and maps having a single integer value?

@neteler neteler modified the milestones: 8.0.2, 8.2.0 Apr 1, 2022
@wenzeslaus wenzeslaus modified the milestones: 8.2.0, 8.4.0 Apr 22, 2022
@nilason nilason added the Python Related code is in Python label Feb 15, 2023
@neteler
Copy link
Member

neteler commented Feb 18, 2023

Maybe a more intuitive example with r.mapcalc and maps having a single integer value?

Anyone willing to propose an example here?

Comment on lines +202 to +205
MAPS="map_1 map_2 map_3 map_4 map_5 map_6 map_7 map_8 map_9 map_10"
for map in ${MAPS} ; do
r.surf.random output=${map} min=278 max=298
echo ${map} >> map_list.txt
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
MAPS="map_1 map_2 map_3 map_4 map_5 map_6 map_7 map_8 map_9 map_10"
for map in ${MAPS} ; do
r.surf.random output=${map} min=278 max=298
echo ${map} >> map_list.txt
for i in `seq 0 11` ; do
r.mapcalc expression="map_${i} = ${i}"
echo map_${i} >> map_list.txt

Copy link
Contributor

Choose a reason for hiding this comment

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

This example makes it much easier to understand what the weight really does as values in input maps are known and constant integer values

basename=tendaily_temp_weighted method=average granularity="10 days" \
sampling=related -w
</pre></div>

Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Let's see the result:
<div class="code"><pre>
t.rast.list input=temperature_10daily_weighted columns=name,start_time,end_time,min,max
name|start_time|end_time|min|max
tendaily_temp_weighted_2021_05_01|2021-05-01 00:00:00|2021-05-11 00:00:00|0.3|0.3
tendaily_temp_weighted_2021_05_11|2021-05-11 00:00:00|2021-05-21 00:00:00|1.6|1.6
tendaily_temp_weighted_2021_05_21|2021-05-21 00:00:00|2021-05-31 00:00:00|3.1|3.1
tendaily_temp_weighted_2021_05_31|2021-05-31 00:00:00|2021-06-10 00:00:00|4.5|4.5
tendaily_temp_weighted_2021_06_10|2021-06-10 00:00:00|2021-06-20 00:00:00|5.9|5.9
tendaily_temp_weighted_2021_06_20|2021-06-20 00:00:00|2021-06-30 00:00:00|7.4|7.4
tendaily_temp_weighted_2021_06_30|2021-06-30 00:00:00|2021-07-10 00:00:00|8.7|8.7
tendaily_temp_weighted_2021_07_10|2021-07-10 00:00:00|2021-07-20 00:00:00|10.3|10.3
tendaily_temp_weighted_2021_07_20|2021-07-20 00:00:00|2021-07-30 00:00:00|11.0|11.0
<pre><div>

@veroandreo
Copy link
Contributor

Maybe a more intuitive example with r.mapcalc and maps having a single integer value?

Anyone willing to propose an example here?

See my suggestions. What do you think?

@neteler neteler modified the milestones: 8.3.0, 8.4.0 Feb 21, 2023
@wenzeslaus wenzeslaus modified the milestones: 8.4.0, Future Apr 27, 2024
@github-actions github-actions bot added temporal Related to temporal data processing HTML Related code is in HTML libraries module docs tests Related to Test Suite labels Oct 17, 2024
@echoix
Copy link
Member

echoix commented Oct 17, 2024

Solved conflicts

@echoix echoix changed the title Adjustments to t.rast.aggregate - temporally weighted aggregation t.rast.aggregate: Adjustments to temporally weighted aggregation Oct 21, 2024
python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
python/grass/temporal/aggregation.py Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs enhancement New feature or request HTML Related code is in HTML libraries module Python Related code is in Python temporal Related to temporal data processing tests Related to Test Suite
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants