Diversifying Argo Surfacing Times

Extracting diel cycles using fleet-level data

Christopher Gordon https://github.com/cgrdn
2023-07-13

A 2021 paper by Johnson and Bif (2021) demonstrated that diel cycles of oxygen can be observed using the Argo network as a collective set of sensors. More recently, Stoer and Fennel (2022) used similar methodology on particle backscatter to estimate Net Primary Production (NPP) from diel cycles in carbon biomass. Each of these recent papers apply the method Gille (2012) demonstrated for diel cycles of temperature to biogeochemical variables. The calculation of the diel cycle depends on multiple factors, one of them being that floats included in the analysis do not surface at a fixed or few times of day for every profile. Instead, floats must demonstrate good temporal coverage of a 24hr period with near even occurrences.

Figure 2 from Johnson and Bif (2021). Their caption reads: a, Mean oxygen anomaly in the upper 20 m from each profile with acceptable cycle timing (N = 14,294) versus local hour of the day. Data from all days of year from 2010 to 2020 are included. b, Mean oxygen anomaly in each hourly interval and the least-squares fit of equation (2) to the data shown in a with GOP = 2.2 \pm 0.3 (1 standard error) mmol m^{−3} d^{−1} O2. c, GOP determined at 2-month intervals in the upper 20 m versus day of year. d, Depth profile of GOP rates for all days of the year. Error bars are one standard error.

This is not necessarily typical behaviour for Argo floats. For the analysis presented in Johnson and Bif (2021), of the 50,736 profiles available in the Northern Hemisphere, only 14,294 profiles satisfied the surface time requirements. In this post we will detail Argo Canada’s effort over the last 2-3 years to shift it’s Argo floats to satisfy this surfacing schedule and contribute to future research using this methodology.

The post will be a mix of text and python code, showing both the changes over time and the python code needed to demonstrate the change. We will use pandas for data handling, and matplotlib and seaborn for plotting. Lets load our packages and the Argo global index:

import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="ticks", palette="colorblind")

# load the global index
global_index = pd.read_csv(
  "ftp://ftp.ifremer.fr/ifremer/argo/ar_index_global_prof.txt.gz", 
  compression="gzip", header=8
)
# subset to only the MEDS DAC, profiles with valid dates
meds = global_index.loc[global_index.file.str.contains('meds')]
meds = meds.loc[meds.date.notna()]

# convert date to pandas timestamps, take only profiles from the last 3 years
meds["date"] = meds.date.astype(str)\
  .apply(lambda x: x.replace(".0", ""))\
  .apply(pd.Timestamp, tz="utc")
meds = meds.loc[meds.date > pd.Timestamp("01-2020", tz="utc")]

The few surviving MetOcean NOVA floats are included here, but it should be noted that these were not specifically reprogrammed for varied surfacing times. Recently deployed deep ARVOR floats are also included, however their cycle period is defined as an integer number of days rather than in hours, and so those will not produce good diel coverage. Now, we will calculate the local time using the location data, and python packages timezonefinder and pytz, and visualize local surfacing times over the last 3 years.

import timezonefinder
tf = timezonefinder.TimezoneFinder()
import pytz

profiler_type = {
    "865":"NOVA      ",
    "844":"ARVOR_SBE ",
    "878":"ARVOR_RBR ",
    "838":"ARVOR_DEEP",
    "836":"PROVOR    ",
}

# exclude invalid locations
meds = meds.loc[(meds.latitude.notna()) & (meds.longitude.notna())]

# get timezone, local time, and hour at surface for each profile
meds["timezone"] = [
  pytz.timezone(tf.certain_timezone_at(lat=lat, lng=lon))\
  for lat, lon in zip(meds.latitude, meds.longitude)
]
meds["local_time"] = [utc_time.tz_convert(tz) for utc_time, tz in zip(meds.date, meds.timezone)]
meds["surface_hour"] = [local_time.hour + 0.5 for local_time in meds.local_time]

# add a column for WMO number as well as platform name
meds["WMO"] = [int(s.split("/")[1]) for s in meds.file]
meds["platform"] = [profiler_type[f"{p}"] for p in meds.profiler_type]

fig, ax = plt.subplots(dpi=300, constrained_layout=True)
sns.lineplot(data=meds, x="local_time", y="surface_hour", hue="platform", 
  units="WMO", estimator=None, alpha=0.25, ax=ax
)
sns.move_legend(ax, "upper left", bbox_to_anchor=(1, 1))
plt.setp(ax.get_xticklabels(), ha="right", rotation=45)

The above plot is very busy, but clearly shows a shift in regime in mid-2021 when we began reprogramming all new deployments as well as existing floats via remote commands. For NKE ARVOR floats, which constitute most of the Canadian fleet, we set the cycle period to 245 hours, or 10 days + 5 hours. This creates diel coverage relatively quickly, without sampling at times near each other on subsequent profiles. NKE PROVOR floats were slightly trickier to reprogram, as instead of a cycle period they have a surface time they aim to achieve. This parameter therefore must be reprogrammed every cycle. This is achieved by running a daily github action powered by python, which you can find on the ArgoCanada github page.

To better understand the timing, lets look closely at an ARVOR float that was deployed in late 2020 and reprogrammed, and a PROVOR float that gets a new command each cycle.

# ARVOR deployed in 2020, PROVOR in 2022
arvor  = 4902523
provor = 4902623
subset = meds.loc[meds.WMO.isin((arvor, provor))]
# make day of mission our time variable so we can plot them on the same axis
subset["mission_day"] = [
  subset.date.loc[i] - subset.date.loc[subset.WMO == subset.WMO.loc[i]].min()\
  for i in subset.index
]
# fractional days
subset["mission_day"] = subset["mission_day"].apply(lambda x: x/pd.to_timedelta(1, 'D'))

fig, ax = plt.subplots(dpi=300, constrained_layout=True)
sns.lineplot(data=subset, x="mission_day", y="surface_hour", hue="platform", 
  style="platform", dashes=False, markers=True, ax=ax
)
ax.set_xlim((0,300))

The ARVOR float was deployed in 2020, and was reprogrammed remotely in the second half of 2021. The PROVOR float was deployed before the surface time reprogramming protocol was live, but has begun taking commands as of May 2023. The lines slope in opposite directions because the ARVORs operate on a 10 days + 5 hours (245hr) cycle, while the PROVORs are being programmed for 10 days - 5 hours (235hr) cycle. The latter is a minor difference, but was a suggestion from the manufacturer as it may produce an extra profile or two if/when a float dies of exhausted battery life.

Finally, to get a better idea of how we have performed fleet-wide, let’s look at the distributions of surfacing times since 2020 by year.

# create column for profile year
meds["year"] = [d.year for d in meds.local_time]
meds = meds.loc[meds.year > 2019] # 2 floats have local times in 2019
# create a FacetGrid that will plot by year, 2020, 2021, 2022, 2023
g = sns.displot(
  meds, x="surface_hour", col="year", hue="platform", 
  kind="hist", bins=list(range(24)), multiple="stack", 
  col_wrap=2, facet_kws=dict(despine=False, sharey=False)
)
g.fig.set_dpi(300)
g.fig.set_constrained_layout(True)

The above figure shows the progression of the Canadian Argo fleet over the years. Blue bars correspond to ARVOR floats with Seabird CTDs, orange bars to ARVOR floats with RBR CTDs and green bars to PROVOR floats. In the 2020 panel, there are two peaks, one representing local times in the Eastern Pacific, and the other in the Western Atlantic. In 2021 these peaks persist, but for roughly half the year we have good coverage. In 2022, some peaks remain as the final floats still operating on 240 hour cycles are reprogrammed. In the final panel, we see that the fleet operates well to cover the entire day. There are slight biases toward 0600-0700 and 1400-1500 local times in the PROVOR floats (green bars) as the live reprogramming was not active until May this year, but those profiles are now being well distributed. Overall, almost all recent profiles recorded by Argo Canada floats should now meet the statistical criteria to be able to construct diel cycles as in Gille (2012), Johnson and Bif (2021), and Stoer and Fennel (2022).

References

Johnson, K.S., Bif, M.B. Constraint on net primary productivity of the global ocean by Argo oxygen measurements. Nat. Geosci. 14, 769-774 (2021). https://doi.org/10.1038/s41561-021-00807-z

Stoer, A.C. and Fennel, K. (2023), Estimating ocean net primary productivity from daily cycles of carbon biomass measured by profiling floats. Limnol. Oceanogr. Lett, 8: 368-375. https://doi.org/10.1002/lol2.10295

Gille, S. T. (2012), Diurnal variability of upper ocean temperatures from microwave satellite measurements and Argo profiles, J. Geophys. Res., 117, C11027, doi:10.1029/2012JC007883.

Citation

For attribution, please cite this work as

Gordon (2023, July 13). Argo Canada Development Blog: Diversifying Argo Surfacing Times. Retrieved from https://argocanada.github.io/blog/posts/2023-07-13-diversifying-argo-surfacing-times/

BibTeX citation

@misc{gordon2023diversifying,
  author = {Gordon, Christopher},
  title = {Argo Canada Development Blog: Diversifying Argo Surfacing Times},
  url = {https://argocanada.github.io/blog/posts/2023-07-13-diversifying-argo-surfacing-times/},
  year = {2023}
}