Skip to content

Commit 8b4de33

Browse files
authored
fix exporting, download overflow, poetry wheels locking (#1433)
1 parent 4e0c17b commit 8b4de33

File tree

10 files changed

+514
-462
lines changed

10 files changed

+514
-462
lines changed

client/platform/web-girder/views/Export.vue

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!-- eslint-disable vue/no-ref-as-operand -->
12
<script lang="ts">
23
import {
34
computed, defineComponent, ref, shallowRef, toRef, watch, PropType, Ref,
@@ -43,14 +44,14 @@ export default defineComponent({
4344

4445
/** State populated from provides if the dialog exists inside a viewer context */
4546
let save = () => Promise.resolve();
46-
const pendingSaveCount = ref(0);
47-
const checkedTypes = ref([] as readonly string[]);
48-
const revisionId = ref(null as null | number);
47+
let pendingSaveCount = ref(0);
48+
let checkedTypes = ref([] as readonly string[]);
49+
let revisionId = ref(null as null | number);
4950
if (props.blockOnUnsaved) {
5051
save = useHandler().save;
51-
pendingSaveCount.value = usePendingSaveCount().value;
52-
checkedTypes.value = useTrackFilters().checkedTypes.value;
53-
revisionId.value = useRevisionId().value;
52+
pendingSaveCount = usePendingSaveCount();
53+
checkedTypes = useTrackFilters().checkedTypes;
54+
revisionId = useRevisionId();
5455
}
5556

5657
async function doExport({ forceSave = false, url }: { url?: string; forceSave?: boolean }) {
@@ -225,6 +226,7 @@ export default defineComponent({
225226
/>
226227
<v-card
227228
outlined
229+
class="downloadMenu"
228230
>
229231
<v-card-title>
230232
Download options
@@ -266,7 +268,7 @@ export default defineComponent({
266268

267269
<v-card-text class="pb-2">
268270
<div>Get latest annotation csv only</div>
269-
<template v-if="dataset.confidenceFilters">
271+
<template v-if="dataset.confidenceFilters || true">
270272
<v-checkbox
271273
v-model="excludeBelowThreshold"
272274
label="exclude tracks below confidence threshold"
@@ -391,3 +393,11 @@ export default defineComponent({
391393
</template>
392394
</v-menu>
393395
</template>
396+
397+
<style scoped>
398+
.downloadMenu {
399+
max-height: calc(100vh - 30px);
400+
overflow-y: auto;
401+
overflow-x: hidden;
402+
}
403+
</style>

docker/girder.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ WORKDIR /opt/dive/src
2424
RUN apt-get update
2525
RUN apt-get install -y build-essential libssl-dev libffi-dev python3-libtiff libgdal-dev python3-dev cargo npm
2626
# Recommended poetry install https://python-poetry.org/docs/master/#installation
27-
RUN curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.8.2 POETRY_HOME=/opt/dive/poetry python -
27+
RUN curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.8.3 POETRY_HOME=/opt/dive/poetry python -
2828
ENV PATH="/opt/dive/poetry/bin:$PATH"
2929
# Create a virtual environment for the installation
3030
RUN python -m venv /opt/dive/local/venv

docker/girder_worker.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \
3333
RUN ln -s /usr/bin/python3.11 /usr/bin/python
3434
WORKDIR /opt/dive/src
3535

36-
RUN curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.8.2 POETRY_HOME=/opt/dive/poetry python -
36+
RUN curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.8.3 POETRY_HOME=/opt/dive/poetry python -
3737
ENV PATH="/opt/dive/poetry/bin:$PATH"
3838
# Create a virtual environment for the installation
3939
RUN python -m venv --copies /opt/dive/local/venv

server/dive_server/crud_dataset.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,12 +306,16 @@ def makeDiveJson():
306306
if (not nestedExcludeBelowThreshold) or track.exceeds_thresholds(thresholds):
307307
# filter by types if applicable
308308
if nestedTypeFilter:
309-
confidence_pairs = [item for item in track.confidencePairs if item[0] in nestedTypeFilter]
309+
confidence_pairs = [
310+
item
311+
for item in track.confidencePairs
312+
if item[0] in nestedTypeFilter
313+
]
310314
# skip line if no confidence pairs
311315
if not confidence_pairs:
312316
continue
313317
updated_tracks[t] = tracks[t]
314-
annotations['tracks'] = updated_tracks
318+
annotations['tracks'] = updated_tracks
315319
yield json.dumps(annotations)
316320

317321
for data in z.addFile(makeMetajson, Path(f'{zip_path}meta.json')):

server/dive_server/crud_rpc.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,28 +331,53 @@ def _get_data_by_type(
331331
)
332332
meta = None
333333
if fps is not None:
334-
meta = { "fps" : fps }
335-
return {'annotations': converted, 'meta': meta, 'attributes': attributes, 'type': as_type}, warnings
334+
meta = {"fps": fps}
335+
return {
336+
'annotations': converted,
337+
'meta': meta,
338+
'attributes': attributes,
339+
'type': as_type,
340+
}, warnings
336341
if as_type == crud.FileType.MEVA_KPF:
337342
converted, attributes = kpf.convert(kpf.load(file_string))
338-
return {'annotations': converted, 'meta': None, 'attributes': attributes, 'type': as_type}, warnings
343+
return {
344+
'annotations': converted,
345+
'meta': None,
346+
'attributes': attributes,
347+
'type': as_type,
348+
}, warnings
339349

340350
# All filetypes below are JSON, so if as_type was specified, it needs to be loaded.
341351
if data_dict is None:
342352
data_dict = json.loads(file_string)
343353
if as_type == crud.FileType.COCO_JSON:
344354
converted, attributes = kwcoco.load_coco_as_tracks_and_attributes(data_dict)
345-
return {'annotations': converted, 'meta': None, 'attributes': attributes, 'type': as_type}, warnings
355+
return {
356+
'annotations': converted,
357+
'meta': None,
358+
'attributes': attributes,
359+
'type': as_type,
360+
}, warnings
346361
if as_type == crud.FileType.DIVE_CONF:
347-
return {'annotations': None, 'meta': data_dict, 'attributes': None, 'type': as_type}, warnings
362+
return {
363+
'annotations': None,
364+
'meta': data_dict,
365+
'attributes': None,
366+
'type': as_type,
367+
}, warnings
348368
if as_type == crud.FileType.DIVE_JSON:
349369
migrated = dive.migrate(data_dict)
350370
annotations, attributes = viame.load_json_as_track_and_attributes(data_dict)
351-
return {'annotations': migrated, 'meta': None, 'attributes': attributes, 'type': as_type}, warnings
371+
return {
372+
'annotations': migrated,
373+
'meta': None,
374+
'attributes': attributes,
375+
'type': as_type,
376+
}, warnings
352377
return None, None
353378

354379

355-
def process_items(
380+
def process_items(
356381
folder: types.GirderModel,
357382
user: types.GirderUserModel,
358383
additive=False,
@@ -423,6 +448,7 @@ def process_items(
423448
crud_dataset.update_metadata(folder, results['meta'], False)
424449
return aggregate_warnings
425450

451+
426452
def postprocess(
427453
user: types.GirderUserModel,
428454
dsFolder: types.GirderModel,

server/dive_server/views_annotation.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from girder.exceptions import RestException
1010
from girder.models.folder import Folder
1111

12-
from dive_utils import constants, setContentDisposition, models, fromMeta
12+
from dive_utils import constants, fromMeta, models, setContentDisposition
1313

1414
from . import crud, crud_annotation
1515

@@ -170,7 +170,9 @@ def export(
170170
if (not excludeBelowThreshold) or track.exceeds_thresholds(thresholds):
171171
# filter by types if applicable
172172
if typeFilter:
173-
confidence_pairs = [item for item in track.confidencePairs if item[0] in typeFilter]
173+
confidence_pairs = [
174+
item for item in track.confidencePairs if item[0] in typeFilter
175+
]
174176
# skip line if no confidence pairs
175177
if not confidence_pairs:
176178
continue

server/dive_utils/models.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from datetime import datetime
2-
from typing import Any, Dict, List, Optional, Tuple, Union
2+
from typing import Any, Dict, List, Optional, Set, Tuple, Union
33

44
from bson.objectid import ObjectId
55
from pydantic import BaseModel, Field, validator
@@ -60,14 +60,31 @@ class BaseAnnotation(BaseModel):
6060
attributes: Dict[str, Any] = Field(default_factory=lambda: {})
6161
meta: Optional[Dict[str, Any]]
6262

63-
def exceeds_thresholds(self, thresholds: Dict[str, float]) -> bool:
63+
def exceeds_thresholds(self, thresholds: Dict[str, float], typeFilter: Set[str]) -> bool:
6464
defaultThresh = thresholds.get('default', 0)
65-
return any(
66-
[
67-
confidence >= thresholds.get(field, defaultThresh)
68-
for field, confidence in self.confidencePairs
69-
]
70-
)
65+
66+
# Check if there is any confidence value that exceeds the threshold
67+
exceeds_default_threshold = False
68+
for field, confidence in self.confidencePairs:
69+
if confidence > thresholds.get(field, defaultThresh):
70+
if (
71+
typeFilter and field in typeFilter
72+
): # field is in the set and confidence > threshold
73+
exceeds_default_threshold = True
74+
elif (
75+
typeFilter
76+
): # if typeFilter has a set and the field isn't in it we return false
77+
exceeds_default_threshold = False
78+
elif (
79+
not typeFilter
80+
): # if no typeFilter we return true based on confidence > threshold
81+
exceeds_default_threshold = True
82+
else:
83+
exceeds_default_threshold = False
84+
if exceeds_default_threshold:
85+
return True
86+
87+
return False
7188

7289
def __hash__(self):
7390
return self.id

server/dive_utils/serializers/viame.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def _deduceType(value: Any) -> Union[bool, float, str, None]:
6868
return None
6969
if value is None:
7070
return None
71-
71+
7272
if value == "true":
7373
return True
7474
if value == "false":
@@ -279,7 +279,8 @@ def custom_sort(row):
279279

280280

281281
def load_csv_as_tracks_and_attributes(
282-
rows: List[str], imageMap: Optional[Dict[str, int]] = None,
282+
rows: List[str],
283+
imageMap: Optional[Dict[str, int]] = None,
283284
) -> Tuple[types.DIVEAnnotationSchema, dict, List[str], Optional[str]]:
284285
"""
285286
Convert VIAME CSV to json tracks
@@ -300,8 +301,8 @@ def load_csv_as_tracks_and_attributes(
300301
for row in sortedlist:
301302
if len(row) == 0 or row[0].startswith('#'):
302303
# This is not a data row
303-
if (len(row) > 0 and row[0] == '# metadata'):
304-
if (row[1].startswith('Fps: ')):
304+
if len(row) > 0 and row[0] == '# metadata':
305+
if row[1].startswith('Fps: '):
305306
fps_splits = row[1].split(':')
306307
if len(fps_splits) > 1:
307308
fps = fps_splits[1]
@@ -500,7 +501,7 @@ def export_tracks_as_csv(
500501

501502
for t in track_iterator:
502503
track = Track(**t)
503-
if (not excludeBelowThreshold) or track.exceeds_thresholds(thresholds):
504+
if (not excludeBelowThreshold) or track.exceeds_thresholds(thresholds, typeFilter):
504505
# filter by types if applicable
505506
if typeFilter:
506507
confidence_pairs = [item for item in track.confidencePairs if item[0] in typeFilter]

0 commit comments

Comments
 (0)