Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/linting_and_testing.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,23 +53,23 @@ jobs:
if: ${{ matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10') }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge "gdal=3.4.3" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for windows python 3.11
if: ${{ matrix.os == 'windows-latest' && matrix.python-version == '3.11' }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} -y
conda run -n test conda install -c loop3d -c conda-forge gdal "netcdf4=*=nompi_py311*" python=${{ matrix.python-version }} libjpeg-turbo -y
conda run -n test conda install -c loop3d -c conda-forge --file dependencies.txt python=${{ matrix.python-version }} -y
conda run -n test conda install pytest python=${{ matrix.python-version }} -y

- name: Install dependencies for other environments
if: ${{ !(matrix.os == 'windows-latest' && (matrix.python-version == '3.9' || matrix.python-version == '3.10' || matrix.python-version == '3.11')) }}
run: |
conda run -n test conda info
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest --file dependencies.txt -y
conda run -n test conda install -c loop3d -c conda-forge python=${{ matrix.python-version }} gdal pytest libjpeg-turbo --file dependencies.txt -y

- name: Install map2loop
run: |
Expand Down
10 changes: 7 additions & 3 deletions map2loop/project.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -569,7 +569,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)
for sorter in sorters
]
Expand DownExpand Up@@ -601,7 +603,9 @@ def calculate_stratigraphic_order(self, take_best=False):
self.stratigraphic_column.stratigraphicUnits,
self.topology.get_unit_unit_relationships(),
self.contact_extractor.contacts,
self.map_data,
self.map_data.get_map_data(Datatype.GEOLOGY),
self.map_data.get_map_data(Datatype.STRUCTURE),
self.map_data.get_map_data(Datatype.DTM),
)

@beartype.beartype
Expand DownExpand Up@@ -1165,4 +1169,4 @@ def save_geotiff_raster(
target_ds.SetProjection(geol.crs.to_string())
target_ds = None
source_layer = None
source_ds = None
source_ds = None
58 changes: 37 additions & 21 deletions map2loop/sorter.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,9 +3,11 @@
import pandas
import numpy as np
import math
from .mapdata import MapData
from typing import Union
from osgeo import gdal
import geopandas

from map2loop.utils import value_from_raster
from .logging import getLogger

logger = getLogger(__name__)
Expand DownExpand Up@@ -41,7 +43,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method (abstract method)
Expand All@@ -50,7 +54,9 @@ def sort(
units (pandas.DataFrame): the data frame to sort (columns must contain ["layerId", "name", "minAge", "maxAge", "group"])
units_relationships (pandas.DataFrame): the relationships between units (columns must contain ["Index1", "Unitname1", "Index2", "Unitname2"])
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: sorted list of unit names
Expand All@@ -75,7 +81,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -84,7 +92,6 @@ def sort(
units (pandas.DataFrame): the data frame to sort
units_relationships (pandas.DataFrame): the relationships between units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -140,7 +147,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -150,7 +159,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -192,7 +200,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -202,7 +212,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -280,7 +289,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame = None,
structure_data: geopandas.GeoDataFrame = None,
dtm_data: gdal.Dataset = None,
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -290,7 +301,6 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available

Returns:
list: the sorted unit names
Expand DownExpand Up@@ -362,7 +372,9 @@ def sort(
units: pandas.DataFrame,
unit_relationships: pandas.DataFrame,
contacts: pandas.DataFrame,
map_data: MapData,
geology_data: geopandas.GeoDataFrame,
structure_data: geopandas.GeoDataFrame,
dtm_data: gdal.Dataset
) -> list:
"""
Execute sorter method takes unit data, relationships and a hint and returns the sorted unit names based on this algorithm.
Expand All@@ -372,19 +384,25 @@ def sort(
units_relationships (pandas.DataFrame): the relationships between units
stratigraphic_order_hint (list): a list of unit names to use as a hint to sorting the units
contacts (pandas.DataFrame): unit contacts with length of the contacts in metres
map_data (map2loop.MapData): a catchall so that access to all map data is available
geology_data (geopandas.GeoDataFrame): the geology data
structure_data (geopandas.GeoDataFrame): the structure data
dtm_data (ggdal.Dataset): the dtm data

Returns:
list: the sorted unit names
"""
import networkx as nx
import networkx.algorithms.approximation as nx_app
from shapely.geometry import LineString, Point
from map2loop.m2l_enums import Datatype

geol = map_data.get_map_data(Datatype.GEOLOGY).copy()
geol = geol.drop(geol.index[np.logical_or(geol["INTRUSIVE"], geol["SILL"])])
orientations = map_data.get_map_data(Datatype.STRUCTURE).copy()
geol = geology_data.copy()
if "INTRUSIVE" in geol.columns:
geol = geol.drop(geol.index[geol["INTRUSIVE"]])
if "SILL" in geol.columns:
geol = geol.drop(geol.index[geol["SILL"]])
orientations = structure_data.copy()
inv_geotransform = gdal.InvGeoTransform(dtm_data.GetGeoTransform())
dtm_array = np.array(dtm_data.GetRasterBand(1).ReadAsArray().T)

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

# Get heights for intersection point and start of ray
height = map_data.get_value_from_raster(Datatype.DTM, start.x, start.y)
height = value_from_raster(inv_geotransform, dtm_array, start.x, start.y)
first_intersect_point = Point(start.x, start.y, height)
height = map_data.get_value_from_raster(
Datatype.DTM, second_intersect_point.x, second_intersect_point.y
)
height = value_from_raster(inv_geotransform, dtm_array, second_intersect_point.x, second_intersect_point.y)
second_intersect_point = Point(second_intersect_point.x, start.y, height)

# Check vertical difference between points and compare to projected dip angle
Expand Down
Loading