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. .. code-block:: python :caption: 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. .. code-block:: python :caption: 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. .. code-block:: python :caption: 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). .. code-block:: python :caption: 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. .. code-block:: python :caption: 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): .. code-block:: python :caption: 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)