-
-
Notifications
You must be signed in to change notification settings - Fork 406
fix: dendrogram edgecases #6669
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6669 +/- ##
=======================================
Coverage 89.02% 89.02%
=======================================
Files 329 329
Lines 70422 70489 +67
=======================================
+ Hits 62693 62754 +61
- Misses 7729 7735 +6 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
because of this line; only kdims currently get expanded (and |
best wait until holoviz-topics/hv-anndata#82 is fixed |
OK, so But when using that PR and this one together, things are still broken (in fact, this PR does nothing to change what happens here): import holoviews as hv
import numpy as np
import scanpy as sc
import hv_anndata
from hv_anndata import ACCESSOR as A
from hv_anndata import register
register()
hv.extension("bokeh")
markers = ["C1QA", "PSAP", "CD79A", "CD79B", "CST3", "LYZ"]
hm = hv.HeatMap(
adata[np.argsort(adata.obs["bulk_labels"], stable=True), markers],
[A.obs.index, A.var.index],
[A[:, :], A.obs["n_counts"]],
).opts(xticks=0, colorbar=True, width=500, height=200)
if dendrogram:
hm = hv.operation.dendrogram(
hm,
adjoint_dims=[A.obs.index],
main_dim=A.obs["n_counts"],
linkage_metric="euclidean",
)
hm running with ![]() running with ![]() |
I updated the image. Looks better, but still changed. Looks reordered, but (and the dendrogram is still a little messed up. Very messed up when passing |
I think it should be reordered, it is finding an order, just not the optimal order. However, I'm not an expert in dendrograms by any means.
Can you share an image. The |
OK, two issues:
with the code from my first comment, but ![]() |
nope! |
I'm currently just looking at "pure" pandas and trying to tackle point 1 you raised. Point 2, I'm not sure if it is currently feasible, and will therefore likely not be part of this fix PR. I think this is what you are seeing by using |
OK, cool! I filed #6683 for that Otherwise, things seem to work when using |
fbd86b1
to
66cdf44
Compare
6ff8e1f
to
26d566d
Compare
Seems like a strange expectation by the Heatmap code; if I change the hv-anndata interface to basically return values.flatten() if flat else values.T it starts to work, I just don’t understand why the holoviews/holoviews/plotting/bokeh/heatmap.py Lines 123 to 124 in 31209ce
When run for the anndata version, dim=A[:, :], expanded=True, flat=True
File "…/holoviews/plotting/plot.py", line 958, in update
return self.initialize_plot()
File "…/holoviews/plotting/bokeh/element.py", line 2172, in initialize_plot
ranges = self.compute_ranges(self.hmap, key, ranges)
File "…/holoviews/plotting/plot.py", line 617, in compute_ranges
self._compute_group_range(group, elements, ranges, framewise,
File "…/holoviews/plotting/plot.py", line 727, in _compute_group_range
data_range = el.range(el_dim, dimension_range=False)
File "…/holoviews/core/data/__init__.py", line 201, in pipelined_fn
result = method_fn(*args, **kwargs)
File "…/holoviews/element/raster.py", line 964, in range
return super().range(dim, data_range, dimension_range)
File "…/holoviews/core/data/__init__.py", line 201, in pipelined_fn
result = method_fn(*args, **kwargs)
File "…/holoviews/core/data/__init__.py", line 529, in range
lower, upper = self.interface.range(self, dim)
File "…/holoviews/core/data/interface.py", line 414, in range
column = dataset.dimension_values(dimension)
File "…/holoviews/core/data/__init__.py", line 201, in pipelined_fn
result = method_fn(*args, **kwargs)
File "…/holoviews/core/data/__init__.py", line 1178, in dimension_values
values = self.interface.values(self, dim, expanded, flat) dim=A[:, :], expanded=True, flat=False
File "…/holoviews/plotting/plot.py", line 958, in update
return self.initialize_plot()
File "…/holoviews/plotting/bokeh/element.py", line 2201, in initialize_plot
self._init_glyphs(plot, element, ranges, source)
File "…/holoviews/plotting/bokeh/heatmap.py", line 154, in _init_glyphs
super()._init_glyphs(plot, element, ranges, source)
File "…/holoviews/plotting/bokeh/element.py", line 2101, in _init_glyphs
data, mapping, style = self.get_data(element, ranges, style)
File "…/holoviews/plotting/bokeh/heatmap.py", line 123, in get_data
zvals = aggregate.dimension_values(2, flat=False)
File "…/holoviews/core/data/__init__.py", line 201, in pipelined_fn
result = method_fn(*args, **kwargs)
File "…/holoviews/core/data/__init__.py", line 1178, in dimension_values
values = self.interface.values(self, dim, expanded, flat) dim=A[:, :], expanded=True, flat=True
File "…/holoviews/plotting/plot.py", line 958, in update
return self.initialize_plot()
File "…/holoviews/plotting/bokeh/element.py", line 2201, in initialize_plot
self._init_glyphs(plot, element, ranges, source)
File "…/holoviews/plotting/bokeh/heatmap.py", line 154, in _init_glyphs
super()._init_glyphs(plot, element, ranges, source)
File "…/holoviews/plotting/bokeh/element.py", line 2101, in _init_glyphs
data, mapping, style = self.get_data(element, ranges, style)
File "…/holoviews/plotting/bokeh/heatmap.py", line 139, in get_data
for v in aggregate.dimension_values(vdim)]
File "…/holoviews/core/data/__init__.py", line 201, in pipelined_fn
result = method_fn(*args, **kwargs)
File "…/holoviews/core/data/__init__.py", line 1178, in dimension_values
values = self.interface.values(self, dim, expanded, flat) |
code_map = defaultdict(lambda: len(code_map)) # noqa: B023 | ||
order = list(map(code_map.__getitem__, ddata)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Performance seems good here:
import pandas as pd
import numpy as np
from collections import defaultdict
from string import ascii_lowercase
var = [*'mtropqnkslmtropqnkslmtropqnkslmtropqnkslmtropqnkslmtropqnkslmtropqnkslmtropqnkslmtropqnkslmtropqnksl'] * 100 + [*ascii_lowercase]
var_np = np.asarray(var)
print(len(var), len(set(var)))
code_map = defaultdict(lambda: len(code_map)) # noqa: B023
order1 = list(map(code_map.__getitem__, var))
order2 = pd.Categorical(var_np, pd.unique(var_np)).codes
np.testing.assert_array_equal(order1, order2)



Just looked into it and it seems like that the |
Yeah, this almost drove me insane. I don't think the conventions of the ordering and orientations expected of the flattened arrays make much sense but there was also some weird handling in the gridded interface. I've tried to resolve this in holoviz-topics/hv-anndata#89 and tried the various conditions, which now seem to work. |
I’ll comment there! |
List of changes, a missing checkmark means a missing unit test
linkage
, not being able to solve error message