diff --git a/bats_ai/core/views/recording.py b/bats_ai/core/views/recording.py index f9926fa..239c672 100644 --- a/bats_ai/core/views/recording.py +++ b/bats_ai/core/views/recording.py @@ -10,7 +10,7 @@ from ninja.files import UploadedFile from ninja.pagination import RouterPaginated -from bats_ai.core.models import Annotations, Recording, Species, TemporalAnnotations +from bats_ai.core.models import Annotations, Recording, Species, Spectrogram, TemporalAnnotations from bats_ai.core.views.species import SpeciesSchema from bats_ai.core.views.temporal_annotations import ( TemporalAnnotationSchema, @@ -103,6 +103,10 @@ def create_recording( comments=payload.comments, ) recording.save() + # Start generating recording as soon as created + # this creates the spectrogram during the upload so it is available immediately afterwards + # it will make the upload process longer but I think it's worth it. + Spectrogram.generate(recording) return {'message': 'Recording updated successfully', 'id': recording.pk} diff --git a/client/INSTRUCTIONS.md b/client/INSTRUCTIONS.md new file mode 100644 index 0000000..41d2bdb --- /dev/null +++ b/client/INSTRUCTIONS.md @@ -0,0 +1,77 @@ +# Instructions + +The following are instructions on how to use this application to share and +annotate bat recordings. + +## Uploading Data + +When you first login, got to the 'Recordings' tab to view two lists of recordings. +The first list is a list of recordings you have uploaded. +You can add new data by clicking the 'Upload+' button and choosing a local +file on your system. +A date and name are required for uploading new data. +Optional data can be added including location/ equipment and comments about the file + +**Public** - using this checkbox will share the data with all other users within the system + +Once others have have made annotations on your own files that are public +you can view them by clicking on the name + + +## Others Shared Data + +This second list of recording files include files that were made public +by other users or the system admin + +This will allow you create annotations on other's files by +clicking on the **Name** field for the annotation file + +## Annotation Editor + +### Viewing Annotations + +The annotation editor has two main views of the spectrogram from the recording: + +**Main View** - This main view has the full annotation zoomed in and can be +dragged/panned using left click and can be zoomed using the mousewheel. +At the top of the screen are the current frequence and time for the mouse cursor. +On the upper right side of the area are buttons for adding/removing information + +**Bat Icon** - turns on/off species annotations for any bounding boxes on the screen +**MS Icon** - will toggle millisecond text annotations to all boxes +**KHZ Icon** - will toggle frequency labels for each bounding box on the screen +**Grid Icon** - toggles gride display across the spectrogram +**Compressed Icon** - toggles on/off the compressed view for the spectrogram + +### Interactions + +**Clicking** - clicking inside of annotation will automatically select it. +It will become cyan in color and the annotation will be selected in either +the Sequence or Pulse list. + +**Right Clicking** - Right clicking on an annotation will swap it into 'Edit Mode' +In 'Edit Mode' the annotation bounds can be modified by clicking on the corners +and dragging them around. + +#### Full Spectrogram View + +Below the main view is a thumbnail of the full spectrogram. This view shows +the entire spectrogram. +The **yellow** bounding box is used to show the current location and zoom +level for the **Main View**. +Clicking on and dragging in the thumbnail view will pan and jump instanlty to +that area in the main view. + +#### Sequence and Pulse Annotations + +On the right side of the screen is a list of the Sequence and Pulse annotations. +These are tabbed views that can be switched between by clicking on the Tab Name. +Annotations can be selected by clicking on them. +When an annotation is selected it can be edited including the species comments and other information. + +**Sequence** - A Sequence annotation is typically used to group multiple pulses together +This can be drawn by clicking on the 'Add+' button and drawing a box around the pulses. +Once created it is shown at the top of the screen + +**Pulse** - A Pulse annotation is an annotation around a single pulse in the system. +These have a fequency range as well a time range. \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index 8671cb2..d5e2da7 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -18,6 +18,7 @@ "geojs": "^1.11.1", "lodash": "^4.17.21", "vue": "^3.3.1", + "vue-markdown-render": "^2.1.1", "vue-router": "^4.0.12", "vuetify": "^3.3.12" }, @@ -25,6 +26,7 @@ "@types/geojson": "^7946.0.13", "@types/jest": "^27.4.1", "@types/lodash": "^4.14.202", + "@types/markdown-it": "^13.0.7", "@vitejs/plugin-vue": "^2.2.0", "@vue/eslint-config-typescript": "^10.0.0", "@vuetify/vite-plugin": "^1.0.0-alpha.10", @@ -3072,12 +3074,34 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "devOptional": true }, + "node_modules/@types/linkify-it": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", + "integrity": "sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==", + "dev": true + }, "node_modules/@types/lodash": { "version": "4.14.202", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", "dev": true }, + "node_modules/@types/markdown-it": { + "version": "13.0.7", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.7.tgz", + "integrity": "sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz", + "integrity": "sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==", + "dev": true + }, "node_modules/@types/node": { "version": "17.0.21", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz", @@ -3901,8 +3925,7 @@ "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/array-union": { "version": "2.1.0", @@ -5107,6 +5130,14 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -7514,6 +7545,14 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -7636,6 +7675,26 @@ "tmpl": "1.0.5" } }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -9069,6 +9128,11 @@ "node": ">=4.2.0" } }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", @@ -9383,6 +9447,17 @@ "node": ">=4.0" } }, + "node_modules/vue-markdown-render": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/vue-markdown-render/-/vue-markdown-render-2.1.1.tgz", + "integrity": "sha512-szuJVbCwgIpVsggd8IHGB2lLo8BH8Ojd+wakaOTASNxdYcccKxoMcvDqUsLoGwgKDY8yJf0U/+ppffEYxsEHkA==", + "dependencies": { + "markdown-it": "^12.3.2" + }, + "peerDependencies": { + "vue": "^3.3.4" + } + }, "node_modules/vue-router": { "version": "4.0.13", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.13.tgz", diff --git a/client/package.json b/client/package.json index 652ce37..5b067ce 100644 --- a/client/package.json +++ b/client/package.json @@ -23,6 +23,7 @@ "geojs": "^1.11.1", "lodash": "^4.17.21", "vue": "^3.3.1", + "vue-markdown-render": "^2.1.1", "vue-router": "^4.0.12", "vuetify": "^3.3.12" }, @@ -30,6 +31,7 @@ "@types/geojson": "^7946.0.13", "@types/jest": "^27.4.1", "@types/lodash": "^4.14.202", + "@types/markdown-it": "^13.0.7", "@vitejs/plugin-vue": "^2.2.0", "@vue/eslint-config-typescript": "^10.0.0", "@vuetify/vite-plugin": "^1.0.0-alpha.10", diff --git a/client/src/views/HomePage.vue b/client/src/views/HomePage.vue index 93ded77..19a3475 100644 --- a/client/src/views/HomePage.vue +++ b/client/src/views/HomePage.vue @@ -1,9 +1,26 @@ @@ -13,8 +30,8 @@ export default defineComponent({ Bat-AI - - For right now please select "Files" to open a specific file in the spectrogram viewer or go to "Species" to view a list of species in the system. + + diff --git a/client/yarn.lock b/client/yarn.lock index 2c901df..bd330de 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -1718,11 +1718,29 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/linkify-it@*": + version "3.0.5" + resolved "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz" + integrity sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw== + "@types/lodash@^4.14.202": version "4.14.202" resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz" integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== +"@types/markdown-it@^13.0.7": + version "13.0.7" + resolved "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-13.0.7.tgz" + integrity sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA== + dependencies: + "@types/linkify-it" "*" + "@types/mdurl" "*" + +"@types/mdurl@*": + version "1.0.5" + resolved "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.5.tgz" + integrity sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA== + "@types/node@*": version "17.0.21" resolved "https://registry.npmjs.org/@types/node/-/node-17.0.21.tgz" @@ -3029,6 +3047,11 @@ enhanced-resolve@^5.15.0: graceful-fs "^4.2.4" tapable "^2.2.0" +entities@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" @@ -4391,6 +4414,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +linkify-it@^3.0.1: + version "3.0.3" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz" + integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ== + dependencies: + uc.micro "^1.0.1" + loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" @@ -4471,6 +4501,22 @@ makeerror@1.0.12: dependencies: tmpl "1.0.5" +markdown-it@^12.3.2: + version "12.3.2" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz" + integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg== + dependencies: + argparse "^2.0.1" + entities "~2.1.0" + linkify-it "^3.0.1" + mdurl "^1.0.1" + uc.micro "^1.0.5" + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" @@ -5361,6 +5407,11 @@ typescript@*, typescript@^4.6.4, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0 resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +uc.micro@^1.0.1, uc.micro@^1.0.5: + version "1.0.6" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz" + integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" @@ -5492,6 +5543,13 @@ vue-eslint-parser@^8.0.0, vue-eslint-parser@^8.0.1: lodash "^4.17.21" semver "^7.3.5" +vue-markdown-render@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/vue-markdown-render/-/vue-markdown-render-2.1.1.tgz" + integrity sha512-szuJVbCwgIpVsggd8IHGB2lLo8BH8Ojd+wakaOTASNxdYcccKxoMcvDqUsLoGwgKDY8yJf0U/+ppffEYxsEHkA== + dependencies: + markdown-it "^12.3.2" + vue-router@^4.0.12, "vue-router@3.x || 4.x": version "4.0.13" resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.13.tgz" @@ -5516,7 +5574,7 @@ vue-tsc@^1.8.27: "@vue/language-core" "1.8.27" semver "^7.5.4" -vue@^3.0.0, vue@^3.2.0, vue@^3.2.25, vue@^3.3.1, "vue@2.x || 3.x", vue@3.3.4: +vue@^3.0.0, vue@^3.2.0, vue@^3.2.25, vue@^3.3.1, vue@^3.3.4, "vue@2.x || 3.x", vue@3.3.4: version "3.3.4" resolved "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz" integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==