Skip to content

Commit

Permalink
CU-863h6ca0d: new feature to click through to annotation dataset from…
Browse files Browse the repository at this point in the history
… the TPs, FNs, FPs page, some extra warnings on the metrics API in case weird requests come in
  • Loading branch information
tomolopolis committed Jul 14, 2023
1 parent 2b244e3 commit bd63f20
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 18 deletions.
13 changes: 12 additions & 1 deletion webapp/api/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,18 @@ def model_loaded(_):
def metrics(request):
p_ids = request.GET.get('projectIds').split(',')
projects = ProjectAnnotateEntities.objects.filter(id__in=p_ids)
# assume projects all use the same model for eval purposes.

# provide warning of inconsistent models used or for models that are not loaded.
p_cdbs = set(p.concept_db for p in projects)
if len(p_cdbs) > 1:
logger.warning('Inconsistent CDBs used in the generation of metrics - should use the same CDB for '
f'consistent results - found {[cdb.name for cdb in p_cdbs]} - metrics will only use the first'
f' CDB {projects[0].concept_db.name}')
for p_cdb in p_cdbs:
if p_cdb not in CDB_MAP:
logger.warning(f'CDB {p_cdb.name} not in CDB_MAP cache - this will now be loaded - '
f'and will not show intermediary training status')

cat = get_medcat(CDB_MAP=CDB_MAP, VOCAB_MAP=VOCAB_MAP,
CAT_MAP=CAT_MAP, project=projects[0])
project_data = retrieve_project_data(projects)
Expand Down
1 change: 0 additions & 1 deletion webapp/frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ export default {
}
.link {
//padding-top: 10px;
display:inline-block;
height: 25px;
cursor: pointer;
Expand Down
22 changes: 19 additions & 3 deletions webapp/frontend/src/components/anns/AnnoResult.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<td class="doc-name">{{result['document name']}}</td>
<td class="cui">{{result.cui}}</td>
<td class="source-value">{{result['source value']}}</td>
<td class="accu">{{result.acc}}</td>
<td class="accu">{{Number(result.acc).toFixed(3)}}</td>
<td class="text">
<v-runtime-template :template="text"></v-runtime-template>
</td>
Expand Down Expand Up @@ -33,7 +33,6 @@ export default {
if (this.type === 'fp' || this.type === 'fn') {
highlightClass = 'highlight-task-1'
}
const srcVal = this.result['source value']
const resTxt = this.result.text
const regexp = RegExp(`${srcVal}`, 'sg')
Expand All @@ -45,13 +44,30 @@ export default {
} else {
outText += `${resTxt.slice(matches[matches.indexOf(match) - 1].index + srcVal.length, match.index)}`
}
outText += `<span class="${highlightClass}">${srcVal}</span>`
outText += `<span class="${highlightClass}" @click="openAnno">${srcVal}</span>`
if (matches.length === 1 || match === matches[-1]) {
outText += `${resTxt.slice(match.index + srcVal.length)}</span>`
}
}
return outText
}
},
methods: {
openAnno () {
const routeData = this.$router.resolve(
{
name: 'train-annotations',
params: {
projectId: this.result['project id'],
docId: this.result['document id'],
},
query: {
annoStart: this.result['start'],
annoEnd: this.result['end']
}
})
window.open(routeData.href, '_blank');
}
}
}
</script>
Expand Down
9 changes: 6 additions & 3 deletions webapp/frontend/src/views/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@
v-if="!loadingProjects"
@row-selected="select">
<template #head(metrics)="data">
Metrics
<div id="metrics-head">Metrics</div>
<button class="btn btn-outline-primary load-metrics" @click="loadMetrics" v-if="selectedProjects.length > 0">
<font-awesome-icon icon="chevron-right"></font-awesome-icon>
</button>
<b-tooltip target="metrics-head"
triggers="hover"
container="projectTable"
title="Access the metrics view for a single or group of projects"></b-tooltip>
</template>
<template #head(cuis)="">
<div id="cuis-header">Concepts</div>
Expand Down Expand Up @@ -119,7 +123,7 @@
<transition name="alert"><div class="alert alert-danger" v-if="modelSavedError" role="alert">Error saving model</div></transition>
<transition name="alert"><div class="alert alert-primary" v-if="loadingModel" role="alert">Loading model</div></transition>
<transition name="alert"><div class="alert alert-danger" v-if="modelCacheLoadError" role="alert">Error loading MedCAT model for project</div></transition>
<transition name="alert"><div class="alert alert-danger" v-if="projectLockedWarning" role="alert">Unable load a locked project. Unlock via /admin/</div></transition>
<transition name="alert"><div class="alert alert-danger" v-if="projectLockedWarning" role="alert">Unable load a locked project. Contact your CogStack administrator to unlock</div></transition>
</div>
<modal v-if="clearModelModal" :closable="true" @modal:close="clearModelModal = false">
<div slot="header">
Expand Down Expand Up @@ -174,7 +178,6 @@ export default {
'anno_class',
'cdb_search_filter',
'model_loaded',
'metrics',
'save_model'
]
},
Expand Down
47 changes: 37 additions & 10 deletions webapp/frontend/src/views/Metrics.vue
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,24 @@
</b-tab>
</b-tabs>
</div>
<modal class="summary-modal" v-if="predictedResults" :closable="true" @modal:close="predictedResults = null">
<h3 slot="header">{{predictionResultsTitle}}</h3>
<modal class="summary-modal" v-if="modalData.results" :closable="true" @modal:close="clearModalData">
<h3 slot="header">{{modalData.title}}</h3>
<div slot="body">
<div v-if="modalData.type === 'fp'">
<p>False positive model predictions can be the result of:</p>
<ul>
<li>Alternative model predictions that are overlapping with other concepts</li>
<li>Genuine missed annotations by an annotator.</li>
</ul>
<p>Clicking through these annotations will not highlight this annotation as it doesn't exist in the dataset </p>
</div>
<div v-if="modalData.type === 'fn'">
<p>False negative model predictions can be the result of:</p>
<ul>
<li>An model mistake that marked an annotation 'correct' where it should be incorrect</li>
<li>An annotator mistake that marked an annotation 'correct' where it should be incorrect</li>
</ul>
</div>
<table class="table table-hover">
<thead>
<tr>
Expand All @@ -150,7 +165,7 @@
</tr>
</thead>
<tbody>
<anno-result v-for="(res, key) of predictedResults" :key="key" :result="res"></anno-result>
<anno-result v-for="(res, key) of modalData.results" :key="key" :result="res" :type="modalData.type"></anno-result>
</tbody>
</table>
</div>
Expand Down Expand Up @@ -222,21 +237,34 @@ export default {
metaAnnsSummary: {
fields: []
},
predictedResults: null,
predictionResultsTitle: null
modalData: {
results: null,
title: null,
type: null
}
}
},
methods: {
clearModalData () {
this.modalData = {
results: null,
title: null,
type: null
}
},
openExamples (exampleType, item) {
if (exampleType === 'tp_examples') {
this.predictionResultsTitle = 'True Positive Model Predictions'
this.modalData.title = 'True Positive Model Predictions'
this.modalData.type = 'tp'
} else if (exampleType === 'fp_examples') {
this.predictionResultsTitle = 'False Positive Model Predictions'
this.modalData.title = 'False Positive Model Predictions'
this.modalData.type = 'fp'
} else {
this.predictionResultsTitle = 'False Negative Model Predictions'
this.modalData.title = 'False Negative Model Predictions'
this.modalData.type = 'fn'
}
const idx = this.conceptSummary.items.indexOf(item)
this.predictedResults = this.conceptSummary.items[idx][exampleType]
this.modalData.results = this.conceptSummary.items[idx][exampleType]
},
perfFormatter (value) {
let txtColorClass = 'good-perf'
Expand Down Expand Up @@ -295,7 +323,6 @@ $metrics-header-height: 42px;
.concept-summary {
overflow-y: auto;
height: 100%
}
.meta-anno-summary {
Expand Down
9 changes: 9 additions & 0 deletions webapp/frontend/src/views/TrainAnnotations.vue
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,15 @@ export default {
this.metaAnnotate = this.currentEnt && (this.currentEnt.assignedValues[TASK_NAME] === CONCEPT_ALTERNATIVE ||
this.currentEnt.assignedValues[TASK_NAME] === CONCEPT_CORRECT)
this.loadingDoc = false
if (this.$route.query.annoStart && this.$route.query.annoEnd) {
const ent = _.find(this.ents, e => {
return Number(this.$route.query.annoStart) === e.start_ind &
Number(this.$route.query.annoEnd) === e.end_ind
})
if (ent) {
this.currentEnt = ent
}
}
}
})
},
Expand Down

0 comments on commit bd63f20

Please sign in to comment.