# Droughtmap Hub The Drought-map Hub is a streamlined system that automates the generation and publication of the Composite Drought Index (CDI) map for Eswatini. # Project Sheet
**Name** | Droughtmap Hub Eswatini |
**Project Scope** | The National Disaster Management Agency (NDMA) of Eswatini requires a system to monitor, evaluate, and analyse drought conditions in the country. Akvo is developing a platform that utilises output data generated by the Composite Drought Index (CDI) script, provided by the National Drought Mitigation Center (NDMC), through the GeoNode platform, which will be deployed by the NDMA. |
**Contract Link** | |
**Project Dashboard Link** | |
**Start Date** | |
**End Date** | |
**Repository Link** | [https://github.com/akvo/eswatini-droughtmap-hub/](https://github.com/akvo/eswatini-droughtmap-hub/) |
**Tech Stack** | List of technologies used to execute the technical scope of the project: - Front-end: JavaScript with React Framework - Back-end: Python with Django Framework - Testing: Django Test Framework, Jest - Coverage: Coveralls - Documentation: RTD, dbdocs - CI & CD: Github Workflows - Hosting: GKE - Database: PostgreSQL, Cloud-SQL - Storage: Cloud Storage Buckets |
**Asana Link** | [2435 - Drought Monitoring - Eng. Planning Board](https://app.asana.com/0/1208796157034791/1208847968993113) |
**Slack Channel Link** | [https://akvo.slack.com/archives/C07C0GG86BW](https://akvo.slack.com/archives/C07C0GG86BW) |
**Inkhungla** | **Initial Value** | **Reviewer 1** | **Reviewer 2** | **Reviewer X** | **Validated Value** |
---|---|---|---|---|---|
Value + rationale | Value + rationale |
Class Name | Class Notes |
Administration | Administration(id, name, region) |
SystemUser | SystemUser(id, name, email, technical\_working\_group) |
Publication | Publication(id, cdi\_geonode\_id, year\_month, initial\_values, validated\_values, published\_at, status, narrative, bulletin\_url) |
Reviews | Review(id, publication, user, administration, suggestion\_values, is\_completed) |
Jobs | Jobs(id, task\_id, type, status, attempt, result, info, user, created, available) |
Task | Task(id, name, func, hook, args, kwargs, result, group, started, stopped, success, attempt\_count) |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | system\_user\_id\_seq | |
2 | name | No | character varying | 100 | |
3 | No | character varying (unique) | 255 | ||
4 | role | No | enum(`UserRoleTypes`) | reviewer | |
5 | password | No | character varying | 128 | |
6 | email\_verified | No | boolean | false | |
7 | email\_verification\_code | Yes | uuid | ||
8 | email\_verification\_expiry | Yes | datetime | ||
9 | reset\_password\_code | Yes | uuid | ||
10 | reset\_password\_code\_expiry | Yes | datetime | ||
11 | technical\_working\_group | Yes | enum(`TechncalWorkingGroup`) | ||
12 | created\_at | No | timestamp | current\_datetime | |
13 | updated\_at | Yes | timestamp | ||
14 | deleted\_at | Yes | timestamp |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | administration\_id\_seq | |
3 | name | No | character varying | 100 | |
4 | region | Yes | character varying | 50 | |
5 | created\_at | No | timestamp | current\_datetime | |
6 | updated\_at | Yes | timestamp |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | cdi\_map\_id\_seq | |
2 | cdi\_geonode\_id | No | int | ||
3 | year\_month | No | date | ||
4 | initial\_values | No | JSON | ||
5 | status | No | int | 5 | |
6 | due\_date | No | date | ||
7 | validated\_values | Yes | JSON | ||
8 | published\_at | Yes | timestamp | ||
10 | narrative | Yes | text | ||
11 | bulletin\_url | Yes | character varying | 255 | |
12 | created\_at | No | timestamp | current\_datetime | |
13 | updated\_at | Yes | timestamp | ||
14 | delete\_at | Yes | timestamp |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | reviewers\_id\_seq | |
2 | publication\_id | No | int | ||
3 | user\_id | No | int | ||
4 | is\_completed | No | boolean | ||
5 | suggestion\_values | Yes | JSON | ||
6 | created\_at | No | timestamp | current\_datetime | |
7 | updated\_at | Yes | timestamp | ||
8 | completed\_at | Yes | timestamp | ||
9 | is\_overdue\_notified | Yes | boolean | false |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | jobs\_id\_seq | |
2 | task\_id | No | character varying | ||
3 | user\_id | No | int | ||
4 | type | No | int | 5 | |
5 | status | No | int | 5 | |
6 | attempt | Yes | int | 5 | |
7 | result | No | JSON | ||
8 | info | Yes | character varying | 255 | |
9 | created\_at | No | timestamp | ||
10 | updated\_at | Yes | timestamp |
**Name** | **Value** | **Description** |
---|---|---|
start | YYYY-MM | Select start month |
end | YYYY-MM | Select end month |
compare | \[\] | Array of Map ID |
**Name** | **Value** | **Description** |
---|---|---|
format | enum( GeoTIFF, CSV, GeoJSON) | Export format (e.g., GeoTIFF, CSV, GeoJSON). |
**Name** | **Value** | **Description** |
---|---|---|
start | YYYY-MM | Select start month |
end | YYYY-MM | Select end month |
status | enum: 1 - Pending 2 - In Review 3 - In Validation 4 - Published | CDI Map Status |
The 3-month SPI reflects positive short and medium-term moisture conditions which has a positive impact on vegetation and surface temperature hence promoting vegetation growth and also lowering the the near-surface air temperature.
", "bulletin_url": "https://example.com/eswatini/cdi-2025-01.pdf", } ``` **Response: 200 OK** on success ```json { "id": 100, "cdi_geonode_id": 150, "year_month": "2025-01", "initial_values": [ { "administration_id": 339, "value": 0.68, "category": "D4" }, { "administration_id": 338, "value": 2, "category": "D3" }, ... { "administration_id": 330, "value": 30, "category": "D0" }, ], "validated_values": [ { "administration_id": 339, "value": 3, "category": "D3" }, { "administration_id": 338, "value": 2, "category": "D3" }, ... { "administration_id": 330, "value": 15, "category": "D1" }, ], "published_at": "2025-01-29 08:00:30TZ", "status": 4, "narrative": "The 3-month SPI reflects positive short and medium-term moisture conditions which has a positive impact on vegetation and surface temperature hence promoting vegetation growth and also lowering the the near-surface air temperature.
", "bulletin_url": "https://example.com/eswatini/cdi-2025-01.pdf", } ``` #### 4. Reviewer API ##### 4.1 Review List **Endpoint**: `GET /api/v1/reviewer/reviews` **JWT Access: Reviewer** **Request params:****Name** | **Value** | **Description** |
---|---|---|
start | YYYY-MM | Select start month |
end | YYYY-MM | Select end month |
status | enum: 1 - Pending 2 - In Review 3 - In Validation 4 - Published | CDI Map Status |
**Message Type** | **Message Detail** |
---|---|
Data is Missing | - Recipient: DroughtHub Admins - Subject: CDI-E Automation - YYYY-MM - Mission data - Body: - Datetime of execution - “The following datasets have not yet been updated. Another attempt will be done in XX days.” - List the datasets for which the data is missing |
Error | - Recipient: Technical Support Contacts - Subject: CDI-E Automation - YYYY-MM - Execution Error - Body: - Datetime of execution - “The CDI automation has failed for month YYYY-MM. See the attached log file for details.” **Attachment: Log file** |
**Inkhundla** | **Initial Value** | **Validated Value** | **Reviewer 1** | **Reviewer 2** | **Reviewer X** |
---|---|---|---|---|---|
Value + rationale | Value + rationale |
Class Name | Class Notes |
Administration | Administration(id, name, region) |
SystemUser | SystemUser(id, name, email, technical\_working\_group) |
Publication | Publication(id, cdi\_geonode\_id, year\_month, initial\_values, validated\_values, published\_at, status, narrative, bulletin\_url) |
Reviews | Review(id, publication, user, administration, suggestion\_values, is\_completed) |
Jobs | Jobs(id, task\_id, type, status, attempt, result, info, user, created, available) |
Task | Task(id, name, func, hook, args, kwargs, result, group, started, stopped, success, attempt\_count) |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | system\_user\_id\_seq | |
2 | name | No | character varying | 100 | |
3 | No | character varying (unique) | 255 | ||
4 | role | No | enum(`UserRoleTypes`) | reviewer | |
5 | password | No | character varying | 128 | |
6 | email\_verified | No | boolean | false | |
7 | email\_verification\_code | Yes | uuid | ||
8 | email\_verification\_expiry | Yes | datetime | ||
9 | reset\_password\_code | Yes | uuid | ||
10 | reset\_password\_code\_expiry | Yes | datetime | ||
11 | technical\_working\_group | Yes | enum(`TechncalWorkingGroup`) | ||
12 | created\_at | No | timestamp | current\_datetime | |
13 | updated\_at | Yes | timestamp | ||
14 | deleted\_at | Yes | timestamp |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | administration\_id\_seq | |
3 | name | No | character varying | 100 | |
4 | region | Yes | character varying | 50 | |
5 | created\_at | No | timestamp | current\_datetime | |
6 | updated\_at | Yes | timestamp |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | cdi\_map\_id\_seq | |
2 | cdi\_geonode\_id | No | int | ||
3 | year\_month | No | date | ||
4 | initial\_values | No | JSON | ||
5 | status | No | int | 5 | |
6 | due\_date | No | date | ||
7 | validated\_values | Yes | JSON | ||
8 | published\_at | Yes | timestamp | ||
10 | narrative | Yes | text | ||
11 | bulletin\_url | Yes | character varying | 255 | |
12 | created\_at | No | timestamp | current\_datetime | |
13 | updated\_at | Yes | timestamp | ||
14 | delete\_at | Yes | timestamp |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | reviewers\_id\_seq | |
2 | publication\_id | No | int | ||
3 | user\_id | No | int | ||
4 | is\_completed | No | boolean | ||
5 | suggestion\_values | Yes | JSON | ||
6 | created\_at | No | timestamp | current\_datetime | |
7 | updated\_at | Yes | timestamp | ||
8 | completed\_at | Yes | timestamp | ||
9 | is\_overdue\_notified | Yes | boolean | false |
**pos** | **column** | **null** | **dtype** | **len** | **default** |
---|---|---|---|---|---|
1 | id | No | int | jobs\_id\_seq | |
2 | task\_id | No | character varying | ||
3 | user\_id | No | int | ||
4 | type | No | int | 5 | |
5 | status | No | int | 5 | |
6 | attempt | Yes | int | 5 | |
7 | result | No | JSON | ||
8 | info | Yes | character varying | 255 | |
9 | created\_at | No | timestamp | ||
10 | updated\_at | Yes | timestamp |
**Name** | **Value** | **Description** |
---|---|---|
start | YYYY-MM | Select start month |
end | YYYY-MM | Select end month |
compare | \[\] | Array of Map ID |
**Name** | **Value** | **Description** |
---|---|---|
format | enum( GeoTIFF, CSV, GeoJSON) | Export format (e.g., GeoTIFF, CSV, GeoJSON). |
**Name** | **Value** | **Description** |
---|---|---|
start | YYYY-MM | Select start month |
end | YYYY-MM | Select end month |
status | enum: 1 - Pending 2 - In Review 3 - In Validation 4 - Published | CDI Map Status |
The 3-month SPI reflects positive short and medium-term moisture conditions which has a positive impact on vegetation and surface temperature hence promoting vegetation growth and also lowering the the near-surface air temperature.
", "bulletin_url": "https://example.com/eswatini/cdi-2025-01.pdf", } ``` **Response: 200 OK** on success ```json { "id": 100, "cdi_geonode_id": 150, "year_month": "2025-01", "initial_values": [ { "administration_id": 339, "value": 0.68, "category": "D4" }, { "administration_id": 338, "value": 2, "category": "D3" }, ... { "administration_id": 330, "value": 30, "category": "D0" }, ], "validated_values": [ { "administration_id": 339, "value": 3, "category": "D3" }, { "administration_id": 338, "value": 2, "category": "D3" }, ... { "administration_id": 330, "value": 15, "category": "D1" }, ], "published_at": "2025-01-29 08:00:30TZ", "status": 4, "narrative": "The 3-month SPI reflects positive short and medium-term moisture conditions which has a positive impact on vegetation and surface temperature hence promoting vegetation growth and also lowering the the near-surface air temperature.
", "bulletin_url": "https://example.com/eswatini/cdi-2025-01.pdf", } ``` #### 4. Reviewer API ##### 4.1 Review List **Endpoint**: `GET /api/v1/reviewer/reviews` **JWT Access: Reviewer** **Request params:****Name** | **Value** | **Description** |
---|---|---|
start | YYYY-MM | Select start month |
end | YYYY-MM | Select end month |
status | enum: 1 - Pending 2 - In Review 3 - In Validation 4 - Published | CDI Map Status |
**API** | **Description** | **Documentation** |
Resources list | This API is used to retrieve CDI data details such as ID, preview, and download links. | [https://docs.geonode.org/en/master/devel/api/usage/index.html#resource-listing-and-details](https://docs.geonode.org/en/master/devel/api/usage/index.html#resource-listing-and-details) |
Resources filter | The purpose of this API is to specifically filter datasets and obtain CDI, NDVI, SPI, and SM datasets. | [https://docs.geonode.org/en/master/devel/api/usage/index.html#resource-searching-and-filtering](https://docs.geonode.org/en/master/devel/api/usage/index.html#resource-searching-and-filtering) |
Upload new resource | The purpose of this API is to upload the CDI script output after it has been successfully executed. | [https://docs.geonode.org/en/master/devel/api/usage/index.html#resource-upload](https://docs.geonode.org/en/master/devel/api/usage/index.html#resource-upload) |
Tracking upload progress | The purpose of this API is to monitor the progress of asynchronous uploads, ensuring data availability within GeoNode. | [https://docs.geonode.org/en/master/devel/api/usage/index.html#tracking-dataset-upload-progress](https://docs.geonode.org/en/master/devel/api/usage/index.html#tracking-dataset-upload-progress) |
Update Metadata | The purpose of this API is to **configure uploaded CDI datasets to be invisible in the public area**, ensuring that only authenticated users can access them | [https://docs.geonode.org/en/master/devel/api/usage/index.html#dataset-update-metadata](https://docs.geonode.org/en/master/devel/api/usage/index.html#dataset-update-metadata) |
Unfortunately, GeoNode **lacks an API for adding new categories**, so this process **cannot be automated** programmatically.
### How can I update the download URL when the dataset source has changed, been moved, or is no longer available? To change the **source URL of the datasets** used to download all necessary files as input for the CDI script, you'll need to update the **`.env` file**. This file is typically hidden from file managers but can be accessed via the terminal using editors like Vim or Nano. The `.env` file is located in the **root folder of the CDI Automation repository**. You can also refer to an example here: [https://github.com/akvo/eswatini-droughtmap-hub-cdi/blob/main/env.example](https://github.com/akvo/eswatini-droughtmap-hub-cdi/blob/main/env.example) Make sure to modify the variables with the `BASE_URL` suffix. This `BASE_URL` should be an **index link that ideally serves as a central hub for dataset links across all periods** (e.g., datasets from 2000 to 2025). Additionally, confirm that the new URL is **accessible and relevant to the variable**. For instance, if the NDVI dataset changes, you'd modify the `DOWNLOAD_NDVI_BASE_URL` variable. Failure to do so might prevent CDI Automation from correctly processing the CDI script. ### Where can I update the shapefile when the polygon has changed? Should you need to **change the current shapefile**, you can do so by **converting it to TopoJSON format**. This conversion is essential for **optimizing map data loaded onto the public web portal** and for processing it for various needs, such as **publication and exporting review results** into other formats available on Drought-map Hub. You can use tools like **[https://mapshaper.org](https://mapshaper.org)** to convert shapefiles to TopoJSON. It's also crucial to **pay attention to the features within the shapefile** to minimize the risk of significant changes. Ensure that the properties listed below are present. We've **highlighted in yellow** the properties that are expected to remain unchanged, as they will impact the **publication and review process of CDI Maps**.**region** | Hhohho |
**name** | Ntfonjeni |
**LAT** | 31.3217 |
**LONG\_1** | -25.8545 |
**INKHUNDLA** | NTFONJENI |
**administration\_id** | **2408937** |
**FID** | 8 |