Skip to content

Commit

Permalink
Merge pull request #23 from tariqshihadah/dev
Browse files Browse the repository at this point in the history
Prepare for 0.1.1 release
  • Loading branch information
tariqshihadah authored Aug 20, 2024
2 parents a3c7cd0 + 1650c8d commit c061557
Show file tree
Hide file tree
Showing 12 changed files with 1,159 additions and 34 deletions.
9 changes: 7 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,14 @@ performing an aggregation function over these values::

Version Notes
=============
0.1.1 (2024-01-31)
0.1.1 (2024-08-20)
-------------------
* Addition of array-like and dataframe label-based length parameter options to the ``EventsCollection.to_windows()`` method. This allows for the creation of segments based on a variable length.
* Addition of array-like, dataframe label-based, and callable ``length`` parameter options to the ``EventsCollection.to_windows()`` method and ``distance`` parameter to the ``EventsCollection.shift()`` method. This allows for the creation of segments based on a variable length. This will be made available to other methods in future versions as well.
* Address ``numpy>=2.x`` compatibility issue in ``EventsCollection.dissolve()`` method which was causing errors in some cases. More fixes related to ``numpy`` updates are expected to come in future versions.
* Address datatype loss issues for LRS columns during ``EventsCollection.to_windows()`` and ``EventsUnion.union()`` methods. This was causing some instances of key columns to be converted to incorrect dtypes.
* Restructure .targets property to be ``keys + [beg, end]`` for more intuitive and consistent performance.
* Addition of ``min`` and ``max`` aggregation methods to the ``EventsMergeAttribute`` class.
* Several example Jupyter Notebooks for common use cases have been added to the ``examples`` folder for user reference. More to come.
* Performance improvements
* Various bug fixes, minor features

Expand Down
221 changes: 221 additions & 0 deletions examples/creating_line_geoms_from_mm.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "cecaac91-c136-4042-a519-004e792ba3e9",
"metadata": {},
"source": [
"# Generating line geometries from a table of line-events with known Route IDs and mile markers\n",
"\n",
"Suppose we have a table of line events with Route ID and mile marker information about where each event happened, but with no associated geometries. \n",
"Suppose further that we also have the linework of the reference routes. \n",
"\n",
"We can use `linref` to generate geometries for each of the rows of the line data. The example below shows the step-by-step process."
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "7c4eb0d7-a00c-44fb-9b89-73652a1d6327",
"metadata": {},
"outputs": [],
"source": [
"# Import dependencies\n",
"from shapely.geometry import LineString\n",
"import pandas as pd\n",
"import geopandas as gpd\n",
"import linref as lr"
]
},
{
"cell_type": "markdown",
"id": "0f552310-3fb3-481d-8901-61cd4e82ff89",
"metadata": {},
"source": [
"First, let's create the sample DataFrames and GeoDataFrames we'll be using throughout this example."
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "2067add6-53de-4d7f-aab9-846a50b44926",
"metadata": {},
"outputs": [],
"source": [
"# `line_df` is the DataFrame containing the lines with route ID and mile marker info but without any\n",
"# actual geometries \n",
"line_df = pd.DataFrame({\n",
" 'line_id':[1,2,3,4],\n",
" 'route_id':['A','A','B','B'],\n",
" 'beg':[1,2,2,3],\n",
" 'end':[2,3,3,4]\n",
"})\n",
"\n",
"\n",
"# `ref_gdf` is the GeoDataFrame that contains the reference linework of the roadway network\n",
"ref_gdf = gpd.GeoDataFrame({\n",
" 'route_id': ['A','B'],\n",
" 'beg': [0,0],\n",
" 'end': [5,5],\n",
" 'geometry': [LineString(((0,0),(5,0))), LineString(((0,2),(5,2)))]\n",
"})"
]
},
{
"cell_type": "markdown",
"id": "4ec5b870-b919-40f2-a296-c876a763ed98",
"metadata": {},
"source": [
"The first processing step is to create `EventCollection` objects for both sets:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "4151acae-13b6-41ce-9d00-029766c45276",
"metadata": {},
"outputs": [],
"source": [
"# For the reference object, notice how we specify the `beg` and `end` parameters because we are dealing with a link-based object.\n",
"# The idea here is that the `beg` and `end` columns indicate which columns contain the start and end mile marker information for \n",
"# each link. \n",
"ref_ec = lr.EventsCollection(\n",
" ref_gdf,\n",
" keys=['route_id'],\n",
" beg='beg',\n",
" end='end',\n",
" geom='geometry'\n",
")\n",
"\n",
"# For the line object, we also need to specify the `beg` and `end` parameters. \n",
"line_ec = lr.EventsCollection(\n",
" line_df, \n",
" keys=['route_id'],\n",
" beg='beg',\n",
" end='end'\n",
")"
]
},
{
"cell_type": "markdown",
"id": "59c9f888-e73d-4a1c-9235-38d8e423c9b9",
"metadata": {},
"source": [
"We then need to build the routes for the reference `EventsCollection` object.\n",
"This step directs the `linref` library to perform some internal processing steps that are required for GIS-based operations."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "3cd299b7-e762-4d5d-a9f1-a095fb0e790b",
"metadata": {},
"outputs": [],
"source": [
"ref_ec.build_routes()"
]
},
{
"cell_type": "markdown",
"id": "16b25371-447b-4019-aaba-fee9d57ddf45",
"metadata": {},
"source": [
"Then, we can create the new geometries by merging the `line_ec` with the `ref_ec` and applying the `cut()` method. \n",
"This will generate a numpy array of `MultiLineString` geometries, which can easily be added to your DataFrame. "
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "b709333b-6f87-4df4-8dee-82661ec4b95e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2 MULTILINESTRING ((2 2, 3 2))\n",
"3 MULTILINESTRING ((3 2, 4 2))\n",
"0 MULTILINESTRING ((1 0, 2 0))\n",
"1 MULTILINESTRING ((2 0, 3 0))\n",
"Name: route, dtype: object\n"
]
}
],
"source": [
"# Now we can merge the point and reference EventsCollections and cut new geometries. The `merge` method defines \n",
"# a linearly referenced relationship between the target and merged collections which can be used to cut new geometries. \n",
"# This relationship is captured and managed within an `EventsMerge` object, commonly referred to as `em`.\n",
"em = line_ec.merge(ref_ec)\n",
"\n",
"# The `cut` method is one of the many aggregators available using the `EventsMerge` class.\n",
"new_geoms = em.cut()\n",
"print(new_geoms)"
]
},
{
"cell_type": "markdown",
"id": "5cc64d52-6ab5-4f22-835a-c0f3fd811c0a",
"metadata": {},
"source": [
"Finally, if you want to want to create a full-fledged GeoDataFrame, you can just make a copy of your original input DataFrame and add the new array of lines as the geometry column."
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "073e2a67-b1db-4eb4-9023-e962523ee911",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" line_id route_id beg end \\\n",
"0 1 A 1 2 \n",
"1 2 A 2 3 \n",
"2 3 B 2 3 \n",
"3 4 B 3 4 \n",
"\n",
" geometry \n",
"0 MULTILINESTRING ((1.00000 0.00000, 2.00000 0.0... \n",
"1 MULTILINESTRING ((2.00000 0.00000, 3.00000 0.0... \n",
"2 MULTILINESTRING ((2.00000 2.00000, 3.00000 2.0... \n",
"3 MULTILINESTRING ((3.00000 2.00000, 4.00000 2.0... \n",
" line_id route_id beg end\n",
"0 1 A 1 2\n",
"1 2 A 2 3\n",
"2 3 B 2 3\n",
"3 4 B 3 4\n"
]
}
],
"source": [
"# Create a new GeoDataFrame with the interpolated geometries\n",
"line_gdf = gpd.GeoDataFrame(line_df, geometry=new_geoms)\n",
"print(line_gdf)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit c061557

Please sign in to comment.