# Climatic variables spatial plotting

Open you preferable Python IDE or Python console and initially import the required libraries. This example is quite more complex than the previous example [simple-climatic-variables-plotting](https://docs.answr.space/coding-examples/simple-climatic-variables-plotting "mention"). Beside the standard libraries also imported in the previous example, we are going to need a couple of geospatial related libraries to better handle coordinates.

{% code overflow="wrap" lineNumbers="true" %}

```python
import requests
import json
import numpy as np
import geopandas as gpd
import matplotlib.pyplot as plt
import shapely.geometry
```

{% endcode %}

After importing the libraries, we define all the needed variables to proceed. **Email**, **password**, **climatic*****\_variable*****\_1** and **coordinates** are the essential variables needed to get your responses from the API. The input coordinates of the API are single points, i.e. to time a call is made on the API it refers to specific location requested. Thus to have a collection of spatially distributed points, multiple requests are needed.

{% hint style="info" %}
It's a good idea to bring all variables that you are going to use up, in order to avoid "hard coding" values later in the code
{% endhint %}

{% code overflow="wrap" lineNumbers="true" %}

```python
# Define the user credentials
email = 'YOUR ACCOUNT EMAIL'
password = 'YOUR PASSWORD'
# Define the climatic variable to plot
climatic_variable_1 = 'a-frost-days'  # Average Frost Days
# Define the coordinates of the polygon
lat_point_list = [50.854457, 52.518172, 50.072651, 48.853033, 50.854457]
lon_point_list = [4.377184, 13.407759, 14.435935, 2.349553, 4.377184]
# Create a geopandas structure with the coordinates
polygon_geom = shapely.geometry.Polygon(zip(lon_point_list, lat_point_list))
gdf = gpd.GeoDataFrame(index=[0], crs='epsg:4326', geometry=[polygon_geom])
# total area for the grid
xmin, ymin, xmax, ymax= gdf.total_bounds
# Define the grid
n_cells=5
cell_size = (xmax-xmin)/n_cells
# Projection of the grid
crs = "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m +no_defs"
```

{% endcode %}

So far, the **polygon**, **bounding box** and **projection** are defined. Following a **grid** is defined within this polygon. This grid contains the point coordinates to be used in the API calls

{% code overflow="wrap" lineNumbers="true" %}

```python
# Create the cells in a loop
grid_cells = []
for x0 in np.arange(xmin, xmax+cell_size, cell_size):
    for y0 in np.arange(ymin, ymax+cell_size, cell_size):
        # bounds
        x1 = x0-cell_size
        y1 = y0+cell_size
        grid_cells.append(shapely.geometry.box(x0, y0, x1, y1))
cell = gpd.GeoDataFrame(grid_cells, columns=['geometry'], crs=crs)
lng = cell.centroid.x
lat = cell.centroid.y
```

{% endcode %}

Following the process, the user needs to generate the temporally authkey to interact with the rest endpoints.

{% code overflow="wrap" lineNumbers="true" %}

```python
# Step 1: Generate a temporal API key to authentic the other API endpoints
headers = {
    'accept': 'application/json',
    # Already added when you pass json= but not when you pass data=
    # 'Content-Type': 'application/json',
}
json_data = {
    'email': email,
    'password': password,
}
# This the variable that holds the temporally API key
auth_response = requests.post('https://api.answr.space/api:auth/auth/login', headers=headers, json=json_data)
```

{% endcode %}

A for loop is used to loop over all points, make the calls to the API and store the responses into a list.

{% code overflow="wrap" lineNumbers="true" %}

```python
authkey = json.loads(auth_response.content)
for i in range(len(cell)):
    # Step 2: Loop over the points and get the data from the answr.space API
    headers = {
        'accept': 'application/json',
        'Authorization': 'Bearer ' + authkey['authToken'] + '',
    }
    params = {
        'Input_point': '{"type":"point","data":{"lng":' + str(lng[i]) + ',"lat":' + str(lat[i]) + '}}',
    }
    response_1 = requests.get('https://api.answr.space/api:climate-variables/' + climatic_variable_1 + '', params=params,headers=headers)
    # Convert byte responses to json format
    climatic_variable_response = json.loads(response_1.content)
    if response_1.content != b'null':
        # Rename json to key to months for better plot visualization. You can find the response keys in the API reference documentation for each endpoint
        new_key = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
        old_key = {"CV76_M1", "CV76_M2", "CV76_M3", "CV76_M4", "CV76_M5", "CV76_M6", "CV76_M7", "CV76_M8", "CV76_M9", "CV76_M10", "CV76_M11", "CV76_M12"}
        responses.append(dict(zip(new_key, list(climatic_variable_response.values()))))
    else:
        responses.append(dict(zip(new_key, [0]*12)))
```

{% endcode %}

Finally, we can plot the points to spatially understand the variation of the climate statistics.

{% code overflow="wrap" lineNumbers="true" %}

```python
df_responses = pd.DataFrame(responses)
plt.scatter(lng, lat, c = df_responses['March'], cmap= 'viridis')
```

{% endcode %}

<figure><img src="https://2993576723-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FaeFFaXxEeZmdbsofIXux%2Fuploads%2F1redEhx9AoGyFE3Ue4dM%2Fimage.png?alt=media&#x26;token=5ff347d9-90bd-46c3-b554-a81543720846" alt=""><figcaption></figcaption></figure>

In case you want to run the entire process with a single command, bellow you can find the entire code.

{% code overflow="wrap" lineNumbers="true" %}

```python
import requests
import json
import numpy as np
import geopandas as gpd
import matplotlib.pyplot as plt
import shapely.geometry
import pandas as pd

# Define the user credentials
email = 'YOUR ACCOUNT EMAIL'
password = 'YOUR PASSWORD'
# Define the climatic variable to plot
climatic_variable_1 = 'a-frost-days'  # Average Frost Days
# Define the coordinates of the polygon
lat_point_list = [50.854457, 52.518172, 50.072651, 48.853033, 50.854457]
lon_point_list = [4.377184, 13.407759, 14.435935, 2.349553, 4.377184]
# Create a geopandas structure with the coordinates
polygon_geom = shapely.geometry.Polygon(zip(lon_point_list, lat_point_list))
gdf = gpd.GeoDataFrame(index=[0], crs='epsg:4326', geometry=[polygon_geom])
# total area for the grid
xmin, ymin, xmax, ymax= gdf.total_bounds
# Define the grid
n_cells=5
cell_size = (xmax-xmin)/n_cells
# Projection of the grid
crs = "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m +no_defs"
# Create the cells in a loop
grid_cells = []
for x0 in np.arange(xmin, xmax+cell_size, cell_size):
    for y0 in np.arange(ymin, ymax+cell_size, cell_size):
        # bounds
        x1 = x0-cell_size
        y1 = y0+cell_size
        grid_cells.append(shapely.geometry.box(x0, y0, x1, y1))
cell = gpd.GeoDataFrame(grid_cells, columns=['geometry'], crs=crs)
lng = cell.centroid.x
lat = cell.centroid.y

# Step 1: Generate a temporal API key to authentic the other API endpoints
headers = {
    'accept': 'application/json',
    # Already added when you pass json= but not when you pass data=
    # 'Content-Type': 'application/json',
}
json_data = {
    'email': email,
    'password': password,
}
# This the variable that holds the temporally API key
auth_response = requests.post('https://api.answr.space/api:auth/auth/login', headers=headers, json=json_data)
responses = []
if auth_response.status_code == 200:
    authkey = json.loads(auth_response.content)
    for i in range(len(cell)):
        # Step 2: Loop over the points and get the data from the answr.space API
        headers = {
            'accept': 'application/json',
            'Authorization': 'Bearer ' + authkey['authToken'] + '',
        }
        params = {
            'Input_point': '{"type":"point","data":{"lng":' + str(lng[i]) + ',"lat":' + str(lat[i]) + '}}',
        }
        response_1 = requests.get('https://api.answr.space/api:climate-variables/' + climatic_variable_1 + '',
                                  params=params,
                                  headers=headers)

        # Convert byte responses to json format
        climatic_variable_response = json.loads(response_1.content)
        if response_1.content != b'null':
            # Rename json to key to months for better plot visualization. You can find the response keys in the API reference documentation for each endpoint
            new_key = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October",
                       "November", "December"}
            old_key = {"CV76_M1", "CV76_M2", "CV76_M3", "CV76_M4", "CV76_M5", "CV76_M6", "CV76_M7", "CV76_M8",
                       "CV76_M9", "CV76_M10", "CV76_M11", "CV76_M12"}
            responses.append(dict(zip(new_key, list(climatic_variable_response.values()))))

        else:
            responses.append(dict(zip(new_key, [0]*12)))
    # Convert responses to data frame
    df_responses = pd.DataFrame(responses)
    plt.scatter(lng, lat, c = df_responses['March'], cmap= 'viridis')


else:
    print('Return status code: ' + str(auth_response.status_code))
    print(auth_response.content)

```

{% endcode %}
