Skip to content

Commit

Permalink
rename slide to cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
jzhang621 committed Nov 26, 2024
1 parent 1b33f21 commit 37ab589
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 52 deletions.
20 changes: 10 additions & 10 deletions web/src/components/Explore/ClusterFilter.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import React from 'react';

export default function ClusterFilter({ clusterLabels, slide, slideAnnotations, setSlide }) {
const handleSlideChange = (e) => {
export default function ClusterFilter({ clusterLabels, cluster, clusterAnnotations, setCluster }) {
const handleClusterChange = (e) => {
if (e.target.value === '-1') {
setSlide(null);
setCluster(null);
return;
}
const cl = clusterLabels.find((cluster) => cluster.cluster === +e.target.value);
if (cl) setSlide(cl);
if (cl) setCluster(cl);
};

return (
<div className={`clusters-select filter-row ${slideAnnotations.length ? 'active' : ''}`}>
<div className={`clusters-select filter-row ${clusterAnnotations.length ? 'active' : ''}`}>
<div className="filter-cell left">
<select onChange={handleSlideChange} value={slide?.cluster >= 0 ? slide.cluster : -1}>
<select onChange={handleClusterChange} value={cluster?.cluster >= 0 ? cluster.cluster : -1}>
<option value="-1">Filter by cluster</option>
{clusterLabels?.map((cluster, index) => (
<option key={index} value={cluster.cluster}>
Expand All @@ -23,10 +23,10 @@ export default function ClusterFilter({ clusterLabels, slide, slideAnnotations,
</select>
</div>
<div className="filter-cell middle">
{slideAnnotations.length ? (
{clusterAnnotations.length ? (
<span>
{slideAnnotations.length} rows
<button className="deselect" onClick={() => setSlide(null)}>
{clusterAnnotations.length} rows
<button className="deselect" onClick={() => setCluster(null)}>
X
</button>
</span>
Expand All @@ -37,7 +37,7 @@ export default function ClusterFilter({ clusterLabels, slide, slideAnnotations,
style={{ visibility: 'hidden' }}
className="deselect"
disabled
onClick={() => setSlide(null)}
onClick={() => setCluster(null)}
>
X
</button>
Expand Down
12 changes: 6 additions & 6 deletions web/src/components/Explore/FilterActions.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const SELECT = 'select';

export default function FilterActions({
clusterLabels,
slide,
slideAnnotations,
setSlide,
cluster,
clusterAnnotations,
setCluster,
searchIndices,
searchLoading,
setSearchText,
Expand Down Expand Up @@ -44,9 +44,9 @@ export default function FilterActions({
filterComponent = (
<ClusterFilter
clusterLabels={clusterLabels}
slide={slide}
slideAnnotations={slideAnnotations}
setSlide={setSlide}
cluster={cluster}
clusterAnnotations={clusterAnnotations}
setCluster={setCluster}
/>
);
} else if (activeFilter === SELECT) {
Expand Down
79 changes: 43 additions & 36 deletions web/src/pages/FullScreenExplore.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,27 @@ import LeftPane from '../components/Explore/LeftPane';
import VisualizationPane from '../components/Explore/VisualizationPane';
import FilterDataTable from '../components/FilterDataTable';

function intersectMultipleArrays(filterMode, ...arrays) {
arrays = arrays.filter((d) => d.length > 0);
if (arrays.length === 0) return [];
if (arrays.length == 1) return arrays[0];

if (filterMode === 'all') {
// AND mode - intersection
return arrays.reduce((acc, curr) => {
const currSet = new Set(curr);
return acc.filter((x) => currSet.has(x));
});
} else {
// ANY mode - union
const unionSet = new Set();
arrays.forEach((arr) => {
arr.forEach((x) => unionSet.add(x));
});
return Array.from(unionSet);
}
}

function Explore() {
const { dataset: datasetId, scope: scopeId } = useParams();
const navigate = useNavigate();
Expand Down Expand Up @@ -185,33 +206,40 @@ function Explore() {
// Clusters
// ====================================================================================================
// indices of items in a chosen slide
const [slide, setSlide] = useState(null);
const [slideAnnotations, setSlideAnnotations] = useState([]);
const [cluster, setCluster] = useState(null);
const [clusterAnnotations, setClusterAnnotations] = useState([]);

useEffect(() => {
if (scope) {
fetchScopeRows();
}
}, [fetchScopeRows, scope, embeddings, setClusterLabels]);

// automatically set the first cluster filter when the scope rows are loaded
useEffect(() => {
if (clusterMap) {
setCluster(clusterMap[0]);
}
}, [clusterMap]);

useEffect(() => {
if (slide) {
const annots = scopeRows.filter((d) => d.cluster == slide.cluster);
setSlideAnnotations(annots);
if (cluster) {
const annots = scopeRows.filter((d) => d.cluster == cluster.cluster);
setClusterAnnotations(annots);
// scatter?.zoomToPoints(
// annots.map((d) => d.ls_index),
// { transition: true, transitionDuration: 1500, padding: 1.5 }
// );
} else {
console.log('==== no slide', scatter);
setSlideAnnotations([]);
setClusterAnnotations([]);
// if (scatter && scatter.zoomToOrigin) {
// console.log('==== zoom to origin', scatter.zoomToOrigin);
// // scatter?.zoomToLocation([0, 0], 1);
// scatter?.zoomToOrigin({ transition: true, transitionDuration: 1500 });
// }
}
}, [slide, scopeRows, scatter, setSlideAnnotations]);
}, [cluster, scopeRows, scatter, setClusterAnnotations]);

// Handlers for responding to individual data points
const handleClicked = useCallback(
Expand All @@ -236,42 +264,21 @@ function Explore() {
);

const clearScope = useCallback(() => {
setSlide(null);
setCluster(null);
}, []);

const clearFilters = useCallback(() => {
setSelectedIndices([]);
setSearchIndices([]);
setIntersectedIndices([]);
setSlide(null);
setCluster(null);
}, [setSelectedIndices, setSearchIndices]);

function intersectMultipleArrays(filterMode, ...arrays) {
arrays = arrays.filter((d) => d.length > 0);
if (arrays.length === 0) return [];
if (arrays.length == 1) return arrays[0];

if (filterMode === 'all') {
// AND mode - intersection
return arrays.reduce((acc, curr) => {
const currSet = new Set(curr);
return acc.filter((x) => currSet.has(x));
});
} else {
// ANY mode - union
const unionSet = new Set();
arrays.forEach((arr) => {
arr.forEach((x) => unionSet.add(x));
});
return Array.from(unionSet);
}
}

const [intersectedIndices, setIntersectedIndices] = useState([]);
// intersect the indices from the various filters
useEffect(() => {
const filteredClusterIndices = scopeRows
.filter((d) => d.cluster == slide?.cluster)
.filter((d) => d.cluster == cluster?.cluster)
.map((d) => d.ls_index);
let indices = intersectMultipleArrays(
'all',
Expand All @@ -280,7 +287,7 @@ function Explore() {
filteredClusterIndices || []
);
setIntersectedIndices(indices);
}, [scopeRows, selectedIndices, searchIndices, slide, tagset]);
}, [scopeRows, selectedIndices, searchIndices, cluster, tagset]);

const handleScopeChange = useCallback(
(e) => {
Expand Down Expand Up @@ -440,9 +447,9 @@ function Explore() {
<div ref={filtersContainerRef}>
<FilterActions
clusterLabels={clusterLabels}
slide={slide}
slideAnnotations={slideAnnotations}
setSlide={setSlide}
slide={cluster}
clusterAnnotations={clusterAnnotations}
setCluster={setCluster}
searchIndices={searchIndices}
searchLoading={searchLoading}
setSearchText={setSearchText}
Expand Down Expand Up @@ -497,7 +504,7 @@ function Explore() {
hoverAnnotations={hoverAnnotations}
intersectedIndices={intersectedIndices}
hoveredCluster={hoveredCluster}
slide={slide}
slide={cluster}
scope={scope}
containerRef={containerRef}
onScatter={setScatter}
Expand Down

0 comments on commit 37ab589

Please sign in to comment.