{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Functions in Python\n", "\n", "\n", "\n", "Functions are a fundamental building block in Python programming, allowing you to organize your code into reusable, logical blocks. Whether you're writing simple scripts or complex applications, functions help make your code cleaner, more modular, and easier to maintain. Once a function is defined, you can call it whenever you need it, avoiding repetitive code. Functions can accept inputs (parameters), perform operations, and return outputs.\n", "\n", "By using functions, we can:\n", "\n", "- Avoid repetitive code\n", "- Break complex tasks into smaller, manageable pieces\n", "- Improve readability and maintainability of your code\n", "\n", "## Defining and Calling Functions\n", "\n", "In Python, you define a function using the `def` keyword followed by the function name and parentheses `( )`. Inside the parentheses, you can define optional parameters." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "def greet():\n", "\n", " \"\"\"This is a simple function that prints a greeting.\"\"\"\n", " print(\"Hello, welcome to the Geospatial Analysis in Python!\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To execute the code inside a function, you simply call it by its name followed by parentheses." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, welcome to the Geospatial Analysis in Python!\n" ] } ], "source": [ "# Call the function\n", "greet()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions with Parameters\n", "\n", "Functions can accept inputs called parameters. Parameters allow you to pass data to the function." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Modric! Welcome to the Geospatial Analysis in Python!\n" ] } ], "source": [ "def greet_user(name):\n", "\n", " \"\"\"This function greets the user by their name.\"\"\"\n", " print(f\"Hello, {name}! Welcome to the Geospatial Analysis in Python!\")\n", " \n", "# Call the function with an argument\n", "greet_user(\"Modric\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions with Return Values\n", "\n", "Sometimes, you want a function to compute and return a result." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The sum is: 13\n" ] } ], "source": [ "def add_numbers(a, b):\n", " \"\"\"This function returns the sum of two numbers.\"\"\"\n", " return a + b\n", "\n", "# Call the function and store the result\n", "result = add_numbers(4, 9)\n", "print(f\"The sum is: {result}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Default Parameters**\n", "\n", "You can set default values for parameters. If no value is provided when calling the function, the default is used." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, Luka!\n", "Hello, Guest!\n" ] } ], "source": [ "def greet(name=\"Guest\"):\n", " \"\"\"This function greets the user, with a default name of 'Guest'.\"\"\"\n", " print(f\"Hello, {name}!\")\n", "\n", "# Call with and without an argument\n", "greet(\"Luka\")\n", "greet()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Keyword Arguments**\n", "\n", "Python allows you to call functions using keyword arguments, which makes your code more readable." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "I love R and enjoy scripting with RStudio.\n", "I love Python and enjoy scripting with VS Code.\n", "I love JavaScript and enjoy scripting with Jupyter Notebook.\n" ] } ], "source": [ "def favorite_IDE(programming, IDE=\"RStudio\"):\n", " \"\"\"This function describes your favorite programming language and IDE.\"\"\"\n", " print(f\"I love {programming} and enjoy scripting with {IDE}.\")\n", "\n", "# Call with positional and keyword arguments\n", "favorite_IDE(\"R\")\n", "favorite_IDE(programming=\"Python\", IDE=\"VS Code\")\n", "favorite_IDE(programming=\"JavaScript\", IDE=\"Jupyter Notebook\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Variables**\n", "\n", "Variables defined inside a function are local to that function and cannot be accessed outside it." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Inside function: 10\n" ] } ], "source": [ "def demo_function():\n", " local_var = 10 # This variable exists only inside the function\n", " print(f\"Inside function: {local_var}\")\n", "\n", "demo_function()\n", "# print(local_var) # This will raise an error because local_var is not defined outside" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Anonymous Functions**\n", "\n", "Anonymous Functions also referred to as Lambda functions are one-liner functions defined using the `lambda` keyword. They are often used for short, simple operations." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "228\n" ] } ], "source": [ "# A simple lambda function to multiply two numbers\n", "multiply = lambda x, y: x * y\n", "\n", "print(multiply(12, 19))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Downloading Geospatial Data\n", "\n", "Downloading geospatial data is a common step in geospatial analysis workflows. Python provides efficient libraries such as `requests` for downloading files from the web, enabling users to automate data acquisition. For instance, you can fetch GeoPackage or GeoTIFF files from online repositories like GADM or ESA. Once downloaded, these datasets can be used for various spatial analyses and visualizations. By writing a script to handle downloads, you ensure consistency, reproducibility, and quick access to the required data. Python’s flexibility also allows users to integrate data downloading with preprocessing workflows for seamless geospatial project management." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "File downloaded successfully and saved to data/downloads/gadm41_SMR.gpkg\n" ] } ], "source": [ "import requests\n", "\n", "# URL of the GADM data of San Marino\n", "url = \"https://geodata.ucdavis.edu/gadm/gadm4.1/gpkg/gadm41_SMR.gpkg\"\n", "\n", "# Destination path to save the file\n", "destfile = \"data/downloads/gadm41_SMR.gpkg\"\n", "\n", "# Download the file\n", "response = requests.get(url)\n", "\n", "# Check if the request was successful\n", "if response.status_code == 200:\n", " # Write the content to a file\n", " with open(destfile, 'wb') as file:\n", " file.write(response.content)\n", " print(f\"File downloaded successfully and saved to {destfile}\")\n", "else:\n", " print(f\"Failed to download file. Status code: {response.status_code}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Automating Data Download\n", "\n", "To simplify the process, we can wrap this functionality into a custom function that takes a URL and destination path as arguments. This can be particularly useful when managing multiple datasets." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download one file at a time\n", "\n", "In this subsection, we will create a function to download country-specific GeoPackage data from the GADM website." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "def get_gadm(iso3=None, path=None):\n", "\n", " if not iso3 or not path:\n", " raise ValueError(\"Both 'iso3' and 'path' parameters must be provided.\")\n", " \n", " # Construct the URL of the GADM data\n", " url = f\"https://geodata.ucdavis.edu/gadm/gadm4.1/gpkg/gadm41_{iso3}.gpkg\"\n", "\n", " # Destination path to save the file\n", " destfile = os.path.join(path, f\"{iso3}.gpkg\")\n", "\n", " # Download the file\n", " response = requests.get(url)\n", "\n", " if response.status_code == 200:\n", " with open(destfile, 'wb') as file:\n", " file.write(response.content)\n", " print(\"Download process completed successfully.\")\n", " else:\n", " print(f\"Failed to download file. HTTP status code: {response.status_code}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parameters:\n", "- `iso3`: str, ISO3 country code (e.g., \"SMR\" for San Marino).\n", "- `path`: str, Directory path where the file will be saved.\n", "\n", "Returns:\n", "- None, but saves the downloaded file to the specified location." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Download process completed successfully.\n" ] } ], "source": [ "# Example 1: Luxembourg\n", "iso3 = \"LUX\"\n", "path = \"data/downloads/\"\n", "get_gadm(iso3, path)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Download process completed successfully.\n" ] } ], "source": [ "# Example 2: Cyprus\n", "get_gadm(iso3 = \"CYP\", path = \"data/downloads/\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download multiple files simultaneously\n", "\n", "In this subsection, we will create a function to download GADM data for multiple countries simultaneously." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "def gadm_downloader(iso3_list=None, path=None):\n", "\n", " if not iso3_list or not path:\n", " raise ValueError(\"Both 'iso3_list' and 'path' parameters must be provided.\")\n", " \n", " for iso3 in iso3_list:\n", " # Construct the URL\n", " url = f\"https://geodata.ucdavis.edu/gadm/gadm4.1/gpkg/gadm41_{iso3}.gpkg\"\n", "\n", " # Destination path to save the file\n", " destfile = os.path.join(path, f\"{iso3}.gpkg\")\n", "\n", " print(f\"Downloading GADM data for country: {iso3}...\")\n", "\n", " try:\n", " # Download the file\n", " response = requests.get(url)\n", "\n", " # Check if the download was successful\n", " if response.status_code == 200:\n", " with open(destfile, 'wb') as file:\n", " file.write(response.content)\n", " print(f\"File for {iso3} downloaded successfully.\")\n", " else:\n", " print(f\"Failed to download file for {iso3}. HTTP status code: {response.status_code}\")\n", "\n", " except Exception as e:\n", " print(f\"An error occurred while downloading file for {iso3}: {e}\")\n", "\n", " print(\"Download process completed.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Key features:\n", "\n", "- Looping through ISO3 codes\n", "- Error Handling with `try-except`\n", "- Dynamic File Naming\n", "- Feedback messages" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Downloading GADM data for country: LUX...\n", "File for LUX downloaded successfully.\n", "Downloading GADM data for country: SMR...\n", "File for SMR downloaded successfully.\n", "Downloading GADM data for country: CYP...\n", "File for CYP downloaded successfully.\n", "Download process completed.\n" ] } ], "source": [ "# Example 3: Cyprus, San Marino, Luxembourg\n", "\n", "gadm_downloader(iso3_list=[\"LUX\", \"SMR\", \"CYP\"],\n", " path=\"data/downloads\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Advantages of Automating Downloads:\n", "\n", "- **Efficiency**: Automates the tedious process of manually downloading files.\n", "- **Reproducibility**: Ensures that analyses can be reproduced with the same datasets.\n", "- **Scalability**: Handles multiple datasets with ease, particularly useful in batch processing.\n", "\n", "By leveraging these techniques, we can integrate data acquisition seamlessly into our Python scripts, ensuring an efficient and organized workflow for geospatial projects." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Computation Functions\n", "\n", "In this section, we will create a function that computes zonal statistics based on the provided Area of Interest (AOI) and raster data. The `compute_zonal_statistics` function calculates zonal statistics for a given raster (spatial dataset) within a defined Area of Interest (AOI)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import geopandas as gpd\n", "import rasterio\n", "import rasterstats\n", "import pandas as pd\n", "\n", "def compute_zonal_statistics(aoi_path, raster_path, stats=[\"mean\", \"sum\"]):\n", "\n", " # Load the AOI polygons\n", " aoi = gpd.read_file(aoi_path)\n", "\n", " # Open the raster file\n", " with rasterio.open(raster_path) as src:\n", "\n", " # Compute zonal statistics using rasterstats\n", " try:\n", " zonal_stats = rasterstats.zonal_stats(\n", " aoi,\n", " raster_path,\n", " stats=stats,\n", " geojson_out=True,\n", " nodata=None # you can set nodata value here if needed\n", " )\n", " except Exception as e:\n", " raise RuntimeError(f\"Error during zonal statistics calculation: {e}\")\n", " \n", " # Convert the results to a GeoDataFrame\n", " results_gdf = gpd.GeoDataFrame.from_features(zonal_stats)\n", "\n", " # Return only the AOI attributes and statistics as a DataFrame\n", " stats_column = [col for col in results_gdf.columns if col in stats]\n", " output_df = results_gdf[aoi.columns.tolist() + stats_column]\n", "\n", " return output_df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parameters:\n", "\n", "- `aoi_path`: str, Path to the shapefile or GeoPackage containing the AOI polygons.\n", "- `raster_path`: str, Path to the raster file.\n", "- `stats`: list of str, Statistics to calculate (e.g., [\"mean\", \"sum\", \"min\", \"max\"]).\n", "\n", "Returns:\n", "\n", "- `pandas.DataFrame` containing the AOI attributes and computed statistics." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " NAME sum mean\n", "0 BaisiBichawa 37900.042969 3.872093\n", "1 Beldandi 46565.355469 14.149303\n", "2 Chandani 72813.015625 17.694536\n", "3 Daijee 49223.929688 3.624737\n", "4 Dekhatbhuli 52221.738281 4.353989\n", "5 Dodhara 64436.566406 20.553929\n", "6 Jhalari 40823.878906 2.517972\n", "7 Kalika 97216.468750 28.830507\n", "8 Krishnapur 36368.550781 1.653792\n", "9 Laxmipur 277108.937500 72.295575\n", "10 MahendranagarN.P. 51835.031250 2.278062\n", "11 Parasan 38199.867188 7.639973\n", "12 Pipaladi 46773.808594 8.258088\n", "13 RaikawarBichawa 44571.746094 4.150456\n", "14 RampurBilaspur 48838.773438 9.415611\n", "15 RauteliBichawa 11581.357422 2.904052\n", "16 Royal Shuklaphanta 131.641449 0.002766\n", "17 Shankarpur 19211.746094 4.094575\n", "18 Sreepur 56755.710938 7.707185\n", "19 Suda 58257.640625 7.586618\n", "20 Tribhuwanbasti 37573.945312 14.512918\n" ] } ], "source": [ "# Example usage:\n", "\n", "aoi_path = \"data/vector/kanchanpur.gpkg\"\n", "raster_path = \"data/raster/popCount_2020.tif\"\n", "\n", "zonal_stats_df = compute_zonal_statistics(aoi_path, raster_path, stats=[\"sum\", \"mean\"])\n", "print(zonal_stats_df[[\"NAME\", \"sum\", \"mean\"]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Key Features:\n", "\n", "- Flexible Statistics \n", "- Nodata Handling\n", "- Output Format\n", "- Error Handling\n", "\n", "This function is scalable for multiple AOIs and different raster datasets." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In conclusion, mastering functions in Python is essential for writing efficient, reusable, and organized code. Functions enable you to simplify complex tasks, eliminate redundancy, and improve the readability and maintainability of your scripts. By understanding how to define and use functions, you can perform a wide range of data manipulation, statistical analysis, and visualization tasks more effectively. With the ability to build custom functions and utilize Python's extensive library of built-in functions, you can significantly enhance your data analysis workflow, making your code more modular and adaptable to various challenges. Functions are a powerful tool that, once mastered, will elevate your Python programming skills to the next level.\n", "\n", "**For this tutorial, this concludes the coverage of functions in Python. If you would like to explore additional functions, examples, or need clarification on any of the steps covered, please visit the GitHub repository: [Python_tutorial](https://github.com/Ohm-Np/Python_tutorial) and feel free to open an issue.**" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.13" } }, "nbformat": 4, "nbformat_minor": 2 }