Running models using the web api directly.
Models can be run without the NoM Client by accessing the web api endpoints directly.
creme-96-gcr sapre web_api no-client

# coding=utf-8
"""
category: tutorial
title: Running models using the web api directly.
description: Models can be run without the NoM Client by accessing the web api endpoints directly.
keywords: creme-96-gcr, sapre, web_api, no-client
"""
import json
from pprint import pprint

import requests

from nom_client.utils.json_encoder_lib import ComplexEncoder

api_key = ""

WEB_API_RUN_MODEL_ENDPOINT = "/models/run"

api_url = "https://nom.esa.int/api"

complete_url = "{0}{1}".format(api_url, WEB_API_RUN_MODEL_ENDPOINT)

# set some headers for content type and bearer token
headers = {'Content-Type': 'application/json',
           'Authorization': 'Bearer {0}'.format(api_key)}

# Create the model parameters payload dict
sapre_payload = {
    "model_name": "sapre",
    "tag": "test_tag",
    "project_name": "my_project",
    "inputs": {
        "mission": {
            "missionDuration": 1
        },
        "sapre": {
            "orbitType": "GEN",
            "perigeeAltitude": 300,
            "apogeeAltitude": 36000
        }
    }
}
# Create JSON
sapre_payload_json = json.dumps(sapre_payload, cls=ComplexEncoder)

# Run the model
sapre_response = requests.post(complete_url, headers=headers, data=sapre_payload_json)

# Check the response code, should be 200 if all OK
print(sapre_response.status_code)

# Grab the actual JSON results data
sapre_result = sapre_response.json()

print(sapre_result['status']) # hopefully 'COMPLETED'
print(sapre_result['message']) # hopfully 'success'
# Grab the run ID of the SAPRE model run. We will need this if we want to use the
# SAPRE result as an input to another model
sapre_result_run_id = sapre_result['results']['run_id']


# Now we can run CREME-96 GCR model, using the orbit result we just ran

gcr_payload = {
    "model_name": "creme-96-gcr",

    "inputs": {
        'gcr': {
            'GCRMOD': 0,
            'lowestIonSpecies': 1,
            'highestIonSpecies': 92,
            'useGeomagneticShielding': 0
        },
        "_external": {"trajectory": sapre_result_run_id}
    }
}

gcr_payload_json = json.dumps(gcr_payload)
gcr_response = requests.post(complete_url, headers=headers, data=gcr_payload_json)
gcr_result = gcr_response.json()

print(gcr_result['status']) # hopefully 'COMPLETED'
print(gcr_result['message']) # hopfully 'success'


gcr_results_data = gcr_result['results']['results']['particle_spectrum']['variables']

# Available data variables
print(list(gcr_results_data.keys()))

# Lets grab the 'differential_flux' data first
diff_flux = gcr_results_data['differential_flux']

# Some meta data
print(diff_flux['name'])
print(diff_flux['quantity'])

# We can get the units for this data
print(diff_flux['units'])

# We can get the quantity and qualifiers
print(diff_flux['quantity'])
# The quantity in this case is 'number flux'
print(diff_flux['qualifiers'])
# The qualifers are:
# {'direction': 'directional', 'form': 'differential', 'species': 'multiple'}
# So we have differential, directional number flux data for all 92 ions

print(diff_flux['axes'])
"""
You can get information about the data structure/model by looking at the axes meta data
The axes meta data: {'1': 'energy', '2': 'species'}
Each entry in the axes data is the name of a variable, in this case energy and species
This data is a 2-dimentional array (list of lists)
The axes meta data describes the data from the inner dimention outwards, so ...
the data specifies that the data will a list of 92 rows of data, one for each of the 92 species requested.
Within each species row of data is a list of 95 flux values, one ofr wach of the energies requested
"""

# Lets look at the energy and species data
energies = gcr_results_data['energy']
print(energies['units'])
print(energies['axes'])
print(energies['row_varying'])
"""
The energy data has units of MeV.
It's axes data is empty because its an independent variable.
It is 'row varying', meaning that there is a value of anergy for every row of flux data
"""

species = gcr_results_data['species']
print(species['units'])
print(species['axes'])
print(species['row_varying'])
"""
The species data has units of '1' (no units).
It's axes data is empty because its an independent variable.
It is NOT 'row varying', meaning that this variable describes the columns of data in the flux dataset

energy  species1    species2    ...     speciesN
1       10000       1000                1
2       9000        900                 0.9
...

The 'species' data is essentially the labels for the species columns in this case
"""

# Now back to the flux data
print(diff_flux['values'])
# Lets get the data for species 26 (Iron)
print(diff_flux['values'][26])