Hello and welcome to the third video of this series.
In this video, I want to talk about the GROOPS parser and how it can make your life
easier and how it can make your GROOPS scripts more flexible. I've prepared a short script. I'll
talk about it in a second, but the purpose of the script is to compare kinematic orbits to dynamic
orbits of a satellite and visualize this in a plot. The result should look something like this.
So we have along, cross, and radial axes. The kinematic orbits, which are noisy, are compared
to a dynamic orbit, which is relatively smooth. For this we have some data. We
have kinematic orbits and reduced-dynamic orbits for four different satellites: GRACE-1, GRACE-2,
Sentinel-1A, and TerraSAR-Xe, each for one week. Both kinematic and reduced-dynamic orbits. So if
we start with our script – I'll go quickly through it – it's very simple. We do not have any global
variables so far. First of all, we remove a "tmp" directory in case it already exists. The next step
is to recreate this "tmp" directory and also create the "plots" directory. And then the
first real step in the script is to synchronize our kinematic orbit and our dynamic orbit so we
ensure that both contain the same epochs, which is necessary because the kinematic orbit might
contain some gaps while the reduced dynamic orbit does not contain gaps. And as you can see here,
I've selected GRACE-1 for 2015-01-01 and the same here, I have selected the reduced dynamic orbit.
Both orbits are then written to their respective files which only contain synchronized
epochs, so epochs that are part of both files. The next step is "InstrumentMultiplyAdd", where
the two temporary files we just wrote
– the dynamic orbit is subtracted from the kinematic orbit – and the result is written to
"orbitDiff.txt". Finally, we want to visualize the orbit in a local orbit system so we simulate
a star camera file based on the dynamic orbit and we rotate the differences from the
celestial reference frame to the local orbit reference frame. And finally, we plot the result.
We have three layers, one for each each component, so along, cross, and radial.
As you can see, we read the orbit file here and "valueX" is "data0", which is the modified Julian
date (MJD). The value of "data1" is the first value, which is the along-track value. We multiply
times 100 to convert it to centimeters and add five centimeters to shift it
in the plot. That's basically it. We also said as the "axisX" we use a "time" axis where we can
define the tick spacing and so on. At the end, we end up with this plot, where we have along shifted
by +5, radial shifted by -5, and the values in centimeters, and a time axis. So far so good.
As you could see, I just used here the orbits from GRACE-1. So now what if we wanted to
visualize the orbit for GRACE-2? We could, of course, change it here to 2 and also here to 2
and run the script and it would work fine. But that's already a bit inconvenient. So
what we can do in GROOPS is we can create a global variable – let's call it "satellite"
– we will give it a type "string" and
just define it as "GRACE-2". And instead of having GRACE-2 here, we can now replace this with
the variable "{satellite}". Same here.
And now, when I run the script, "{satellite}" will be replaced by "GRACE-2". Another location where
we can put it is, for example, in the title. We can say, okay, we're going to have the name of
the satellite in the title and also, maybe, in the file name. So let's say the file name should
be "{satellite}_orbitDiff.png". And if we now run this...
Goes by pretty quickly. And now we have a file not only called "orbitDiff.png" but
"GRACE-2_orbitDiff.png" and also it contains GRACE-2 in there and, as you can see,
it's different to GRACE-1. The original one was GRACE-1. So it's already pretty convenient.
As I mentioned in the beginning, we also have data for one week but here it's basically hard-coded to
use 2015-01-01. We can also circumvent this by creating a global variable – let's call
it "time" and it's from type "time" – and we can just say, okay, we want to visualize 2015-01-02,
let's say. As you can see, the modified Julian date (MJD) value is this. And I can now replace
the date here with the variable "time", but you have to be careful here. If I just use "{time}",
it would use "57024" as the value, because that's the value which represents the time. But of course
the file name does not contain the modified Julian date but it contains the actual date.
Here we can use another feature of our parser: We can specify a format. We could do
"{time:%Y-%m-%d}" or as an alternative we can just use
"{time:%D}" for date, which will parse the date in the ISO format, as shown here.
We can do the same here. We can replace it and, again, this will be – when I run the script – this
will be replaced. What you can also do is add the date to the file name and if I now run this...
I should have another plot – exactly – I have now this plot which is called
"GRACE-2_orbitDiff_2015-01-02.png". And as you can see, again, this is different than
2015-01-01 we plotted before. Now it's easy for me to just plot, for example,
"TerraSAR-X" instead of "GRACE-" and 2015-01-07. So if I run this now...
Done, and now I have a figure or plot "TerraSAR-X_orbitDiff_2015-01-07.png". So,
yeah, that's pretty handy! Another thing I want to show you is – let's add another layer – and
we'll use the same input file "orbitDiff.txt",
but instead of – what we now want to do is we want to highlight outliers in our time series.
Let's define an outlier by the total difference being larger than five centimeters.
So I can first compute the total difference which would be "sqrt(data1^2+data2^2+data3^2)".
And let's say this should be – or, rather, let's now add a condition, so you can write if this
distance is larger – let's multiply it by 100, so let's do it in centimeters – if
this is larger than five centimeters, then at a "valueY" of 10 – or then use a "valueY"
of 10, otherwise use "nan" (not a number). And what we want to happen is
we want to have a symbol – let's pick a black diamond – at the value of 10 on the Y-axis if
the total distance between the kinematic and the reduced dynamic orbit is larger than 5
centimeters. Otherwise we use the value "nan", which is this function. So what you can see here
is that the parser can interpret mathematical expressions. There are quite a few of them:
from square root to other mathematical operations, comparisons, and also
specific functions. We can take a look at the GROOPS documentation. If you go to Parser,
there's a list of the mathematical expressions that are supported: logical expressions, functions
with multiple arguments and so on. And there's also the text parser, you can see we earlier used
"%Y-%m-%d" but also "%D" for the date. So here, there's an explanation of
these parser options you have. Okay, and if we now run it again, we should hopefully end up with –
yeah, see, so now in our TerraSAR-X figure we have black diamonds at the locations where the
total difference between the kinematic orbit and the reduced-dynamic orbit is larger than 5
centimeters. Of course, there are many more options you can use or many more functions you
can use with the GROOPS parser, but in principle it's super handy to simplify the script, make it
more flexible, use the same script for different satellites, for different dates and so on.
In the next video we will use this because we will then extend our script
to include loops and conditions and there, again, these expressions and the parser will
be very convenient. So until the next video, see you. Bye bye!