Skip to content

Commit

Permalink
Noaa features (#1462)
Browse files Browse the repository at this point in the history
* Add filter and transcode pipelines to allowed patterns

* Add new pipe type for display

* Read input for filter and transcode pipelines

* add frame counts, fix everything downloading, add multi-detection downloading

* respecting tracks without keyframes

* add toggle All interpolation

* updating lock

* update help text

---------

Co-authored-by: Jacob Nesbitt <[email protected]>
  • Loading branch information
BryonLewis and jjnesbitt authored Jan 13, 2025
1 parent 53fa6cf commit 7f320bf
Show file tree
Hide file tree
Showing 9 changed files with 408 additions and 296 deletions.
4 changes: 3 additions & 1 deletion client/dive-common/components/UserGuideDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ export default defineComponent({
{
name: 'Toggle Interpolation', icon: 'mdi-keyboard', actions: ['I'], description: 'Toggle Interpolation On/Off',
},
{
name: 'Toggle Interpolation All', icon: 'mdi-keyboard', actions: ['CTRL+I'], description: 'Toggle Interpolation On/Off for all Frames',
},
{
name: 'Split Track', icon: 'mdi-keyboard', actions: ['X'], description: 'Split Track',
},
Expand Down
23 changes: 23 additions & 0 deletions client/platform/web-girder/views/Export.vue
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,16 @@ export default defineComponent({
params: { folderIds: JSON.stringify(props.datasetIds) },

}),
exportAllUrlDetections: getUri({
url: 'dive_dataset/export',
params: {
...params,
folderIds: JSON.stringify(props.datasetIds),
includeDetections: true,
includeMedia: false,
},
}),

};
});

Expand Down Expand Up @@ -388,6 +398,19 @@ export default defineComponent({
Everything
</v-btn>
</v-card-actions>
<v-card-text class="pb-0">
Export All selected Dataset Detections in VIAME CSV and TrackJSON
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
depressed
block
@click="doExport({ url: exportUrls && exportUrls.exportAllUrlDetections })"
>
Detections
</v-btn>
</v-card-actions>
</template>
</v-card>
</template>
Expand Down
52 changes: 45 additions & 7 deletions client/src/components/FilterList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import {
import { difference, union } from 'lodash';
import { usePrompt } from 'dive-common/vue-utilities/prompt-service';
import { useReadOnlyMode } from '../provides';
import {
useCameraStore, useReadOnlyMode, useSelectedCamera, useTime,
} from '../provides';
import TooltipBtn from './TooltipButton.vue';
import TypeEditor from './TypeEditor.vue';
import TypeItem from './TypeItem.vue';
Expand Down Expand Up @@ -60,10 +62,13 @@ export default defineComponent({
setup(props) {
const { prompt } = usePrompt();
const readOnlyMode = useReadOnlyMode();
const cameraStore = useCameraStore();
const selectedCamera = useSelectedCamera();
const { frame } = useTime();
const trackStore = cameraStore.camMap.value.get(selectedCamera.value)?.trackStore;
// Ordering of these lists should match
const sortingMethods = ['a-z', 'count'];
const sortingMethodIcons = ['mdi-sort-alphabetical-ascending', 'mdi-sort-numeric-ascending'];
const sortingMethods = ['a-z', 'count', 'frame count'];
const sortingMethodIcons = ['mdi-sort-alphabetical-ascending', 'mdi-sort-numeric-ascending', 'mdi-sort-clock-ascending-outline'];
const data = reactive({
showPicker: false,
Expand Down Expand Up @@ -137,6 +142,26 @@ export default defineComponent({
return acc;
}, new Map<string, number>()));
const filteredTracksForFrame = computed(() => {
const trackIdsForFrame = trackStore?.intervalTree
.search([frame.value, frame.value])
.map((str) => parseInt(str, 10));
const filteredKeyFrameTracks = filteredTracksRef.value.filter((track) => {
const keyframe = trackStore?.getPossible(track.annotation.id)?.getFeature(frame.value)[0];
return !!keyframe;
});
return (filteredKeyFrameTracks.filter((track) => trackIdsForFrame?.includes(track.annotation.id)));
});
const currentFrameTrackTypes = computed(() => filteredTracksForFrame.value.reduce((acc, filteredTrack) => {
const confidencePair = filteredTrack.annotation
.getType(filteredTrack.context.confidencePairIndex);
const trackType = confidencePair;
acc.set(trackType, (acc.get(trackType) || 0) + 1);
return acc;
}, new Map<string, number>()));
function sortAndFilterTypes(types: Ref<readonly string[]>) {
const filtered = types.value
.filter((t) => t.toLowerCase().includes(data.filterText.toLowerCase()));
Expand All @@ -147,6 +172,10 @@ export default defineComponent({
return filtered.sort(
(a, b) => (typeCounts.value.get(b) || 0) - (typeCounts.value.get(a) || 0),
);
case 'frame count':
return filtered.sort(
(a, b) => (currentFrameTrackTypes.value.get(b) || 0) - (currentFrameTrackTypes.value.get(a) || 0),
);
default:
return filtered;
}
Expand All @@ -163,10 +192,11 @@ export default defineComponent({
const typeCountsDeRef = typeCounts.value;
const typeStylingDeRef = typeStylingRef.value;
const checkedTypesDeRef = checkedTypesRef.value;
const frameTRackTypesDeRef = currentFrameTrackTypes.value;
return visibleTypes.value.map((item) => ({
type: item,
confidenceFilterNum: confidenceFiltersDeRef[item] || 0,
displayText: `${item} (${typeCountsDeRef.get(item) || 0})`,
displayText: `${typeCountsDeRef.get(item) || 0}:${frameTRackTypesDeRef.get(item) || 0} ${item}`,
color: typeStylingDeRef.color(item),
checked: checkedTypesDeRef.includes(item),
}));
Expand Down Expand Up @@ -258,11 +288,19 @@ export default defineComponent({
class="my-1 type-checkbox"
@change="headCheckClicked"
/>
<b>Type Filter</b>
<v-tooltip
open-delay="100"
bottom
>
<template #activator="{ on }">
<b v-on="on">Type Filter</b>
</template>
<span>Toggle Type TotalCount:FrameCount Type Name</span>
</v-tooltip>
<v-spacer />
<tooltip-btn
:icon="sortingMethodIcons[data.sortingMethod]"
tooltip-text="Sort types by count or alphabetically"
:tooltip-text="`Sort types by Total Count, Alphabetically or Frame Count, current: ${sortingMethods[data.sortingMethod]}`"
@click="clickSortToggle"
/>
<slot name="settings" />
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/TooltipButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default Vue.extend({
:tile="tile"
class="ma-0"
v-on="on"
@click="$emit('click')"
@click="$emit('click', $event)"
>
<v-icon>
{{ icon }}
Expand Down
18 changes: 16 additions & 2 deletions client/src/components/TrackItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,17 @@ export default defineComponent({
props.track.toggleInterpolation(frameRef.value);
}
function toggleAllInterpolation() {
props.track.toggleInterpolationForAllGaps(frameRef.value);
}
function clickToggleInterpolation(event: MouseEvent) {
if (event.ctrlKey) {
toggleAllInterpolation();
} else {
toggleInterpolation();
}
}
function gotoNext() {
const nextFrame = props.track.getNextKeyframe(frameRef.value + 1);
if (nextFrame !== undefined) {
Expand Down Expand Up @@ -170,6 +181,8 @@ export default defineComponent({
handler,
openMultiCamTools,
toggleInterpolation,
clickToggleInterpolation,
toggleAllInterpolation,
toggleKeyframe,
setTrackType,
typeStyling,
Expand Down Expand Up @@ -250,6 +263,7 @@ export default defineComponent({
v-mousetrap="[
{ bind: 'k', handler: toggleKeyframe },
{ bind: 'i', handler: toggleInterpolation },
{ bind: 'ctrl+i', handler: toggleAllInterpolation },
{ bind: 'home', handler: () => $emit('seek', track.begin) },
{ bind: 'end', handler: () => $emit('seek', track.end) },
]"
Expand Down Expand Up @@ -285,8 +299,8 @@ export default defineComponent({
:icon="(feature.shouldInterpolate)
? 'mdi-vector-selection'
: 'mdi-selection-off'"
tooltip-text="Toggle interpolation"
@click="toggleInterpolation"
tooltip-text="Toggle interpolation, ctrl+click to toggle all interpolation"
@click="clickToggleInterpolation($event)"
/>
</span>
<span v-else>
Expand Down
16 changes: 16 additions & 0 deletions client/src/track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,22 @@ export default class Track extends BaseAnnotation {
}
}

toggleInterpolationForAllGaps(frame: number): void {
const { interpolate } = this.canInterpolate(frame);

for (let i = this.begin; i < this.end; i += 1) {
const { features } = this.canInterpolate(i);
const [real, lower, upper] = features;
const targetKeyframe = real?.keyframe ? real : (lower || upper);
if (targetKeyframe) {
this.setFeature({
...targetKeyframe,
interpolate: !interpolate,
});
}
}
}

setFeature(feature: Feature, geometry: GeoJSON.Feature<TrackSupportedFeature>[] = []): Feature {
const f = this.features[feature.frame] || {};
this.features[feature.frame] = {
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ services:
source: ${PUBLIC_DATA_PATH:-./docker/girder_data}
target: /data/public
read_only: true
volume:
nocopy: true
environment:
- "GIRDER_MONGO_URI=mongodb://mongo:27017/girder"
- "GIRDER_ADMIN_USER=${GIRDER_ADMIN_USER:-admin}"
Expand Down
2 changes: 1 addition & 1 deletion server/dive_utils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class BaseAnnotation(BaseModel):
attributes: Dict[str, Any] = Field(default_factory=lambda: {})
meta: Optional[Dict[str, Any]]

def exceeds_thresholds(self, thresholds: Dict[str, float], typeFilter: Set[str]) -> bool:
def exceeds_thresholds(self, thresholds: Dict[str, float], typeFilter: Set[str] = None) -> bool:
defaultThresh = thresholds.get('default', 0)

# Check if there is any confidence value that exceeds the threshold
Expand Down
Loading

0 comments on commit 7f320bf

Please sign in to comment.