Skip to content
This repository was archived by the owner on Sep 21, 2026. It is now read-only.

Commit 3666bcb

Browse files
Fix: refactor sorter (#233)
* refactor sorter * fix sorter abstract class sort method to include optional parameters * refactor calculate_stratigraphic_order in project class * style: style fixes by ruff and autoformatting by black * add libjpeg-turbo installation to yml file * fix dtm in SorterObservationProjections
1 parent 7076512 commit 3666bcb

3 files changed

Lines changed: 47 additions & 27 deletions

File tree

‎.github/workflows/linting_and_testing.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,23 @@ jobs:
5353
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
5454
run: |
5555
conda run -n test conda info
56-
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
56+
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
5757
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
5858
conda run -n test conda install pytest python=${{ matrix.python-version }} -y
5959
6060
- name: Install dependencies for windows python 3.11
6161
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
6262
run: |
6363
conda run -n test conda info
64-
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
64+
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
6565
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
6666
conda run -n test conda install pytest python=${{ matrix.python-version }} -y
6767
6868
- name: Install dependencies for other environments
6969
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
7070
run: |
7171
conda run -n test conda info
72-
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
72+
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y
7373
7474
- name: Install map2loop
7575
run: |

‎map2loop/project.py‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
569569
self.stratigraphic_column.stratigraphicUnits,
570570
self.topology.get_unit_unit_relationships(),
571571
self.contact_extractor.contacts,
572-
self.map_data,
572+
self.map_data.get_map_data(Datatype.GEOLOGY),
573+
self.map_data.get_map_data(Datatype.STRUCTURE),
574+
self.map_data.get_map_data(Datatype.DTM),
573575
)
574576
for sorter in sorters
575577
]
@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
601603
self.stratigraphic_column.stratigraphicUnits,
602604
self.topology.get_unit_unit_relationships(),
603605
self.contact_extractor.contacts,
604-
self.map_data,
606+
self.map_data.get_map_data(Datatype.GEOLOGY),
607+
self.map_data.get_map_data(Datatype.STRUCTURE),
608+
self.map_data.get_map_data(Datatype.DTM),
605609
)
606610

607611
@beartype.beartype
@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
11651169
target_ds.SetProjection(geol.crs.to_string())
11661170
target_ds = None
11671171
source_layer = None
1168-
source_ds = None
1172+
source_ds = None

‎map2loop/sorter.py‎

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import pandas
44
import numpy as np
55
import math
6-
from .mapdata import MapData
76
from typing import Union
7+
from osgeo import gdal
8+
import geopandas
89

10+
from map2loop.utils import value_from_raster
911
from .logging import getLogger
1012

1113
logger = getLogger(__name__)
@@ -41,7 +43,9 @@ def sort(
4143
units: pandas.DataFrame,
4244
unit_relationships: pandas.DataFrame,
4345
contacts: pandas.DataFrame,
44-
map_data: MapData,
46+
geology_data: geopandas.GeoDataFrame = None,
47+
structure_data: geopandas.GeoDataFrame = None,
48+
dtm_data: gdal.Dataset = None,
4549
) -> list:
4650
"""
4751
Execute sorter method (abstract method)
@@ -50,7 +54,9 @@ def sort(
5054
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
5155
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
5256
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
53-
map_data (map2loop.MapData): a catchall so that access to all map data is available
57+
geology_data (geopandas.GeoDataFrame): the geology data
58+
structure_data (geopandas.GeoDataFrame): the structure data
59+
dtm_data (ggdal.Dataset): the dtm data
5460
5561
Returns:
5662
list: sorted list of unit names
@@ -75,7 +81,9 @@ def sort(
7581
units: pandas.DataFrame,
7682
unit_relationships: pandas.DataFrame,
7783
contacts: pandas.DataFrame,
78-
map_data: MapData,
84+
geology_data: geopandas.GeoDataFrame = None,
85+
structure_data: geopandas.GeoDataFrame = None,
86+
dtm_data: gdal.Dataset = None,
7987
) -> list:
8088
"""
8189
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
@@ -84,7 +92,6 @@ def sort(
8492
units (pandas.DataFrame): the data frame to sort
8593
units_relationships (pandas.DataFrame): the relationships between units
8694
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
87-
map_data (map2loop.MapData): a catchall so that access to all map data is available
8895
8996
Returns:
9097
list: the sorted unit names
@@ -140,7 +147,9 @@ def sort(
140147
units: pandas.DataFrame,
141148
unit_relationships: pandas.DataFrame,
142149
contacts: pandas.DataFrame,
143-
map_data: MapData,
150+
geology_data: geopandas.GeoDataFrame = None,
151+
structure_data: geopandas.GeoDataFrame = None,
152+
dtm_data: gdal.Dataset = None,
144153
) -> list:
145154
"""
146155
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
@@ -150,7 +159,6 @@ def sort(
150159
units_relationships (pandas.DataFrame): the relationships between units
151160
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
152161
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
153-
map_data (map2loop.MapData): a catchall so that access to all map data is available
154162
155163
Returns:
156164
list: the sorted unit names
@@ -192,7 +200,9 @@ def sort(
192200
units: pandas.DataFrame,
193201
unit_relationships: pandas.DataFrame,
194202
contacts: pandas.DataFrame,
195-
map_data: MapData,
203+
geology_data: geopandas.GeoDataFrame = None,
204+
structure_data: geopandas.GeoDataFrame = None,
205+
dtm_data: gdal.Dataset = None,
196206
) -> list:
197207
"""
198208
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
@@ -202,7 +212,6 @@ def sort(
202212
units_relationships (pandas.DataFrame): the relationships between units
203213
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
204214
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
205-
map_data (map2loop.MapData): a catchall so that access to all map data is available
206215
207216
Returns:
208217
list: the sorted unit names
@@ -280,7 +289,9 @@ def sort(
280289
units: pandas.DataFrame,
281290
unit_relationships: pandas.DataFrame,
282291
contacts: pandas.DataFrame,
283-
map_data: MapData,
292+
geology_data: geopandas.GeoDataFrame = None,
293+
structure_data: geopandas.GeoDataFrame = None,
294+
dtm_data: gdal.Dataset = None,
284295
) -> list:
285296
"""
286297
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
@@ -290,7 +301,6 @@ def sort(
290301
units_relationships (pandas.DataFrame): the relationships between units
291302
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
292303
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
293-
map_data (map2loop.MapData): a catchall so that access to all map data is available
294304
295305
Returns:
296306
list: the sorted unit names
@@ -362,7 +372,9 @@ def sort(
362372
units: pandas.DataFrame,
363373
unit_relationships: pandas.DataFrame,
364374
contacts: pandas.DataFrame,
365-
map_data: MapData,
375+
geology_data: geopandas.GeoDataFrame,
376+
structure_data: geopandas.GeoDataFrame,
377+
dtm_data: gdal.Dataset
366378
) -> list:
367379
"""
368380
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
@@ -372,19 +384,25 @@ def sort(
372384
units_relationships (pandas.DataFrame): the relationships between units
373385
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
374386
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
375-
map_data (map2loop.MapData): a catchall so that access to all map data is available
387+
geology_data (geopandas.GeoDataFrame): the geology data
388+
structure_data (geopandas.GeoDataFrame): the structure data
389+
dtm_data (ggdal.Dataset): the dtm data
376390
377391
Returns:
378392
list: the sorted unit names
379393
"""
380394
import networkx as nx
381395
import networkx.algorithms.approximation as nx_app
382396
from shapely.geometry import LineString, Point
383-
from map2loop.m2l_enums import Datatype
384397

385-
geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
386-
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
387-
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
398+
geol = geology_data.copy()
399+
if "INTRUSIVE" in geol.columns:
400+
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
401+
if "SILL" in geol.columns:
402+
geol = geol.drop(geol.index[geol["SILL"]])
403+
orientations = structure_data.copy()
404+
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
405+
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)
388406

389407
# Create a map of maps to store younger/older observations
390408
ordered_unit_observations = []
@@ -434,11 +452,9 @@ def sort(
434452
continue
435453

436454
# Get heights for intersection point and start of ray
437-
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
455+
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
438456
first_intersect_point = Point(start.x, start.y, height)
439-
height = map_data.get_value_from_raster(
440-
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
441-
)
457+
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
442458
second_intersect_point = Point(second_intersect_point.x, start.y, height)
443459

444460
# Check vertical difference between points and compare to projected dip angle

0 commit comments

Comments
 (0)