Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ export interface ExperimentMetadata {
// can precompute min/max for each column across experiments
locationMetadataList: LocationMetadata[];
compositeTabularDataFilename?: string;
// how the segmentation files are saved
// split by cell (default), split by frame
segmentationGrouping?: SegmentationGroupingOptions;
}

export type SegmentationGroupingOptions = 'CellFiles' | 'FrameFiles';

export type Tags = Record<string, string>;

export interface LocationMetadata {
Expand Down Expand Up @@ -81,6 +86,14 @@ export const useDatasetSelectionStore = defineStore(
return null;
});

const segmentationGrouping = computed<SegmentationGroupingOptions>(() => {
// TODO: calc based on currentExperimentMetadata
if (!currentExperimentMetadata.value) {
return 'CellFiles'
}
return currentExperimentMetadata.value.segmentationGrouping ?? 'CellFiles';
})

// Generate Experiment List
const experimentFilenameList = asyncComputed<string[]>(async () => {
if (configStore.serverUrl == null) return null;
Expand Down Expand Up @@ -406,6 +419,7 @@ export const useDatasetSelectionStore = defineStore(
compTableName,
aggTableName,
shownSelectedLocationIds,
segmentationGrouping,
};
}
);
70 changes: 35 additions & 35 deletions apps/client/src/stores/dataStores/segmentationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ import {
type Track,
} from '@/stores/dataStores/cellMetaDataStore';
import { useDatasetSelectionStore } from '@/stores/dataStores/datasetSelectionUntrrackedStore';
import type { Feature } from 'geojson';
import type { Feature, FeatureCollection } from 'geojson';
import { LRUCache } from 'lru-cache';
import { useConfigStore } from '../misc/configStore';


// interface LocationSegmentations {
// location: string,
// segmentations: Feature[];
// }
/**
* Custom store for managing segmentations.
* @returns An object containing functions to retrieve segmentations.
Expand All @@ -23,14 +18,18 @@ export const useSegmentationStore = defineStore('segmentationStore', () => {
const datasetSelectionStore = useDatasetSelectionStore();
const cellMetaData = useCellMetaData();
const configStore = useConfigStore();
const filesGroupedByFrame = computed(() => datasetSelectionStore.segmentationGrouping === 'FrameFiles');

const cache = ref(
new LRUCache<string, Feature>({
max: 25_000,
new LRUCache<string, Feature | FeatureCollection>({
// TODO: this max for the cache is probably too large if we are saving frames.
// could use diff max depending on if we are grabbing from frames vs. cells.
max: filesGroupedByFrame.value ? 500 : 25_000,
// each item is small (1-2 KB)
fetchMethod: async (jsonUrl, staleValue, { signal }) => {
return (await fetch(jsonUrl, { signal }).then((res) =>
res.json()
)) as Feature;
)) as Feature | FeatureCollection;
},
})
);
Expand All @@ -40,7 +39,12 @@ export const useSegmentationStore = defineStore('segmentationStore', () => {
* @returns An array of GeoJson features representing the segmentations.
*/
async function getFrameSegmentations(frame: number): Promise<Feature[]> {
// Implementation goes here
if (filesGroupedByFrame.value) {
const featureCollection = (await cache.value.fetch(
`${segmentationFolderUrl.value}/${frame}.json`
)) as FeatureCollection;
return featureCollection.features;
}
const cells = cellMetaData.frameMap.get(frame);
if (!cells) return [];
const promises = cells.map((cell) => getCellSegmentation(cell));
Expand All @@ -49,15 +53,6 @@ export const useSegmentationStore = defineStore('segmentationStore', () => {
) as Feature[];
}

// /**
// * Get segmentations for a specific track.
// * @param track - The track object.
// * @returns An array of GeoJson features representing the segmentations.
// */
// async function getTrackSegmentations(track: Track): Promise<Feature[]> {
// // Implementation goes here
// }

const segmentationFolderUrl = computed<string>(() => {
if (
datasetSelectionStore.currentLocationMetadata
Expand All @@ -71,21 +66,20 @@ export const useSegmentationStore = defineStore('segmentationStore', () => {
return url;
});

async function getCellLocationSegmentations(
cells: Cell[]
): Promise<Feature[] | undefined> {
const promises = cells.map((cell) => getCellSegmentation(cell));
return (await Promise.all(promises)).filter(
(x) => x != null
) as Feature[];
}

// Based on the frame, the id, and the location, return the feature (segmentation)
async function getCellLocationSegmentation (frame: string, trackId: string, location: string): Promise<Feature | undefined> {
async function getCellLocationSegmentation(frame: string, trackId: string, location: string): Promise<Feature | undefined> {
const locationSegmentationUrl = configStore.getFileUrl(datasetSelectionStore.getLocationMetadata(location)?.segmentationsFolder || '');
return await cache.value.fetch(
if (filesGroupedByFrame.value) {
const featureCollection = (await cache.value.fetch(
`${locationSegmentationUrl}/${frame}.json`
)) as FeatureCollection;
return featureCollection.features.find(
(feature) => feature.properties?.id.toString() === trackId.toString()
);
}
return (await cache.value.fetch(
`${locationSegmentationUrl}/cells/${frame}-${trackId}.json`
);
)) as Feature;
}

/**
Expand All @@ -98,9 +92,17 @@ export const useSegmentationStore = defineStore('segmentationStore', () => {
): Promise<Feature | undefined> {
const frame = cellMetaData.getFrame(cell);
const id = cell.trackId;
return await cache.value.fetch(
if (filesGroupedByFrame.value) {
const featureCollection = (await cache.value.fetch(
`${segmentationFolderUrl.value}/${frame}.json`
)) as FeatureCollection;
return featureCollection.features.find(
(feature) => feature.properties?.id.toString() === id.toString()
);
}
return (await cache.value.fetch(
`${segmentationFolderUrl.value}/cells/${frame}-${id}.json`
);
)) as Feature;
}

async function getCellSegmentations(
Expand All @@ -115,8 +117,6 @@ export const useSegmentationStore = defineStore('segmentationStore', () => {
return {
getFrameSegmentations,
getCellLocationSegmentation,
getCellLocationSegmentations,
// getTrackSegmentations,
getCellSegmentation,
getCellSegmentations,
};
Expand Down
Loading