2424 import_concepts_from_cdb
2525from .data_utils import upload_projects_export
2626from .metrics import calculate_metrics
27- from .model_cache import get_medcat , get_cached_cdb , VOCAB_MAP , clear_cached_medcat , CAT_MAP , CDB_MAP , is_model_loaded
27+ from .model_cache import get_medcat , get_medcat_from_model_pack_id , get_cached_cdb , VOCAB_MAP , clear_cached_medcat , clear_cached_medcat_by_model_pack_id , is_model_pack_loaded , CAT_MAP , CDB_MAP , is_model_loaded
2828from .permissions import *
2929from .serializers import *
3030from .solr_utils import collections_available , search_collection , ensure_concept_searchable
@@ -637,32 +637,87 @@ def update_meta_annotation(request):
637637
638638@api_view (http_method_names = ['POST' ])
639639def annotate_text (request ):
640- p_id = request .data [ 'project_id' ]
641- message = request .data [ 'message' ]
642- cuis = request .data [ 'cuis' ]
643- if message is None or p_id is None :
644- return HttpResponseBadRequest ( 'No message to annotate' )
640+ message = request .data . get ( 'message' )
641+ cuis = request .data . get ( 'cuis' , [])
642+ p_id = request .data . get ( 'project_id' )
643+ modelpack_id = request . data . get ( 'modelpack_id' )
644+ include_sub_concepts = request . data . get ( 'include_sub_concepts' , False )
645645
646- project = ProjectAnnotateEntities .objects .get (id = p_id )
646+ if message is None or (p_id is None and modelpack_id is None ):
647+ return HttpResponseBadRequest ('No message to annotate' )
647648
648- cat = get_medcat (project = project )
649- cat .config .components .linking .filters .cuis = set (cuis )
649+ if modelpack_id is not None :
650+ try :
651+ cat = get_medcat_from_model_pack_id (int (modelpack_id ))
652+ except (ValueError , TypeError ):
653+ logger .warning (f'Invalid modelpack_id received for project:{ p_id } ' )
654+ return HttpResponseBadRequest ('Invalid modelpack_id for project' )
655+ except ModelPack .DoesNotExist :
656+ logger .warning (f'ModelPack does not exist received for project:{ p_id } ' )
657+ return HttpResponseBadRequest ('ModelPack does not exist for project' )
658+ else :
659+ project = ProjectAnnotateEntities .objects .get (id = p_id )
660+ cat = get_medcat (project = project )
661+
662+ # Normalise cuis to a set[str]
663+ if isinstance (cuis , str ):
664+ cuis_set = {c .strip () for c in cuis .split (',' ) if c .strip ()}
665+ elif isinstance (cuis , (list , tuple , set )):
666+ cuis_set = {str (c ).strip () for c in cuis if str (c ).strip ()}
667+ else :
668+ cuis_set = set ()
669+
670+ # Expand CUIs to include sub-concepts if requested
671+ if include_sub_concepts and cuis_set and cat .cdb :
672+ expanded_cuis = set (cuis_set )
673+ for parent_cui in cuis_set :
674+ try :
675+ child_cuis = get_all_ch (parent_cui , cat .cdb )
676+ expanded_cuis .update (child_cuis )
677+ except Exception as e :
678+ logger .warning (f'Failed to get children for CUI { parent_cui } : { e } ' )
679+ cuis_set = expanded_cuis
680+
681+ curr_cuis = cat .config .components .linking .filters
682+ cat .config .components .linking .filters .cuis = cuis_set
650683 spacy_doc = cat (message )
684+ cat .config .components .linking .filters = curr_cuis
651685
652686 ents = []
653687 anno_tkns = []
654688 for ent in spacy_doc .linked_ents :
655689 cnt = Entity .objects .filter (label = ent .cui ).count ()
656690 inc_ent = all (tkn not in anno_tkns for tkn in ent )
657691 if inc_ent and cnt != 0 :
692+ meta_annotations = []
693+ if 'meta_cat_meta_anns' in ent .get_available_addon_paths ():
694+ meta_anns = ent .get_addon_data ('meta_cat_meta_anns' )
695+ for meta_ann_task , pred in meta_anns .items ():
696+ # Extract value and confidence from pred
697+ # pred can be a dict, object, or string
698+ if isinstance (pred , dict ):
699+ pred_value = pred .get ('value' , str (pred ))
700+ pred_confidence = pred .get ('confidence' , None )
701+ elif hasattr (pred , 'value' ):
702+ pred_value = pred .value
703+ pred_confidence = getattr (pred , 'confidence' , None )
704+ else :
705+ pred_value = str (pred )
706+ pred_confidence = None
707+ meta_annotations .append ({
708+ 'task' : meta_ann_task ,
709+ 'value' : pred_value ,
710+ 'confidence' : pred_confidence
711+ })
658712 anno_tkns .extend ([tkn for tkn in ent ])
659713 entity = Entity .objects .get (label = ent .cui )
660714 ents .append ({
661715 'entity' : entity .id ,
662716 'value' : ent .base .text ,
663717 'start_ind' : ent .base .start_char_index ,
664718 'end_ind' : ent .base .end_char_index ,
665- 'acc' : ent .context_similarity
719+ 'acc' : ent .context_similarity ,
720+ 'meta_annotations' : meta_annotations
666721 })
667722
668723 ents .sort (key = lambda e : e ['start_ind' ])
@@ -752,7 +807,7 @@ def upload_deployment(request):
752807
753808
754809@api_view (http_method_names = ['GET' , 'DELETE' ])
755- def cache_model (request , project_id ):
810+ def cache_project_model (request , project_id ):
756811 try :
757812 project = ProjectAnnotateEntities .objects .get (id = project_id )
758813 is_loaded = is_model_loaded (project )
@@ -772,6 +827,24 @@ def cache_model(request, project_id):
772827 return Response ({'message' : f'{ str (e )} ' }, 500 )
773828
774829
830+ @api_view (http_method_names = ['GET' , 'DELETE' ])
831+ def cache_modelpack (request , modelpack_id : int ):
832+ try :
833+ if request .method == 'GET' :
834+ if not is_model_pack_loaded (modelpack_id ):
835+ get_medcat_from_model_pack_id (modelpack_id )
836+ return Response ('success' , 200 )
837+ elif request .method == 'DELETE' :
838+ clear_cached_medcat_by_model_pack_id (modelpack_id )
839+ return Response ('success' , 200 )
840+ else :
841+ return Response (f'Invalid method' , 404 )
842+ except ModelPack .DoesNotExist :
843+ return Response (f'ModelPack with id:{ modelpack_id } does not exist' , 404 )
844+ except Exception as e :
845+ return Response ({'message' : f'{ str (e )} ' }, 500 )
846+
847+
775848
776849@api_view (http_method_names = ['GET' ])
777850def model_loaded (_ ):
0 commit comments