Skip to content

Commit

Permalink
Merge pull request #20 from etalbert102/opacitychange
Browse files Browse the repository at this point in the history
add ability to use gradient opacity
  • Loading branch information
etalbert102 authored Jun 21, 2024
2 parents 597df85 + c3e56b0 commit b8ceced
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 15 deletions.
2 changes: 1 addition & 1 deletion geochron/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""The package version"""

__version__ = 'v0.5.1' # pragma: no cover
__version__ = 'v0.5.2' # pragma: no cover
63 changes: 51 additions & 12 deletions geochron/visualization/folium.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Folium helpers"""
import json
from typing import Callable, Optional, Union
from typing import Any, Callable, Optional, Union
import h3
import pandas as pd
from branca.colormap import LinearColormap
Expand Down Expand Up @@ -107,16 +107,46 @@ def timehex_backgroundata(timehex: pd.DataFrame):

return backgroundata

def add_hashmap_properties(original_hashmap:dict, time:pd.Timestamp, opacity: float \
, cmap: Union[Optional[Callable]] = None):
def normalize(value: float, min_val: float, max_val: float):
"""
Normalize a value on a scale from 1 to 0 based on a given
min and max value.
Args:
value: a value
min_val: the minimum value
max_val: the maximum value
Returns:
a scaled value between 1 to 0
"""
if max_val == min_val:
raise ValueError("max_val and min_val cannot be equal (division by zero)")
scaled_value = (value - min_val) / (max_val - min_val)
return scaled_value

def constant_return(value: float, constant: Any):
"""
Returns a constant when fed a value
Args:
value: any value
constant: any constant
Returns:
the specified constant
"""
return constant

def add_hashmap_properties(original_hashmap:dict, time:pd.Timestamp, opacity: Union[float, str] \
, cmap: Union[Optional[Callable], list] = None):
"""
Adds properties to the hashmap necessary for display.
Args:
original_hashmap: a hashmap
time: time of hashmap
cmap: a Branca colormap or a list of colors
opacity: desired opacity of shapes
opacity: desired opacity of shapes takes key word gradient
to vary opacity based on weight of shape in the time period
Returns:
a GeoJson FeatureCollection
"""
Expand All @@ -127,11 +157,11 @@ def add_hashmap_properties(original_hashmap:dict, time:pd.Timestamp, opacity: fl
color_min = 0
color_max = 0
else:
max_key = max(removed_empty, key=removed_empty.get) # type: ignore[arg-type]
min_key = min(removed_empty, key=removed_empty.get) # type: ignore[arg-type]
color_min = removed_empty[min_key]
max_key = max(removed_empty, key=removed_empty.get) # type: ignore[arg-type]
min_key = min(removed_empty, key=removed_empty.get) # type: ignore[arg-type]
color_min = removed_empty[min_key]
color_max = removed_empty[max_key]

if cmap is None:
used_cmap = LinearColormap(colors=['blue','red'], \
vmin= color_min, vmax= color_max)
Expand All @@ -141,19 +171,28 @@ def add_hashmap_properties(original_hashmap:dict, time:pd.Timestamp, opacity: fl
else:
used_cmap = cmap

if opacity == "gradient":
used_opacity = lambda x: normalize(x,min_val = color_min, max_val= color_max)
else:
used_opacity = lambda x: constant_return(x, constant= opacity)

for key, value in removed_empty.items():
new_dict[key] = {'popup': 'weight= ' + str(value) +
'<br> center(lat,lon)= ' + str(h3.h3_to_geo(key)),
'time': time,'style':{'opacity': opacity, 'color': used_cmap(value)}}
'<br> center(lat,lon)= ' + str(h3.h3_to_geo(key)),
'time': time,'style':{'opacity': used_opacity(value), 'color': used_cmap(value),
'fillOpacity': used_opacity(value)}}
return new_dict

def timehex_timestampedgeojson(timehex: pd.DataFrame, opacity= float(.7), cmap: Union[Optional[Callable]] = None):
def timehex_timestampedgeojson(timehex: pd.DataFrame, opacity: Union[float, str] = .7 \
, cmap: Union[Optional[Callable], list] = None):
"""
Formats a timehex into the correct data format for Folium's timestampedgeojson
Args:
timehex: A timehex dataframe
opacity: desired opacity of shapes takes key word gradient
to vary opacity based on weight of shape in the time period
cmap: a Branca colormap or a list of colors
Returns:
a GeoJson FeatureCollection
"""
Expand Down
25 changes: 23 additions & 2 deletions tests/visualization/test_folium.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import pandas as pd
import h3
import pytest
from branca.colormap import LinearColormap
from geochron.visualization.folium import *

Expand Down Expand Up @@ -99,6 +100,26 @@ def test_timehex_backgroundata():
assert len(feature["geometry"]["coordinates"]) > 0
assert feature["id"] in timehex.columns

def test_normalize():
# Test case 1: Normalization with min_val = 0 and max_val = 1
assert normalize(0.5, 0, 1) == 0.5

# Test case 2: Normalization with min_val = -1 and max_val = 1
assert normalize(0, -1, 1) == 0.5

# Test case 3: Normalization with min_val = 10 and max_val = 20
assert normalize(15, 10, 20) == 0.5

with pytest.raises(ValueError):
normalize(0, 0, 0)

def test_constant_return():
# Test case 1: Value doesn't matter; constant should always be returned
assert constant_return(42, 5) == 5

# Test case 2: Another arbitrary value and constant
assert constant_return(0, -10) == -10


def test_add_hashmap_properties():
# Define a simple colormap function for testing
Expand All @@ -118,15 +139,15 @@ def cmap(value):
'89283082837ffff': {
'popup': 'weight= 1<br> center(lat,lon)= ' + str(h3.h3_to_geo('89283082837ffff')),
'time': time,
'style': {'opacity': opacity, 'color': cmap(1)}
'style': {'opacity': opacity, 'color': cmap(1), 'fillOpacity': opacity}
}
}

expected_result_color_list = {
'89283082837ffff': {
'popup': 'weight= 1<br> center(lat,lon)= ' + str(h3.h3_to_geo('89283082837ffff')),
'time': time,
'style': {'opacity': opacity, 'color': '#0000ffff'}
'style': {'opacity': opacity, 'color': '#0000ffff', 'fillOpacity': opacity}
}
}

Expand Down

0 comments on commit b8ceced

Please sign in to comment.