-
Notifications
You must be signed in to change notification settings - Fork 10
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
Add nourishment functions #20
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New functionality looks like it adds some pretty useful stuff. A few thoughts:
-
I think the nourishment functions would make for a good new example, which I'd be happy to add to this PR before it's merged, if you agree that would be a worthwhile addition.
I do agree that this would be a nice addition to have in the example suite. Once created, the
.py
file should be added to the list of examples we run in our continuous integration in the "Run examples" section of thebuild.yml
file (~line 100) so that in the future we ensure the example isn't broken by changes to it, or the underlying code it uses. -
I got the impression that changes to the
unstruct2grid
function were intended to be backwards-compatible. However the failing unit test suggests that something has changed (although it isn't entirely obvious to me what is impacting the unit test). Before merging we need to figure out either what caused the change, and if we are okay with it we can modify the unit test, or the changes tounstruct2grid
may need to be implemented in a slightly different way. We also should add a unit test for the new functionality being added tounstruct2grid
-
Similarly, we are currently unit testing all of the functions in
particle_track.py
, so with the addition of these new functions we should add unit tests to ensure they work as expected.
for jj in list(range(1, len(walk_data['xinds'][ii])-1)): | ||
# Running total of particles in this cell to find average | ||
visit_freq[walk_data['xinds'][ii][jj], | ||
walk_data['yinds'][ii][jj]] += 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the calculation for nourishment_area()
is embedded within the nourishment_time()
function as well. Do you think there is value to combining these functions into a calculate_nourishment()
function that has an input parameter "nourishment_type" or something similar that controls whether the visit frequency, mean time, or both are returned by the function? I can imagine wanting both the visit frequencies and mean times and it seems like they could be rolled into a single function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about it and I think it will be simpler to use/read the code if we keep them as two separate functions. I think they're different enough that their use cases aren't guaranteed to overlap. Plus, I think each function may work best with different degrees of smoothing/clipping, so it's easiest if they're not tied together.
Alright, I think this is ready for another look when you have a chance. In the latest commits, I have:
On that last point, that seems to be the only line with commits that conflict with the existing commits. Could use some help figuring out how to resolve that, still not very familiar with handling parallel commit histories. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made some comments throughout, mostly minor. Some other comments that I didn't necessarily associate with a specific line are below:
-
It would be helpful to resolve the conflict in
__init__.py
so we can be sure this PR doesn't break anything -
Does the nourishment area image need a colorbar? I don't mind either way but was just a thought.
-
Add tests that use the smoothing in the nourishment calculations (sigma > 0)
-
test_nourishment_area()
fails when I run the unit tests locally (seems to be producing somenan
values in place of some expected 0s?) -
Do we know if
get_time_state()
is working as intended? Doesn't have to be resolved by this PR if there is an issue but we should open up an issue if there is a known bug
Sorry I missed addressing this point. GitHub has a reasonable conflict resolution built into the website, so I think you can do it in the PR by hitting the "Resolve conflicts" button and working through the GitHub GUI. Especially since the conflict is pretty minor. Otherwise the other option (I'm familiar with) would be doing it via the command line by fetching the "current" version of the code and pulling it into your branch. Then the Let me know if you want more info or want to go through it together and we can do that sometime. |
I think probably not, since everything is normalized. Included one for the time function because the nominal values mean something, whereas area is all relative.
Aside from being exhaustive, do you think there's any utility in doing this? When sigma > 0, it isn't easy to compute what the a priori answer should be without just using this function to compute it, so we'd essentially be forcing this function to give us the answer it already gave us.
This was a good catch, fixed the
All my local testing of the new version works, there's very little that can go wrong now that we've collapsed the main loops/ifs into one simple numpy search. But I still don't know if this is what was giving Nelson problems |
👍
I think it is worth doing (beyond being exhaustive) for the following 2 reasons:
👍
Sounds good. |
Think this might be ready! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! 👍
PR introduces three main feature additions:
nourishment_area
: Adds two functions for the computation and plotting of the "nourishment area" of a seed injection point, i.e. the region of the domain which receives material from the injection point. Following the convention set by theexposure_time
functions, this includes: (A)particle_track.nourishment_area()
, which loops through awalk_data
, and returns a raster indicating how many occasions each cell was occupied by particles, normalized to the range 0-1. Because these paths are single realizations and inherently spatially-noisey, this function also allows you to smooth the output with a gaussian filter controlled by the variablesigma
. (B)routines.show_nourishment_area()
, which provides an easy aesthetically-pleasing way to plot that output overtop one of the existing grids. The visit frequency raster is shown as a heatmap, in which alphas fade to zero near the tail of the colormap, indicating areas sparsely visited by particles. Users can control most of the features of the plot using the function inputs, which I've tested on WLD and DeltaRCM outputs and looks pretty spiffy in both applications. Examples shown belownourishment_time
: Similarly adds two functions for the computation and plotting of the "nourishment time" of a seed injection point, i.e. the amount of time particles tend to spend in each area of the domain. In a way, this function is the time-equivalent of the above function: once particles get to a cell, how long on average do they stay there? Similarly broken up into computation (particle_track.nourishment_time()
) and plotting (routines.show_nourishment_time()
), with both functions working very similarly to above. Furthermore, if you take the product of thenourishment_time
andnourishment_area
output rasters, you obtain the same thing as if you just added up all of the time particles spent in each cell, which may be interesting in its own right. Example belowNative boundary-cropping for
unstruct2grid
: Adds an optional parameter,boundary
, to this function, which will optionally crop the interpolated rasters to a domain boundary usingmatplotlib.path.Path()
. Previously, if your domain wasn't a perfect rectangle, areas outside would still get interpolated to a numeric value, so this just allows people to fix that boundary behavior.I think the nourishment functions would make for a good new example, which I'd be happy to add to this PR before it's merged, if you agree that would be a worthwhile addition. If not, we can merge whenever things look good.