[MUSIC PLAYING]
BEN CARLSON: Hello, my name is Ben Carlson,
and I'm a PhD candidate at Yale University.
And I'm going to be speaking today
about merging dynamic point and environmental data using
customized layers in Earth Engine.
So what do I mean by merging environmental and point data?
In some circles, this is called environmental annotation.
So what is environmental annotation?
Pretty simply, it's associating point data
with coincident environmental values.
So if you've done any sort of spatial analysis,
you've probably done this operation before,
where you have a raster and you want to understand--
or you want to associate the values
at the raster with the point data.
And this is a really important step
in a lot of different analyses.
And usually these are in any regression analyzes
involving spatial environmental covariates.
So from my field of ecology, this
is really important in when you're
doing species distribution models or resource selection
functions.
So how do we actually do annotation?
The simple example is something I call static annotation.
And this is when you have a single raster,
say, something like elevation, and you
want to extract the values at the locations of your points.
This can usually be done with a lot of standard tools
on your local computer, so something
like ArcGIS, R, or Python could all do this operation for you.
Now, a lot of data comes in time series.
So I work with movement data, and with each of the data
points is associated a timestamp,
because we're taking a point every, say,
five minutes as the animal is moving around the landscape.
Now, environmental conditions change over time,
and so a lot of times, we don't want
to annotate against a static raster.
But instead, we want to annotate against a time
series of rasters.
So think about the Motus time series or the Landsat time
series data sets.
Now, these are really large data sets,
and it's not really practical to put them
on your local computer.
And so there are systems out there that actually have access
to these big data sets.
And all you have to do is give the systems your point data,
and then they'll do the annotation for you.
So examples of this are Stoat, which
is great for annotating biodiversity data,
such as data from GBIF.
Movebank is really good for movement data,
and then Earth Engine, as everybody knows,
has a large catalog of data sets and can also do this operation.
So that's great if you find the data that you
want within these systems.
However, what I want to talk about today
is, what about if you don't find the data that you want?
So I found myself in this situation.
I study the movements of white storks,
and I was interested in understanding stork movements
in relation to dynamic water bodies.
So there is a layer in Earth Engine called the JRC Global
Surface Water that provides a 30-meter monthly water
or no water per pixel.
But what I wanted to know was not whether a pixel
was water or not but, for each pixel, what
is the distance to the water?
Now, there was no existing data set for this sort of layer.
So I tried kind of the standard approach at first,
is I attempted to generate the layer
and export it as an asset.
But I quickly realized that this layer was--
or the time series was so large that I just couldn't export it.
I was using up all of my memory or all of my cloud storage
capacity.
And so I had to figure out a different way.
And I realized that there was a simple solution.
Instead of exporting the time series, because
of Earth Engine's really unique capabilities,
you could just annotate directly against the image collection
resulting from some sort of a script or function that
creates the layer on the fly.
So this is annotating, instead of against an asset,
annotating against a computed object.
And so this is a really simple solution,
but it was really something different from how
I'd been trained as an ecologist,
because we always think in terms of rasters and existing layers.
And it seemed kind of crazy to annotate
against this dynamically generated layer,
but it actually worked pretty well.
And so it worked so well I got very excited,
and I've been helping other people do
this sort of annotation.
And I want to show you just a really simple example
so you can see just how simple this is
and what exactly I'm talking about.
So this is a script that summarizes
EVI in three-month increments, so that is seasonal EVI
but over each year.
And so it's pretty simple.
So you just-- the first step is to create the custom layer,
and this is just merging all of the EVI
into three-month time series bins
and then taking the mean of that.
And then once we have that done, what we have is a--
here we calculate the EVI down here,
and now we just have an image collection.
So we didn't export it.
We just have an image collection.
And then further on in the script,
we can just do the standard code to annotate.
So here we join it to the points,
and then we do the annotation.
And then we export it.
So that's a really simple example,
just to show you, that it's more mindset change as opposed
to something that's hard to do in Earth Engine.
But it's really because Earth Engine
is built the way it's built that makes this possible.
Now, how did I actually implement the monthly distance
to water?
I did some additional abstraction.
So the code that I'm showing here is rgee,
but it's very similar to the JavaScript code.
And what I did is I created a script that
generated the distance to water per month.
And importantly, I put it into this function called
getLayer().
And so getLayer() just returns the image collection,
which I then feed into a general script,
which is called gee_anno.
And there I get the layer, and this script
can annotate against any image collection.
So whether this is an image collection directly loaded
from an asset or one derived by a script
that I'm showing above, it's completely agnostic to that.
So this really allows me to annotate
against any sort of derived layer that I want to.
And so why is this such an important capability?
So in my field of remote sensing--
I'm sorry, in my field of animal movement,
if we want to do remote sensing for animal movement,
the requirements are pretty strict.
So we need high spatial resolution,
high temporal resolution, and we often
need layers that are very species or region specific.
And so I'm showing an example here
of three different days of the same field,
and you can see, June 28, no interest in this field.
June 29, all of these dots represent two different storks.
So there's something about this field
that the stalks were very interested in.
And then June 29, no more interest.
So you can see this is a very ephemeral effect,
and so we need very fine grained daily layers.
And what's happening here is storks
are strongly attracted to farmers mowing their fields.
And they'll fly down, and chase after the tractors,
and eat any of the insects that pop out as the farmer's mowing.
And so this is a very specific species
and region-specific type of layer,
and it's not really reasonable that we
are going to have these layers just
sitting around on the shelf.
So we really need the ability to generate these specific layers
but also annotate against them.
Now I'm actually leading a project
that is in collaboration with some of my colleagues
at Yale and with people at the JPL and NOAA.
And what we're doing is we're interviewing movement
ecologists to understand these very specific requirements,
and we are performing a gap analysis
against the current and planned remote sensing technology.
And importantly, for this talk, we're
also trying to identify what sorts of tools
are going to be needed to really make
use of remote sensing for animal movement.
And this dynamic annotation against derived layers
is something that's going to be very important, I think.
So I have written some research code
that helps [INAUDIBLE] work with really large movement data
sets, and so I'm not going to get into all of the components,
but the piece that is relevant here
is something called Mosey Env.
And that interfaces directly with Earth Engine.
Actually, the code that I showed earlier, the rgee code,
is part of Mosey Env.
And this is a repo on GitHub, so you're welcome to take a look.
And it's probably not production ready,
but if you want to just see how I've implemented things
or you're interested in using it, go for it.
Or please feel free to contact me if you're interested.
So the Earth Engine team has been
really great about listening to user recommendations,
and so I thought I'd just make a couple here.
And I'm sure they've heard all this before,
but one of the things that's really complicated when
using Earth Engine is actually getting all the data in and out
of Earth Engine.
So most of the Mosey Env code that I've written
is all around just getting data in and out.
And in terms of movement data and models,
this tends to be pretty dynamic because we
want to constantly put data in and constantly get data out
to do analyses.
And so if there's any capacity to make this easier,
that would be great.
Secondly, the annotation works, but it
seems that I can only get about a million points per task.
And in terms of when you're working with movement data
sets, that's not many data points per task.
And so a lot of the complexity of the code
is also because I need to split up
any data set into many tasks, and then I
need to merge all that back together.
And so if there was some sort of functions
that could be made specific to this sort of operation that
would maybe work over larger data sets,
I think that would also simplify things quite a bit.
So just to summarize, so environmental annotation
is associating coincident environmental data
with point data.
So Earth Engine is uniquely suited
to annotate point data with custom-derived layers,
and this capability is very important
in the field of movement ecology.
And I think it's probably going to be
important to a lot of other fields as well.
So I'd just like to thank everyone
that's helped me out with this research, my funding agencies.
And my email address is right here at the bottom
if you'd like to contact me for any reason.
Thank you very much.
[MUSIC PLAYING]