Skip to content
Open
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
16 changes: 13 additions & 3 deletions graphistry/layout/ring/categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def ring_categorical(
format_axis: Optional[Callable[[List[Dict]], List[Dict]]] = None,
format_labels: Optional[Callable[[Any, int, float], str]] = None,
reverse: bool = False,
play_ms: int = 0,
play_ms: Optional[int] = None,
engine: EngineAbstractType = EngineAbstract.AUTO
) -> Plottable:

Expand All @@ -102,7 +102,7 @@ def ring_categorical(
:format_axis: Optional[Callable[[List[Dict]], List[Dict]]] Optional transform function to format axis
:format_label: Optional[Callable[[Any, int, float], str]] Optional transform function to format axis label text based on axis value, ring number, and ring position
:reverse: bool Reverse the direction of the rings
:play_ms: int initial layout time in milliseconds, default 2000
:play_ms: Optional[int] initial layout time in milliseconds. If None (default), honors existing url_params['play'] or defaults to 0
:engine: EngineAbstractType, default EngineAbstract.AUTO, pick CPU vs GPU engine via 'auto', 'pandas', 'cudf'

:returns: Plotter
Expand Down Expand Up @@ -250,13 +250,23 @@ def unique() -> List[Any]:

#print('axis', axis)

if play_ms is not None:
play_value = play_ms
elif 'play' in g._url_params:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong - if 0 is set, we should respect it

I can imagine changing the type signature to : Optional[int] = 0, and having None mean "honor url param if already set, otherwise default to 0", but that feels unnecessarily complicated

try:
play_value = int(g._url_params['play'])
except (ValueError, TypeError):
play_value = 0
else:
play_value = 0

g2 = (
g
.nodes(lambda g: g._nodes.assign(x=x, y=y, r=r))
.encode_axis(axis_out)
.bind(point_x='x', point_y='y')
.settings(url_params={
'play': play_ms,
'play': play_value,
'lockedR': True,
'bg': '%23E2E2E2' # Light grey due to labels being fixed to dark
})
Expand Down
16 changes: 13 additions & 3 deletions graphistry/layout/ring/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def ring_continuous(
format_axis: Optional[Callable[[List[Dict]], List[Dict]]] = None,
format_labels: Optional[Callable[[float, int, float], str]] = None,
reverse: bool = False,
play_ms: int = 0,
play_ms: Optional[int] = None,
engine: EngineAbstractType = EngineAbstract.AUTO
) -> Plottable:

Expand Down Expand Up @@ -105,7 +105,7 @@ def ring_continuous(
:format_axis: Optional[Callable[[List[Dict]], List[Dict]]] Optional transform function to format axis
:format_label: Optional[Callable[[float, int, float], str]] Optional transform function to format axis label text based on axis value, ring number, and ring width
:reverse: bool Reverse the direction of the rings
:play_ms: int initial layout time in milliseconds, default 2000
:play_ms: Optional[int] initial layout time in milliseconds. If None (default), honors existing url_params['play'] or defaults to 0
:engine: EngineAbstractType, default EngineAbstract.AUTO, pick CPU vs GPU engine via 'auto', 'pandas', 'cudf'

:returns: Plotter
Expand Down Expand Up @@ -248,13 +248,23 @@ def ring_continuous(

#print('axis', axis)

if play_ms is not None:
play_value = play_ms
elif 'play' in g._url_params:
try:
play_value = int(g._url_params['play'])
except (ValueError, TypeError):
play_value = 0
else:
play_value = 0

g2 = (
g
.nodes(lambda g: g._nodes.assign(x=x, y=y, r=r))
.encode_axis(axis_out)
.bind(point_x='x', point_y='y')
.settings(url_params={
'play': play_ms,
'play': play_value,
'lockedR': True,
'bg': '%23E2E2E2' # Light grey due to labels being fixed to dark
})
Expand Down
16 changes: 13 additions & 3 deletions graphistry/layout/ring/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def time_ring(
format_axis: Optional[Callable[[List[Dict]], List[Dict]]] = None,
format_label: Optional[Callable[[np.datetime64, int, np.timedelta64], str]] = None,
format_labels: Optional[Callable[[np.datetime64, int, np.timedelta64], str]] = None,
play_ms: int = 2000,
play_ms: Optional[int] = None,
engine: EngineAbstractType = EngineAbstract.AUTO
) -> Plottable:
"""Radial graph layout where nodes are positioned based on a datetime64-typed column time_col
Expand All @@ -250,7 +250,7 @@ def time_ring(
:format_axis: Optional[Callable[[List[Dict]], List[Dict]]] Optional transform function to format axis
:format_label: Optional[Callable[[numpy.datetime64, int, numpy.timedelta64], str]] Optional transform function to format axis label text based on axis time, ring number, and ring duration width
:format_labels: Optional[Callable[[numpy.datetime64, int, numpy.timedelta64], str]] Deprecated alias for ``format_label``
:play_ms: int initial layout time in milliseconds, default 2000
:play_ms: Optional[int] initial layout time in milliseconds. If None (default), honors existing url_params['play'] or defaults to 2000
:engine: EngineAbstractType, default EngineAbstract.AUTO, pick CPU vs GPU engine via 'auto', 'pandas', 'cudf'

:returns: Plotter
Expand Down Expand Up @@ -401,13 +401,23 @@ def time_ring(

#print('axis', axis)

if play_ms is not None:
play_value = play_ms
elif 'play' in g._url_params:
try:
play_value = int(g._url_params['play'])
except (ValueError, TypeError):
play_value = 2000
else:
play_value = 2000

g2 = (
g
.nodes(lambda g: g._nodes.assign(x=x, y=y, r=r))
.bind(point_x='x', point_y='y')
.encode_axis(axis)
.settings(url_params={
'play': play_ms,
'play': play_value,
'lockedR': True,
'bg': '%23E2E2E2' # Light grey due to labels being fixed to dark
})
Expand Down
43 changes: 43 additions & 0 deletions graphistry/tests/layout/ring/test_continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,46 @@ def test_ring_cudf(self):
for i, row in enumerate(g._complex_encodings['node_encodings']['default']['pointAxisEncoding']['rows']):
assert row['r'] == 500 + 100 * i
assert row['label'] == str(2 + 2 * i)

def test_play_ms_preserves_url_param(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': [1, 2, 3]}))
.settings(url_params={'play': 6000})
.ring_continuous_layout('t')
)
assert g._url_params.get('play') == 6000

def test_play_ms_explicit_zero(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': [1, 2, 3]}))
.settings(url_params={'play': 6000})
.ring_continuous_layout('t', play_ms=0)
)
assert g._url_params.get('play') == 0

def test_play_ms_explicit_value(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': [1, 2, 3]}))
.settings(url_params={'play': 6000})
.ring_continuous_layout('t', play_ms=3000)
)
assert g._url_params.get('play') == 3000

def test_play_ms_default_when_no_url_param(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': [1, 2, 3]}))
.ring_continuous_layout('t')
)
assert g._url_params.get('play') == 0
65 changes: 65 additions & 0 deletions graphistry/tests/layout/ring/test_ring_categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,68 @@ def test_ring_cudf(self):
for i, row in enumerate(g._complex_encodings['node_encodings']['default']['pointAxisEncoding']['rows']):
assert row['r'] == 500 + 100 * i
assert row['label'] == ['a', 'bb', 'cc', 'dd'][i]

def test_play_ms_preserves_url_param(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': ['x', 'y', 'z']}))
.settings(url_params={'play': 6000})
.ring_categorical_layout('t')
)
assert g._url_params.get('play') == 6000

def test_play_ms_explicit_zero(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': ['x', 'y', 'z']}))
.settings(url_params={'play': 6000})
.ring_categorical_layout('t', play_ms=0)
)
assert g._url_params.get('play') == 0

def test_play_ms_explicit_value(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': ['x', 'y', 'z']}))
.settings(url_params={'play': 6000})
.ring_categorical_layout('t', play_ms=3000)
)
assert g._url_params.get('play') == 3000

def test_play_ms_default_when_no_url_param(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': ['x', 'y', 'z']}))
.ring_categorical_layout('t')
)
assert g._url_params.get('play') == 0

def test_play_ms_invalid_url_param_fallback(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': ['x', 'y', 'z']}))
.settings(url_params={'play': 'invalid'})
.ring_categorical_layout('t')
)
assert g._url_params.get('play') == 0

def test_play_ms_string_number_parsed(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({'n': ['a', 'b', 'c'], 't': ['x', 'y', 'z']}))
.settings(url_params={'play': '5000'})
.ring_categorical_layout('t')
)
assert g._url_params.get('play') == 5000
55 changes: 55 additions & 0 deletions graphistry/tests/layout/ring/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,58 @@ def test_ring_cudf(self):
assert 'y' in g._nodes
assert not g._nodes.x.isna().any()
assert not g._nodes.y.isna().any()

def test_play_ms_preserves_url_param(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({
'n': ['a', 'b', 'c'],
't': pd.Series(['2015-01-16', '2015-01-17', '2015-01-18'], dtype='datetime64[ns]')
}))
.settings(url_params={'play': 6000})
.time_ring_layout('t')
)
assert g._url_params.get('play') == 6000

def test_play_ms_explicit_zero(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({
'n': ['a', 'b', 'c'],
't': pd.Series(['2015-01-16', '2015-01-17', '2015-01-18'], dtype='datetime64[ns]')
}))
.settings(url_params={'play': 6000})
.time_ring_layout('t', play_ms=0)
)
assert g._url_params.get('play') == 0

def test_play_ms_explicit_value(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({
'n': ['a', 'b', 'c'],
't': pd.Series(['2015-01-16', '2015-01-17', '2015-01-18'], dtype='datetime64[ns]')
}))
.settings(url_params={'play': 6000})
.time_ring_layout('t', play_ms=3000)
)
assert g._url_params.get('play') == 3000

def test_play_ms_default_when_no_url_param(self):
lg = LGFull()
g = (
lg
.edges(pd.DataFrame({'s': ['a', 'b'], 'd': ['b', 'c']}), 's', 'd')
.nodes(pd.DataFrame({
'n': ['a', 'b', 'c'],
't': pd.Series(['2015-01-16', '2015-01-17', '2015-01-18'], dtype='datetime64[ns]')
}))
.time_ring_layout('t')
)
assert g._url_params.get('play') == 2000
Loading