From 3f082eae85fbd79c0b7d9b9a06feda28833a335f Mon Sep 17 00:00:00 2001 From: Chime Ogbuji Date: Tue, 22 Oct 2024 10:18:48 -0400 Subject: [PATCH] Additional useful model bits. Add popover help for iconography --- .../commands/load_snomed_ct_data.py | 4 +-- src/snomed_ct/models.py | 27 +++++++++++++++---- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/snomed_ct/management/commands/load_snomed_ct_data.py b/src/snomed_ct/management/commands/load_snomed_ct_data.py index 0384d25..9fed431 100644 --- a/src/snomed_ct/management/commands/load_snomed_ct_data.py +++ b/src/snomed_ct/management/commands/load_snomed_ct_data.py @@ -15,10 +15,8 @@ def tqdm(item): from django.core.management.base import BaseCommand, CommandError from django.db import transaction, connection -from glob import glob -import argparse import re -from zipfile import ZipFile, Path as ZipPath, BadZipFile +from zipfile import ZipFile, Path as ZipPath from snomed_ct.models import Concept, Description, TextDefinition, Relationship, ICD10_Mapping, TransitiveClosure INTERNATIONAL_FILENAME_COMPONENT = '_INT_' diff --git a/src/snomed_ct/models.py b/src/snomed_ct/models.py index 57361b7..cd42707 100755 --- a/src/snomed_ct/models.py +++ b/src/snomed_ct/models.py @@ -1,5 +1,6 @@ from enum import Enum import uuid +import functools import re from django.core.cache import caches from functools import reduce @@ -26,7 +27,7 @@ def print_function_entry_and_exit(decorated_function): Entry and exit as logging.info, parameters as logging.DEBUG. """ - import inspect, time, functools + import inspect @functools.wraps(decorated_function) def wrapper(*dec_fn_args, **dec_fn_kwargs): @@ -338,13 +339,17 @@ def part_of_transitive(self, chain=None, stop_concepts=None, recursion_depth=0, # return Concept.objects.filter(id__in=self.inbound_relationships() # .filter(type_id=PART_OF).values_list('source', flat=True)) + @functools.cache def isa_transitive(self, chain=None, **kwargs): - chain = chain if chain else [] + chain = chain if chain else () + if self.id in chain: + return tuple(chain) + rt = [self.id] if self.id != 404684003 and self.id not in chain: - for concept in self.isa: - rt.extend(concept.isa_transitive(rt, **kwargs)) - return chain + rt + for concept in self.isa.exclude(id__in=chain): + rt = list(concept.isa_transitive(tuple(rt), **kwargs)) + rt + return tuple(rt + list(chain)) def transitive_general_concept(self): return self.transitive_isa.general_concepts @@ -394,6 +399,10 @@ class DescriptionQuerySet(CommonSNOMEDQuerySet): def fully_specified_names(self): return self.filter(type_id=DESCRIPTION_TYPES['Fully specified name']) + @property + def other_names(self): + return self.exclude(type_id=DESCRIPTION_TYPES['Fully specified name']) + @property def concepts(self): return Concept.by_ids(set(self.values_list('concept__id', flat=True))) @@ -422,6 +431,10 @@ def fully_specified_names(self): def synonyms(self): return self.get_queryset().synonyms + @property + def active(self): + return self.get_queryset().active + class TransitiveClosureQuerySet(CommonSNOMEDQuerySet): @property def general_concepts(self): @@ -827,6 +840,10 @@ def has_definitions(self): @property def concepts(self): return Concept.objects.filter(id__in=self.values_list('referenced_component', flat=True)) + + def with_active_concepts(self): + return self.filter(referenced_component__active=True) + class ICD10_MappingManager(models.Manager): def get_queryset(self): return ICD10_MappingQuerySet(self.model)