Creating a mask based on a contour in python


Is there a clean way to create a mask in python that separates two areas, one “left” and one “right” of any contour?

There is an example using for loops in a COSIMA-recipe script (cell 25). I want to do the same thing, but for a different contour. Can this be done in a more general/computational efficient way? The example doesn’t do the job for the contour I chose.

A comment in the notebook suggests using DataArray.shift or DataArray.roll, I don’t really understand how they help to mask data away from the contour.

Any suggestions on how to approach the problem would be appreciated!

I agree that that method is not particularly efficient. But then again, it only needs to be done once, so the efficiency is likely not such an issue in the big picture.

Perhaps it would be useful to figure out why the method doesn’t work for your contour, as I’m guessing a more efficient method may have the same issue. My guess is that your contour is not connected in the same way as that script assumes. e.g. Are there points on your contour that are only diagonally connected? i.e. a point on the contour at (i,j), followed by the next point at (i+1,j+1). I think that code assumes the points are not diagonally connected, i.e. there should be a point in between those two points at either (i,j+1) or (i+1,j).

I think @angus-g is suggesting something similar to what is done in the age at the bottom example:

So you should be able to just mask directly, using the value you’re using for the contour. One complication you have is that there might more than one location in each x-coordinate value that satisfies that criteria. In that case you might need a step to identify only one of those values (maybe the “top one”). If not, you’re good to go.

Edit: You could still use the contour approach as above, extract out the points from the counter and build a little xarray dataset with the correct coordinates and use the indexing approach outlined in the “Age at the Bottom” example above.

Thanks @adele157 and @Aidan

The contour has diagonal connections, but that’s also the case for the given example. I’ll dig into where the issue occurs.

I played around with the shifting earlier (similar method to the age at the bottom example) but I think the contour is too complicated (as in curved) to not end up with multiple extra cases.

The current code does not actually take that long to run, I was hoping a different approach would simplify the approach. I might have to fine tune the for loops…

At some point it probably make sense to use GeoPandas and shapely.

but they generally require data with coordinate reference systems and “GIS stuff”. At that point I’d be tempted to say “HELP!” to @felicity.chun