Skip to content

Commit

Permalink
ArgoFloat spec and online/offline implementations
Browse files Browse the repository at this point in the history
this is a refactoring
  • Loading branch information
gmaze committed Jan 9, 2025
1 parent 29250a5 commit cd7b334
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 59 deletions.
4 changes: 2 additions & 2 deletions argopy/stores/float/argo_float.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ class ArgoFloat(FloatStore):
"""
Main docstring for ArgoFloat
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
56 changes: 46 additions & 10 deletions argopy/stores/float/implementations/argo_float_offline.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from errors import InvalidOption
import pandas as pd
import numpy as np
from pathlib import Path
import logging

from ....errors import InvalidOption
from ..spec import ArgoFloatProto


Expand All @@ -13,29 +15,63 @@ class ArgoFloatOffline(ArgoFloatProto):

def __init__(
self,
*args,
**kwargs,
):
super().__init__(**kwargs)
super().__init__(*args, **kwargs)

if self.host_protocol != "file":
raise InvalidOption("Trying to work with the offline store using a remote host !")
raise InvalidOption(
"Trying to work with the offline store using a remote host !"
)

# Load some data (in a perfect world, this should be done asynchronously):
# self.load_index()
self.load_dac() # must come before metadata
self.load_metadata()
self.load_dac()

def load_metadata(self):
"""Method to load float meta-data"""
data = {}
data.update({"deployment": {"launchDate": "?"}})
data.update({"cycles": []})
data.update({"networks": ['?']})
data.update({"platform": {'type': '?'}})
data.update({"maker": '?'})
# data.update({"cycles": []})

ds = self.open_dataset("meta")
data.update(
{
"deployment": {
"launchDate": pd.to_datetime(ds["LAUNCH_DATE"].values, utc=True)
}
}
)
data.update(
{"platform": {"type": ds["PLATFORM_TYPE"].values[np.newaxis][0].strip()}}
)
data.update(
{"maker": ds["PLATFORM_MAKER"].values[np.newaxis][0].strip()}
)

def infer_network(this_ds):
if this_ds['PLATFORM_FAMILY'].values[np.newaxis][0].strip() == 'FLOAT_DEEP':
network = ['DEEP']
if len(this_ds['SENSOR'].values) > 4:
network.append('BGC')

elif this_ds['PLATFORM_FAMILY'].values[np.newaxis][0].strip() == 'FLOAT':
if len(this_ds['SENSOR'].values) > 4:
network = ['BGC']
else:
network = ['CORE']

else:
network = ['?']

return network

data.update({"networks": infer_network(ds)})

data.update({"cycles": np.unique(self.open_dataset("prof")['CYCLE_NUMBER'])})

self._metadata = data
return self._metadata

def load_dac(self):
"""Load the DAC short name for this float"""
Expand Down
54 changes: 23 additions & 31 deletions argopy/stores/float/implementations/argo_float_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@

class ArgoFloatOnline(ArgoFloatProto):
_online = True
_eafleetmonitoring_server = "https://fleetmonitoring.euro-argo.eu"
_technicaldata = None

def __init__(
self,
*args,
**kwargs,
):
super().__init__(**kwargs)
super().__init__(*args, **kwargs)

if self.host_protocol == "s3":
self.host = self.host.replace(
Expand All @@ -30,14 +33,13 @@ def __init__(

# Load some data (in a perfect world, this should be done asynchronously):
# self.load_index()
self.load_metadata()
self.load_metadata() # must come before load_dac
self.load_dac()

def load_metadata(self):
"""Load float meta data from Euro-Argo fleet-monitoring API"""
api_server = "https://fleetmonitoring.euro-argo.eu"
# api_point = f"{api_server}/floats/basic/{self.WMO}"
api_point = f"{api_server}/floats/{self.WMO}"
# api_point = f"{self._eafleetmonitoring_server}/floats/basic/{self.WMO}"
api_point = f"{self._eafleetmonitoring_server}/floats/{self.WMO}"
self._metadata = httpstore(
cache=self.cache, cachedir=self.cachedir
).open_json(api_point)
Expand All @@ -47,6 +49,22 @@ def load_metadata(self):
self._metadata["deployment"]["launchDate"]
)

def load_technicaldata(self):
"""Load float meta data from Euro-Argo fleet-monitoring API"""
# api_point = f"{self._eafleetmonitoring_server}/technical-data/basic/{self.WMO}"
api_point = f"{self._eafleetmonitoring_server}/technical-data/{self.WMO}"
self._technicaldata = httpstore(
cache=self.cache, cachedir=self.cachedir
).open_json(api_point)

@property
def technicaldata(self) -> dict:
"""A dictionary holding float technical-data, based on the EA fleet-monitoring API json schema
"""
if self._technicaldata is None:
self.load_technicaldata()
return self._technicaldata

def load_dac(self):
"""Load the DAC short name for this float"""
try:
Expand All @@ -59,29 +77,3 @@ def load_dac(self):

# For the record, another method to get the DAC name, based on the profile index
# self._dac = self.idx.search_wmo(self.WMO).read_dac_wmo()[0][0] # Get DAC from Argo index

def __repr__(self):
summary = ["<argofloat.%i.%s>" % (self.WMO, self.host_protocol)]
status = "online ✅" if isconnected(self.path, maxtry=1) else "offline 🚫"
summary.append("GDAC host: %s [%s]" % (self.host, status))
summary.append("DAC name: %s" % self.dac)
summary.append("Network(s): %s" % self.metadata['networks'])

launchDate = self.metadata["deployment"]["launchDate"]
today = pd.to_datetime('now', utc=True)
summary.append(
"Deployment date: %s [%s ago]"
% (launchDate, (today-launchDate).days)
)
summary.append(
"Float type and manufacturer: %s [%s]"
% (
self.metadata["platform"]["type"],
self.metadata["maker"],
)
)
summary.append("Number of cycles: %s" % self.N_CYCLES)
summary.append("Dashboard: %s" % dashboard(wmo=self.WMO, url_only=True))
summary.append("Netcdf dataset available: %s" % list(self.avail_dataset().keys()))

return "\n".join(summary)
35 changes: 19 additions & 16 deletions argopy/stores/float/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def __init__(
cache: bool = False,
cachedir: str = "",
timeout: int = 0,
**kwargs,
):

self.WMO = check_wmo(wmo)[0]
Expand All @@ -51,6 +52,10 @@ def __init__(
raise InvalidOption("Trying to work with remote host '%s' without a web connection. Check your connection parameters or try to work with a local GDAC path." % self.host)


def load_index(self):
"""Load the Argo full index in memory and trigger search for this float"""
self.idx.load().search_wmo(self.WMO)

@property
def metadata(self) -> dict:
"""A dictionary holding float meta-data, based on the EA fleet-monitoring API json schema
Expand All @@ -59,7 +64,7 @@ def metadata(self) -> dict:
self._metadata["deployment"]["launchDate"] # pd.Datetime
self._metadata['cycles'] # list
self.metadata['networks'] # list of str
self.metadata["platform"]["type"] #
self.metadata["platform"]["type"] # from Reference table 23
self.metadata["maker"] #
"""
if self._metadata is None:
Expand All @@ -71,15 +76,16 @@ def load_metadata(self):
"""Method to load float meta-data"""
raise NotImplementedError("Not implemented")

def load_index(self):
"""Load the Argo full index in memory and trigger search for this float"""
self.idx.load().search_wmo(self.WMO)

@abstractmethod
def load_dac(self):
"""Load the DAC short name for this float"""
raise NotImplementedError("Not implemented")

@property
def dac(self) -> str:
"""Name of the DAC responsible for this float"""
return self._dac

@property
def host_protocol(self) -> str:
"""Protocol of the GDAC host"""
Expand All @@ -90,11 +96,6 @@ def host_sep(self) -> str:
"""Host path separator"""
return self.fs.fs.sep

@property
def dac(self) -> str:
"""Name of the DAC responsible for this float"""
return self._dac

@property
def path(self) -> str:
"""Return float path
Expand Down Expand Up @@ -144,7 +145,7 @@ def N_CYCLES(self) -> int:
If the float is still active, this is the current value.
"""
return len(self.fleetmonitoring_metadata['cycles'])
return len(self.metadata['cycles'])

def describe_profiles(self) -> pd.DataFrame:
"""Return a :class:`pd.DataFrame` describing profile files"""
Expand All @@ -171,16 +172,17 @@ def describe_profiles(self) -> pd.DataFrame:

def __repr__(self):
summary = ["<argofloat.%i.%s>" % (self.WMO, self.host_protocol)]
status = "online ✅" if isconnected(self.path, maxtry=1) else "offline 🚫"
summary.append("GDAC host: %s [%s]" % (self.host, status))
# status = "online ✅" if isconnected(self.path, maxtry=1) else "offline 🚫"
# summary.append("GDAC host: %s [%s]" % (self.host, status))
summary.append("GDAC host: %s" % self.host)
summary.append("DAC name: %s" % self.dac)
summary.append("Network(s): %s" % self.metadata['networks'])

launchDate = self.metadata["deployment"]["launchDate"]
today = pd.to_datetime('now', utc=True)
summary.append(
"Deployment date: %s [%s ago]"
% (launchDate, (today-launchDate).days)
"Deployment date: %s [%s days ago]"
% (launchDate.strftime("%Y-%m-%d %H:%M"), (today-launchDate).days)
)
summary.append(
"Float type and manufacturer: %s [%s]"
Expand All @@ -190,7 +192,8 @@ def __repr__(self):
)
)
summary.append("Number of cycles: %s" % self.N_CYCLES)
summary.append("Dashboard: %s" % dashboard(wmo=self.WMO, url_only=True))
if self._online:
summary.append("Dashboard: %s" % dashboard(wmo=self.WMO, url_only=True))
summary.append("Netcdf dataset available: %s" % list(self.avail_dataset().keys()))

return "\n".join(summary)

0 comments on commit cd7b334

Please sign in to comment.