Skip to content

Commit

Permalink
upload metadata, scaling annotations, duration labels
Browse files Browse the repository at this point in the history
  • Loading branch information
BryonLewis committed Feb 29, 2024
1 parent 6fa1bfa commit 9394f3d
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 25 deletions.
20 changes: 14 additions & 6 deletions client/src/components/AnnotationEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ export default defineComponent({
});
const speciesEdit: Ref<string[]> = ref( props.annotation?.species?.map((item) => item.species_code || item.common_name) || []);
const comments: Ref<string> = ref(props.annotation?.comments || '');
const type: Ref<string> = ref('');
const type: Ref<string[]> = ref([]);
const callTypes = ref(['Search', 'Approach', 'Terminal', 'Social']);
if (selectedType.value === 'sequence') {
type.value = (props.annotation as SpectrogramTemporalAnnotation).type || '';
type.value = (props.annotation as SpectrogramTemporalAnnotation).type?.split('+') || [''];
}
watch(() => props.annotation, () => {
if (props.annotation?.species) {
Expand All @@ -46,7 +48,7 @@ export default defineComponent({
comments.value = props.annotation.comments;
}
if (selectedType.value === 'pulse' && (props.annotation as SpectrogramTemporalAnnotation).type) {
type.value = (props.annotation as SpectrogramTemporalAnnotation).type || '';
type.value = (props.annotation as SpectrogramTemporalAnnotation).type?.split('+') || [];
}
});
const updateAnnotation = async () => {
Expand All @@ -62,7 +64,8 @@ export default defineComponent({
if (selectedType.value === 'pulse') {
await patchAnnotation(props.recordingId, props.annotation?.id, { ...props.annotation, comments: comments.value }, speciesIds );
} else if (selectedType.value === 'sequence') {
await patchTemporalAnnotation(props.recordingId, props.annotation.id, {...props.annotation, comments: comments.value, type: type.value,}, speciesIds);
const updateType = type.value.join('+');
await patchTemporalAnnotation(props.recordingId, props.annotation.id, {...props.annotation, comments: comments.value, type: updateType,}, speciesIds);
}
// Signal to redownload the updated annotation values if possible
emit('update:annotation');
Expand All @@ -82,6 +85,7 @@ export default defineComponent({
};
return {
callTypes,
speciesList,
speciesEdit,
comments,
Expand Down Expand Up @@ -122,10 +126,14 @@ export default defineComponent({
/>
</v-row>
<v-row v-if="selectedType === 'sequence'">
<v-text-field
<v-autocomplete
v-model="type"
multiple
closable-chips
chips
:items="callTypes"
label="Type"
@change="updateAnnotation()"
@update:model-value="updateAnnotation()"
/>
</v-row>

Expand Down
2 changes: 2 additions & 0 deletions client/src/components/AnnotationList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ export default defineComponent({
<v-row>
<v-col class="annotation-time">
<span>{{ annotation.start_time }}-{{ annotation.end_time }}ms</span>
<span class="pl-2"><b>({{ annotation.end_time - annotation.start_time }}ms)</b></span>
</v-col>
<v-col class="annotation-freq">
<span>{{ (annotation.low_freq/1000).toFixed(1) }}-{{ (annotation.high_freq/1000).toFixed() }}Khz </span>
Expand Down Expand Up @@ -184,6 +185,7 @@ export default defineComponent({
<v-row>
<v-col class="annotation-time">
<span>{{ annotation.start_time }}-{{ annotation.end_time }}ms</span>
<span class="pl-2"><b>({{ annotation.end_time - annotation.start_time }}ms)</b></span>
</v-col>
<v-col class="annotation-time">
<b>Type:</b><span>{{ annotation.type }}</span>
Expand Down
16 changes: 15 additions & 1 deletion client/src/components/HelpSystem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,24 @@ export default defineComponent({
color=""
variant="flat"
>
<v-icon>mdi-arrow-left-right</v-icon>
<h3>ms</h3>
</v-btn>
</v-col>
<v-col>Toggle millisecond/timing labels</v-col>
<v-col>Toggle millisecond/timing endpoint labels</v-col>
</v-row>
<v-row>
<v-col>
<v-btn
size="35"
color=""
variant="flat"
>
<v-icon>mdi-arrow-expand-horizontal</v-icon>
<h3>ms</h3>
</v-btn>
</v-col>
<v-col>Toggle millisecond/timing duration labels</v-col>
</v-row>
<v-row>
<v-col>
Expand Down
1 change: 1 addition & 0 deletions client/src/components/TemporalList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export default defineComponent({
<v-row>
<v-col class="annotation-time">
<span>{{ annotation.start_time }}-{{ annotation.end_time }}ms</span>
<span class="pl-2"><b>({{ annotation.end_time - annotation.start_time }}ms)</b></span>
</v-col>
</v-row>
<v-row
Expand Down
29 changes: 21 additions & 8 deletions client/src/components/UploadRecording.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default defineComponent({
const errorText = ref('');
const progressState = ref('');
const recordedDate = ref(props.editing ? props.editing.date : new Date().toISOString().split('T')[0]); // YYYY-MM-DD Time
const recordedTime = ref(props.editing ? props.editing.time : getCurrentTime()); // HHMMSS
const recordedTime = ref(props.editing ? props.editing.time.replaceAll(':','') : getCurrentTime()); // HHMMSS
const uploadProgress = ref(0);
const name = ref(props.editing ? props.editing.name : '');
const equipment = ref(props.editing ? props.editing.equipment : '');
Expand All @@ -53,18 +53,31 @@ export default defineComponent({
const gridCellId: Ref<number | undefined> = ref();
const publicVal = ref(props.editing ? props.editing.public : false);
const autoFill = async (filename: string) => {
const parts = filename.split("_");
const regexPattern = /^(\d+)_(.+)_(\d{8})_(\d{6})(?:_(.*))?$/;
// Match the file name against the regular expression
const match = filename.match(regexPattern);
// If there's no match, return null
if (!match) {
return null;
}
// Extract the matched groups
const cellId = match[1];
const labelName = match[2];
const date = match[3];
const timestamp = match[4];
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const extraData = match[5] || null; // Additional data after the required parts
// Extracting individual components
const cellId = parts[0];
const quadrant = parts[1];
const date = parts[2];
const timestamp = parts[3];
if (cellId) {
gridCellId.value = parseInt(cellId, 10);
let updatedQuadrant;
if (['SW', 'NE', 'NW', 'SE'].includes(quadrant)) {
updatedQuadrant = quadrant as 'SW' | 'NE' | 'NW' | 'SE' | undefined;
if (['SW', 'NE', 'NW', 'SE'].includes(labelName)) {
updatedQuadrant = labelName as 'SW' | 'NE' | 'NW' | 'SE' | undefined;
}
const { latitude: lat , longitude: lon } = (await getCellLocation(gridCellId.value, updatedQuadrant)).data;
if (lat && lon) {
Expand Down
9 changes: 7 additions & 2 deletions client/src/components/geoJS/LayerManager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export default defineComponent({
}
} else if (creating) {
if (geoJSON && props.spectroInfo) {
const conversionResult = geojsonToSpectro(geoJSON, props.spectroInfo);
const conversionResult = geojsonToSpectro(geoJSON, props.spectroInfo, props.scaledWidth, props.scaledHeight);
if (conversionResult.error) {
displayError.value = true;
Expand Down Expand Up @@ -332,7 +332,12 @@ export default defineComponent({
legendLayer.setGridEnabled(false);
}
legendLayer.redraw();
if (layerVisibility.value.includes("time")) {
if (layerVisibility.value.includes("time") || layerVisibility.value.includes('duration')) {
if (layerVisibility.value.includes("time")) {
timeLayer.displayDuration = false;
} else {
timeLayer.displayDuration = true;
}
timeLayer.formatData(annotations, temporalAnnotations);
timeLayer.redraw();
} else {
Expand Down
66 changes: 63 additions & 3 deletions client/src/components/geoJS/layers/timeLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default class TimeLayer {
scaledWidth: number;
scaledHeight: number;

displayDuration: boolean;

// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(
Expand All @@ -68,7 +69,7 @@ export default class TimeLayer {
.position((data: TextData) => ({ x: data.x, y: data.y }));

this.lineLayer = layer.createFeature("line");

this.displayDuration = true;
this.textStyle = this.createTextStyle();
this.lineStyle = this.createLineStyle();
}
Expand All @@ -87,8 +88,7 @@ export default class TimeLayer {
}
}


formatData(annotationData: SpectrogramAnnotation[], temporalData: SpectrogramTemporalAnnotation[] =[]) {
createRange(annotationData: SpectrogramAnnotation[], temporalData: SpectrogramTemporalAnnotation[] =[]) {
this.textData = [];
this.lineData = [];
const lineDist = 12;
Expand Down Expand Up @@ -193,6 +193,66 @@ export default class TimeLayer {

}

createDuration(annotationData: SpectrogramAnnotation[], temporalData: SpectrogramTemporalAnnotation[] =[]) {
this.textData = [];
this.lineData = [];
const lineDist = 12;
annotationData.forEach((annotation: SpectrogramAnnotation) => {
const polygon = spectroToGeoJSon(annotation, this.spectroInfo, 1, this.scaledWidth, this.scaledHeight);
const {start_time, end_time } = annotation;
const [xmin, ymin] = polygon.coordinates[0][0];
const [xmax, ymax] = polygon.coordinates[0][2];
// For the compressed view we need to filter out default or NaN numbers
if (Number.isNaN(xmax) || Number.isNaN(xmin) || Number.isNaN(ymax) || Number.isNaN(ymin)) {
return;
}
if (xmax === -1 && ymin === -1 && ymax === -1 && xmin === -1) {
return;
}
const xpos = (xmin + xmax) / 2.0;
const ypos = (ymax + ymin) /2.0;
// Now we need to create the text Labels
this.textData.push({
text: `${end_time - start_time}ms`,
x: xpos,
y: ypos + lineDist,
offsetX: 0,
offsetY: 0,
});
});
temporalData.forEach((annotation: SpectrogramTemporalAnnotation) => {
const polygon = spectroTemporalToGeoJSon(annotation, this.spectroInfo, -10, -50, 1, this.scaledWidth, this.scaledHeight);
const {start_time, end_time } = annotation;
const [xmin, ymin] = polygon.coordinates[0][0];
const [xmax, ymax] = polygon.coordinates[0][2];
// For the compressed view we need to filter out default or NaN numbers
if (Number.isNaN(xmax) || Number.isNaN(xmin) || Number.isNaN(ymax) || Number.isNaN(ymin)) {
return;
}
if (xmax === -1 && ymin === -1 && ymax === -1 && xmin === -1) {
return;
}
const xpos = (xmin + xmax) / 2.0;
// Now we need to create the text Labels
this.textData.push({
text: `${end_time-start_time}ms`,
x: xpos,
y: (ymax - ymin) / 2.0,
offsetX: 0,
offsetY: -5,
});
});

}

formatData(annotationData: SpectrogramAnnotation[], temporalData: SpectrogramTemporalAnnotation[] =[]) {
if (!this.displayDuration) {
this.createRange(annotationData, temporalData);
} else {
this.createDuration(annotationData, temporalData);
}
}

redraw() {
// add some styles
this.lineLayer
Expand Down
10 changes: 9 additions & 1 deletion client/src/use/useState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { OtherUserAnnotations, Recording, SpectrogramAnnotation, SpectrogramTemp

const annotationState: Ref<AnnotationState> = ref("");
const creationType: Ref<'pulse' | 'sequence'> = ref("pulse");
type LayersVis = "time" | "freq" | "species" | "grid" | 'temporal';
type LayersVis = "time" | "freq" | "species" | "grid" | 'temporal' | 'duration';
const layerVisibility: Ref<LayersVis[]> = ref(['temporal', 'species', 'time', 'freq']);
const colorScale: Ref<d3.ScaleOrdinal<string, string, never> | undefined> = ref();
const selectedUsers: Ref<string[]> = ref([]);
Expand Down Expand Up @@ -36,6 +36,14 @@ export default function useState() {
// If the value is present, remove it
clone.splice(index, 1);
}
if (value === 'time' && clone.includes('duration')) {
const durationInd = layerVisibility.value.indexOf('duration');
clone.splice(durationInd, 1);
}
if (value === 'duration' && clone.includes('time')) {
const timeInd = layerVisibility.value.indexOf('time');
clone.splice(timeInd, 1);
}
layerVisibility.value = clone;
}
const setSelectedUsers = (newUsers: string[]) => {
Expand Down
18 changes: 16 additions & 2 deletions client/src/views/Recordings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export default defineComponent({
:headers="headers"
:items="recordingList"
density="compact"
class="elevation-1"
class="elevation-1 my-recordings"
>
<template #item.edit="{ item }">
<v-icon @click="editRecording(item.raw)">
Expand Down Expand Up @@ -277,6 +277,7 @@ export default defineComponent({
mdi-close
</v-icon>
</template>
<template #bottom />
</v-data-table>
</v-card-text>
<v-dialog
Expand Down Expand Up @@ -304,7 +305,7 @@ export default defineComponent({
:headers="sharedHeaders"
:items="sharedList"
density="compact"
class="elevation-1"
class="elevation-1 shared-recordings"
>
<template #item.name="{ item }">
<router-link
Expand Down Expand Up @@ -367,7 +368,20 @@ export default defineComponent({
mdi-close
</v-icon>
</template>
<template #bottom />
</v-data-table>
</v-card-text>
</v-card>
</template>

<style scoped>
.my-recordings {
height: 40vh;
max-height: 40vh;
overflow-y:scroll;
}
.shared-recordings {
height: 40vh;
max-height: 40vh;
}
</style>
20 changes: 18 additions & 2 deletions client/src/views/Spectrogram.vue
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,26 @@ export default defineComponent({
:color="layerVisibility.includes('time') ? 'blue' : ''"
@click="toggleLayerVisibility('time')"
>
<h3>ms</h3>
<v-icon>mdi-arrow-left-right</v-icon>
<h4>ms</h4>
</v-btn>
</template>
<span> Turn Time Label On/Off</span>
<span> Turn Time Endpoint Labels On/Off</span>
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ props: subProps }">
<v-btn
v-bind="subProps"
size="35"
class="mr-5 mt-5"
:color="layerVisibility.includes('duration') ? 'blue' : ''"
@click="toggleLayerVisibility('duration')"
>
<v-icon>mdi-arrow-expand-horizontal</v-icon>
<h4>ms</h4>
</v-btn>
</template>
<span> Turn Time Duration Labels On/Off</span>
</v-tooltip>
<v-tooltip bottom>
<template #activator="{ props: subProps }">
Expand Down

0 comments on commit 9394f3d

Please sign in to comment.