Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions medcat-trainer/webapp/api/api/model_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@ def get_medcat(project,
cdb_map: Dict[str, CDB]=CDB_MAP,
vocab_map: Dict[str, Vocab]=VOCAB_MAP,
cat_map: Dict[str, CAT]=CAT_MAP):
cat = get_cached_medcat(project, cat_map)
if cat is not None:
return cat
try:
if project.model_pack is None:
cat = get_medcat_from_cdb_vocab(project, cdb_map, vocab_map, cat_map)
Expand Down
2 changes: 1 addition & 1 deletion medcat-trainer/webapp/api/api/solr_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def drop_collection(cdb_model: ConceptDB):

def ensure_concept_searchable(cui, cdb: CDB, cdb_model: ConceptDB):
"""
Adds a single cui and associated metadata is available in the assocaited solr search index.
Adds a single cui and associated metadata is available in the associated solr search index.
Args:
cui: concept unique identifier of the concept to make searchable
cdb: the MedCAT CDB where the cui can be found
Expand Down
1 change: 0 additions & 1 deletion medcat-trainer/webapp/api/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ def get_create_cdb_infos(cdb, concept, cui, cui_info_prop, code_prop, desc_prop,
return model_clazz.objects.filter(code__in=codes)



def create_annotation(source_val: str, selection_occurrence_index: int, cui: str, user: User,
project: ProjectAnnotateEntities, document: Document):
text = document.text
Expand Down
32 changes: 23 additions & 9 deletions medcat-trainer/webapp/api/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,30 +435,44 @@ def add_concept(request):

cat = get_medcat(project=project)

if cui in cat.cdb.cui2names:
err_msg = f'Cannot add a concept "{name}" with cui:{cui}. CUI already linked to {cat.cdb.cui2names[cui]}'
if cui in cat.cdb.cui2info:
err_msg = f'Cannot add a concept "{name}" with cui:{cui}. CUI already linked to {cat.cdb.cui2info[cui]["preferred_name"]}'
logger.error(err_msg)
return Response({'err': err_msg}, 400)

spacy_doc = cat(document.text)
spacy_entity = None
if source_val in spacy_doc.text:
start = spacy_doc.text.index(source_val)
end = start + len(source_val)
spacy_entity = [tkn for tkn in spacy_doc if tkn.idx >= start and tkn.idx <= end]

# Find all occurrences of source_val in the text
all_occurrences_start_idxs = []
idx = 0
while idx != -1:
idx = spacy_doc.text.find(source_val, idx)
if idx != -1:
all_occurrences_start_idxs.append(idx)
idx += len(source_val)

# Use selection_idx to get the correct occurrence
if sel_occur_idx < len(all_occurrences_start_idxs):
start = all_occurrences_start_idxs[sel_occur_idx]
end = start + len(source_val)
# Find tokens that overlap with the span [start, end)
# A token overlaps if: token_start < end AND token_end > start
spacy_entity = [tkn for tkn in spacy_doc if tkn.char_index < end and (tkn.char_index + len(tkn.text)) > start]
# if len(spacy_entity) == 0:
# spacy_entity = None
cat.trainer.add_and_train_concept(cui=cui, name=name, name_status='P', mut_doc=spacy_doc, mut_entity=spacy_entity)


id = create_annotation(source_val=source_val,
selection_occurrence_index=sel_occur_idx,
cui=cui,
user=user,
project=project,
document=document,
cat=cat)
document=document)

# ensure new concept detail is available in SOLR search service
ensure_concept_searchable(cui, cat.cdb, project.concept_db)
ensure_concept_searchable(cui, cat.cdb, project.cdb_search_filter.first())

# add to project cuis if required.
if (project.cuis or project.cuis_file) and project.restrict_concept_lookup:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,14 @@ export default {
cui: this.selectedCUI.cui
}
this.loading = true
this.$http.get(`/api/cache-model/${this.project.id}/`).then(_ => {
this.$http.post('/api/add-annotation/', payload).then(resp => {
this.loading = false
this.$http.post('/api/add-annotation/', payload).then(resp => {
this.$emit('request:addAnnotationComplete', resp.data.id)
this.selectedCUI = null
})
this.$emit('request:addAnnotationComplete', resp.data.id)
this.selectedCUI = null
}).catch(err => {
this.loading = false
this.errorMessage = err.response.data.message || 'Error loading model.'
})

},
cancel () {
this.$emit('request:addAnnotationComplete')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,16 @@
</tbody>
</table>
<div class="footer action-buttons">
<button class="btn btn-primary" :disabled="!addConceptEnabled()"
@click="addConcept">Add Concept</button>
<button class="btn btn-primary" :disabled="!addConceptEnabled() || loading"
@click="addConcept">
<font-awesome-icon v-if="!loading" icon="plus"></font-awesome-icon>
<font-awesome-icon v-if="loading" icon="spinner" spin size="xs" />
Add Concept
</button>
</div>
<div class="alert alert-info" role="alert" v-if="loading">
<font-awesome-icon icon="spinner" spin size="xs" />
Caching model, please wait...
</div>
<div class="alert alert-danger" role="alert" v-if="addConceptErr">
{{addConceptErr}}
Expand Down Expand Up @@ -73,7 +81,8 @@ export default {
cui: '',
synonyms: ''
},
addConceptErr: false
addConceptErr: false,
loading: false
}
},
methods: {
Expand All @@ -96,23 +105,35 @@ export default {
let nextCtx = this.selection.nextText.slice(0, 30).split(' ').slice(0, -1)
payload['context'] = `${this.selection.prevText}${this.selection.selStr}${nextCtx}`

this.$http.post(`/api/add-concept/`, payload).then(resp => {
this.$emit('request:addConceptComplete', resp.data.id)
this.loading = true
this.$http.get(`/api/cache-model/${this.project.id}/`).then(_ => {
this.$http.post(`/api/add-concept/`, payload).then(resp => {
this.loading = false
this.$emit('request:addConceptComplete', resp.data.id)
}).catch(err => {
this.loading = false
if (err.code === 400) {
this.addConceptErr = 'Invalid CUI value. CUI already exists in MedCAT.'
let that = this
setTimeout(function () {
that.addConceptErr = false
}, 5000)
} else {
this.addConceptErr = `Error adding concept:${(err.response.data || {}).err || 'Unknown error: more info in the console'}`
console.error(err)
let that = this
setTimeout(function () {
that.addConceptErr = false
}, 5000)
}
})
}).catch(err => {
if (err.code === 400) {
this.addConceptErr = 'Invalid CUI value. CUI already exists in MedCAT.'
let that = this
setTimeout(function () {
that.addConceptErr = false
}, 5000)
} else {
this.addConceptErr = `Error adding concept:${(err.response.data || {}).err || 'Unknown error: more info in the console'}`
console.error(err)
let that = this
setTimeout(function () {
that.addConceptErr = false
}, 5000)
}
this.loading = false
this.addConceptErr = err.response?.data?.message || 'Error loading model.'
let that = this
setTimeout(function () {
that.addConceptErr = false
}, 5000)
})
}
}
Expand Down