Creating Catalogues

The two main elements required to start preparing a TFCat feature collection is the choice of the CRS and the list of feature geometries (with its set of time and spectral coordinates). In the following code snippet, a CRS object is created with a time axis using the unix timestamp representation, a spectral axis (frequency in kHz) and a reference position set to the Juno spacecraft.

Example CRS definition
from tfcat import CRS
crs = CRS({
   "type": "local",
   "properties": {
      "name": "Time-Frequency",
      "time_coords_id": "unix",
      "spectral_coords": {
         "type": "frequency",
         "unit": "kHz"
      },
   "ref_position_id": "juno",
   }
})

In the following example, we create a TFCat feature with a TFCat Polygon geometry and two custom feature properties called feature_type and integrated_flux_density. The set of coordinates are available as two variables called tt and ff, containing respectively the time coordinates (as a unix timestamp), and the frequency coordinates (in kHz). Note, that a Polygon geometry requires that the last coordinate point of the input sequence should be the same as the first one (closed polygon condition). It also requires that the segments forming the polygon are not crossing over (no cross-over condition). The polygon must also be curled counter-clockwise. We use the shapely package to check those conditions.

Creating a TFCat Polygon
from tfcat import Polygon, Feature
from shapely.geometry import LinearRing

# packing coordinates into a list
coords = list(zip(tt, ff))

# checking if polygon is valid
if not LinearRing(coords).isvalid:
   raise ValueError("Polygon is invalid")

# checking if list of coordinates is curled in the direct trigonometric sense (counter-clockwise)
if not LinearRing(coords).is_ccw:
   coords = coords[::-1]

# creating the TFCat Feature
feature = Feature(
   geometry=Polygon([coords]),
   properties={
      "feature_type": "Io-A",
      "integrated_flux_density": 1.22e-19,
   },
)

Each properties must be defined at the main level of the feature collection object, using a set of TFCat Field objects, as shown below.

Defining the TFCat Fields
fields = {
   "feature_type": {
      "info": "Feature Type",
      "datatype": "str",
      "ucd": "meta.id",
   },
   "integrated_flux_density": {
      "info": "Integrated Flux Density",
      "datatype": "float",
      "ucd": "phot.flux.density;stat.mean",
      "unit": "W m-2 Hz-1",
   }
}

The feature collection can also include main level properties, listing global metadata for the collection, such as the author, the instrument, etc. The next code snippet shows a set of collection level properties. We recommend to use keywords compliant with the EPNcore metadata dictionary. For authors, we recommend to use a list of dictionaries containing GivenName, FamilyName, ORCID and Affiliation (using Research Organisation Registry identifier when possible).

Defining main level properties
properties = {
   "instrument_host_name": "Juno",
   "instrument_name": "Waves",
   "title": "Catalogue of Juno Radio emissions",
   "authors": [
      {
         "GivenName": "Corentin K.",
         "FamilyName": "Louis",
         "ORCID": "https://orcid.org/0000-0002-9552-8822",
         "Affiliation": "https://ror.org/051sx6d27"
      },
   ],
   "target_name": "Jupiter",
   "target_class": "planet",
   "target_region": "magnetosphere",
   "feature_name": "radio emissions",
   "bib_reference": "TBD",
   "publisher": "PADC/MASER",
   "version": "1.0"
}

Finally, the collection can be built, assuming a list of features is available in an iterable called features. The JSON schema URI should also be referenced.

Finalizing TFCat collection
from tfcat import FeatureCollection
SCHEMA_URI = "https://voparis-ns.obspm.fr/maser/tfcat/v1.0/schema#"

# creating the collection
collection = FeatureCollection(
   schema=SCHEMA_URI,
   features=features,
   properties=properties,
   fields=fields,
   crs=crs
)

Writing the collection into a file is straightforward, since tje TFCat module implements the same interfaces as the json python module for file system interactions (i.e., dump(), dumps(), load(), loads() methods):

Dumping into File
# write out the collection on disk
from tfcat import dump
filename = "tfcat.json"
with open(filename, "w") as f:
   dump(collection, f)