/// <summary> /// Find snomed concept with indicated name. /// </summary> /// <param name="name"></param> /// <returns></returns> public RF2ConceptGroup FindSnomedConcept(String name) { name = name.ToUpper(); List <RF2ConceptGroup> retVal = new List <RF2ConceptGroup>(); foreach (RF2DescriptionGroup descriptionGroup in this.DescriptionGroups.Values) { foreach (RF2Description description in descriptionGroup.Items) { if (String.Compare(description?.Term.Trim().ToUpper(), name) == 0) { RF2ConceptGroup cg = this.GetConceptGroup(description.ConceptId); if (retVal.Contains(cg) == false) { retVal.Add(cg); } } } } if (retVal.Count == 0) { throw new ApplicationException("No Snomed CT Concept records found"); } if (retVal.Count > 1) { throw new ApplicationException("Multiple Snomed CT Concept records found"); } return(retVal[0]); }
/// <summary> /// Iterate over all rf2Parser concepts and create correct GcSnomedConcept derived class for each element. /// </summary> void CreateConceptRecords() { foreach (KeyValuePair <Int64, RF2ConceptGroup> kvp in this.rf2Parser.ConceptGroups) { RF2ConceptGroup rf2ConceptGroup = kvp.Value; SnomedQueryConcept concept = this.CreateConceptRecord(rf2ConceptGroup); if (concept != null) { this.modelManager.Add(concept); } } }
/// <summary> /// Pathc relationships. /// This must be run after concepts are read in. /// </summary> /// <param name="path"></param> void FixRelationships() { foreach (KeyValuePair <Int64, RF2RelationshipGroup> kvp in this.RelationshipGroups) { RF2RelationshipGroup relationshipGroup = kvp.Value; RF2Relationship relationship = relationshipGroup.Active; if (relationship != null) { RF2ConceptGroup sourceConcept = this.GetConceptGroup(relationship.SourceId); RF2ConceptGroup destinationConcept = this.GetConceptGroup(relationship.DestinationId); sourceConcept.AddSourceRelationship(relationshipGroup); destinationConcept.AddDestinationRelationship(relationshipGroup); } } }
/// <summary> /// Iterate over all rf2Parser concepts and create correct GcSnomedConcept derived class for each element. /// </summary> SnomedQueryConcept CreateConceptRecord(RF2ConceptGroup rf2ConceptGroup) { RF2Concept rf2Concept = rf2ConceptGroup.Active; if (rf2Concept == null) { return(null); } RF2ConceptGroup module = this.rf2Parser.GetConceptGroup(rf2Concept.ModuleId); RF2ConceptGroup definitionStatus = this.rf2Parser.GetConceptGroup(rf2Concept.DefinitionStatusId); List <String> synonyms = new List <string>(); foreach (RF2DescriptionGroup descriptionGroup in rf2ConceptGroup.DescriptionGroups) { RF2Description description = descriptionGroup.GetActiveEnglishDescription(); switch (description.TypeId) { case RF2Parser.SynonymTypeId: synonyms.Add(description.Term); break; case RF2Parser.FullySpecifiedNameConceptId: break; default: Console.WriteLine($"Unimplemented description type {this.rf2Parser.GetConceptGroup(description.TypeId).GetFullySpecifiedName()}"); break; } } SnomedQueryConcept concept = new SnomedQueryConcept( rf2Concept.Id, // conceptId, rf2ConceptGroup.GetFullySpecifiedName(), // conceptFullyQualifiedName, synonyms.ToArray(), // conceptSynonymns, module.GetFullySpecifiedName(), // String conceptModule, definitionStatus.GetFullySpecifiedName(), // String conceptDefinitionStatus, rf2Concept.EffectiveTime // conceptEffectiveTime ); return(concept); }
/// <summary> /// Load raw snomed description data into memory. /// </summary> /// <param name="path"></param> public void LoadFromRF2Files(String conceptPath, String relationshipPath, String descriptionPath) { // Load main three snomed files (concepts, relationships, and descriptions). // Load files concurrently { Thread loadConceptsTask = new Thread(() => this.LoadConcepts(conceptPath)); Thread loadRelationshipsTask = new Thread(() => this.LoadRelationships(relationshipPath)); Thread loadDescriptionsTask = new Thread(() => this.LoadDescriptions(descriptionPath)); loadConceptsTask.Start(); loadRelationshipsTask.Start(); loadDescriptionsTask.Start(); loadConceptsTask.Join(); loadRelationshipsTask.Join(); loadDescriptionsTask.Join(); } // Perform cleanup on above loaded files. { Thread fixConceptsTask = new Thread(this.FixConcepts); Thread fixRelationshipsTask = new Thread(this.FixRelationships); Thread fixDescriptionsTask = new Thread(this.FixDescriptions); fixConceptsTask.Start(); fixRelationshipsTask.Start(); fixDescriptionsTask.Start(); fixConceptsTask.Join(); fixRelationshipsTask.Join(); fixDescriptionsTask.Join(); } this.RootConcept = this.FindSnomedConcept("SNOMED CT CONCEPT"); }
/// <summary> /// Load raw snomed concept data into memory. /// </summary> /// <param name="path"></param> void LoadConcepts(String path) { StreamReader reader = new StreamReader(File.OpenRead(path)); String[] parts = reader.ReadLine().Split('\t'); if ( (parts.Length != 5) || (String.Compare(parts[0], "id") != 0) || (String.Compare(parts[1], "effectiveTime") != 0) || (String.Compare(parts[2], "active") != 0) || (String.Compare(parts[3], "moduleId") != 0) || (String.Compare(parts[4], "definitionStatusId") != 0) ) { throw new ApplicationException("Invalid header line to concept file"); } RF2ConceptGroup conceptGroup = null; while (true) { String line = reader.ReadLine(); if (line == null) { break; } RF2Concept concept = RF2Concept.Parse(this, line); if (concept != null) { /* * Relationships in a common group are usually grouped together, so check * last relationship to see if it is same group first. */ if ((conceptGroup != null) && (conceptGroup.Id != concept.Id)) { conceptGroup = null; } if ( (conceptGroup == null) && (this.ConceptGroups.TryGetValue(concept.Id, out conceptGroup) == false) ) { conceptGroup = null; } if (conceptGroup == null) { conceptGroup = new RF2ConceptGroup() { Parser = this, Id = concept.Id }; if (this.ConceptGroups.TryAdd(concept.Id, conceptGroup) == false) { throw new ApplicationException("Error adding concept to dictionary"); } } conceptGroup.AddConcept(concept); } } }