Skip to content

Commit

Permalink
Add group field to subject and minor frontend fixes (#284)
Browse files Browse the repository at this point in the history
* Add group field to subject

* Cosmetic changes

* Add selected project id key to current tasks map

* Change fill character for progress bar
  • Loading branch information
annehaley authored Feb 28, 2023
1 parent d84b76f commit 6a5d82f
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 41 deletions.
17 changes: 17 additions & 0 deletions shapeworks_cloud/core/migrations/0025_subject_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.2.17 on 2023-02-25 00:19

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
('core', '0024_world_local_nullable'),
]

operations = [
migrations.AddField(
model_name='subject',
name='group',
field=models.CharField(blank=True, max_length=100, null=True),
),
]
1 change: 1 addition & 0 deletions shapeworks_cloud/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def safe_get(model, **kwargs):

class Subject(TimeStampedModel, models.Model):
name = models.CharField(max_length=255)
group = models.CharField(max_length=100, null=True, blank=True)
dataset = models.ForeignKey(Dataset, on_delete=models.CASCADE, related_name='subjects')


Expand Down
3 changes: 3 additions & 0 deletions swcc/examples/ellipsoid/ellipsoid.swproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"data": [
{
"name": "ellipsoid_00_DT",
"group": "A",
"shape_1": "./ellipsoid_00_DT.nrrd",
"groomed_1": "./groomed/ellipsoid_00_DT.nrrd",
"local_particles_1": "./particles/ellipsoid_00_DT_local.particles",
Expand All @@ -11,6 +12,7 @@
},
{
"name": "ellipsoid_01_DT",
"group": "B",
"shape_1": "./ellipsoid_01_DT.nrrd",
"groomed_1": "./groomed/ellipsoid_01_DT.nrrd",
"local_particles_1": "./particles/ellipsoid_01_DT_local.particles",
Expand All @@ -20,6 +22,7 @@
},
{
"name": "ellipsoid_02_DT",
"group": "B",
"shape_1": "./ellipsoid_02_DT.nrrd",
"groomed_1": "./groomed/ellipsoid_02_DT.nrrd",
"local_particles_1": "./particles/ellipsoid_02_DT_local.particles",
Expand Down
4 changes: 3 additions & 1 deletion swcc/swcc/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ def interpret_data(self, input_data):
if len(subjects) > 0:
subject = subjects[0]
else:
subject = Subject(name=entry.get('name'), dataset=self.project.dataset).create()
subject = Subject(
name=entry.get('name'), group=entry.get('group'), dataset=self.project.dataset
).create()

entry_values: Dict = {p: [] for p in expected_key_prefixes}
entry_values['anatomy_ids'] = []
Expand Down
3 changes: 2 additions & 1 deletion swcc/swcc/models/subject.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pathlib import Path
from typing import Iterator, List
from typing import Iterator, List, Optional

from .api_model import ApiModel
from .dataset import Dataset
Expand All @@ -12,6 +12,7 @@ class Subject(ApiModel):

name: NonEmptyString
dataset: Dataset
group: Optional[str]

@property
def segmentations(self) -> Iterator[Segmentation]:
Expand Down
2 changes: 1 addition & 1 deletion swcc/swcc/models/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def print_progress_bar(
suffix='Complete.',
decimals=1,
length=30,
fill='',
fill='X',
):
percent = ('{0:.' + str(decimals) + 'f}').format(100 * (iteration / float(total)))
filled_length = int(length * iteration // total)
Expand Down
20 changes: 12 additions & 8 deletions web/shapeworks/src/components/AnalysisTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
analysis, analysisFileShown,
currentAnalysisFileParticles, meanAnalysisFileParticles,
currentTasks,
selectedProject,
} from '@/store'
import { defineComponent, ref, computed, watch } from '@vue/composition-api'
import { lineChartOptions, lineChartProps } from '@/charts'
Expand Down Expand Up @@ -66,7 +67,7 @@ export default defineComponent({
{text: 'value', value: 'value', align: 'end'}
],
items: [
{key: 'Lambda', value: currPCA.value?.lambda_value},
{key: 'Lambda', value: currPCA.value?.lambda_value || 0},
{key: 'Eigenvalue', value: currMode.value?.eigen_value},
{key: 'Explained Variance', value: currMode.value?.explained_variance, class: 'percentage'},
{key: 'Cumulative Explained Variance', value: currMode.value?.cumulative_explained_variance, class:'percentage'},
Expand Down Expand Up @@ -104,7 +105,10 @@ export default defineComponent({
}
const taskData = computed(
() => currentTasks.value['analyze_task']
() => {
if (!selectedProject.value) return undefined
return currentTasks.value[selectedProject.value.id]['analyze_task']
}
)
return {
Expand Down Expand Up @@ -169,12 +173,12 @@ export default defineComponent({
:max="stdDevRange[1]"
:step="stdDevRange[2]"
ticks="always"
tick-size="8"
>
<template v-slot:prepend>
Std. Devs. from Mean
</template>
</v-slider>
tick-size="4"
thumb-label
track-color="#aaa"
track-fill-color="#aaa"
label="Std. Devs. from Mean"
/>
<br/>
<v-data-table
:headers="pcaInfo.headers"
Expand Down
7 changes: 6 additions & 1 deletion web/shapeworks/src/components/DataList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ export default defineComponent({
v-model="selectedAnatomies"
:value="anatomy_type"
></v-checkbox>
<v-list-item-title v-text="anatomy_type"/>
<v-list-item-title>
{{ anatomy_type }}
</v-list-item-title>
</v-list-item>
</v-list-item-group>
<v-subheader>SUBJECTS</v-subheader>
Expand All @@ -139,6 +141,9 @@ export default defineComponent({
v-on="on"
>
Subject: {{ subject.name }}
<span v-if="subject.group" class="pl-3">
(Group {{ subject.group }})
</span>
</v-list-item-title>
</template>
<span>
Expand Down
15 changes: 10 additions & 5 deletions web/shapeworks/src/components/TabForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import VJsf from '@koumoul/vjsf'
import '@koumoul/vjsf/dist/main.css'
import Ajv from 'ajv';
import defaults from 'json-schema-defaults';
import { spawnJob, jobAlreadyDone, allDataObjectsInDataset, currentTasks, spawnJobProgressPoll } from '../store';
import { spawnJob, jobAlreadyDone, allDataObjectsInDataset, currentTasks, spawnJobProgressPoll, selectedProject } from '../store';
import { DataObject } from '../types/index';
Vue.use(Vuetify)
Expand Down Expand Up @@ -87,8 +87,9 @@ export default defineComponent({
}
async function submitForm(_: Event, confirmed=false){
if(currentTasks.value[`${props.form}_task`]) {
currentTasks.value[`${props.form}_task`] = undefined
if (!selectedProject.value) return
if (!currentTasks.value[selectedProject.value.id]) {
currentTasks.value[selectedProject.value.id] = {}
}
if(alreadyDone.value && !confirmed){
showSubmissionConfirmation.value = true
Expand All @@ -100,13 +101,17 @@ export default defineComponent({
setTimeout(() => messages.value = '', 10000)
} else {
messages.value = `Successfully submitted ${props.form} job. Awaiting results...`
currentTasks.value = Object.assign(currentTasks.value, taskIds)
currentTasks.value[selectedProject.value.id] = taskIds
spawnJobProgressPoll()
}
}
const taskData = computed(
() => currentTasks.value[`${props.form}_task`]
() => {
if(!selectedProject.value?.id ||
!currentTasks.value[selectedProject.value.id]) return undefined
return currentTasks.value[selectedProject.value.id][`${props.form}_task`]
}
)
Expand Down
53 changes: 29 additions & 24 deletions web/shapeworks/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,7 @@ export const vtkShapesByType = ref<Record<string, any[]>>({
"Particles": []
})

export const currentTasks = ref<Record<string, Task| undefined>>({
groom_task: undefined,
optimize_task: undefined,
analyze_task: undefined
})
export const currentTasks = ref<Record<number, Record<string, Task| undefined>>>({})

export const jobProgressPoll = ref();

Expand Down Expand Up @@ -198,25 +194,34 @@ export async function spawnJobProgressPoll() {
}

export async function pollJobProgress(){
const refreshedTasks = await Promise.all(Object.entries(currentTasks.value)
.map(async ([taskName, task]) => {
if (task?.task_id){
task = await getTaskProgress(task.task_id)
if (task?.task_id && task?.percent_complete === 100) {
await deleteTaskProgress(task?.task_id)
task.task_id = undefined
setTimeout(() => {
currentTasks.value[taskName] = undefined
}, 1000)
fetchJobResults(taskName.replace('_task', ''))
}
if(selectedProject.value && currentTasks.value[selectedProject.value.id]){
const refreshedTasks = await Promise.all(
Object.entries(currentTasks.value[selectedProject.value.id])
.map(async ([taskName, task]) => {
if (task?.task_id){
task = await getTaskProgress(task.task_id)
if (task?.task_id && task?.percent_complete === 100) {
await deleteTaskProgress(task?.task_id)
task.task_id = undefined
setTimeout(() => {
if (selectedProject.value){
currentTasks.value[selectedProject.value.id][taskName] = undefined
}
}, 1000)
fetchJobResults(taskName.replace('_task', ''))
}
}
return [taskName, task]
}))
currentTasks.value[selectedProject.value.id] = Object.fromEntries(refreshedTasks)
currentTasks.value = {...currentTasks.value} // reassign for watch response
if (
Object.values(currentTasks.value[selectedProject.value.id])
.every(task => task?.task_id === undefined)
) {
clearInterval(jobProgressPoll.value)
jobProgressPoll.value = undefined
}
return [taskName, task]
}))
currentTasks.value = Object.fromEntries(refreshedTasks)
if (Object.values(currentTasks.value).every(task => task?.task_id === undefined)) {
clearInterval(jobProgressPoll.value)
jobProgressPoll.value = undefined
}
}

Expand Down Expand Up @@ -263,7 +268,7 @@ export async function switchTab(tabName: string){
switch(tabName) {
// add any other tab-switching updates here
case 'analyze':
if (refreshedProject && !currentTasks.value['analyze_task']) {
if (refreshedProject && !currentTasks.value[selectedProject.value.id]['analyze_task']) {
analysis.value = refreshedProject.last_cached_analysis
}
}
Expand Down

0 comments on commit 6a5d82f

Please sign in to comment.