Phase correction
One of the main challenge with VLF data is the phase measurements. Indeed, the phase measured present two problems:
It is constrained between -180° and 180°, which adds spurious phase jumps.
The absolute value of the phase is unknown [cohen2018] .
A common method to correct the phase is first to unwrap it (to remove the spurious jumps) and then to detrend it (to remove the slope that is added by the unwrap). This works really well in post-processing, but cannot always be used in real-time, as the detrend depends on the past data.
Correcting the phase with the polarisation parameters
To correct the phase in real-time the phase, one way is to use the polarisation parameters as explained in [gross2018] . Their computation is done via the function EllispeParams(). The different parameters are described in the paper by the authors.
Of particular interest to us is the start phase. If the data is represented as an ellipse to characterise its polarisation, the start phase is defined as the opposite of the phase of the semi-major axis (Equation 12 of [gross2018] ) oriented in the direction perpendicular to the transmitter (because it is much less noisy). Thus, the start phase reprensents changes common to both the N/S and E/W channels.
Method to correct the phase
To correct in real-time the phase, we thus use the method presented below. To illustrate it, we use the example of the data for 2023/11/05 for the NRK transmitter.
Uncorrected amplitude and phase data
Phase unwrap
The first step of the phase correction is to unwrap the data, i.e. to correct for every 90° jump caused by keeping the phase constrained between -180° and 180°.
This is done by the unwrap function of the numpy module
Unwrapped phase
Phase detrend
As seen in the example above, after the unwrap the phase doesn’t present any jumps, but it drifts. There is thus a slope to remove.
In post-processing, the detrend method works well, as the natural slopes present in the data at sunrise and sunset are short in time: the trend that is compensated by detrend mainly depends on points during daytime and nighttime, for which the slope is close to zero. Moreover, the positive slope for sunrise roughtly balances the negative slope due to sunset.
However, in real-time, since we only have the data from the beginning of the file, we often only have sunrise (but not sunset) and part of the daytime data. Because of this, the sharp positive slope due to sunrise will have much more importance, and this may cause the detrend to fail. The slopes for sunrise and sunset will not balance anymore.
A solution to this problem would be to read the data for two consecutive days; but this requires reading an additional file, specifying its path (because files are usually moved from one day to the next), and this will only work if there weren’t any problem for either of the days.
Lastly, an additonal problem with this method in real-time is the case when the transmitter is off; in this case, the measured phase is not constant anymore, as nothing is transmitting, and will vary greatly. Using a detrend on this data will fail, as spurious slopes may be induce by this period of time.
Method
The phase drift that is observed when unwrapping the phase is due to a slight shift in the transmitter frequency, \(\delta f\). Once this shift is measured, the corrected phase can simply be obtained by:
\(\phi_{corrected} = \phi_{unwrapped} + \delta f \times 2 \pi * \text{the_time} \times \frac{180}{\pi}\)
where the_time is the time in second since the beginning of the day. df is an attribute of the Python class station, which should be regularly updated (see Updating df values).
Note
Finding \(\delta f\)
The value of \(\delta f\) depends on the transmitter. It can be estimated by unwrapping the phase for several consecutive days separately, and looking at the jump of the phase one day to tne next. Then, the \(\delta f\) value is found by:
\(\delta f = \frac{\pi}{180} \times \frac{jump}{86400} \frac{1}{2 \pi}\)
where jump is the phase discontinuity between two days (in °) and 84600 is
the number of second in a day. A function vlf4ions.correct_phase.compute_df() is included in the package to compute this parameter.
Unwrapped and detrended phase