Skip to content
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

Feature: adds display of tag descriptions and regexp searching for tags #528

Merged
merged 11 commits into from
Mar 18, 2024
64 changes: 54 additions & 10 deletions src/segmentation_display_state/property_map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ export function parseSegmentQuery(
});
continue;
}
if (labels === undefined) {
if (labels === undefined && tagNames.length == 0) {
errors.push({
begin: startIndex,
end: endIndex,
Expand Down Expand Up @@ -778,7 +778,7 @@ export function parseSegmentQuery(
});
continue;
}
if (labels === undefined) {
if (labels === undefined && tagNames.length == 0) {
errors.push({
begin: startIndex,
end: endIndex,
Expand Down Expand Up @@ -806,6 +806,7 @@ export interface TagCount {
tag: string;
tagIndex: number;
count: number;
desc: string;
}

export interface PropertyHistogram {
Expand Down Expand Up @@ -860,7 +861,10 @@ export function executeSegmentQuery(
}
const properties = inlineProperties?.properties;
const totalIds = inlineProperties.ids.length / 2;
const totalTags = db?.tags?.tags?.length || 0;
let indices = makeIndicesArray(totalIds, totalIds);
const showTags = makeIndicesArray(totalTags, totalTags);
showTags.fill(1);
for (let i = 0; i < totalIds; ++i) {
indices[i] = i;
}
Expand All @@ -877,16 +881,50 @@ export function executeSegmentQuery(
}
indices = indices.subarray(0, outIndex);
};
const filterByTagDescriptions = (regexp: RegExp) => {
const tagDescriptions = db!.tags!.tagDescriptions!;
const tags = db!.tags!.tags!;

// reset showTags
showTags.fill(0);

// iterate over tagDescriptions with a for loop
for (let i = 0; i < tagDescriptions.length; i++) {
if (tagDescriptions[i].match(regexp) !== null) {
showTags[i] = 1;
}
if (tags[i].match(regexp) !== null) {
showTags[i] = 1;
}
}
};

// Filter by label
if (query.regexp !== undefined || query.prefix !== undefined) {
const values = db!.labels!.values;
const { regexp, prefix } = query;
if (regexp !== undefined) {
filterIndices((index) => values[index].match(regexp) !== null);
if (db!.labels !== undefined) {
const values = db!.labels!.values;
if (regexp !== undefined) {
filterIndices((index) => values[index].match(regexp) !== null);
}
if (prefix !== undefined) {
filterIndices((index) => values[index].startsWith(prefix));
}
}
if (prefix !== undefined) {
filterIndices((index) => values[index].startsWith(prefix));
// if the regular expression returns nothing
// then assudme the user wants to search through the tags
// and/or tag descriptions
if (
(indices.length == 0 && regexp !== undefined) ||
(db!.labels == undefined && regexp != undefined)
) {
indices = makeIndicesArray(totalIds, totalIds);
for (let i = 0; i < totalIds; ++i) {
indices[i] = i;
}
filterByTagDescriptions(regexp);
// reset regexp to none so that it doesn't get applied again
query.regexp = undefined;
}
}

Expand Down Expand Up @@ -924,7 +962,6 @@ export function executeSegmentQuery(
const regexp = new RegExp(pattern);
filterIndices((index) => values[index].match(regexp) !== null);
}

let intermediateIndicesMask: IndicesArray | undefined;
let intermediateIndices: IndicesArray | undefined;

Expand Down Expand Up @@ -970,7 +1007,7 @@ export function executeSegmentQuery(
let tagStatistics: TagCount[] = [];
if (tagsProperty !== undefined) {
const tagStatisticsInQuery: TagCount[] = [];
const { tags, values } = tagsProperty;
const { tags, values, tagDescriptions } = tagsProperty;
const tagCounts = new Uint32Array(tags.length);
for (let i = 0, n = indices.length; i < n; ++i) {
const value = values[indices[i]];
Expand All @@ -983,9 +1020,16 @@ export function executeSegmentQuery(
tagIndex < numTags;
++tagIndex
) {
if (showTags[tagIndex] === 0) continue;
const count = tagCounts[tagIndex];
const tag = tags[tagIndex];
const tagCount = { tag, tagIndex, count: tagCounts[tagIndex] };
const tagDesc = tagDescriptions[tagIndex];
const tagCount = {
tag,
tagIndex,
count: tagCounts[tagIndex],
desc: tagDesc,
};
if (query.includeTags.includes(tag) || query.excludeTags.includes(tag)) {
tagStatisticsInQuery.push(tagCount);
} else if (count > 0) {
Expand Down
10 changes: 8 additions & 2 deletions src/ui/segment_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -990,12 +990,18 @@ function renderTagSummary(
const filterQuery = queryResult.query as FilterQuery;
const tagList = document.createElement("div");
tagList.classList.add("neuroglancer-segment-query-result-tag-list");
for (const { tag, count } of tags) {
for (const { tag, count, desc } of tags) {
const tagElement = document.createElement("div");
tagElement.classList.add("neuroglancer-segment-query-result-tag");
const tagName = document.createElement("span");
tagName.classList.add("neuroglancer-segment-query-result-tag-name");
tagName.textContent = tag;
// if the tag is different than desc, show both
if (tag !== desc && desc !== undefined && desc !== "") {
tagName.textContent = tag + " (" + desc + ")";
} else {
tagName.textContent = tag;
}

tagList.appendChild(tagElement);
const included = filterQuery.includeTags.includes(tag);
const excluded = filterQuery.excludeTags.includes(tag);
Expand Down
Loading