Skip to content


June 27, 2020. The periodograms now show “failed” satellite tracks in light gray. The thicker colored lines are “successful” tracks using generally requirements (tracks must be long enough in time but not include both a rising and setting satellite track for one periodogram) and on the QC metrics you have provided.

Quick Instructions:

There are currently three modes:

  1. Example stations – where I have made the analysis choices.
  2. Pick a station name, year, day of year and analysis choices and the app uses a RINEX file from one of the global archives.
  3. Upload your own RINEX 2.11 file and analysis choices.

User Inputs:

  1. Min and Max RH are the constraints on the allowed reflector heights (in meters).
  2.  Min and Max Elevation angles for the SNR data you allow (in degrees).
  3. ReqAmp is required amplitude (volts/volts) and Pk2Noise are quality control parameters. The amplitude is influenced by receiver type, so I do not have a hard and fast rule, but the default is a useful first try.  Pk2Noise should be ~4 for snow/ice, but likely should be smaller for water, say 3.

Regardless of where it comes from, the RINEX file must have an a priori receiver position in it. It doesn’t have to be super accurate, but it does need to be there. I nominally check that you haven’t put a silly receiver position in your file (i.e. the middle of the Earth).

If you upload your own RINEX file, it checks that you have used a compliant filename. The filename should be entirely lower case and ssssddd0.yyo or ssssddd0.yyd. ssss is the station name, ddd is day of year and yy is the two character year.  o is a normal RINEX file and d is the Hatanaka RINEX file. After the ddd I require a zero. It is currently limited to RINEX 2.11. Because I use teqc to reduce the observables, C3 is not allowed.

You are strongly encouraged to compress your RINEX files before uploading them. The app is limited by how long it takes you to upload that file, so if you have slow internet, the app may time out.  This limit is set by heroku.

Only gz or Z compression is allowed. Only RINEX files less than 10 Megabytes are allowed.

Only GPS frequencies are used by the web app: L1, L2, L5 and L2C.  Running the code on a desktop, you can (and should) use all GNSS signals if they are available. However, the app should not crash if you upload a RINEX file with more observables.  It simply ignores them.

You can vary the minimum required periodogram amplitude if you like – there is nothing magical about the default (8). L2C will always have a bigger amplitude – but L2P will be much much smaller (maybe try 1 or 2).  You can also just put a zero in that spot and let the code return (most) everything.  The only QC it will use is whether you have a peak greater than a noise metric, which is set by the RH range you have chosen.

Access to Modern GPS Data for the Web App:It is very hard to get modern GPS signals (L2C, L5) from RINEX version 2.11 files from archives operated by geodesists. If UNAVCO has the raw GPS data, which is almost always the case, they can create RINEX v2.11 files for you with L2C/L5 in them. I cannot speak for the other archives. Your other solution is to use RINEX v3,  which generally has everything and then convert them to RINEX 2.11.

What if the archive you are using does not provide RINEX 3 files?  If the archive is to support the public, I suggest you insist they add this option and that they track all modern signals.  This way they can continue to provide old signals in the RINEX 2.11 versions and everything in the RINEX 3 versions.  For people interested in using PBO data, many of the 1-Hz RINEX files have L2C in them.  You can download these files and decimate them for reflectometry applications.

What does this web app do?

Once the RINEX file exists (from an archive or via upload), this app downloads a GPS  orbit file. It strips out the Signal to Noise Ratio (SNR) data in your RINEX file and creates the orbit specific information that are needed for GNSS-IR. Because I am trying to keep the code running quickly enough to run in an app, I only allow sampling GNSS rates of 15 or 30 sec. For that reason, you can only look at reflections that are less than 25 meters. This restriction does not apply if you are running the code on your own machine. The web app might time out if you try to do all of this, so in most cases a task queue is created and the job is set off to a worker. The web site generated will query the task queue and let you know when the task is done. For the RINEX upload option, there is no task queue, but if you have a slow internet connection you still might have a time out problem (the web server heroku limits this – not me).

The app evaluates the presence of periodic signals in each of the four quadrants around your site (Northwest, Northeast, Southwest, Southeast). It presents them in the form of a periodogram where the x-axis is the “reflector height.” This term just means the vertical distance between your antenna and the ground, snow, or water. You are looking for nice strong peaks at the appropriate x-axis location. For snow/ground, they will be clustered at the same x-value. For tides, they will be spread along the x-axis in a way that represents the tides. Very minimal amounts of quality control metrics are applied, so if you don’t see results in one of your four quadrants, it means your site was deemed to have no useful reflections in that direction.

One QC metric is the minimum amplitude of the periodogram (which you control) and the other is a crude peak to noise ratio, which is nominally set at 3 I think (i.e. the peak must be 3 times bigger than the noise in your periodogram). I would suggest something like 4 for ice sheets, but this is something you can check for after you run the app (i.e. you can further apply QC using the values in the text file).

The app puts out a google Map display. If you upload a RINEX file, the coordinates for this Map display are taken from the station header. For the other options the station coordinates are taken from the  University of Nevada Reno database.

More advanced options:

If you know something about your site you can window your data to provide a more representative GNSS-IR analysis. For example: you know the GNSS site is ~16 meters above the ice, but the default limit is 8 meters.  Here you want to make sure you window your data to include 16, so go to max reflector height of 20 meters or so.

Another example would be where you know the reflection zones will include two different planar reflectors if you use the default elevation angle limits of 5 and 25 degrees. Station AT01 is one such site. If you use 5 and 15 as your elevation angle limits, you will have good water or ice reflections, depending on the season. If you don’t, you will see  peaks for both soil and the water/ice. This might confuse the quality control metrics. If you want to make sure you only look at water/ice, you could further restrict the reflector heights at this site, i.e. 5 to 15 meters.


Do you support running this web app from the command line? Yes, there is a bash script that allows that.

Where can I find code to try out GNSS-IR on my desk top computer? Look to

Why does it take 5 seconds to run this webb app for some stations and 15 seconds for others?  Part of this is just the computational load on heroku (which hosts the app).  The other part is the sampling rate of the GNSS file. It is twice as fast to compute orbits for a  30-second file than a 15-second file.  If your reflection target is less than 10 meters, I have decimated your RINEX file to speed it up. But above that level, you really need the higher sample rate data.

What do all the colors mean on the periodograms? Each rising or setting satellite track I identify that passes QC checks is plotted in a different color in that quadrant.

Does GNSS-IR having timing information? Each periodogram is associated with a specific time of day, but it is not shown on the plot. That information is in the text file.

Is this GNSS or just GPS? Currently the web app is only GPS. Adding other GNSS signals to the web app would require external support.

Why don’t you allow higher sampling rates or taller sites? This is mostly a cpu issue. The higher the sampling rate, the longer it takes to compute orbits. This is not a big problem on your desktop, but on the web server I am using I don’t control how much cpu I am being given.

What about RINEX 3? I now allow 30-second RINEX 3 files from the CDDIS archive.  They are not currently allowed from the upload option.

Why do site photos show up only some of the time? This app only queries UNAVCO for photographs. If UNAVCO does not have a photo where it should be located, it is not displayed

What is this web app written in? Python, javascript, and Flask.

How did you learn to make a web app? By watching youtube videos and reading stack exchange posts.

Where are the soil moisture data? Adding soil moisture to this web app would require external support.

How can I learn more about GNSS-IR? You can find some papers in the publications section of my website.

What models are not applied? I am not currently using a refraction correction. If there is sufficient interest, I can do this, but the effect is small for short reflector heights.  The RH dot correction is needed for most tidal measurements.  If I have external support, I will add this. I am also not applying a phase center model.  So if the L1 and L2 results are different, that is likely the reason.

Acknowledgements: Thank you to raxod502,  Julian Nash, Evan Crouch, Bucky Roberts, Joakim Strandberg, Felipe Nievinski, and Simon Williams for help with this web app.

I would also like to thank everyone who has written software to manipulate RINEX files, particularly:

  • Lou Estey (teqc)
  • Nischan, Thomas (2016): GFZRNX – RINEX GNSS Data Conversion and Manipulation Toolbox. GFZ Data Services.
  • Hatanaka-san (CRX2RNX)