Skip to content

Commit

Permalink
get_bearing_summary_stats: take alignment as input
Browse files Browse the repository at this point in the history
merges #37
  • Loading branch information
dhimmel authored Dec 31, 2024
1 parent 180398e commit ce1746b
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 39 deletions.
5 changes: 2 additions & 3 deletions openskistats/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ def analyze_all_ski_areas_polars(skip_runs: bool = False) -> None:
hemisphere=pl.first("hemisphere"),
_bearing_stats=pl.struct(
"bearing",
pl.col("distance_vertical_drop").alias("bearing_magnitude_net"),
pl.col("distance_vertical_drop").alias("bearing_magnitude_cum"),
"hemisphere",
).map_batches(_get_bearing_summary_stats_pl, returns_scalar=True),
Expand Down Expand Up @@ -263,8 +262,8 @@ def _get_bearing_summary_stats_pl(struct_series: pl.Series) -> BearingStatsModel
hemisphere = None
return get_bearing_summary_stats(
bearings=df.get_column("bearing").to_numpy(),
net_magnitudes=df.get_column("bearing_magnitude_net").to_numpy(),
cum_magnitudes=df.get_column("bearing_magnitude_cum").to_numpy(),
alignments=df.get_column("bearing_alignment", default=None),
hemisphere=hemisphere,
)

Expand Down Expand Up @@ -310,8 +309,8 @@ def aggregate_ski_areas_pl(
longitude=pl.mean("longitude"),
_bearing_stats=pl.struct(
pl.col("bearing_mean").alias("bearing"),
"bearing_magnitude_net",
"bearing_magnitude_cum",
"bearing_alignment",
"hemisphere",
).map_batches(_get_bearing_summary_stats_pl, returns_scalar=True),
)
Expand Down
18 changes: 9 additions & 9 deletions openskistats/bearing.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ def get_bearing_histogram(

def get_bearing_summary_stats(
bearings: list[float] | npt.NDArray[np.float64],
net_magnitudes: list[float] | npt.NDArray[np.float64] | None = None,
cum_magnitudes: list[float] | npt.NDArray[np.float64] | None = None,
alignments: list[float] | npt.NDArray[np.float64] | None = None,
hemisphere: Literal["north", "south"] | None = None,
) -> BearingStatsModel:
"""
Expand All @@ -255,14 +255,13 @@ def get_bearing_summary_stats(
bearings:
An array or list of bearing angles in degrees. These represent directions, headings, or orientations.
net_magnitudes:
An array or list of weights (importance factors, influence coefficients, scaling factors) applied to each bearing.
If None, all weights are assumed to be 1.
These represent external weighting factors, priorities, or significance levels assigned to each bearing.
cum_magnitudes:
An array or list of combined verticals of the each bearing.
If None, all combined verticals are assumed to be 1.
These represent the total verticals of all the original group of segments attributing to this bearing.
alignments:
An array or list of alignments between 0 and 1 useful for repeated bearing summarization.
Defaults to 100% alignment (1.0) for all bearings when not specified.
hemisphere:
The hemisphere in which the bearings are located used to calculate poleward affinity.
If None, poleward affinity is not calculated.
Expand All @@ -280,14 +279,15 @@ def get_bearing_summary_stats(
- https://chatgpt.com/share/6718521f-6768-8011-aed4-db345efb68b7
- https://chatgpt.com/share/a2648aee-194b-4744-8a81-648d124d17f2
"""
if net_magnitudes is None:
net_magnitudes = np.ones_like(bearings, dtype=np.float64)
if cum_magnitudes is None:
cum_magnitudes = np.ones_like(bearings, dtype=np.float64)
if alignments is None:
alignments = np.ones_like(bearings, dtype=np.float64)
bearings = np.array(bearings, dtype=np.float64)
net_magnitudes = np.array(net_magnitudes, dtype=np.float64)
cum_magnitudes = np.array(cum_magnitudes, dtype=np.float64)
assert bearings.shape == net_magnitudes.shape == cum_magnitudes.shape
alignments = np.array(alignments, dtype=np.float64)
assert bearings.shape == cum_magnitudes.shape == alignments.shape
net_magnitudes = cum_magnitudes * alignments

# Sum all vectors in their complex number form using weights and bearings
total_complex = sum(net_magnitudes * np.exp(1j * np.deg2rad(bearings)))
Expand Down
1 change: 0 additions & 1 deletion openskistats/osmnx_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ def create_networkx_with_metadata(
graph.graph["combined_vertical"] = sum(weights)
stats = get_bearing_summary_stats(
bearings=bearings,
net_magnitudes=weights,
cum_magnitudes=weights,
hemisphere=graph.graph["hemisphere"],
)
Expand Down
1 change: 0 additions & 1 deletion openskistats/plot_runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ def get_latitude_histogram(self) -> pl.DataFrame:
*self._get_agg_metrics(),
_bearing_stats=pl.struct(
"bearing",
pl.col("distance_vertical_drop").alias("bearing_magnitude_net"),
pl.col("distance_vertical_drop").alias("bearing_magnitude_cum"),
"hemisphere",
).map_batches(_get_bearing_summary_stats_pl, returns_scalar=True),
Expand Down
50 changes: 25 additions & 25 deletions openskistats/tests/test_bearing.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ class BearingSummaryStatsPytestParam:
"""

bearings: list[float]
weights: list[float] | None
combined_vertical: list[float] | None
alignments: list[float] | None
hemisphere: Literal["north", "south"] | None
expected_bearing: float
expected_strength: float
expected_alignment: float
expected_poleward_affinity: float | None = None
excepted_eastward_affinity: float | None = None

Expand All @@ -69,92 +69,92 @@ class BearingSummaryStatsPytestParam:
[
BearingSummaryStatsPytestParam(
bearings=[0.0],
weights=[2.0],
combined_vertical=[2.0],
alignments=[1.0],
hemisphere="north",
expected_bearing=0.0,
expected_strength=1.0,
expected_alignment=1.0,
expected_poleward_affinity=1.0,
excepted_eastward_affinity=0.0,
),
BearingSummaryStatsPytestParam(
bearings=[0.0, 90.0],
weights=[1.0, 1.0],
combined_vertical=None,
alignments=[1.0, 1.0],
hemisphere="south",
expected_bearing=45.0,
expected_strength=0.7071068,
expected_alignment=0.7071068,
expected_poleward_affinity=-0.5,
excepted_eastward_affinity=0.5,
),
BearingSummaryStatsPytestParam(
bearings=[0.0, 90.0],
weights=[0.5, 0.5],
combined_vertical=[0.5, 0.5],
alignments=[1.0, 1.0],
hemisphere="north",
expected_bearing=45.0,
expected_strength=0.7071068,
expected_alignment=0.7071068,
expected_poleward_affinity=0.5,
excepted_eastward_affinity=0.5,
),
BearingSummaryStatsPytestParam(
bearings=[0.0, 90.0],
weights=None,
combined_vertical=[2.0, 2.0],
alignments=None,
hemisphere="north",
expected_bearing=45.0,
expected_strength=0.3535534,
expected_poleward_affinity=0.25,
excepted_eastward_affinity=0.25,
expected_alignment=0.7071068,
expected_poleward_affinity=0.5,
excepted_eastward_affinity=0.5,
),
BearingSummaryStatsPytestParam(
bearings=[0.0, 360.0],
weights=[1.0, 1.0],
combined_vertical=None,
alignments=[1.0, 1.0],
hemisphere="north",
expected_bearing=0.0,
expected_strength=1.0,
expected_alignment=1.0,
expected_poleward_affinity=1.0,
excepted_eastward_affinity=0.0,
),
BearingSummaryStatsPytestParam(
bearings=[0.0, 90.0],
weights=[0.0, 1.0],
combined_vertical=[0.5, 1.5],
alignments=[0.0, 1.0],
hemisphere="north",
expected_bearing=90.0,
expected_strength=0.5,
expected_alignment=0.75,
expected_poleward_affinity=0.0,
excepted_eastward_affinity=0.5,
excepted_eastward_affinity=0.75,
),
BearingSummaryStatsPytestParam(
bearings=[90.0, 270.0],
weights=None,
combined_vertical=None,
alignments=None,
hemisphere="north",
expected_bearing=0.0,
expected_strength=0.0,
expected_alignment=0.0,
expected_poleward_affinity=0.0,
excepted_eastward_affinity=0.0,
), # should cancel each other out
BearingSummaryStatsPytestParam(
bearings=[90.0],
weights=[0.0],
combined_vertical=None,
alignments=[0.0],
hemisphere="north",
expected_bearing=0.0,
expected_strength=0.0,
expected_alignment=0.0,
expected_poleward_affinity=0.0,
excepted_eastward_affinity=0.0,
), # strength can only be 0 when weight is 0
# weights and strengths
BearingSummaryStatsPytestParam(
bearings=[0.0, 90.0],
weights=[2, 4],
combined_vertical=[10.0, 10.0],
alignments=[0.2, 0.4],
hemisphere="north",
expected_bearing=63.4349488,
expected_strength=0.2236068,
expected_alignment=0.2236068,
expected_poleward_affinity=0.1,
excepted_eastward_affinity=0.2,
),
Expand All @@ -163,12 +163,12 @@ class BearingSummaryStatsPytestParam:
def test_get_bearing_summary_stats(param: BearingSummaryStatsPytestParam) -> None:
stats = get_bearing_summary_stats(
bearings=param.bearings,
net_magnitudes=param.weights,
cum_magnitudes=param.combined_vertical,
alignments=param.alignments,
hemisphere=param.hemisphere,
)
assert stats.bearing_mean == pytest.approx(param.expected_bearing)
assert stats.bearing_alignment == pytest.approx(param.expected_strength)
assert stats.bearing_alignment == pytest.approx(param.expected_alignment)
assert stats.poleward_affinity == pytest.approx(param.expected_poleward_affinity)
assert stats.eastward_affinity == pytest.approx(param.excepted_eastward_affinity)

Expand Down

0 comments on commit ce1746b

Please sign in to comment.