Repository: r5py/r5py (language: python)

Issue:
`r5py.sampledata` namespace with `r5py.sampledata.sao_paulo` and `r5py.sampledata.helsinki` sub-packages
For the sake of clarity in the documentation, and for making data retrieval in workshops easier, we should create sub-packages that contain the sample data (or, rather, download them on the fly on first use, both PyPi and conda have limitations when it comes to package size)

Also see discussion between @HTenkanen and me on our slack


Discussion / hints:
relates to #345 
I’m thinking whether we should implement this right away, as it’s probably not so much more work than compiling a downloadable zip file
@christophfink I think it would be great, if we manage to do this right away! 👍🏻 I guess you had a good idea how to do this? 
Yes, I have it in my head, but won’t be able to put it into code until earliest tomorrow (but I guess the other issues for v0.1.1 need a bit of work, too)

Fix patch:
diff --git a/.gitignore b/.gitignore
index d1b98859..eedd2b79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,8 +30,10 @@ docs/data/*.mapdb
 docs/data/*.mapdb.p
 **/.ipynb_checkpoints
 docs/jupyter_execute/
+docs/user-guide/user-manual/travel_times_to_helsinki_railway_station.csv
+docs/user-guide/user-manual/detailed_itineraries.gpkg
 
 .tox
 .coverage
 coverage.xml
-.vscode/*
\ No newline at end of file
+.vscode/*
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 38d97198..4a4a9fe6 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -9,7 +9,10 @@ build:
 
 python:
     install:
-        - requirements: docs/requirements.txt
+        - method: pip
+          path: .
+          extra_requirements: 
+            - docs
 
 sphinx:
     configuration: docs/conf.py
diff --git a/ci/python_310_dev.yaml b/ci/python_310_dev.yaml
deleted file mode 100644
index dd672009..00000000
--- a/ci/python_310_dev.yaml
+++ /dev/null
@@ -1,48 +0,0 @@
-name: r5py
-
-channels:
-    - conda-forge
-
-dependencies:
-    - python=3.10
-    - configargparse
-    - filelock
-    - fiona
-    - geopandas
-    - importlib_resources
-    - joblib
-    - jpype1
-    - numpy
-    - pandas
-    - pyproj
-    - psutil
-    - requests
-
-    # testing / dev / docs related
-    - black
-    - black-jupyter
-    - codecov
-    - folium
-    - gitpython
-    - jupyterlab
-    - jupyterlab-myst
-    - jupytext[myst]
-    - mapclassify
-    - matplotlib
-    - myst-nb
-    - nbsphinx
-    - nbstripout
-    - openjdk
-    - pytest
-    - pytest-asyncio
-    - pytest-cov
-    - pytest-lazy-fixture
-    - shapely
-    - sphinx
-    - sphinx-book-theme
-    - sphinx-design
-
-    - pip
-    - pip:
-        - pybtex-apa7-style
-        - sphinxcontrib-images
diff --git a/ci/python_311_dev.yaml b/ci/python_311_dev.yaml
index 966ce102..37197dcc 100644
--- a/ci/python_311_dev.yaml
+++ b/ci/python_311_dev.yaml
@@ -37,6 +37,8 @@ dependencies:
     - pytest-asyncio
     - pytest-cov
     - pytest-lazy-fixture
+    - r5py.sampledata.helsinki>=0.1.1dev2
+    - r5py.sampledata.sao_paulo>=0.1.1dev2
     - shapely
     - sphinx
     - sphinx-book-theme
diff --git a/docs/_static/data/Helsinki/GTFS.zip b/docs/_static/data/Helsinki/GTFS.zip
deleted file mode 100644
index 330afa60..00000000
Binary files a/docs/_static/data/Helsinki/GTFS.zip and /dev/null differ
diff --git a/docs/_static/data/Helsinki/kantakaupunki.osm.pbf b/docs/_static/data/Helsinki/kantakaupunki.osm.pbf
deleted file mode 100644
index 52b76fee..00000000
Binary files a/docs/_static/data/Helsinki/kantakaupunki.osm.pbf and /dev/null differ
diff --git a/docs/_static/data/Helsinki/population_grid_2020.gpkg b/docs/_static/data/Helsinki/population_grid_2020.gpkg
deleted file mode 100644
index 21ae1ca2..00000000
Binary files a/docs/_static/data/Helsinki/population_grid_2020.gpkg and /dev/null differ
diff --git a/docs/_static/data/Helsinki/scripts/download_population_grid.py b/docs/_static/data/Helsinki/scripts/download_population_grid.py
deleted file mode 100755
index 00a912b7..00000000
--- a/docs/_static/data/Helsinki/scripts/download_population_grid.py
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env python3
-
-"""Download a population grid data set from HSY’s WFS service."""
-
-import geopandas
-import pathlib
-
-
-def main():
-    """Download a population grid data set from HSY’s WFS service."""
-    # Where to save the downloaded data sets? One directory up from this script
-    OUTPUT_DIRECTORY = pathlib.Path().absolute().parent
-
-    # Download vector data set for the specified bounding box
-    # in the upstream native reference system ETRS GK-25 (EPSG:3879),
-    # then reproject it to WGS-84 (EPSG:4326)
-    df = (
-        geopandas.read_file(
-            "https://kartta.hsy.fi/geoserver/wfs"
-            "?service=wfs"
-            "&version=2.0.0"
-            "&request=GetFeature"
-            "&typeName=asuminen_ja_maankaytto:Vaestotietoruudukko_2020"
-            "&srsName=EPSG:3879"
-            "&bbox=25494767,6671328,25497720,6673701,EPSG:3879"
-        )
-        .set_crs("EPSG:3879")
-        .to_crs("EPSG:4326")
-    )
-
-    # discard most columns (detailed data), and add a sequential index column
-    df = df[["asukkaita", "geometry"]].reset_index()
-
-    # rename columns from Finnish to English, also `index` to `id`
-    df = df.rename(columns={"index": "id", "asukkaita": "population"})
-
-    # save the resulting data to a file
-    df.to_file(OUTPUT_DIRECTORY / "population_grid_2020.gpkg")
-
-    # derive a data set containing centroid points instead of grid cell polygons
-    df.geometry = df.geometry.centroid
-    # and save the resulting data to another file
-    df.to_file(OUTPUT_DIRECTORY / "population_points_2020.gpkg")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/docs/_static/data/README.md b/docs/_static/data/README.md
deleted file mode 100644
index ce1e5e0e..00000000
--- a/docs/_static/data/README.md
+++ /dev/null
@@ -1,71 +0,0 @@
-# Data
-
-Details about the bundled datasets.
-
-
-## Helsinki
-
-### `GTFS.zip`
-
-General Transit Feed Specification ([GTFS](https://developers.google.com/transit/gtfs/reference))
-data representing the public transport schedules, stop locations, lines, etc.
-The data was created by Helsinki Region Transport (HLS) and obtained from
-[TransitFeeds.com](https://transitfeeds.com/p/helsinki-regional-transport/735).
-
-This GTFS data set is licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
-
-
-### `kantakaupunki.osm.pbf`
-
-A sample dataset representing OpenStreetMap data in protocolbuffer binary format (PBF),
-which was obtained from [Geofabrik](https://download.geofabrik.de/europe/finland.html).
-The data is licensed under the [Open Data Commons Open Database License (ODbL)](https://www.openstreetmap.org/copyright).
-
-We used [osmium](https://osmcode.org/osmium-tool/) to crop the data to the given extent.
-
-
-### `population_points_2020.gpkg`, `population_grid_2020.gpkg`
-
-A sample dataset representing the population of Helsinki.
-The data is obtained from Helsinki Region Environmental Services (HSY).
-The data is licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
-
-The data is downloaded from the Helsinki Region Environmental Services’ (HSY)
-*Web Feature Service (WFS)* endpoint (see the
-[Helsinki Region Infoshare’s data description](https://hri.fi/data/en_GB/dataset/vaestotietoruudukko)).
-We used [a script](scripts/download_population_grid.py), that we share with this package, to download
-the data set and adapt it to the requirements of r5py’s documentation. Namely, we:
-
-- reindexed the data,
-- omitted some columns,
-- renamed the remaining columns from Finnish to English
-- reprojected the data to "EPSG:4326", and
-- extracted centroids from the grid polygons (for the point data set)
-
-
-## São Paulo
-
-### `spo_gtfs.zip`
-
-General Transit Feed Specification ([GTFS](https://developers.google.com/transit/gtfs/reference))
-data representing the public transport schedules, stop locations, lines, etc.
-
-In contrast to the GTFS data set for Helsinki, the São Paulo data also has schedules expressed
-in frequencies rather than fixed departure times.
-
-[This data set has been published by São Paulo Transporte S/A, the public transport company of the
-city of São Paulo for open use, but without a specific license specified.](https://www.sptrans.com.br/desenvolvedores)
-
-
-### `spo_osm.pbf`
-
-A sample dataset representing OpenStreetMap data in protocolbuffer binary format (PBF),
-which was obtained from [Geofabrik](https://download.geofabrik.de/europe/finland.html).
-The data is licensed under the [Open Data Commons Open Database License (ODbL)](https://www.openstreetmap.org/copyright).
-
-
-### `spo_hexgrid.csv`
-
-A regular, hexagonally distributed, point grid data set over the extent of São Paulo, created by
-the authors of [r5r](https://github.com/ipeaGIT/r5r/tree/master/r-package/inst/extdata/spo). This data
-set is used in some of the tests.
diff --git "a/docs/_static/data/S\303\243o Paulo/spo_gtfs.zip" "b/docs/_static/data/S\303\243o Paulo/spo_gtfs.zip"
deleted file mode 100644
index cd5e22fd..00000000
Binary files "a/docs/_static/data/S\303\243o Paulo/spo_gtfs.zip" and /dev/null differ
diff --git "a/docs/_static/data/S\303\243o Paulo/spo_hexgrid.csv" "b/docs/_static/data/S\303\243o Paulo/spo_hexgrid.csv"
deleted file mode 100644
index 0a6e5c0a..00000000
diff --git "a/docs/_static/data/S\303\243o Paulo/spo_hexgrid.csv" "b/docs/_static/data/S\303\243o Paulo/spo_hexgrid.csv"
deleted file mode 100644
index 0a6e5c0a..00000000
--- "a/docs/_static/data/S\303\243o Paulo/spo_hexgrid.csv"
+++ /dev/null
@@ -1,324 +0,0 @@
-"id","lon","lat","population","jobs","schools"
-"89a8100c603ffff",-46.6079746773408,-23.5710980272876,1146,1155,0
-"89a8100c617ffff",-46.6110766030175,-23.5724900009772,700,463,1
-"89a8100c60fffff",-46.607884390391,-23.5680319362552,377,257,0
-"89a8100c607ffff",-46.6109863014463,-23.5694239761506,743,687,0
-"89a8100c6abffff",-46.6140882002316,-23.5708159194855,601,29,0
-"89a8100c6a3ffff",-46.6171900867289,-23.5722077662522,1097,338,1
-"89a8100c677ffff",-46.6077941043028,-23.5649657312752,29,2701,0
-"89a8100c63bffff",-46.6108960007368,-23.5663578373717,774,195,0
-"89a8100c633ffff",-46.6139978849014,-23.567749846916,674,473,0
-"89a8100c6afffff",-46.6170997567787,-23.5691417599002,300,63,0
-"89a8100c6a7ffff",-46.6202016163505,-23.5705335763164,2389,312,0
-"89a8100c46bffff",-46.6233034635987,-23.5719252961567,1206,800,0
-"89a8100c667ffff",-46.6077038190762,-23.5618994123588,6,0,0
-"89a8100c62bffff",-46.6108057008889,-23.5632915846519,3,439,0
-"89a8100c623ffff",-46.6139075704331,-23.564683660401,124,604,1
-"89a8100c637ffff",-46.6170094276904,-23.5660756395982,1140,547,0
-"89a8100c0dbffff",-46.620111272643,-23.5674675222356,1052,281,0
-"89a8100c0d3ffff",-46.6232131052726,-23.5688593083052,1240,377,2
-"89a8100c46fffff",-46.6263149255612,-23.5702509977993,3954,342,0
-"89a8100c467ffff",-46.6294167334906,-23.5716425907097,973,444,0
-"89a8100c29bffff",-46.6076135347111,-23.5588329795171,10,225,0
-"89a8100c293ffff",-46.6107154019028,-23.5602252180022,0,367,0
-"89a8100c62fffff",-46.6138172568265,-23.5616173599516,123,691,0
-"89a8100c627ffff",-46.6169190994641,-23.5630094053573,1096,816,0
-"89a8100c0cbffff",-46.6200209297975,-23.5644013542114,2103,1024,0
-"89a8100c0c3ffff",-46.6231227478087,-23.5657932065059,1576,2173,0
-"89a8100c0d7ffff",-46.6262245534794,-23.5671849622329,1792,647,0
-"89a8100c09bffff",-46.6293263467916,-23.5685766213846,2542,248,0
-"89a8100c093ffff",-46.6324281277272,-23.5699681839531,2533,1001,0
-"89a8100c42fffff",-46.6355298962681,-23.5713596499304,2033,502,0
-"89a8100c28bffff",-46.6075232512075,-23.5557664327614,706,763,0
-"89a8100c283ffff",-46.6106251037782,-23.5571587374341,159,1279,0
-"89a8100c297ffff",-46.6137269440816,-23.5585509455792,526,243,0
-"89a8100c05bffff",-46.6168287720996,-23.5599430571888,440,998,0
-"89a8100c053ffff",-46.6199305878141,-23.561335072255,1425,712,0
-"89a8100c0cfffff",-46.6230323912068,-23.5627269907698,1561,301,0
-"89a8100c0c7ffff",-46.6261341822599,-23.5641188127254,1782,237,0
-"89a8100c08bffff",-46.629235960955,-23.5655105381138,2515,292,1
-"89a8100c083ffff",-46.6323377272742,-23.5669021669271,3897,497,0
-"89a8100c097ffff",-46.6354394811993,-23.5682936991575,4562,2223,0
-"89a8100c55bffff",-46.6385412227123,-23.569685134797,2781,3016,0
-"89a8100c553ffff",-46.6416429517949,-23.5710764738377,1258,1395,0
-"89a8100c213ffff",-46.6074329685654,-23.5526997721031,370,444,0
-"89a8100c28fffff",-46.6105348065153,-23.5540921429587,244,196,0
-"89a8100c287ffff",-46.6136366321986,-23.555484417295,1102,326,1
-"89a8100c04bffff",-46.616738445597,-23.5568765951039,747,542,0
-"89a8100c043ffff",-46.6198402466926,-23.5582686763777,2113,277,0
-"89a8100c057ffff",-46.6229420354671,-23.5596606611083,3086,795,0
-"89a8100c01bffff",-46.6260438119026,-23.5610525492879,1405,290,0
-"89a8100c013ffff",-46.6291455759808,-23.5624443409084,2611,304,0
-"89a8100c08fffff",-46.6322473276837,-23.5638360359621,4340,1259,0
-"89a8100c087ffff",-46.6353490669932,-23.5652276344411,951,1707,0
-"89a8100c54bffff",-46.6384507938911,-23.5666191363373,3005,3991,1
-"89a8100c543ffff",-46.6415525083594,-23.5680105416429,951,11122,0
-"89a8100c557ffff",-46.6446542103799,-23.5694018503501,602,10937,1
-"89a8100c51bffff",-46.6477558999346,-23.5707930624508,4054,5992,0
-"89a8100c203ffff",-46.6073426867848,-23.5496329975532,741,1525,0
-"89a8100c217ffff",-46.6104445101141,-23.5510254345873,770,787,0
-"89a8100c2bbffff",-46.6135463211772,-23.5524177751102,181,706,0
-"89a8100c2b3ffff",-46.6166481199563,-23.553810019114,979,1017,0
-"89a8100c04fffff",-46.6197499064331,-23.5552021665907,1012,369,0
-"89a8100c047ffff",-46.6228516805895,-23.5565942175326,622,95,0
-"89a8100c00bffff",-46.6259534424075,-23.5579861719316,1139,361,1
-"89a8100c003ffff",-46.6290551918689,-23.5593780297798,756,471,0
-"89a8100c017ffff",-46.6321569289557,-23.5607697910693,2702,431,0
-"89a8100c0bbffff",-46.6352586536496,-23.5621614557922,1649,1469,1
-"89a8100c0b3ffff",-46.6383603659327,-23.5635530239407,2393,2251,0
-"89a8100c54fffff",-46.6414620657867,-23.5649444955067,1925,2482,0
-"89a8100c547ffff",-46.6445637531937,-23.5663358704824,2888,2466,0
-"89a8100c50bffff",-46.6476654281354,-23.56772714886,1991,5353,0
-"89a8100c503ffff",-46.6507670905939,-23.5691183306314,2068,7163,0
-"89a8100c517ffff",-46.6538687405509,-23.5705094157889,4130,1016,0
-"89a8100c20fffff",-46.6072524058657,-23.5465661091231,1758,253,0
-"89a8100c207ffff",-46.6103542145744,-23.547958612331,2635,378,0
-"89a8100c2abffff",-46.6134560110177,-23.549351019036,719,521,0
-"89a8100c2a3ffff",-46.6165577951774,-23.5507433292301,471,1022,0
-"89a8100c2b7ffff",-46.6196595670356,-23.5521355429054,593,811,0
-"89a8100c07bffff",-46.622761326574,-23.5535276600539,2156,1032,2
-"89a8100c073ffff",-46.6258630737747,-23.5549196806678,141,684,0
-"89a8100c00fffff",-46.6289648086194,-23.5563116047391,3648,153,0
-"89a8100c007ffff",-46.6320665310901,-23.5577034322599,3936,551,0
-"89a8100c0abffff",-46.6351682411686,-23.5590951632223,2069,2868,0
-"89a8100c0a3ffff",-46.6382699388369,-23.5604867976184,758,1683,0
-"89a8100c0b7ffff",-46.6413716240769,-23.5618783354403,2414,596,0
-"89a8100c57bffff",-46.6444732968704,-23.5632697766801,2204,1375,1
-"89a8100c573ffff",-46.6475749571993,-23.5646611213299,2391,3845,0
-"89a8100c50fffff",-46.6506766050456,-23.5660523693817,2024,17682,0
-"89a8100c507ffff",-46.6537782403912,-23.5674435208278,4232,2524,0
-"89a8100c5abffff",-46.6568798632178,-23.5688345756602,3802,2813,0
-"89a8100c5a3ffff",-46.6599814735075,-23.570225533871,1802,2436,0
-"89a8100c277ffff",-46.6071621258081,-23.543499106824,1086,659,1
-"89a8100c23bffff",-46.6102639198963,-23.5448916762013,1025,417,0
-"89a8100c233ffff",-46.6133657017198,-23.5462841490838,1142,89,0
-"89a8100c2afffff",-46.6164674712604,-23.5476765254636,535,249,2
-"89a8100c2a7ffff",-46.6195692285,-23.5490688053328,1798,233,0
-"89a8100c06bffff",-46.6226709734206,-23.5504609886835,3031,1411,0
-"89a8100c063ffff",-46.6257727060041,-23.5518530755077,454,858,0
-"89a8100c077ffff",-46.6288744262322,-23.5532450657976,6514,1124,1
-"89a8100c03bffff",-46.631976134087,-23.5546369595451,3670,7112,0
-"89a8100c033ffff",-46.6350778295502,-23.5560287567425,893,3298,0
-"89a8100c0afffff",-46.6381795126039,-23.5574204573817,2185,1098,0
-"89a8100c0a7ffff",-46.6412811832299,-23.5588120614549,2353,1066,0
-"89a8100c56bffff",-46.64438284141,-23.5602035689542,2839,2926,0
-"89a8100c563ffff",-46.6474844871263,-23.5615949798717,3999,1183,0
-"89a8100c577ffff",-46.6505861203606,-23.5629862941995,2237,642,0
-"89a8100c53bffff",-46.6536877410947,-23.5643775119296,1137,13055,0
-"89a8100c533ffff",-46.6567893493106,-23.5657686330543,3041,1205,0
-"89a8100c5afffff",-46.6598909449902,-23.5671596575656,1967,1408,0
-"89a8100c5a7ffff",-46.6629925281154,-23.5685505854555,2211,1441,0
-"89a8100c267ffff",-46.6070718466119,-23.5404319906673,1773,1062,0
-"89a8100c22bffff",-46.6101736260798,-23.5418246262093,909,1101,0
-"89a8100c223ffff",-46.6132753932836,-23.5432171652648,2130,744,0
-"89a8100c237ffff",-46.6163771482052,-23.5446096078258,228,524,0
-"89a8100c3dbffff",-46.6194788908265,-23.5460019538844,1657,692,1
-"89a8100c3d3ffff",-46.6225806211293,-23.5473942034326,705,1170,0
-"89a8100c06fffff",-46.6256823390956,-23.5487863564626,363,437,0
-"89a8100c067ffff",-46.6287840447073,-23.5501784129665,1337,214,0
-"89a8100c02bffff",-46.6318857379463,-23.5515703729362,177,1696,0
-"89a8100c023ffff",-46.6349874187944,-23.552962236364,652,2800,0
-"89a8100c037ffff",-46.6380890872335,-23.5543540032418,2532,1471,0
-"89a8100c1dbffff",-46.6411907432457,-23.5557456735618,3571,1349,2
-"89a8100c1d3ffff",-46.6442923868126,-23.5571372473161,2488,1088,0
-"89a8100c56fffff",-46.6473940179163,-23.5585287244968,2787,1003,0
-"89a8100c567ffff",-46.6504956365387,-23.5599201050959,1497,2336,0
-"89a8100c52bffff",-46.6535972426615,-23.5613113891056,1526,1983,0
-"89a8100c523ffff",-46.6566988362668,-23.562702576518,470,4078,0
-"89a8100c537ffff",-46.6598004173365,-23.5640936673252,3316,1332,0
-"89a8100eadbffff",-46.6629019858523,-23.5654846615193,4363,1188,0
-"89a8100dc9bffff",-46.6069815682772,-23.537364760664,493,1046,0
-"89a8100dc93ffff",-46.6100833331249,-23.5387574623662,519,1622,0
-"89a8100c22fffff",-46.6131850857091,-23.5401500675902,395,1655,1
-"89a8100c227ffff",-46.6162868260118,-23.5415425763278,170,1984,0
-"89a8100c3cbffff",-46.6193885540148,-23.5429349885712,1837,923,0
-"89a8100c3c3ffff",-46.6224902697,-23.5443273043125,1258,1451,0
-"89a8100c3d7ffff",-46.6255919730494,-23.5457195235438,501,706,0
-"89a8100c39bffff",-46.6286936640447,-23.5471116462571,106,376,1
-"89a8100c393ffff",-46.631795342668,-23.5485036724445,637,1774,0
-"89a8100c02fffff",-46.6348970089011,-23.5498956020981,283,6493,0
-"89a8100c027ffff",-46.6379986627259,-23.55128743521,1545,1843,0
-"89a8100c1cbffff",-46.6411003041243,-23.5526791717723,4014,1724,1
-"89a8100c1c3ffff",-46.6442019330781,-23.554070811777,2246,1311,1
-"89a8100c1d7ffff",-46.6473035495694,-23.5554623552163,2179,905,1
-"89a8100c19bffff",-46.6504051535799,-23.5568538020823,4549,2230,0
-"89a8100c193ffff",-46.6535067450917,-23.558245152367,3695,9209,0
-"89a8100c52fffff",-46.6566083240865,-23.5596364060626,1875,7460,0
-"89a8100c527ffff",-46.6597098905463,-23.5610275631612,1020,10067,0
-"89a8100eacbffff",-46.6628114444529,-23.5624186236548,2699,1424,0
-"89a8100dc8bffff",-46.606891290804,-23.5342974168256,432,621,0
-"89a8100dc83ffff",-46.6099930410316,-23.5356901846835,869,1963,0
-"89a8100dc97ffff",-46.6130947789963,-23.5370828560712,411,2260,1
-"89a8100c35bffff",-46.6161965046802,-23.5384754309809,367,3052,0
-"89a8100c353ffff",-46.6192982180651,-23.5398679094047,515,1271,0
-"89a8100c3cfffff",-46.6223999191328,-23.5412602913345,370,626,0
-"89a8100c3c7ffff",-46.6255016078653,-23.5426525767625,1417,1494,0
-"89a8100c38bffff",-46.6286032842445,-23.5440447656807,56,78,0
-"89a8100c383ffff",-46.6317049482522,-23.5454368580812,180,6335,0
-"89a8100c397ffff",-46.6348065998704,-23.5468288539561,67,17678,0
-"89a8100c15bffff",-46.6379082390809,-23.5482207532975,1958,2850,0
-"89a8100c153ffff",-46.6410098658656,-23.5496125560975,1826,908,1
-"89a8100c1cfffff",-46.6441114802065,-23.5510042623481,6334,1133,0
-"89a8100c1c7ffff",-46.6472130820855,-23.5523958720415,4768,1695,0
-"89a8100c18bffff",-46.6503146714843,-23.5537873851698,6774,1118,0
-"89a8100c183ffff",-46.653416248385,-23.555178801725,4555,1369,0
-"89a8100c197ffff",-46.6565178127695,-23.5565701216992,1409,2648,0
-"89a8100ea5bffff",-46.6596193646196,-23.5579613450847,848,16414,0
-"89a8100ea53ffff",-46.6627209039172,-23.5593524718734,1689,6080,0
-"89a8100dc13ffff",-46.6068010141921,-23.5312299591633,230,327,0
-"89a8100dc8fffff",-46.6099027497997,-23.5326227931722,400,1298,0
-"89a8100dc87ffff",-46.6130044731452,-23.5340155307193,284,3070,0
-"89a8100c34bffff",-46.6161061842104,-23.5354081717965,297,2677,0
-"89a8100c343ffff",-46.6192078829773,-23.536800716396,282,3347,0
-"89a8100c357ffff",-46.6223095694276,-23.5381931645097,264,1051,1
-"89a8100c31bffff",-46.6254112435434,-23.5395855161298,412,481,0
-"89a8100c313ffff",-46.6285129053065,-23.5409777712484,660,1853,0
-"89a8100c38fffff",-46.6316145546988,-23.5423699298575,198,5957,0
-"89a8100c387ffff",-46.6347161917021,-23.5437619919492,1498,4371,0
-"89a8100c14bffff",-46.6378178162985,-23.5451539575156,142,9032,0
-"89a8100c143ffff",-46.6409194284698,-23.5465458265487,1485,13292,0
-"89a8100c157ffff",-46.6440210281978,-23.5479375990407,2769,6584,0
-"89a8100c11bffff",-46.6471226154646,-23.5493292749837,681,1107,2
-"89a8100c113ffff",-46.6502241902519,-23.5507208543697,2769,2120,0
-"89a8100c18fffff",-46.6533257525417,-23.5521123371908,2526,4240,0
-"89a8100c187ffff",-46.6564273023159,-23.5535037234392,2701,1978,0
-"89a8100ea4bffff",-46.6595288395564,-23.554895013107,3050,5676,0
-"89a8100ea43ffff",-46.662630364245,-23.5562862061862,1549,12066,0
-"89a8100dc03ffff",-46.6067107384417,-23.5281623876883,597,481,0
-"89a8100dc17ffff",-46.6098124594295,-23.5295552878437,796,1662,0
-"89a8100dcbbffff",-46.6129141681558,-23.5309480915456,462,1299,0
-"89a8100dcb3ffff",-46.6160158646024,-23.5323407987858,757,1525,0
-"89a8100c34fffff",-46.6191175487514,-23.5337334095564,1092,1191,0
-"89a8100c347ffff",-46.6222192205845,-23.5351259238495,885,1730,0
-"89a8100c30bffff",-46.6253208800836,-23.5365183416572,921,153,0
-"89a8100c303ffff",-46.6284225272308,-23.5379106629716,829,609,0
-"89a8100c317ffff",-46.6315241620077,-23.5393028877847,731,4787,0
-"89a8100c3bbffff",-46.6346257843964,-23.5406950160886,1957,1474,0
-"89a8100c3b3ffff",-46.6377273943788,-23.5420870478754,2257,4382,0
-"89a8100c14fffff",-46.6408289919367,-23.5434789831372,906,12777,1
-"89a8100c147ffff",-46.643930577052,-23.544870821866,2830,8631,0
-"89a8100c10bffff",-46.6470321497067,-23.546262564054,3123,3596,0
-"89a8100c103ffff",-46.6501337098826,-23.5476542096932,4502,4000,1
-"89a8100c117ffff",-46.6532352575616,-23.5490457587758,2720,760,1
-"89a8100c1bbffff",-46.6563367927257,-23.5504372112938,522,520,0
-"89a8100c1b3ffff",-46.6594383153567,-23.5518285672393,626,3808,0
-"89a8100ea4fffff",-46.6625398254365,-23.5532198266046,811,4586,0
-"89a8100dc0fffff",-46.6066204635527,-23.5250947024119,530,453,0
-"89a8100dc07ffff",-46.6097221699207,-23.5264876687093,1476,1027,1
-"89a8100dcabffff",-46.612823864028,-23.5278805385613,1050,990,0
-"89a8100dca3ffff",-46.6159255458562,-23.5292733119599,803,607,0
-"89a8100dcb7ffff",-46.6190272153874,-23.5306659888972,654,1798,0
-"89a8100c37bffff",-46.6221288726033,-23.5320585693652,363,1370,0
-"89a8100c373ffff",-46.625230517486,-23.5334510533559,1572,379,1
-"89a8100c30fffff",-46.6283321500173,-23.5348434408616,1253,720,0
-"89a8100c307ffff",-46.6314337701791,-23.5362357318741,2356,517,0
-"89a8100c3abffff",-46.6345353779532,-23.5376279263857,1485,1485,0
-"89a8100c3a3ffff",-46.6376369733217,-23.5390200243884,1242,2450,1
-"89a8100c3b7ffff",-46.6407385562663,-23.5404120258742,5018,2079,0
-"89a8100c17bffff",-46.6438401267691,-23.5418039308353,3861,4189,0
-"89a8100c173ffff",-46.6469416848118,-23.5431957392638,2213,3187,0
-"89a8100c10fffff",-46.6500432303764,-23.5445874511517,3302,2916,0
-"89a8100c107ffff",-46.6531447634448,-23.5459790664911,2123,763,0
-"89a8100c1abffff",-46.6562462839988,-23.5473705852742,3816,894,0
-"89a8100c1a3ffff",-46.6593477920204,-23.548762007493,1918,3681,0
-"89a8100c1b7ffff",-46.6624492874915,-23.5501533331396,571,726,0
-"89a8100dc77ffff",-46.606530189525,-23.5220269033454,228,164,1
-"89a8100dc3bffff",-46.6096318812735,-23.5234199357803,50,133,0
-"89a8100dc33ffff",-46.6127335607618,-23.5248128717779,224,738,0
-"89a8100dcafffff",-46.6158352279717,-23.5262057113303,1187,281,0
-"89a8100dca7ffff",-46.6189368828852,-23.5275984544296,1028,773,0
-"89a8100c36bffff",-46.6220385254842,-23.5289911010679,517,1141,0
-"89a8100c363ffff",-46.6251401557505,-23.5303836512371,2189,611,0
-"89a8100c377ffff",-46.6282417736661,-23.5317761049295,600,18,0
-"89a8100c33bffff",-46.6313433792128,-23.5331684621369,1132,688,0
-"89a8100c333ffff",-46.6344449723725,-23.5345607228516,744,401,0
-"89a8100c3afffff",-46.6375465531272,-23.5359528870656,850,1136,0
-"89a8100c3a7ffff",-46.6406481214587,-23.537344954771,2726,2067,0
-"89a8100c16bffff",-46.643749677349,-23.5387369259598,2183,1873,0
-"89a8100c163ffff",-46.6468512207799,-23.5401288006242,3644,883,0
-"89a8100c177ffff",-46.6499527517333,-23.5415205787562,4147,7109,1
-"89a8100c13bffff",-46.6530542701911,-23.542912260348,2081,2528,0
-"89a8100c133ffff",-46.6561557761353,-23.5443038453916,4124,862,0
-"89a8100c1afffff",-46.6592572695477,-23.5456953338791,2025,1513,1
-"89a8100c1a7ffff",-46.6623587504102,-23.5470867258027,1158,293,0
-"89a8100dc23ffff",-46.6126432583572,-23.5217450912065,0,115,0
-"89a8100dc37ffff",-46.615744910949,-23.5231379969082,964,328,0
-"89a8100dddbffff",-46.618846551245,-23.524530806165,888,527,1
-"89a8100ddd3ffff",-46.621948179227,-23.525923518969,572,1473,1
-"89a8100c36fffff",-46.6250497948771,-23.5273161353122,1194,670,0
-"89a8100c367ffff",-46.6281513981771,-23.5287086551866,702,735,0
-"89a8100c32bffff",-46.6312529891088,-23.5301010785845,476,971,2
-"89a8100c323ffff",-46.6343545676543,-23.5314934054977,1277,383,2
-"89a8100c337ffff",-46.6374561337953,-23.5328856359185,411,1670,0
-"89a8100cedbffff",-46.6405576875139,-23.5342777698388,1900,535,0
-"89a8100ced3ffff",-46.6436592287917,-23.5356698072509,1745,497,0
-"89a8100c16fffff",-46.6467607576109,-23.5370617481466,2024,4599,0
-"89a8100c167ffff",-46.6498622739533,-23.5384535925182,4105,1086,0
-"89a8100c12bffff",-46.6529637778007,-23.5398453403578,3193,1080,1
-"89a8100c123ffff",-46.6560652691351,-23.5412369916574,2739,1629,0
-"89a8100c137ffff",-46.6591667479384,-23.5426285464091,3162,4536,0
-"89a8100ccdbffff",-46.6622682141925,-23.544020004605,854,716,0
-"89a8100ddcbffff",-46.6187562204665,-23.5214630441146,29,7,0
-"89a8100ddc3ffff",-46.6218578338319,-23.5228558230797,14,69,1
-"89a8100ddd7ffff",-46.6249594348658,-23.5242485055923,161,222,0
-"89a8100dd9bffff",-46.6280610235503,-23.5256410916443,848,862,0
-"89a8100dd93ffff",-46.6311625998673,-23.527033581228,1731,531,0
-"89a8100c32fffff",-46.6342641637985,-23.5284259743352,2639,1004,0
-"89a8100c327ffff",-46.637365715326,-23.5298182709582,1577,2740,0
-"89a8100cecbffff",-46.6404672544317,-23.531210471089,255,4570,1
-"89a8100cec3ffff",-46.6435687810973,-23.5326025747196,691,534,0
-"89a8100ced7ffff",-46.6466702953049,-23.5339945818423,2269,4009,1
-"89a8100ce9bffff",-46.6497717970363,-23.5353864924489,2428,944,0
-"89a8100ce93ffff",-46.6528732862735,-23.5367783065317,6580,2284,0
-"89a8100c12fffff",-46.6559747629983,-23.5381700240827,6434,1286,0
-"89a8100c127ffff",-46.6590762271926,-23.5395616450941,2617,797,0
-"89a8100cccbffff",-46.6621776788383,-23.5409531695578,2266,923,0
-"89a8100ddc7ffff",-46.6248690757166,-23.5211807620888,0,1097,0
-"89a8100dd8bffff",-46.6279706497858,-23.5225734143139,266,572,0
-"89a8100dd83ffff",-46.631072211488,-23.5239659700787,126,1120,0
-"89a8100dd97ffff",-46.6341737608052,-23.5253584293754,176,790,0
-"89a8100ce5bffff",-46.6372752977193,-23.5267507921961,2068,1101,0
-"89a8100ce53ffff",-46.6403768222122,-23.5281430585327,657,3383,0
-"89a8100cecfffff",-46.6434783342658,-23.5295352283775,767,1054,0
-"89a8100cec7ffff",-46.6465798338619,-23.5309273017224,3274,8943,1
-"89a8100ce8bffff",-46.6496813209825,-23.5323192785595,4023,1083,0
-"89a8100ce83ffff",-46.6527827956095,-23.533711158881,2189,875,0
-"89a8100ce97ffff",-46.6558842577247,-23.5351029426789,3957,1790,0
-"89a8100cc5bffff",-46.6589857073101,-23.5364946299454,3446,712,0
-"89a8100cc53ffff",-46.6620871443476,-23.5378862206724,2180,3474,0
-"89a8100dd8fffff",-46.6309818239711,-23.520898245148,123,89,0
-"89a8100dd87ffff",-46.6340833586744,-23.5222907706296,0,915,0
-"89a8100ce4bffff",-46.6371848809752,-23.5236831996434,522,785,0
-"89a8100ce43ffff",-46.6402863908554,-23.5250755321813,2360,1418,0
-"89a8100ce57ffff",-46.643387888297,-23.5264677682356,461,2333,1
-"89a8100ce1bffff",-46.6464893732818,-23.5278599077982,2592,507,0
-"89a8100ce13ffff",-46.6495908457917,-23.5292519508613,1104,367,0
-"89a8100ce8fffff",-46.6526923058086,-23.530643897417,3224,534,1
-"89a8100ce87ffff",-46.6557937533145,-23.5320357474572,2180,1373,0
-"89a8100cc4bffff",-46.6588951882911,-23.5334275009742,4215,1279,0
-"89a8100cc43ffff",-46.6619966107205,-23.53481915796,3299,1338,0
-"89a8100ddb3ffff",-46.6370944650936,-23.5206154933113,782,6,0
-"89a8100ce4fffff",-46.6401959603613,-23.5220078920461,383,350,0
-"89a8100ce47ffff",-46.643297443191,-23.5234001943053,1215,2872,0
-"89a8100ce0bffff",-46.6463989135646,-23.5247924000811,706,1062,0
-"89a8100ce03ffff",-46.6495003714639,-23.5261845093656,1539,1089,0
-"89a8100ce17ffff",-46.6526018168709,-23.5275765221508,2234,424,0
-"89a8100cebbffff",-46.6557032497675,-23.5289684384289,1786,2073,1
-"89a8100ceb3ffff",-46.6588046701356,-23.5303602581919,1844,1007,0
-"89a8100cc4fffff",-46.661906077957,-23.5317519814319,2300,1657,1
-"89a8100ce7bffff",-46.6432069989478,-23.5203325065978,962,164,0
-"89a8100ce73ffff",-46.6463084547103,-23.5217247785823,509,1392,0
-"89a8100ce0fffff",-46.6494098979992,-23.5231169540836,590,1793,0
-"89a8100ce07ffff",-46.6525113287964,-23.5245090330939,429,411,0
-"89a8100ceabffff",-46.6556127470838,-23.5259010156052,237,527,0
-"89a8100cea3ffff",-46.6587141528434,-23.5272929016097,631,469,0
-"89a8100ceb7ffff",-46.661815546057,-23.5286846910993,464,790,0
-"89a8100ce77ffff",-46.6493194253975,-23.5200492850267,168,623,2
-"89a8100ce3bffff",-46.652420841585,-23.5214414302574,961,2318,0
-"89a8100ce33ffff",-46.6555222452634,-23.5228334789974,415,2581,1
-"89a8100ceafffff",-46.6586236364146,-23.5242254312388,348,526,0
-"89a8100cea7ffff",-46.6617250150204,-23.5256172869736,34,2483,0
-"89a8100ce23ffff",-46.6554317443062,-23.5197658286169,382,395,1
-"89a8100ce37ffff",-46.6585331208492,-23.5211578470906,10,202,0
-"89a8100c8dbffff",-46.6616344848474,-23.5225497690659,19,438,0
-"89a8100c8cbffff",-46.6615439555379,-23.5194821373876,12,1375,0
diff --git "a/docs/_static/data/S\303\243o Paulo/spo_hexgrid_EPSG32723.gpkg.zip" "b/docs/_static/data/S\303\243o Paulo/spo_hexgrid_EPSG32723.gpkg.zip"
deleted file mode 100644
index 1fa87997..00000000
Binary files "a/docs/_static/data/S\303\243o Paulo/spo_hexgrid_EPSG32723.gpkg.zip" and /dev/null differ
diff --git "a/docs/_static/data/S\303\243o Paulo/spo_osm.pbf" "b/docs/_static/data/S\303\243o Paulo/spo_osm.pbf"
deleted file mode 100644
index 89e29301..00000000
Binary files "a/docs/_static/data/S\303\243o Paulo/spo_osm.pbf" and /dev/null differ
diff --git a/docs/conf.py b/docs/conf.py
index 85e62931..f19584c2 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -14,7 +14,6 @@
 
 # -- Add project paths -------------------------------------------------------
 sys.path = [
-    str(pathlib.Path().resolve().parent / "src"),
     str(pathlib.Path().resolve()),
     str(pathlib.Path().resolve() / "_extensions"),
 ] + sys.path
diff --git a/docs/contributing/CODE_OF_CONDUCT.md b/docs/contributing/CODE_OF_CONDUCT.md
index c84b2761..fc2f53ff 100644
--- a/docs/contributing/CODE_OF_CONDUCT.md
+++ b/docs/contributing/CODE_OF_CONDUCT.md
@@ -117,7 +117,7 @@ the community.
 
 This Code of Conduct is adapted from the [Contributor Covenant][homepage],
 version 2.0, available at
-https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
 
 Community Impact Guidelines were inspired by [Mozilla's code of conduct
 enforcement ladder](https://github.com/mozilla/diversity).
@@ -125,5 +125,5 @@ enforcement ladder](https://github.com/mozilla/diversity).
 [homepage]: https://www.contributor-covenant.org
 
 For answers to common questions about this code of conduct, see the FAQ at
-https://www.contributor-covenant.org/faq. Translations are available at
-https://www.contributor-covenant.org/translations.
+<https://www.contributor-covenant.org/faq>. Translations are available at
+<https://www.contributor-covenant.org/translations>.
diff --git a/docs/requirements.txt b/docs/requirements.txt
deleted file mode 100644
index 4eea05e1..00000000
--- a/docs/requirements.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-# sphinx + dependencies
-GitPython
-jupyterlab_myst
-myst-nb
-pybtex-apa7-style
-sphinx
-sphinx-book-theme
-sphinx-design
-sphinxcontrib-bibtex
-sphinxcontrib-images
-
-# r5py:
-ConfigArgParse
-contextily
-filelock
-folium
-geopandas
-importlib_resources
-joblib
-jpype1
-numpy
-pandas
-pyproj
-psutil
-requests
-
-# documentation:
-contextily
-folium
-h3>=4.0.0b2
-mapclassify
-matplotlib
diff --git a/docs/user-guide/installation/installation.md b/docs/user-guide/installation/installation.md
index ea5785e5..2a105b16 100644
--- a/docs/user-guide/installation/installation.md
+++ b/docs/user-guide/installation/installation.md
@@ -124,3 +124,37 @@ OpenJDK has been installed as a dependency, and you are ready to go. If you used
 Consider installing it from your system’s package manager, or the official
 [Microsoft build](https://learn.microsoft.com/en-gb/java/openjdk/download) in
 case you work on Windows.
+
+
+## Sample data sets
+
+For the examples in the user manual, we prepared sample data sets, covering the
+city centres of Helsinki, Finland, and São Paulo, Brazil, both cities that
+researchers who contributed to *r5py* are familiar with. 
+
+These sample data sets are packaged separately. If you work through the examples
+independently, be sure to install `r5py.sampledata.helsinki` and
+`r5py.sampledata.sao_paulo`, using either `pip` or `conda`/`mamba`:
+
+```
+pip install r5py.sampledata.helsinki r5py.sampledata.sao_paulo
+```
+
+```
+conda install --channel conda-forge r5py.sampledata.helsinki r5py.sampledata.sao_paulo
+```
+
+The two packages then provide {class}`pathlib.Path` objects that point to sample
+data sets, and can be used directly in {meth}`geopandas.read_file()`,
+{meth}`pandas.read_csv()`, {class}`r5py.TransportNetwork()`, and any other
+method or function that expects a file path.
+
+
+:::{admonition} Data is downloaded on demand 
+:class: caution
+
+Note that the `r5py.sampledata.*` packages do not contain the actual data sets.
+Instead, the data sets are downloaded to a cache directory upon first use. This
+means that **you need an internet connection when you first access a data set**.
+On subsequent runs, the files are served from your computer’s cache.
+:::
diff --git a/docs/user-guide/user-manual/advanced-use.md b/docs/user-guide/user-manual/advanced-use.md
index d431d9a2..81258b80 100644
--- a/docs/user-guide/user-manual/advanced-use.md
+++ b/docs/user-guide/user-manual/advanced-use.md
@@ -15,34 +15,19 @@ kernelspec:
 ```{code-cell}
 :tags: [remove-input, remove-output]
 
-# this cell is hidden from output
-# it’s used to set sys.path to point to the local repo,
-# and to define a `DATA_DIRECTORY` pathlib.Path
-import pathlib
-import sys
-
-NOTEBOOK_DIRECTORY = pathlib.Path().resolve()
-DOCS_DIRECTORY = NOTEBOOK_DIRECTORY.parent.parent
-DATA_DIRECTORY = DOCS_DIRECTORY / "_static" / "data"
-R5PY_DIRECTORY = DOCS_DIRECTORY.parent / "src"
-sys.path.insert(0, str(R5PY_DIRECTORY))
-```
-
-```{code-cell}
-:tags: [remove-input, remove-output]
-
-# also this cell is hidden in READTHEDOCS
+# this cell is hidden in READTHEDOCS
 # it loads input geodata for the examples below
 
 # if you opened this notebook elsewhere, be sure to run
 # this cell, so data is read from disk
 
 import r5py
+import r5py.sampledata.helsinki
 
 transport_network = r5py.TransportNetwork(
-    f"{DATA_DIRECTORY}/Helsinki/kantakaupunki.osm.pbf",
+    r5py.sampledata.helsinki.osm_pbf,
     [
-        f"{DATA_DIRECTORY}/Helsinki/GTFS.zip",
+        r5py.sampledata.helsinki.gtfs,
     ]
 )
 ```
diff --git a/docs/user-guide/user-manual/data-requirements.md b/docs/user-guide/user-manual/data-requirements.md
index 59140300..e7ba793a 100644
--- a/docs/user-guide/user-manual/data-requirements.md
+++ b/docs/user-guide/user-manual/data-requirements.md
@@ -141,12 +141,11 @@ instructions](https://geopandas.org/en/stable/gallery/create_geopandas_from_pand
 to convert them into a {class}`geopandas.GeoDataFrame`.
 
 
-## Sample datasets
+## Sample data sets
 
-In this documentation, we use some sample data sets that you can also find in the
-[source code
-repository](https://github.com/r5py/r5py/tree/main/docs/_static/data/). In
-particular, the sample data comprises of the following data sets:
+In this documentation, we use some sample data sets that you can [install
+separately](../installation/installation.md#sample-data-sets). In particular,
+the sample data comprises of the following data sets:
 
 - Helsinki, Finland
   - A population grid data set of Helsinki city centre, obtained from the
diff --git a/docs/user-guide/user-manual/detailed-itineraries.md b/docs/user-guide/user-manual/detailed-itineraries.md
index 33e812a6..dad18c97 100644
--- a/docs/user-guide/user-manual/detailed-itineraries.md
+++ b/docs/user-guide/user-manual/detailed-itineraries.md
@@ -16,31 +16,20 @@ jupytext:
 
 # this cell is hidden from READTHEDOCS output
 # it’s used to
-#    - set sys.path to point to the local *r5py* source code, to
 #    - use a different upstream R5 jar, so we can display the
-#      geometries of public transport routes, to
-#    - define a `DATA_DIRECTORY` pathlib.Path, and to
+#      geometries of public transport routes, and to
 #    - force pandas to show all columns of the (very wide)
 #      result data set
 
-import pathlib
 import sys
-
 import pandas
 
-NOTEBOOK_DIRECTORY = pathlib.Path().resolve()
-DOCS_DIRECTORY = NOTEBOOK_DIRECTORY.parent.parent
-DATA_DIRECTORY = DOCS_DIRECTORY / "_static" / "data"
-R5PY_DIRECTORY = DOCS_DIRECTORY.parent / "src"
-
 sys.argv.extend([
     "--r5-classpath",
     "https://github.com/DigitalGeographyLab/r5/releases/download/"
     "v6.9-post16-g1054c1e-20230619/r5-v6.9-post16-g1054c1e-20230619-all.jar"
 ])
 
-sys.path.insert(0, str(R5PY_DIRECTORY))
-
 pandas.set_option("display.max_columns", None)
 ```
 
@@ -58,30 +47,6 @@ if "MEM_LIMIT" in os.environ:  # binder/kubernetes!
     sys.argv.extend(["--max-memory", f"{max_memory}"])
 ```
 
-```{code-cell}
-:tags: [remove-input, remove-output]
-
-# also this cell is hidden in READTHEDOCS
-# it loads input geodata for the examples below
-
-# if you opened this notebook elsewhere, be sure to run
-# this cell, so data is read from disk
-
-import geopandas
-import r5py
-import shapely
-
-population_grid = geopandas.read_file(DATA_DIRECTORY / "Helsinki" / "population_grid_2020.gpkg")
-RAILWAY_STATION = shapely.Point(24.941521, 60.170666)
-
-transport_network = r5py.TransportNetwork(
-    f"{DATA_DIRECTORY}/Helsinki/kantakaupunki.osm.pbf",
-    [
-        f"{DATA_DIRECTORY}/Helsinki/GTFS.zip",
-    ]
-)
-```
-
 
 # Compute travel times with a detailed breakdown of the routing results
 
@@ -116,6 +81,26 @@ data of Helsinki.
 :::
 
 
+```{code-cell}
+:tags: [remove-output]
+
+import geopandas
+import r5py
+import r5py.sampledata.helsinki
+import shapely
+
+population_grid = geopandas.read_file(r5py.sampledata.helsinki.population_grid)
+RAILWAY_STATION = shapely.Point(24.941521, 60.170666)
+
+transport_network = r5py.TransportNetwork(
+    r5py.sampledata.helsinki.osm_pbf,
+    [
+        r5py.sampledata.helsinki.gtfs,
+    ]
+)
+```
+
+
 ```{code-cell}
 :tags: ["remove-output"]
 
@@ -382,6 +367,6 @@ travel_details = travel_details[
     ]
 ]
 
-travel_details.to_file(DATA_DIRECTORY / "detailed_itineraries.gpkg")
+travel_details.to_file("detailed_itineraries.gpkg")
 
 ```
diff --git a/docs/user-guide/user-manual/quickstart.md b/docs/user-guide/user-manual/quickstart.md
index 5deaa94c..ebd70ca2 100644
--- a/docs/user-guide/user-manual/quickstart.md
+++ b/docs/user-guide/user-manual/quickstart.md
@@ -35,25 +35,8 @@ configuration
 :tags: [remove-input, remove-output]
 
 # this cell is hidden from READTHEDOCS output
-# it’s used to set sys.path to point to the local *r5py* source code,
-# and to define a `DATA_DIRECTORY` pathlib.Path
-import pathlib
-import sys
-
-NOTEBOOK_DIRECTORY = pathlib.Path().resolve()
-DOCS_DIRECTORY = NOTEBOOK_DIRECTORY.parent.parent
-DATA_DIRECTORY = DOCS_DIRECTORY / "_static" / "data"
-R5PY_DIRECTORY = DOCS_DIRECTORY.parent / "src"
-
-sys.path.insert(0, str(R5PY_DIRECTORY))
-```
-
-```{code-cell}
-:tags: [remove-input, remove-output]
-
-# also this cell is hidden from READTHEDOCS output
 # it’s used to set a stricter memory limit in binderhub notebooks
-# as otherwise, the examples would fail
+# as, otherwise, the examples would fail
 
 import os
 
@@ -62,6 +45,7 @@ if "MEM_LIMIT" in os.environ:  # binder/kubernetes!
     sys.argv.extend(["--max-memory", f"{max_memory}"])
 ```
 
+
 One of the core functionalities of *r5py* is to compute travel time matrices
 efficiently, and for large extents such as entire cities or countries. This
 page walks you through the - pleasantly few - steps required to do so.
@@ -74,33 +58,50 @@ cells in a population grid data set to the city’s main railway station.
 ## Origins and destination
 
 As we intend to compute the travel times from the centre points of population grid
-cells to the railway station, we need to know the locations of these places. 
-
-For this example, we prepared the data ahead of time: `population_grid` is a
-[`geopandas.GeoDataFrame`](https://geopandas.org/en/stable/docs/user_guide/data_structures.html)
-containing a 250 ⨉ 250 m grid covering parts of downtown Helsinki, and obtained
-from the [Helsinki Region Environmental Services
-(HSY)](https://hri.fi/data/en_GB/dataset/vaestotietoruudukko). The
-[constant](https://stackoverflow.com/q/44636868) `RAILWAY_STATION` is a
-[`shapely.Point`](https://shapely.readthedocs.io/en/stable/reference/shapely.Point.html),
-its coordinates refer to Helsinki’s main railway station in the
+cells to the railway station, we need to know the locations of these places.
+
+:::{admonition} Sample data set
+:class: info
+
+For this example, we prepared the data ahead of time. If you repeat the code
+examples independently, [install
+`r5py.sampledata.helsinki`](../installation/installation.md#sample-data-sets).
+
+`r5py.sampledata.helsinki.population_grid` is a vector data set in [GeoPackage
+(GPKG)](http://www.opengeospatial.org/standards/geopackage) format containing a
+250 ⨉ 250 m grid covering parts of downtown Helsinki, and obtained from the
+[Helsinki Region Environmental Services
+(HSY)](https://hri.fi/data/en_GB/dataset/vaestotietoruudukko).
+
+:::
+
+We open the sample data set file using {meth}`geopandas.GeoDataFrame.read_file()`.
+
+Because, in our example, we only use one destination, the railway station, we
+define its location as a {class}`geopandas.GeoDataFrame` containing one
+geometry, a {class}`shapely.Point`, the coordinates of which refer to Helsinki’s
+main railway station in the
 [`EPSG:4326`](https://spatialreference.org/ref/epsg/4326/) reference system.
 
 ```{code-cell}
 import geopandas
-population_grid = geopandas.read_file(DATA_DIRECTORY / "Helsinki" / "population_grid_2020.gpkg")
-
+import r5py.sampledata.helsinki
 import shapely
-RAILWAY_STATION = shapely.Point(24.941521, 60.170666)
+
+population_grid = geopandas.read_file(r5py.sampledata.helsinki.population_grid)
+
+railway_station = geopandas.GeoDataFrame(
+    {
+        "id": ["railway_station"],
+        "geometry": [shapely.Point(24.94152, 60.17066)]
+    },
+    crs="EPSG:4326",
+)
 ```
 
 ```{code-cell}
-import folium
-import geopandas
-import shapely
-
 overview_map = population_grid.explore("population", cmap="Reds")
-folium.Marker((RAILWAY_STATION.y, RAILWAY_STATION.x)).add_to(overview_map)
+overview_map = railway_station.explore(m=overview_map, marker_type="marker")
 overview_map
 ```
 
@@ -117,32 +118,31 @@ understands and reads the following types of transport networks:
 - a public transport schedule from one or more
   [GTFS](https://en.wikipedia.org/wiki/GTFS) files (optional).
 
-For the quickstart example, you find sample data sets in the `DATA_DIRECTORY`
-([`docs/_static/data`](https://github.com/r5py/r5py/tree/main/docs/_static/data/)
-in the source code repository).
+For the quickstart example, you find sample data sets in the
+`r5py.sampledata.helsinki` package (see [above](#origins-and-destination)).
 
 To import the street and public transport networks, instantiate an
 {class}`r5py.TransportNetwork` with the file paths to the OSM extract and to
-zero or more GTFS files:
+zero or more GTFS files. With the sample data set, the file paths are in the
+`r5py.sampledata.helsinki` namespace:
 
 ```{code-cell}
 :tags: ["remove-output"]
 
 import r5py
+import r5py.sampledata.helsinki
 
 transport_network = r5py.TransportNetwork(
-    DATA_DIRECTORY / "Helsinki" / "kantakaupunki.osm.pbf",
-    [
-        DATA_DIRECTORY / "Helsinki" / "GTFS.zip",
-    ]
+    r5py.sampledata.helsinki.osm_pbf,
+    [r5py.sampledata.helsinki.gtfs],
 )
 ```
 
 At this stage, *r5py* has created a routable transport network, that is stored
 in the `transport_network` variable. We can now use this network for travel time
 calculations. Depending on the extent of the network, this step can take up to
-several minutes. However, you can reuse the same `TransportNetwork` instance in
-subsequent analyses.
+several minutes. Once loaded, you can reuse the same `TransportNetwork` instance
+in subsequent analyses.
 
 
 ## Compute a travel time matrix
@@ -160,9 +160,9 @@ the following input arguments:
 - a `transport_network` ({class}`r5py.TransportNetwork`), such as the one we
   just created,
 - `origins`, a {class}`geopandas.GeoDataFrame` with one or more points
-  representing the departure points of routes, 
+  representing the departure points of routes,
 - `destinations`, a {class}`geopandas.GeoDataFrame` with one or more points
-  representing the destinations of routes, 
+  representing the destinations of routes,
 - `departure`, a {class}`datetime.datetime`
   refering to the departure date and time for routing, and
 - `transport_modes`, a list of {class}`r5py.TransportMode`s: the travel modes
@@ -180,13 +180,7 @@ import datetime
 origins = population_grid.copy()
 origins.geometry = origins.geometry.centroid
 
-destinations = geopandas.GeoDataFrame(
-        {
-            "id": [1],
-            "geometry": [RAILWAY_STATION]
-        },
-        crs="EPSG:4326",
-)
+destinations = railway_station.copy()
 
 travel_time_matrix_computer = r5py.TravelTimeMatrixComputer(
     transport_network,
@@ -222,7 +216,7 @@ Simply use the {meth}`to_csv()<pandas.DataFrame.to_csv()>` method of pandas data
 frames:
 
 ```{code-cell}
-travel_times.to_csv(DATA_DIRECTORY / "travel_times_to_helsinki_railway_station.csv")
+travel_times.to_csv("travel_times_to_helsinki_railway_station.csv")
 ```
 
 
diff --git a/docs/user-guide/user-manual/travel-time-matrices.md b/docs/user-guide/user-manual/travel-time-matrices.md
index b05812cd..60e85983 100644
--- a/docs/user-guide/user-manual/travel-time-matrices.md
+++ b/docs/user-guide/user-manual/travel-time-matrices.md
@@ -17,23 +17,7 @@ kernelspec:
 ```{code-cell}
 :tags: [remove-input, remove-output]
 
-# this cell is hidden from output
-# it’s used to set sys.path to point to the local repo,
-# and to define a `DATA_DIRECTORY` pathlib.Path
-import pathlib
-import sys
-
-NOTEBOOK_DIRECTORY = pathlib.Path().resolve()
-DOCS_DIRECTORY = NOTEBOOK_DIRECTORY.parent.parent
-DATA_DIRECTORY = DOCS_DIRECTORY / "_static" / "data"
-R5PY_DIRECTORY = DOCS_DIRECTORY.parent / "src"
-sys.path.insert(0, str(R5PY_DIRECTORY))
-```
-
-```{code-cell}
-:tags: [remove-input, remove-output]
-
-# also this cell is hidden from READTHEDOCS output
+# this cell is hidden from READTHEDOCS output
 # it’s used to set a stricter memory limit in binderhub notebooks
 # as otherwise, the examples would fail
 
@@ -90,17 +74,19 @@ required for computing a travel time matrix:
 In the example below, we first create a
 {class}`TransportNetwork<r5py.TransportNetwork>`. To do so, we load an
 OpenStreetMap extract of the São Paulo city centre as well as a public transport
-schedule in GTFS format covering the same area:
+schedule in GTFS format covering the same area. Again, we use the [sample data
+sets that can be installed separately](../installation/installation.md#sample-data-sets)
 
 ```{code-cell}
 :tags: [remove-output]
 
 import r5py
+import r5py.sampledata.sao_paulo
 
 transport_network = r5py.TransportNetwork(
-    DATA_DIRECTORY / "São Paulo" / "spo_osm.pbf",
+    r5py.sampledata.sao_paulo.osm_pbf,
     [
-        DATA_DIRECTORY / "São Paulo" / "spo_gtfs.zip",
+        r5py.sampledata.sao_paulo.gtfs,
     ]
 )
 ```
@@ -120,7 +106,7 @@ The `id` column refers to the H3 address of the grid cells.
 ```{code-cell}
 import geopandas
 
-hexagon_grid = geopandas.read_file(DATA_DIRECTORY / "São Paulo" / "spo_hexgrid_EPSG32723.gpkg.zip")
+hexagon_grid = geopandas.read_file(r5py.sampledata.sao_paulo.hexgrid_gpkg)
 hexagon_grid
 ```
 
@@ -284,7 +270,7 @@ hexagons_with_travel_time_to_centre.explore(
 ```
 
 You can clearly see how travel times do not increase uniformly, but are shorter
-along the major transport axis (metro, railways, bus corridors).
+along the major transport axes (metro, railways, bus corridors).
 
 
 ***
diff --git a/pyproject.toml b/pyproject.toml
index 85f5021a..11b50f67 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,11 +44,16 @@ license = {text = "GPL-3.0-or-later or MIT"}
 dynamic = ["version"]
 
 [project.optional-dependencies]
-doc = ["contextily", "folium", "h3", "mapclassify", "matplotlib", "myst-nb",
-        "nbsphinx", "pybtex-apa7-style", "shapely", "sphinx",
+docs = ["contextily", "folium", "GitPython", "h3>=4.0.0b2", "jupyterlab_myst",
+        "mapclassify", "matplotlib", "myst-nb", "nbsphinx", "pybtex-apa7-style",
+        "r5py.sampledata.helsinki>=0.1.1.dev2",
+        "r5py.sampledata.sao_paulo>=0.1.1.dev2", "shapely", "sphinx",
         "sphinx-book-theme", "sphinx-design", "sphinxcontrib-bibtex",
         "sphinxcontrib-images"]
-test = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-lazy-fixture"]
+tests = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-lazy-fixture",
+        "r5py.sampledata.helsinki>=0.1.1.dev2",
+        "r5py.sampledata.sao_paulo>=0.1.1.dev2"]
+
 
 [project.urls]
 Documentation = "https://r5py.readthedocs.org/"
diff --git a/src/r5py/__init__.py b/src/r5py/__init__.py
index 3ef91365..aa224e10 100644
--- a/src/r5py/__init__.py
+++ b/src/r5py/__init__.py
@@ -2,7 +2,7 @@
 
 """Python wrapper for the R5 routing analysis engine."""
 
-__version__ = "0.1.1.dev1"
+__version__ = "0.1.1.dev2"
 
 from .r5 import (
     DetailedItinerariesComputer,
diff --git a/src/r5py/sampledata/_keep/__init__.py b/src/r5py/sampledata/_keep/__init__.py
new file mode 100644
index 00000000..0e88e332
--- /dev/null
+++ b/src/r5py/sampledata/_keep/__init__.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env
+
+"""A placeholder for plugin-style sample data packages within the r5py.sampledata.* namespace."""
diff --git a/src/r5py/util/data_set.py b/src/r5py/util/data_set.py
deleted file mode 100644
index f2721cd0..00000000
--- a/src/r5py/util/data_set.py
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env python3
-
-
-"""A remote data set that is downloaded on demand."""
-
-
-import hashlib
-import pathlib
-import warnings
-
-from r5py.util.config import Config
-from r5py.util.validating_requests_session import ValidatingRequestsSession
-
-
-config = Config()
-
-
-class DataSet(pathlib.Path):
-    """Data set that is downloaded and cached as needed."""
-
-    # decide which kind of pathlib.Path we are (Windows, Unix, ...)
-    # cf. https://stackoverflow.com/a/66613346/463864
-    _flavour = type(pathlib.Path())._flavour
-
-    def __new__(cls, remote_url, sha256_checksum):
-        # pathlib.Path does everything in __new__, rather than __init__
-        cached_path = pathlib.Path(config.CACHE_DIR) / pathlib.Path(remote_url).name
-        return super().__new__(cls, cached_path)
-
-    def __init__(self, remote_url, sha256_checksum, *args, **kwargs):
-        """
-        Define a data set that is downloaded and cached on demand.
-
-        Arguments
-        ---------
-        remote_url : str
-            source URL for this data set
-        sha256_checksum : str
-            checksum for this data set, using an SHA256 algorithm
-        """
-        super().__init__()
-        self.remote_url = remote_url
-        self.checksum = sha256_checksum
-        self.cached_path = (
-            pathlib.Path(config.CACHE_DIR) / pathlib.Path(remote_url).name
-        )
-        self._downloaded = False
-
-    def _download_remote_file(self):
-        if not self._downloaded:
-            try:
-                assert (
-                    hashlib.sha256(self.cached_path.read_bytes()).hexdigest()
-                    == self.checksum
-                )
-            except (AssertionError, FileNotFoundError):
-                if config.arguments.verbose:
-                    warnings.warn(
-                        f"First access to {pathlib.Path(self.remote_url).name}, "
-                        "downloading remote file to local cache",
-                        RuntimeWarning,
-                    )
-                with ValidatingRequestsSession() as session, session.get(
-                    self.remote_url, self.checksum
-                ) as response:
-                    self.cached_path.write_bytes(response.content)
-
-    def __str__(self):
-        self._download_remote_file()
-        return super().__str__()
-
-    def __fspath__(self):
-        self._download_remote_file()
-        return super().__fspath__()
diff --git a/src/r5py/util/sample_data_set.py b/src/r5py/util/sample_data_set.py
new file mode 100644
index 00000000..8fff222f
--- /dev/null
+++ b/src/r5py/util/sample_data_set.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+
+"""A remote data set that is downloaded on demand."""
+
+
+import hashlib
+import pathlib
+import warnings
+
+from .config import Config
+from .validating_requests_session import ValidatingRequestsSession
+
+
+config = Config()
+
+
+class SampleDataSet(pathlib.Path):
+    """Data set that is downloaded and cached as needed."""
+
+    # decide which kind of pathlib.Path we are (Windows, Unix, ...)
+    # cf. https://stackoverflow.com/a/66613346/463864
+    _flavour = type(pathlib.Path())._flavour
+
+    _CACHE_DIR = pathlib.Path(config.CACHE_DIR) / "sampledata"
+
+    def __new__(cls, remote_url, sha256_checksum):
+        # pathlib.Path does everything in __new__, rather than __init__
+        cached_path = cls._CACHE_DIR / pathlib.Path(remote_url).name
+        return super().__new__(cls, cached_path)
+
+    def __init__(self, remote_url, sha256_checksum, *args, **kwargs):
+        """
+        Define a data set that is downloaded and cached on demand.
+
+        Arguments
+        ---------
+        remote_url : str
+            source URL for this data set
+        sha256_checksum : str
+            checksum for this data set, using an SHA256 algorithm
+        """
+        super().__init__()
+        self.remote_url = remote_url
+        self.checksum = sha256_checksum
+        self.cached_path = self._CACHE_DIR / pathlib.Path(remote_url).name
+        self._download_remote_file()
+
+    def _download_remote_file(self):
+        try:
+            assert (
+                hashlib.sha256(self.cached_path.read_bytes()).hexdigest()
+                == self.checksum
+            )
+        except (AssertionError, FileNotFoundError):
+            if config.arguments.verbose:
+                warnings.warn(
+                    f"First access to {pathlib.Path(self.remote_url).name}, "
+                    "downloading remote file to local cache",
+                    RuntimeWarning,
+                )
+            self.cached_path.parent.mkdir(exist_ok=True)
+            with ValidatingRequestsSession() as session, session.get(
+                self.remote_url, self.checksum
+            ) as response:
+                self.cached_path.write_bytes(response.content)


Test patch:
diff --git a/.github/workflows/lint-test-upon-push.yml b/.github/workflows/lint-test-upon-push.yml
index e3ab5c10..3b4db9b3 100644
--- a/.github/workflows/lint-test-upon-push.yml
+++ b/.github/workflows/lint-test-upon-push.yml
@@ -85,6 +85,7 @@ jobs:
         run: |
           conda info
           conda list
+          pip list --verbose
 
       - name: Test r5py
         run: python -m pytest
diff --git a/tests/conftest.py b/tests/conftest.py
index 4d8ddb75..81f898f9 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -3,7 +3,7 @@
 # This is a init file common to all tests. It is automatically sourced
 # by pytest et al.
 
-# Define common constants (e.g., paths to test_data) and fixtures (e.g.,
+# Define common constants (e.g., paths to test data) and fixtures (e.g.,
 # transport network) here.
 
 
@@ -21,28 +21,14 @@
 import shapely
 
 
-# test_data
-DATA_DIRECTORY = (
-    pathlib.Path(__file__).resolve().parent.parent / "docs" / "_static" / "data"
-)
-
-
-OSM_PBF = DATA_DIRECTORY / "Helsinki" / "kantakaupunki.osm.pbf"
-GTFS = DATA_DIRECTORY / "Helsinki" / "GTFS.zip"
-POPULATION_GRID = DATA_DIRECTORY / "Helsinki" / "population_grid_2020.gpkg"
-
-
-ORIGINS_INVALID_NO_ID = (
-    DATA_DIRECTORY / "test_data" / "test_invalid_points_no_id_column.geojson"
-)
+# test data
+DATA_DIRECTORY = pathlib.Path(__file__).resolve().parent / "data"
+ORIGINS_INVALID_NO_ID = DATA_DIRECTORY / "test_invalid_points_no_id_column.geojson"
 ORIGINS_INVALID_DUPLICATE_IDS = (
-    DATA_DIRECTORY / "test_data" / "test_invalid_points_duplicate_ids.geojson"
-)
-ORIGINS_VALID_IDS = DATA_DIRECTORY / "test_data" / "test_valid_points_data.geojson"
-SINGLE_VALID_ORIGIN = (
-    DATA_DIRECTORY / "test_data" / "test_valid_single_point_data.geojson"
+    DATA_DIRECTORY / "test_invalid_points_duplicate_ids.geojson"
 )
-
+ORIGINS_VALID_IDS = DATA_DIRECTORY / "test_valid_points_data.geojson"
+SINGLE_VALID_ORIGIN = DATA_DIRECTORY / "test_valid_single_point_data.geojson"
 
 R5_JAR_URL = "https://github.com/conveyal/r5/releases/download/v6.9/r5-v6.9-all.jar"
 R5_JAR_SHA256 = "a7e1c5ff8786a9fb9191073b8f31a6933b862f44b9ff85b2c00a68c85491274d"
@@ -51,34 +37,23 @@
     "14aa2347be79c280e4d0fd3a137fb8f5bf2863261a1e48e1a122df1a52a0f453"
 )
 
-
 SNAPPED_POPULATION_GRID_POINTS = (
-    DATA_DIRECTORY / "test_data" / "test_snapped_population_grid_centroids.geojson"
-)
-WALKING_TIMES_SNAPPED = DATA_DIRECTORY / "test_data" / "test_walking_times_snapped.csv"
-WALKING_TIMES_NOT_SNAPPED = (
-    DATA_DIRECTORY / "test_data" / "test_walking_times_not_snapped.csv"
-)
-WALKING_DETAILS_SNAPPED = (
-    DATA_DIRECTORY / "test_data" / "test_walking_details_snapped.csv"
-)
-WALKING_DETAILS_NOT_SNAPPED = (
-    DATA_DIRECTORY / "test_data" / "test_walking_details_not_snapped.csv"
+    DATA_DIRECTORY / "test_snapped_population_grid_centroids.geojson"
 )
 
+WALKING_TIMES_SNAPPED = DATA_DIRECTORY / "test_walking_times_snapped.csv"
+WALKING_TIMES_NOT_SNAPPED = DATA_DIRECTORY / "test_walking_times_not_snapped.csv"
+WALKING_DETAILS_SNAPPED = DATA_DIRECTORY / "test_walking_details_snapped.csv"
+WALKING_DETAILS_NOT_SNAPPED = DATA_DIRECTORY / "test_walking_details_not_snapped.csv"
+
 DETAILED_ITINERARIES_BICYCLE = (
-    DATA_DIRECTORY / "test_data" / "test_detailed_itineraries_bicycle.gpkg.zip"
-)
-DETAILED_ITINERARIES_CAR = (
-    DATA_DIRECTORY / "test_data" / "test_detailed_itineraries_car.gpkg.zip"
+    DATA_DIRECTORY / "test_detailed_itineraries_bicycle.gpkg.zip"
 )
+DETAILED_ITINERARIES_CAR = DATA_DIRECTORY / "test_detailed_itineraries_car.gpkg.zip"
 DETAILED_ITINERARIES_TRANSIT = (
-    DATA_DIRECTORY / "test_data" / "test_detailed_itineraries_transit.gpkg.zip"
+    DATA_DIRECTORY / "test_detailed_itineraries_transit.gpkg.zip"
 )
-DETAILED_ITINERARIES_WALK = (
-    DATA_DIRECTORY / "test_data" / "test_detailed_itineraries_walk.gpkg.zip"
-)
-
+DETAILED_ITINERARIES_WALK = DATA_DIRECTORY / "test_detailed_itineraries_walk.gpkg.zip"
 
 SAMPLE_DATA_SET_URL = "https://raw.githubusercontent.com/r5py/r5py.sampledata.sao_paulo/main/data/spo_hexgrid.csv"
 SAMPLE_DATA_SET_SHA256 = (
@@ -132,17 +107,23 @@ def detailed_itineraries_walk():
 
 @pytest.fixture
 def gtfs_file():
-    yield GTFS
+    import r5py.sampledata.helsinki
+
+    yield r5py.sampledata.helsinki.gtfs
 
 
 @pytest.fixture
 def not_a_gtfs_file():
-    yield OSM_PBF
+    import r5py.sampledata.helsinki
+
+    yield r5py.sampledata.helsinki.osm_pbf
 
 
 @pytest.fixture
 def gtfs_file_path():
-    yield GTFS
+    import r5py.sampledata.helsinki
+
+    yield r5py.sampledata.helsinki.gtfs
 
 
 @pytest.fixture
@@ -175,12 +156,16 @@ def origins_valid_ids():
 
 @pytest.fixture
 def osm_pbf_file_path():
-    yield OSM_PBF
+    import r5py.sampledata.helsinki
+
+    yield r5py.sampledata.helsinki.osm_pbf
 
 
 @pytest.fixture(scope="session")
 def population_grid():
-    yield geopandas.read_file(POPULATION_GRID)
+    import r5py.sampledata.helsinki
+
+    yield geopandas.read_file(r5py.sampledata.helsinki.population_grid)
 
 
 @pytest.fixture(scope="session")
@@ -277,7 +262,9 @@ def snapped_population_grid_points():
 
 @pytest.fixture
 def transport_network_files_tuple():
-    yield OSM_PBF, [GTFS]
+    import r5py.sampledata.helsinki
+
+    yield r5py.sampledata.helsinki.osm_pbf, [r5py.sampledata.helsinki.gtfs]
 
 
 @pytest.fixture
@@ -288,13 +275,21 @@ def transport_network(transport_network_from_test_files):
 @pytest.fixture(scope="session")
 def transport_network_from_test_directory():
     import r5py
+    import r5py.sampledata.helsinki
+    from .temporary_directory import TemporaryDirectory
 
-    transport_network = r5py.TransportNetwork.from_directory(
-        DATA_DIRECTORY / "Helsinki"
-    )
-    yield transport_network
+    with TemporaryDirectory() as temp_directory:
+        (temp_directory / r5py.sampledata.helsinki.osm_pbf.name).symlink_to(
+            r5py.sampledata.helsinki.osm_pbf
+        )
+        (temp_directory / r5py.sampledata.helsinki.gtfs.name).symlink_to(
+            r5py.sampledata.helsinki.gtfs
+        )
 
-    del transport_network
+        transport_network = r5py.TransportNetwork.from_directory(temp_directory)
+        yield transport_network
+
+        del transport_network
 
     time.sleep(0.5)
     jpype.java.lang.System.gc()
@@ -303,8 +298,11 @@ def transport_network_from_test_directory():
 @pytest.fixture(scope="session")
 def transport_network_from_test_files():
     import r5py
+    import r5py.sampledata.helsinki
 
-    transport_network = r5py.TransportNetwork(OSM_PBF, [GTFS])
+    transport_network = r5py.TransportNetwork(
+        r5py.sampledata.helsinki.osm_pbf, [r5py.sampledata.helsinki.gtfs]
+    )
     yield transport_network
 
     del transport_network
@@ -316,8 +314,9 @@ def transport_network_from_test_files():
 @pytest.fixture(scope="session")
 def transport_network_from_test_files_without_gtfs():
     import r5py
+    import r5py.sampledata.helsinki
 
-    transport_network = r5py.TransportNetwork(OSM_PBF, [])
+    transport_network = r5py.TransportNetwork(r5py.sampledata.helsinki.osm_pbf, [])
     yield transport_network
 
     del transport_network
diff --git a/docs/_static/data/test_data/test_detailed_itineraries_bicycle.gpkg.zip b/tests/data/test_detailed_itineraries_bicycle.gpkg.zip
similarity index 100%
rename from docs/_static/data/test_data/test_detailed_itineraries_bicycle.gpkg.zip
rename to tests/data/test_detailed_itineraries_bicycle.gpkg.zip
diff --git a/docs/_static/data/test_data/test_detailed_itineraries_car.gpkg.zip b/tests/data/test_detailed_itineraries_car.gpkg.zip
similarity index 100%
rename from docs/_static/data/test_data/test_detailed_itineraries_car.gpkg.zip
rename to tests/data/test_detailed_itineraries_car.gpkg.zip
diff --git a/docs/_static/data/test_data/test_detailed_itineraries_transit.gpkg.zip b/tests/data/test_detailed_itineraries_transit.gpkg.zip
similarity index 100%
rename from docs/_static/data/test_data/test_detailed_itineraries_transit.gpkg.zip
rename to tests/data/test_detailed_itineraries_transit.gpkg.zip
diff --git a/docs/_static/data/test_data/test_detailed_itineraries_walk.gpkg.zip b/tests/data/test_detailed_itineraries_walk.gpkg.zip
similarity index 100%
rename from docs/_static/data/test_data/test_detailed_itineraries_walk.gpkg.zip
rename to tests/data/test_detailed_itineraries_walk.gpkg.zip
diff --git a/docs/_static/data/test_data/test_invalid_points_duplicate_ids.geojson b/tests/data/test_invalid_points_duplicate_ids.geojson
similarity index 100%
rename from docs/_static/data/test_data/test_invalid_points_duplicate_ids.geojson
rename to tests/data/test_invalid_points_duplicate_ids.geojson
diff --git a/docs/_static/data/test_data/test_invalid_points_no_id_column.geojson b/tests/data/test_invalid_points_no_id_column.geojson
similarity index 100%
rename from docs/_static/data/test_data/test_invalid_points_no_id_column.geojson
rename to tests/data/test_invalid_points_no_id_column.geojson
diff --git a/docs/_static/data/test_data/test_snapped_population_grid_centroids.geojson b/tests/data/test_snapped_population_grid_centroids.geojson
similarity index 100%
rename from docs/_static/data/test_data/test_snapped_population_grid_centroids.geojson
rename to tests/data/test_snapped_population_grid_centroids.geojson
diff --git a/docs/_static/data/test_data/test_valid_points_data.geojson b/tests/data/test_valid_points_data.geojson
similarity index 100%
rename from docs/_static/data/test_data/test_valid_points_data.geojson
rename to tests/data/test_valid_points_data.geojson
diff --git a/docs/_static/data/test_data/test_valid_single_point_data.geojson b/tests/data/test_valid_single_point_data.geojson
similarity index 100%
rename from docs/_static/data/test_data/test_valid_single_point_data.geojson
rename to tests/data/test_valid_single_point_data.geojson
diff --git a/docs/_static/data/test_data/test_walking_details_not_snapped.csv b/tests/data/test_walking_details_not_snapped.csv
similarity index 100%
rename from docs/_static/data/test_data/test_walking_details_not_snapped.csv
rename to tests/data/test_walking_details_not_snapped.csv
diff --git a/docs/_static/data/test_data/test_walking_details_snapped.csv b/tests/data/test_walking_details_snapped.csv
similarity index 100%
rename from docs/_static/data/test_data/test_walking_details_snapped.csv
rename to tests/data/test_walking_details_snapped.csv
diff --git a/docs/_static/data/test_data/test_walking_times_not_snapped.csv b/tests/data/test_walking_times_not_snapped.csv
similarity index 100%
rename from docs/_static/data/test_data/test_walking_times_not_snapped.csv
rename to tests/data/test_walking_times_not_snapped.csv
diff --git a/docs/_static/data/test_data/test_walking_times_snapped.csv b/tests/data/test_walking_times_snapped.csv
similarity index 100%
rename from docs/_static/data/test_data/test_walking_times_snapped.csv
rename to tests/data/test_walking_times_snapped.csv
diff --git a/tests/test_data_set.py b/tests/test_sample_data_set.py
similarity index 70%
rename from tests/test_data_set.py
rename to tests/test_sample_data_set.py
index ac0736f8..298f02bc 100644
--- a/tests/test_data_set.py
+++ b/tests/test_sample_data_set.py
@@ -7,45 +7,48 @@
 import pytest
 
 from r5py.util.config import Config
-from r5py.util.data_set import DataSet
+from r5py.util.sample_data_set import SampleDataSet
 
 
-class TestDataSet:
+class TestSampleDataSet:
     def test_data_set_with_verbose(self, sample_data_set_url, sample_data_set_sha256):
         sys.argv.extend(
             [
                 "--verbose",
             ]
         )
+
+        # make sure the cached file does not exist
         try:
             (
                 pathlib.Path(Config().CACHE_DIR)
+                / "sampledata"
                 / pathlib.Path(sample_data_set_url).name
             ).unlink()
         except FileNotFoundError:
             pass
 
-        data_set = DataSet(sample_data_set_url, sample_data_set_sha256)
         with pytest.warns(
             RuntimeWarning,
             match="First access to .*, downloading remote file to local cache",
         ):
+            data_set = SampleDataSet(sample_data_set_url, sample_data_set_sha256)
             assert data_set.exists()
 
         data_set.unlink()
         sys.argv = sys.argv[:-1]
 
     def test_data_set(self, sample_data_set_url, sample_data_set_sha256):
-        data_set = DataSet(sample_data_set_url, sample_data_set_sha256)
+        data_set = SampleDataSet(sample_data_set_url, sample_data_set_sha256)
         assert data_set.exists()
         data_set.unlink()
 
     def test_data_set_invalid_hash(self, sample_data_set_url, sample_data_set_sha256):
-        data_set = DataSet(sample_data_set_url, sample_data_set_sha256)
+        data_set = SampleDataSet(sample_data_set_url, sample_data_set_sha256)
         data_set.write_text("foobar")  # change file, invalidate checksum
         del data_set
 
         # try again:
-        data_set = DataSet(sample_data_set_url, sample_data_set_sha256)
+        data_set = SampleDataSet(sample_data_set_url, sample_data_set_sha256)
         assert data_set.exists()
         data_set.unlink()