2. Find survey intersections#

[11]:
%load_ext autoreload
%autoreload 2


import logging

import geopandas as gpd
import pandas as pd
import plotly.io as pio

import airbornegeo

logging.getLogger("airbornegeo").setLevel("INFO")
logging.basicConfig()
pio.renderers.default = "notebook"
The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

2.1. Load data#

This is a subset of the BAS AGAP survey over Antarctica’s Gamburtsev Subglacial Mountains. The file is download and subset in the notebook AGAP_magnetic_survey, and the BAS processing steps are repeated in the notebook processing_AGAP_magnetic_survey.

[ ]:
data_df = pd.read_csv("data/AGAP_magnetic_survey_processed.csv")
data_df = data_df[
    [
        "easting",
        "northing",
        "height",
        "line",
        "unixtime",
        "distance_along_line",
        "mag",
    ]
]

# for testing limit number of lines
data_df = data_df[data_df.line.isin([149, 162, 47, 64, 80])]
data_df = data_df[
    ~(data_df.line == 47) | ~(data_df.distance_along_line.between(125e3, 134e3))
]
data_df = data_df[~(data_df.line == 64) | ~(data_df.distance_along_line > 497e3)]

data_df.head()
easting northing height line unixtime distance_along_line mag
244630 1.078385e+06 324738.995745 4188.1 47 1.230251e+09 0.0 11.24
244631 1.078385e+06 324738.995745 4188.1 47 1.230251e+09 0.0 8.04
244632 1.078385e+06 324738.995745 4188.1 47 1.230251e+09 0.0 4.84
244633 1.078385e+06 324738.995745 4188.1 47 1.230251e+09 0.0 1.64
244634 1.078385e+06 324738.995745 4188.1 47 1.230251e+09 0.0 -1.56
[13]:
# define flight lines vs tie lines with column 'tie' which is True or False
data_df["tie"] = False
data_df.loc[data_df.line >= 142, "tie"] = True
[14]:
data_df[data_df.tie].line.sort_values().unique()
[14]:
array([149, 162])
[15]:
data_df[~data_df.tie].line.sort_values().unique()
[15]:
array([47, 64, 80])
[16]:
airbornegeo.plotly_points(
    data_df,
    color_col="line",
    hover_cols=["distance_along_line", "tie"],
)

2.2. Calculate intersections of lines and ties#

[17]:
# convert dataframe into geodataframe
data_df = gpd.GeoDataFrame(
    data_df,
    geometry=gpd.points_from_xy(data_df.easting, data_df.northing),
    crs="EPSG:3031",
)
[21]:
# calculate theoretical intersection points
inters = airbornegeo.create_intersection_table(
    data_df,
    plot_hist=False,
)
inters
Line/tie combinations: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 6/6 [00:00<00:00, 1449.23it/s]
Potential intersections: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 5/5 [00:00<00:00, 203.44it/s]
INFO:airbornegeo:found 5 intersections
[21]:
line tie geometry max_dist easting northing
0 47 149 POINT (590788 237703) 12.785759 590788.0 237703.0
1 47 162 POINT (947875 301515) 1470.097394 947875.0 301515.0
2 64 162 POINT (961606 224280) 13.818089 961606.0 224280.0
3 80 149 POINT (616278 93894) 8.205492 616278.0 93894.0
4 80 162 POINT (973552 156679) 22.552582 973552.0 156679.0

From the above map and table we can see there are 5 intersection points. You can hover your mouse over the points in the plot to see some more information about them, including which line and tie they belong to, and the distance from the intersection point to the nearest actual measurement of the line and tie.

Theoretically since there are 2 ties and 3 lines, there could be 6 intersection points. Notice that line 64 ends just before crossing tie 149. If you zoom in on the flight survey plot, you can see this.

2.2.1. Buffer the ends of each line#

Since those two lines would cross if line 64 was just a few hundred meters longer, we can buffer all the lines to see if you can include it as an intersection. We show this below with the buffer_dist parameter.

[25]:
# calculate theoretical intersection points
inters = airbornegeo.create_intersection_table(
    data_df,
    buffer_dist=200,  # if intersection would be within 200 m of end of line, include it
    plot_hist=False,
)
inters
Line/tie combinations: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 6/6 [00:00<00:00, 829.10it/s]
Potential intersections: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 34/34 [00:00<00:00, 221.70it/s]
INFO:airbornegeo:found 6 intersections
[25]:
line tie geometry max_dist easting northing
0 47 149 POINT (590788 237703) 12.785759 590788.0 237703.0
1 47 162 POINT (947753 301493) 1346.129682 947753.0 301493.0
2 64 149 POINT (604391 161048) 173.862216 604391.0 161048.0
3 64 162 POINT (961606 224280) 13.818089 961606.0 224280.0
4 80 149 POINT (616278 93894) 8.205492 616278.0 93894.0
5 80 162 POINT (973552 156679) 22.552582 973552.0 156679.0

Now you can see we’ve included this 6th intersection, and it was only ~170m away from the end of line 64. Notice that the itersection of line 47 and tie 162 is over 1 km away from the nearest actual data point of line 47. This might be too far away to be useful as an intersection.

2.2.2. Exclude intersections far away from data#

Below we show how the cutoff_dist parameter can be used to exclude intersections which are far away from either the tie or line data. Each itersection point has a max_dist parameter, which is the largest of the distances between the point and the nearest line data point, and the point and the nearest tie data point.

[33]:
# calculate theoretical intersection points
inters = airbornegeo.create_intersection_table(
    data_df,
    buffer_dist=500,  # if intersection would be within 500 m of end of line, include it
    cutoff_dist=1e3,  # if intersection is more than 1km from nearest line or tie data, it is not included
    plot_hist=False,
)
inters
Line/tie combinations: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 6/6 [00:00<00:00, 865.13it/s]
Potential intersections: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 34/34 [00:00<00:00, 209.31it/s]
INFO:airbornegeo:found 6 intersections
INFO:airbornegeo:removed 1 intersection point(s) with a max distance greater than 1 km
[33]:
line tie geometry max_dist easting northing
0 47 149 POINT (590788 237703) 12.785759 590788.0 237703.0
1 64 149 POINT (604391 161048) 173.862216 604391.0 161048.0
2 64 162 POINT (961606 224280) 13.818089 961606.0 224280.0
3 80 149 POINT (616278 93894) 8.205492 616278.0 93894.0
4 80 162 POINT (973552 156679) 22.552582 973552.0 156679.0

We have now successfull included the intersection which was within 200 m of the end of a line using the buffer_dist, and also excluded the intersection which was over 1 km away from the nearest data point, using cutoff_dist.

2.2.3. Manually exclude intersections#

We can manually exclude intersections if we know they have issues. You can supply tuples of pairs on line and tie numbers, or if you want to exclude an entire line or tie, just supply the individual line or tie number.

[53]:
# calculate theoretical intersection points
inters = airbornegeo.create_intersection_table(
    data_df,
    buffer_dist=500,  # if intersection would be within 500 m of end of line, include it
    cutoff_dist=1e3,  # if intersection is more than 1km from nearest line or tie data, it is not included
    exclude_ints=[
        [47],
        [80, 149],
    ],  # exclude all intersection of line 47 and the intersection of 80 and 149
    plot_hist=False,
)
inters
Line/tie combinations: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 6/6 [00:00<00:00, 927.33it/s]
Potential intersections: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 34/34 [00:00<00:00, 227.49it/s]
INFO:airbornegeo:found 6 intersections
INFO:airbornegeo:removed 1 intersection point(s) with a max distance greater than 1 km
INFO:airbornegeo:manually omitted 2 intersections points
[53]:
line tie geometry max_dist easting northing
0 64 149 POINT (604391 161048) 173.862216 604391.0 161048.0
1 64 162 POINT (961606 224280) 13.818089 961606.0 224280.0
2 80 162 POINT (973552 156679) 22.552582 973552.0 156679.0