Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 22 additions & 12 deletions reports/annual_category_location_heatmap.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "28ca77da",
"metadata": {},
"source": [
"# Nature Recorder Heatmap\n",
"# Category-Location Annual Heatmap\n",
"\n",
"This notebook generates and exports a heatmap of species sightings for a category for a given location and year. To use it, update the year, location, category and required export format in the first code cell, below, before running the notebook."
]
Expand All @@ -21,7 +21,7 @@
"year = \"\"\n",
"\n",
"# Name of the location to report on\n",
"location = \"\"\n",
"locations = [\"\"]\n",
"\n",
"# Species category to report on\n",
"category = \"\"\n",
Expand All @@ -30,7 +30,7 @@
"# PNG - export as PNG image\n",
"# PDF - export as PDF file\n",
"# <blank> - do not export\n",
"export_format = \"\""
"export_format = \"PNG\""
]
},
{
Expand All @@ -41,17 +41,24 @@
"outputs": [],
"source": [
"from pathlib import Path\n",
"import sqlparse\n",
"\n",
"# Read the query file\n",
"query_file_path = Path(\"sql\") / \"sightings.sql\"\n",
"with open(query_file_path.absolute(), \"r\") as f:\n",
" query = f.read().replace(\"\\n\", \" \")\n",
"\n",
"# Generate a list of locations suitable for use in the IN clause in the query\n",
"location_list = \", \".join([f\"'{l}'\" for l in locations])\n",
"\n",
"# Replace the location and year placeholders\n",
"query = query.replace(\"$YEAR\", year) \\\n",
" .replace(\"$LOCATION\", location) \\\n",
" .replace(\"$LOCATION\", location_list) \\\n",
" .replace(\"$CATEGORY\", category) \\\n",
" .replace(\"$SPECIES\", \"\")"
" .replace(\"$SPECIES\", \"\")\n",
"\n",
"# Show a pretty-printed form of the query\n",
"print(sqlparse.format(query, reindent=True, keyword_case='upper'))"
]
},
{
Expand All @@ -72,7 +79,8 @@
"\n",
"# Check there is some data\n",
"if not df.shape[0]:\n",
" message = f\"No data found for category '{category}' at location '{location}' during '{year}'\"\n",
" locations_list = \", \".join(locations)\n",
" message = f\"No data found for category '{category}' at locations '{locations_list}' during '{year}'\"\n",
" raise ValueError(message)"
]
},
Expand Down Expand Up @@ -106,8 +114,9 @@
"heatmap_data.columns = [calendar.month_abbr[m] for m in heatmap_data.columns]\n",
"\n",
"# Export the heatmap data to Excel\n",
"clean_location = re.sub(\"[^0-9a-zA-Z\\-]+\", \"\", location.replace(\" \", \"-\"))\n",
"export_file_path = export_folder_path / f\"{year}-{category}-{clean_location}-Heatmap.xlsx\"\n",
"locations_list = \"-\".join(locations).replace(\" \", \"-\")\n",
"clean_locations = re.sub(\"[^0-9a-zA-Z\\-]+\", \"\", locations_list)\n",
"export_file_path = export_folder_path / f\"{year}-{category}-{clean_locations}-Heatmap.xlsx\"\n",
"heatmap_data.to_excel(export_file_path.absolute(), sheet_name=\"Sightings\")\n",
"\n",
"# Print the heatmap data\n",
Expand All @@ -131,18 +140,19 @@
"# Generate the heatmap\n",
"plt.figure(figsize=(12, heatmap_data.shape[0] / 3))\n",
"sns.heatmap(heatmap_data, cmap=\"YlOrRd\", annot=False)\n",
"plt.title(f\"Number of Sightings of {category} at {location} in {year}\")\n",
"locations_list = \", \".join(locations)\n",
"plt.title(f\"Number of Sightings of {category} at {locations_list} in {year}\")\n",
"plt.xlabel(\"\")\n",
"plt.ylabel(\"\")\n",
"\n",
"# Export to PNG\n",
"if export_format.casefold() == \"png\":\n",
" export_file_path = export_folder_path / f\"{year}-{category}-{clean_location}-Heatmap.png\"\n",
" export_file_path = export_folder_path / f\"{year}-{category}-{clean_locations}-Heatmap.png\"\n",
" plt.savefig(export_file_path.absolute(), format=\"png\", dpi=300, bbox_inches=\"tight\")\n",
"\n",
"# Export to PDF\n",
"if export_format.casefold() == \"pdf\":\n",
" export_file_path = export_folder_path / f\"{year}-{category}-{clean_location}-Heatmap.pdf\"\n",
" export_file_path = export_folder_path / f\"{year}-{category}-{clean_locations}-Heatmap.pdf\"\n",
" plt.savefig(export_file_path.absolute(), format=\"pdf\", bbox_inches=\"tight\")\n",
"\n",
"# And show the plot\n",
Expand All @@ -152,7 +162,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "venv",
"language": "python",
"name": "python3"
},
Expand Down
1 change: 1 addition & 0 deletions reports/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Send2Trash==1.8.3
six==1.17.0
sniffio==1.3.1
soupsieve==2.6
sqlparse==0.5.3
stack-data==0.6.3
terminado==0.18.1
tinycss2==1.4.0
Expand Down
2 changes: 1 addition & 1 deletion reports/sql/sightings.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM SIGHTINGS s
INNER JOIN SPECIES sp ON sp.Id = s.SpeciesId
INNER JOIN CATEGORIES c ON c.Id = sp.CategoryId
INNER JOIN LOCATIONS l ON l.Id = s.LocationId
WHERE l.Name = '$LOCATION'
WHERE l.Name IN ( $LOCATION )
AND s.Date LIKE '$YEAR-%'
AND sp.Name LIKE '%$SPECIES%'
AND c.Name = "$CATEGORY";