diff --git a/content/tutorials/conda/conda-quickstart.qmd b/content/tutorials/conda/conda-quickstart.qmd new file mode 100644 index 0000000..b3a9c24 --- /dev/null +++ b/content/tutorials/conda/conda-quickstart.qmd @@ -0,0 +1,261 @@ +--- +title: "Getting started with GRASS for Conda" +author: Brendan Harmon +date: last-modified +license: CC BY-SA +categories: [Python, beginner] +description: > + Get started with GRASS for Conda. +image: images/natural-earth-01.webp +bibliography: conda.bib +csl: ../../../acm.csl +links: + grass_projects: "[projects](https://grass.osgeo.org/grass-devel/manuals/grass_projects.html)" + g_proj: "[g.proj](https://grass.osgeo.org/grass-stable/manuals/g.proj.html)" + d_rast: "[d.rast](https://grass.osgeo.org/grass-stable/manuals/d.rast.html)" + d_vect: "[d.vect](https://grass.osgeo.org/grass-stable/manuals/d.vect.html)" + v_colors: "[v.colors](https://grass.osgeo.org/grass-stable/manuals/v.colors.html)" + conda_create: "[conda create](https://docs.conda.io/projects/conda/en/stable/commands/create.html)" + conda_install: "[conda install](https://docs.conda.io/projects/conda/en/stable/commands/install.html)" + conda_activate: "[conda activate](https://docs.conda.io/projects/conda/en/stable/commands/activate.html)" +format: + ipynb: default + html: + toc: true + code-tools: true + code-copy: true +engine: jupyter +execute: + eval: false +jupyter: python3 +--- + +![Natural Earth](images/natural-earth-01.webp) + +This is a very short introduction to +the [GRASS Python package](https://grass.osgeo.org/download/conda/) +distributed via Conda. +With the GRASS Python package, +you can call GRASS tools +in Python scripts +or Jupyter notebooks. +This means that you can easily integrate GRASS +into data science workflows +using the Python scientific ecosystem. +This brief tutorial covers: + +* Installing the Conda package and environment manager +* Creating a GRASS environment with Conda +* Running GRASS in a Jupyter notebook + + + +## Manager + +Conda is an open source package and environment manager. +Many open source projects +use Conda to publish their software +as Python packages. +With Conda, you can easily install +collections of these packages +in isolated environments +to avoid conflicting software dependencies. +With Conda, packages are distributed via channels, +remote repositories that host packages. +The GRASS Python package is distributed via conda-forge, +a community smithy and repository +[@condaforge]. +There are several different distributions of Conda. +For this tutorial, +install [Miniforge](https://conda-forge.org/download/), +a minimal distribution of Conda +that uses conda-forge as its default channel +[@Miniforge]. +We recommend Miniforge +because it is the easiest, cleanest way to +install the GRASS Python Package. +Other distributions may be incompatible with conda-forge, +requiring proper +[configuration](https://conda-forge.org/docs/user/transitioning_from_defaults/) +to work. + +::: {.callout-note title="Unix"} +On Unix-like platforms - +including {{< fa brands linux >}} Linux, +{{< fa brands apple >}} MacOS, +and {{< fa brands microsoft >}}{{< fa brands linux >}} +Windows Subsystem for Linux - +download the installation shell script +and then run it in a terminal: +```{bash} +bash Miniforge3-$(uname)-$(uname -m).sh +``` +::: + +::: {.callout-note title="Windows"} +For {{< fa brands microsoft >}} Windows, +download and run the binary installer. +See [here](https://github.com/conda-forge/miniforge#install) +for more detailed instructions. +::: + +## Environment + +Now that Conda is installed, +let's use it to create an environment for GRASS. +We will install the GRASS and Jupyter Lab Python packages +and all of their dependencies into this environment. +In a terminal, +run {{< meta links.conda_create >}} +to create a GRASS environment named `grass`. +Then use {{< meta links.conda_install >}} +to install the GRASS package. +Next, run {{< meta links.conda_activate >}} +to start the environment. + +```{bash} +conda create --name grass +conda install grass jupyterlab +conda activate grass +``` + +You can do this with just one line of code: +```{bash} +conda create -n grass grass jupyterlab && conda activate grass +``` + +If you use a Conda distribution other than Miniforge, +you will need to specify the conda-forge channel +when creating the environment with +`-c conda-forge`. +You may also need to override your default channel settings +with `--override-channels` to prevent conflicts. + +## Notebook + +Let's try the GRASS Python package +in a Jupyter notebook. +We will using scripting to display maps +from a sample dataset. +We will download the dataset, +start a GRASS session in the dataset, +and then display raster and vector maps +from the dataset. +Let's begin by launching Jupyter Lab from the terminal. +This will open an new Jupyter notebook +in a web browser window. + +```{bash} +jupyter lab +``` + +### Start GRASS + +To start a GRASS session, +we need to define a project +and its coordinate reference system. +For this demonstration, +we will use the Natural Earth Dataset for GRASS [@NaturalEarth]. +This dataset is a GRASS project +with a collection of global raster and vector data +in the World Geodetic System 1984. +In your Jupyter notebook, +use Python to download and unarchive the dataset. +Then start a GRASS session using the dataset as a project. +Read more about {{< meta links.grass_projects >}} in GRASS here. +Since the dataset is approximately 120MB, +it may take a couple of minutes to download. +As a test that GRASS started correctly, +run {{< meta links.g_proj >}} with flag `g` +to print the current projection. + +```{python} +# Import libraries +import os +import sys +import subprocess +from pathlib import Path +import requests +from zipfile import ZipFile + +# Find GRASS Python packages +sys.path.append( + subprocess.check_output( + ["grass", "--config", "python_path"], + text=True + ).strip() + ) + +# Import GRASS packages +import grass.script as gs +import grass.jupyter as gj + +# Set GRASS database +gisdbase = Path.home() / "grassdata" + +# Download dataset +url = "https://zenodo.org/records/13370131/files/natural_earth_dataset.zip?download=1" +filepath = gisdbase / "natural_earth_dataset.zip" +request = requests.get(url, allow_redirects=True) +if request.status_code != 200: + raise ConnectionError(f"Error downloading file: {request.status_code}") +filepath.write_bytes(request.content) + +# Unarchive dataset +with ZipFile(filepath, 'r') as archive: + archive.extractall(gisdbase) + +# Delete archive +os.remove(filepath) + +# Start GRASS in project +session = gj.init(gisdbase / "natural_earth_dataset") + +# Print projection information +gs.run_command("g.proj", flags="g") +``` + +### Display raster map + +The Natural Earth raster is a global basemap +with land cover and shaded relief +rendered with a natural color scheme. +Display the Natural Earth raster map +with {{< meta links.d_rast >}}. + +```{python} +# Display natural earth raster +m = gj.Map(width=800) +m.d_rast(map="natural_earth") +m.show() +``` + +![Natural Earth](images/natural-earth-01.webp) + +### Display vector map + +Now display a vector map of global rivers. +First apply a thematic color gradient to the rivers +based on their stream order +with {{< meta links.v_colors >}}. +Then display the map with +{{< meta links.d_vect >}}, +scaling the line width by stream order. + +```{python} +# Display rivers +m = gj.Map(width=800) +gs.run_command("v.colors", map="rivers", use="attr", column="scalerank", color="water") +m.d_vect(map="rivers", width_column="strokeweig", width_scale=2) +m.show() +``` + +![Rivers](images/natural-earth-02.webp) \ No newline at end of file diff --git a/content/tutorials/conda/conda.bib b/content/tutorials/conda/conda.bib new file mode 100644 index 0000000..9b80628 --- /dev/null +++ b/content/tutorials/conda/conda.bib @@ -0,0 +1,31 @@ +@misc{condaforge, +author = {{conda-forge community}}, +title = {{The conda-forge Project:} Community-based Software + Distribution Built on the conda Package Format and + Ecosystem + }, +month = {7}, +year = {2015}, +publisher = {Zenodo}, +doi = {10.5281/zenodo.4774217}, +url = {https://conda-forge.org/}, +} + +@software{Miniforge, +title = {Miniforge}, +author = {{conda-forge community}}, +year = {2026}, +license = {BSD 3-Clause License}, +url = {https://conda-forge.org/download/}, +version = {26.3.2-0}, +repository= {https://github.com/conda-forge/miniforge} +} + +@dataset{NaturalEarth, +author = {Harmon, Brendan and van Breugel, Paulo}, +title = {Natural Earth Dataset for GRASS GIS}, +year = 2020, +publisher = {Zenodo}, +version = {2.0.0}, +doi = {10.5281/zenodo.3762773} +} \ No newline at end of file diff --git a/content/tutorials/conda/images/natural-earth-01.webp b/content/tutorials/conda/images/natural-earth-01.webp new file mode 100644 index 0000000..bc58c7a Binary files /dev/null and b/content/tutorials/conda/images/natural-earth-01.webp differ diff --git a/content/tutorials/conda/images/natural-earth-02.webp b/content/tutorials/conda/images/natural-earth-02.webp new file mode 100644 index 0000000..486c2ac Binary files /dev/null and b/content/tutorials/conda/images/natural-earth-02.webp differ