diff --git a/datascience/maps.py b/datascience/maps.py index 652491b3..ef8c4d6e 100644 --- a/datascience/maps.py +++ b/datascience/maps.py @@ -527,25 +527,40 @@ def copy(self): def _folium_kwargs(self): attrs = self._attrs.copy() attrs['location'] = self.lat_lon + icon_args = {k: attrs.pop(k) for k in attrs.keys() & {'color', 'marker_icon', 'clustered_marker', 'icon_angle', 'popup_width'}} if 'marker_icon' in icon_args: icon_args['icon'] = icon_args.pop('marker_icon') + if 'color' in icon_args and icon_args['color'][0] == '#': - # Checks if color provided is a hex code instead; if it is, uses BeautifyIcon to create markers. - # If statement does not check to see if color is an empty string. - icon_args['background_color'] = icon_args['border_color'] = icon_args.pop('color') - if icon_args['background_color'][1] == icon_args['background_color'][3] == icon_args['background_color'][5] == 'f': - icon_args['text_color'] = 'gray' - else: - icon_args['text_color'] = 'white' + # Use hex code -> BeautifyIcon + hex_color = icon_args.pop('color') + icon_args['background_color'] = hex_color + icon_args['border_color'] = hex_color + + # Determine a visible text color + def text_color_for_bg(bg): + bg = bg.lstrip('#') + r, g, b = int(bg[0:2], 16), int(bg[2:4], 16), int(bg[4:6], 16) + brightness = (r*299 + g*587 + b*114)/1000 + if brightness > 240: + return 'gray' + elif brightness > 186: + return 'black' + else: + return 'white' + + icon_args['textColor'] = text_color_for_bg(hex_color) icon_args['icon_shape'] = 'marker' if 'icon' not in icon_args: icon_args['icon'] = 'circle' attrs['icon'] = BeautifyIcon(**icon_args) else: attrs['icon'] = folium.Icon(**icon_args) + return attrs + def geojson(self, feature_id): """GeoJSON representation of the marker as a point.""" lat, lon = self.lat_lon diff --git a/datascience/tables.py b/datascience/tables.py index 51298c88..b7c5696f 100644 --- a/datascience/tables.py +++ b/datascience/tables.py @@ -3045,7 +3045,8 @@ def to_df(self): >>> type(table_df) - + + """ return pandas.DataFrame(self._columns) diff --git a/tests/test_formats.py b/tests/test_formats.py index 9659afd3..1124cdf4 100644 --- a/tests/test_formats.py +++ b/tests/test_formats.py @@ -152,3 +152,11 @@ def _mult_ten(v): func_formatter = formats.FunctionFormatter(_mult_ten) assert func_formatter.format_value(5) == '50' + +def test_distribution_formatter_negative(): + """Test that DistributionFormatter raises assertion on negative values.""" + import numpy as np + counts = np.array([9, 10, -18, 23]) + formatter = ds.DistributionFormatter() + with pytest.raises(AssertionError): + formatter.convert_column(counts) diff --git a/tests/test_maps.py b/tests/test_maps.py index de9b8e63..d9cfaa42 100644 --- a/tests/test_maps.py +++ b/tests/test_maps.py @@ -44,6 +44,7 @@ def test_setup_map(): 'width': 960, 'height': 500, 'features': [], + 'attr': 'Map data © OpenStreetMap contributors' } """ Tests features as NumPy array. """ kwargs2 = { @@ -56,6 +57,7 @@ def test_setup_map(): ds.Marker(51.514, -0.139), ds.Marker(51.519, -0.132) ]), + 'attr': 'Map data © OpenStreetMap contributors' } ds.Map(**kwargs1).show() ds.Map(**kwargs2).show() @@ -163,12 +165,14 @@ def test_marker_copy(): def test_background_color_condition_white(): # Test the condition when the background color is white (all 'f' in the hex code) marker = ds.Marker(0, 0, color='#ffffff') - assert marker._folium_kwargs['icon'].options['textColor'], 'gray' + assert marker._folium_kwargs['icon'].options.get('textColor', None) == 'gray' + def test_background_color_condition_not_white(): # Test the condition when the background color is not white marker = ds.Marker(0, 0, color='#ff0000') - assert marker._folium_kwargs['icon'].options['textColor'], 'white' + assert marker._folium_kwargs['icon'].options.get('textColor', None) == 'white' + def test_icon_args_icon_not_present(): # Test when 'icon' key is not present in icon_args diff --git a/tests/test_util.py b/tests/test_util.py index 5066b1f2..83e8d7c8 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -148,3 +148,33 @@ def __len__(self): pass is_sequence = IsSequence() assert ds.is_non_string_iterable(is_sequence) == True + + +def test_plot_normal_cdf_no_shading(): + """Test plot_normal_cdf with no shading.""" + ds.plot_normal_cdf() + + +def test_plot_normal_cdf_right_bound(): + """Test plot_normal_cdf with right boundary.""" + ds.plot_normal_cdf(rbound=1.5) + + +def test_plot_normal_cdf_left_bound(): + """Test plot_normal_cdf with left boundary.""" + ds.plot_normal_cdf(lbound=-1.5) + + +def test_plot_normal_cdf_both_bounds(): + """Test plot_normal_cdf with both boundaries.""" + ds.plot_normal_cdf(lbound=-1.0, rbound=1.0) + + +def test_plot_normal_cdf_custom_params(): + """Test plot_normal_cdf with custom mean and standard deviation.""" + ds.plot_normal_cdf(lbound=-2.0, rbound=2.0, mean=0, sd=1) + + +def test_plot_cdf_area(): + """Test plot_cdf_area (old name for plot_normal_cdf).""" + ds.plot_cdf_area(rbound=1.0)