From f19426f414f6172e1d528c0606ad9ca5ef5cd2fd Mon Sep 17 00:00:00 2001 From: Oliver Maus Date: Fri, 24 May 2024 16:05:13 +0200 Subject: [PATCH 1/6] Add ControlledVocabulary dependency --- src/OBO.NET/OBO.NET.fsproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/OBO.NET/OBO.NET.fsproj b/src/OBO.NET/OBO.NET.fsproj index e525b27..5127a25 100644 --- a/src/OBO.NET/OBO.NET.fsproj +++ b/src/OBO.NET/OBO.NET.fsproj @@ -38,6 +38,7 @@ + From 2e583a575a69371abacd6aea61eb61e8505e65b7 Mon Sep 17 00:00:00 2001 From: Oliver Maus Date: Fri, 24 May 2024 16:05:33 +0200 Subject: [PATCH 2/6] Add `toCvTerm` functionality to DBXref --- playground.fsx | 211 ++++-------------------------------------- src/OBO.NET/DBXref.fs | 16 ++++ 2 files changed, 33 insertions(+), 194 deletions(-) diff --git a/playground.fsx b/playground.fsx index 3fb8ca3..ddeb251 100644 --- a/playground.fsx +++ b/playground.fsx @@ -4,11 +4,11 @@ #I "src/OBO.NET.CodeGeneration/bin/Release/netstandard2.0" #r "OBO.NET.dll" -#r "OBO.NET.CodeGeneration.dll" +//#r "OBO.NET.CodeGeneration.dll" open OBO.NET open OBO.NET.DBXref -open OBO.NET.CodeGeneration +//open OBO.NET.CodeGeneration #r "nuget: FSharpAux" #r "nuget: ARCTokenization" @@ -22,200 +22,23 @@ open System open type System.Environment +let term1 = OboTerm.Create "" +let term2 = OboTerm.Create "" +let r = term1.Xrefs |> List.exists (fun x1 -> term2.Xrefs |> List.exists (fun x2 -> x2.Name = x1.Name)) + +type OboOntology with + + member this.AreTermsEquivalent(term1 : OboTerm, term2 : OboTerm) = + term1.Xrefs + |> List.exists ( + fun x1 -> + term2.Id = x1.Name + && + this.TreatXrefsAsEquivalents + |> List.exists (fun t -> term2.) + ) -type OboOntology = - - { - Terms : OboTerm list - TypeDefs : OboTypeDef list - FormatVersion : string - DataVersion : string option - Ontology : string option - Date : DateTime option - SavedBy : string option - AutoGeneratedBy : string option - Subsetdefs : string list - Imports : string list // needs its own type (Record?) - Synonymtypedefs : string list // rethink type, maybe create a mother type (Union? Maybe Record'd be better) - Idspaces : string list // rethink as own Record type - DefaultRelationshipIdPrefix : string option - IdMappings : string list // rethink: maybe a new record? or TermRelation? - Remarks : string list - TreatXrefsAsEquivalents : string list - TreatXrefsAsGenusDifferentias : string list // rethink: maybe a new record? or plain string option? - TreatXrefsAsRelationships : string list // maybe better as its own (Record/Union?) type - TreatXrefsAsIsAs : string list - RelaxUniqueIdentifierAssumptionForNamespaces : string list - RelaxUniqueLabelAssumptionForNamespaces : string list - } - - /// Creates an OboOntology based on the given parameters. - static member create terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idspaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces = - { - Terms = terms - TypeDefs = typedefs - FormatVersion = formatVersion - DataVersion = dataVersion - Ontology = ontology - Date = date - SavedBy = savedBy - AutoGeneratedBy = autoGeneratedBy - Subsetdefs = subsetdefs - Imports = imports - Synonymtypedefs = synonymtypedefs - Idspaces = idspaces - DefaultRelationshipIdPrefix = defaultRelationshipIdPrefix - IdMappings = idMappings - Remarks = remarks - TreatXrefsAsEquivalents = treatXrefsAsEquivalents - TreatXrefsAsGenusDifferentias = treatXrefsAsGenusDifferentias - TreatXrefsAsRelationships = treatXrefsAsRelationships - TreatXrefsAsIsAs = treatXrefsAsIsAs - RelaxUniqueIdentifierAssumptionForNamespaces = relaxUniqueIdentifierAssumptionForNamespaces - RelaxUniqueLabelAssumptionForNamespaces = relaxUniqueLabelAssumptionForNamespaces - } - - /// Creates an OboOntology based on the given arguments. - static member Create(terms, typedefs, formatVersion, ?DataVersion, ?Ontology, ?Date, ?SavedBy, ?AutoGeneratedBy, ?Subsetdefs, ?Imports, ?Synonymtypedefs, ?Idspaces, ?DefaultRelationshipIdPrefix, ?IdMappings, ?Remarks, ?TreatXrefsAsEquivalents, ?TreatXrefsAsGenusDifferentias, ?TreatXrefsAsRelationships, ?TreatXrefsAsIsAs, ?RelaxUniqueIdentifierAssumptionForNamespaces, ?RelaxUniqueLabelAssumptionForNamespaces) = { - Terms = terms - TypeDefs = typedefs - FormatVersion = formatVersion - DataVersion = DataVersion - Ontology = Ontology - Date = Date - SavedBy = SavedBy - AutoGeneratedBy = AutoGeneratedBy - Subsetdefs = defaultArg Subsetdefs [] - Imports = defaultArg Imports [] - Synonymtypedefs = defaultArg Synonymtypedefs [] - Idspaces = defaultArg Idspaces [] - DefaultRelationshipIdPrefix = DefaultRelationshipIdPrefix - IdMappings = defaultArg IdMappings [] - Remarks = defaultArg Remarks [] - TreatXrefsAsEquivalents = defaultArg TreatXrefsAsEquivalents [] - TreatXrefsAsGenusDifferentias = defaultArg TreatXrefsAsGenusDifferentias [] - TreatXrefsAsRelationships = defaultArg TreatXrefsAsRelationships [] - TreatXrefsAsIsAs = defaultArg TreatXrefsAsIsAs [] - RelaxUniqueIdentifierAssumptionForNamespaces = defaultArg RelaxUniqueIdentifierAssumptionForNamespaces [] - RelaxUniqueLabelAssumptionForNamespaces = defaultArg RelaxUniqueLabelAssumptionForNamespaces [] - } - -//let res = (createRegex RegexOptions.None """format-version\s:\s*(?.+)""").Match "format-version : 17.5.1" -//let res = (createRegex RegexOptions.None """format-version\s:\s*(?.+)""").Match "format-verson: 17.5.1" -//res.Groups["formatVersion"].Value -//DateTime.ParseExact("31:12:2000 23:59", "dd:MM:yyyy HH:mm", Globalization.CultureInfo.InvariantCulture) - - /// Reads an OBO Ontology containing document header tags, and term and type def stanzas from lines. - static member fromLines verbose (input : seq) = - - let rxFormatVersion = createRegex RegexOptions.None @"format-version\s*:\s*(?.+)" - let rxDataVersion = createRegex RegexOptions.None @"(?:data-version|version)\s*:\s*(?.+)" - let rxOntology = createRegex RegexOptions.None @"ontology\s*:\s*(?.+)" - let rxDate = createRegex RegexOptions.None @"date\s*:\s*(?\d{2}:\d{2}:\d{4} \d{2}:\d{2})" - let rxSavedBy = createRegex RegexOptions.None @"saved-by\s*:\s*(?.+)" - let rxAutoGeneratedBy = createRegex RegexOptions.None @"auto-generated-by\s*:\s*(?.+)" - let rxSubsetdef = createRegex RegexOptions.None @"subsetdef\s*:\s*(?.+)" - let rxImport = createRegex RegexOptions.None @"import\s*:\s*(?.+)" - let rxSynonymtypedef = createRegex RegexOptions.None @"synonymtypedef\s*:\s*(?.+)" - let rxIdspace = createRegex RegexOptions.None @"idspace\s*:\s*(?.+)" - let rxDefaultRelationshipIdPrefix = createRegex RegexOptions.None @"default-relationship-id-prefix\s*:\s*(?.+)" - let rxIdMapping = createRegex RegexOptions.None @"id-mapping\s*:\s*(?.+)" - let rxRemark = createRegex RegexOptions.None @"remark\s*:\s*(?.+)" - let rxTreatXrefsAsEquivalent = createRegex RegexOptions.None @"treat-xrefs-as-equivalent\s*:\s*(?.+)" - let rxTreatXrefsAsGenusDifferentia = createRegex RegexOptions.None @"treat-xrefs-as-genus-differentia\s*:\s*(?.+)" - let rxTreatXrefsAsRelationship = createRegex RegexOptions.None @"treat-xrefs-as-relationship\s*:\s*(?.+)" - let rxTreatXrefsAsIsA = createRegex RegexOptions.None @"treat-xrefs-as-is_a\s*:\s*(?.+)" - let rxRelaxUniqueIdentifierAssumptionForNamespace = createRegex RegexOptions.None @"relax-unique-identifier-assumption-for-namespace\s*:\s*(?.+)" - let rxRelaxUniqueLabelAssumptionForNamespace = createRegex RegexOptions.None @"relax-unique-label-assumption-for-namespace\s*:\s*(?.+)" - - let en = input.GetEnumerator() - - let rec loop (en : System.Collections.Generic.IEnumerator) terms typedefs formatVersion (dataVersion : string option) ontology (date : DateTime option) (savedBy : string option) (autoGeneratedBy : string option) subsetdefs imports synonymtypedefs idSpaces (defaultRelationshipIdPrefix : string option) idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces lineNumber = - - match en.MoveNext() with - | true -> - match trimComment en.Current with - | "[Term]" -> - let lineNumber,parsedTerm = OboTerm.fromLines verbose en lineNumber "" "" false [] "" "" [] [] [] [] [] [] [] [] false [] [] [] false "" "" - loop en (parsedTerm :: terms) typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsIsAs treatXrefsAsRelationships treatXrefsAsGenusDifferentias relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces lineNumber - | "[Typedef]" -> - let lineNumber,parsedTypeDef = OboTypeDef.fromLines verbose en lineNumber "" "" "" "" [] [] false false false false false false false - loop en terms (parsedTypeDef :: typedefs) formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces lineNumber - | x when (rxFormatVersion.Match x).Success -> - if formatVersion <> "" then printfn "WARNING: Duplicate format-version in document header tags!" - loop en terms typedefs (rxFormatVersion.Match x).Groups["formatVersion"].Value dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxDataVersion.Match x).Success -> - if dataVersion.IsSome then printfn "WARNING: Duplicate data-version in document header tags!" - loop en terms typedefs formatVersion (Some (rxDataVersion.Match x).Groups["dataVersion"].Value) ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxOntology.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ((rxOntology.Match x).Groups["ontology"].Value |> Some) date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxDate.Match x).Success -> - if date.IsSome then printfn "WARNING: Duplicate date in document header tags!" - let parsedDate = - try DateTime.ParseExact((rxDate.Match x).Groups["date"].Value, "dd:MM:yyyy HH:mm", Globalization.CultureInfo.InvariantCulture) |> Some with - _ -> - printfn "ERROR: Inproper date given!" - None - loop en terms typedefs formatVersion dataVersion ontology parsedDate savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxSavedBy.Match x).Success -> - if savedBy.IsSome then printfn "WARNING: Duplicate saved-by in document header tags!" - loop en terms typedefs formatVersion dataVersion ontology date ((rxSavedBy.Match x).Groups["savedBy"].Value |> Some) autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxAutoGeneratedBy.Match x).Success -> - if autoGeneratedBy.IsSome then printfn "WARNING: Duplicate auto-generated-by in document header tags!" - loop en terms typedefs formatVersion dataVersion ontology date savedBy ((rxAutoGeneratedBy.Match x).Groups["autoGeneratedBy"].Value |> Some) subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxSubsetdef.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy ((rxSubsetdef.Match x).Groups["subsetdef"].Value :: subsetdefs) imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxImport.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs ((rxImport.Match x).Groups["import"].Value :: imports) synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxSynonymtypedef.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports ((rxSynonymtypedef.Match x).Groups["synonymtypedef"].Value :: synonymtypedefs) idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxIdspace.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs ((rxIdspace.Match x).Groups["idspace"].Value :: idSpaces) defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxDefaultRelationshipIdPrefix.Match x).Success -> - if defaultRelationshipIdPrefix.IsSome then printfn "WARNING: Duplicate default-relationship-id-prefix in document header tags!" - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces ((rxDefaultRelationshipIdPrefix.Match x).Groups["defaultRelationshipIdPrefix"].Value |> Some) idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxIdMapping.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix ((rxIdMapping.Match x).Groups["idMapping"].Value :: idMappings) remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxRemark.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings ((rxRemark.Match x).Groups["remark"].Value :: remarks) treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxTreatXrefsAsEquivalent.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks ((rxTreatXrefsAsEquivalent.Match x).Groups["treatXrefsAsEquivalent"].Value :: treatXrefsAsEquivalents) treatXrefsAsIsAs treatXrefsAsRelationships treatXrefsAsGenusDifferentias relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxTreatXrefsAsGenusDifferentia.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents ((rxTreatXrefsAsGenusDifferentia.Match x).Groups["treatXrefsAsGenusDifferentia"].Value :: treatXrefsAsGenusDifferentias) treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxTreatXrefsAsRelationship.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias ((rxTreatXrefsAsRelationship.Match x).Groups["treatXrefsAsRelationship"].Value :: treatXrefsAsRelationships) treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxTreatXrefsAsIsA.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships ((rxTreatXrefsAsIsA.Match x).Groups["treatXrefsAsIsA"].Value :: treatXrefsAsIsAs) relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxRelaxUniqueIdentifierAssumptionForNamespace.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs ((rxRelaxUniqueIdentifierAssumptionForNamespace.Match x).Groups["relaxUniqueIdentifierAssumptionForNamespace"].Value :: relaxUniqueIdentifierAssumptionForNamespaces) relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | x when (rxRelaxUniqueLabelAssumptionForNamespace.Match x).Success -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces ((rxRelaxUniqueLabelAssumptionForNamespace.Match x).Groups["relaxUniqueLabelAssumptionForNamespace"].Value :: relaxUniqueLabelAssumptionForNamespaces) (lineNumber + 1) - | _ -> - loop en terms typedefs formatVersion dataVersion ontology date savedBy autoGeneratedBy subsetdefs imports synonymtypedefs idSpaces defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsGenusDifferentias treatXrefsAsRelationships treatXrefsAsIsAs relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces (lineNumber + 1) - | false -> - OboOntology.create (List.rev terms) (List.rev typedefs) formatVersion dataVersion ontology date savedBy autoGeneratedBy (List.rev subsetdefs) (List.rev imports) (List.rev synonymtypedefs) (List.rev idSpaces) defaultRelationshipIdPrefix idMappings remarks treatXrefsAsEquivalents treatXrefsAsIsAs treatXrefsAsRelationships treatXrefsAsGenusDifferentias relaxUniqueIdentifierAssumptionForNamespaces relaxUniqueLabelAssumptionForNamespaces - - loop en [] [] String.Empty None None None None None [] [] [] [] None [] [] [] [] [] [] [] [] 0 // was 1 before - -let fl1 = OboOntology.fromLines false (IO.File.ReadAllLines(IO.Path.Combine(__SOURCE_DIRECTORY__, "tests", "OBO.NET.Tests", "References", "HeaderTags_correct.obo"))) -let fl2 = OboOntology.fromLines false (IO.File.ReadAllLines(IO.Path.Combine(__SOURCE_DIRECTORY__, "tests", "OBO.NET.Tests", "References", "HeaderTags_incorrect.obo"))) -let fl3 = OboOntology.fromLines false (IO.File.ReadAllLines(IO.Path.Combine(__SOURCE_DIRECTORY__, "tests", "OBO.NET.Tests", "References", "HeaderTags_duplicates.obo"))) - - - - -let expected = - $"namespace ARCTokenization.StructuralOntology{NewLine}{NewLine} open ControlledVocabulary{NewLine}{NewLine} module Investigation ={NewLine}{NewLine} let Investigation_Metadata = CvTerm.create(\"INVMSO:00000001\", \"Investigation Metadata\", \"INVMSO\"){NewLine}{NewLine} let ONTOLOGY_SOURCE_REFERENCE = CvTerm.create(\"INVMSO:00000002\", \"ONTOLOGY SOURCE REFERENCE\", \"INVMSO\"){NewLine}{NewLine} let Term_Source_Name = CvTerm.create(\"INVMSO:00000003\", \"Term Source Name\", \"INVMSO\")" - |> String.replace "\r" "" -let actual = - CodeGeneration.toSourceCode "Investigation" InvestigationMetadata.ontology - |> String.splitS NewLine - |> Array.take 11 - |> String.concat "\n" - |> String.replace "\r" "" - -OBO.NET.OboOntology.toFile @"C:\Repos\CSBiology\OBO.NET\tests\OBO.NET.CodeGeneration.Tests\References\ReferenceOboFile.obo" InvestigationMetadata.ontology // DEPRECATED diff --git a/src/OBO.NET/DBXref.fs b/src/OBO.NET/DBXref.fs index 96aa9b0..d278e54 100644 --- a/src/OBO.NET/DBXref.fs +++ b/src/OBO.NET/DBXref.fs @@ -1,6 +1,9 @@ namespace OBO.NET +open FSharpAux +open ControlledVocabulary + open System @@ -37,6 +40,8 @@ module DBXref = //Note that the trailing modifiers (like all trailing modifiers) do not need to be decoded or round-tripped by parsers; trailing modifiers can always be optionally ignored. However, all parsers must be able to gracefully ignore trailing modifiers. It is important to recognize that lines which accept a dbxref list may have a trailing modifier for each dbxref in the list, and another trailing modifier for the line itself. + // EXAMPLE (taken from GO_Slim Agr): "xref: RO:0002093" + let trimComment (line : string) = line.Split('!').[0].Trim() @@ -49,4 +54,15 @@ module DBXref = Name = matches.Item("xrefName").Value Description = matches.Item("xrefDescription").Value Modifiers = matches.Item("xrefModifiers").Value + } + + /// Creates a CvTerm (with an empty name) of a given DBXref. + let toCvTerm dbxref : CvTerm = + { + Name = "" + Accession = dbxref.Name + RefUri = + String.split ':' dbxref.Name + |> Array.head + |> String.trim } \ No newline at end of file From 50645d76dad7d3d86d2cf41f705e33bca32c1569 Mon Sep 17 00:00:00 2001 From: omaus Date: Tue, 4 Jun 2024 12:28:23 +0200 Subject: [PATCH 3/6] Add DBXref functionality and expand type --- src/OBO.NET/DBXref.fs | 47 ++++++++++++++---------- tests/OBO.NET.Tests/DBXref.Tests.fs | 35 ++++++++++++++++++ tests/OBO.NET.Tests/OBO.NET.Tests.fsproj | 3 +- 3 files changed, 63 insertions(+), 22 deletions(-) create mode 100644 tests/OBO.NET.Tests/DBXref.Tests.fs diff --git a/src/OBO.NET/DBXref.fs b/src/OBO.NET/DBXref.fs index d278e54..5b35ff2 100644 --- a/src/OBO.NET/DBXref.fs +++ b/src/OBO.NET/DBXref.fs @@ -7,13 +7,34 @@ open ControlledVocabulary open System -/// Representation of dbxrefs. -type DBXref = { +/// Representation of DBXrefs. +type DBXref = + { Name : string Description : string Modifiers : string } + /// Parses a given string to a DBXref + static member ofString (v : string) = + let xrefRegex = Text.RegularExpressions.Regex("""(?^([^"{])*)(\s?)(?\"(.*?)\")?(\s?)(?\{(.*?)}$)?""") + let matches = xrefRegex.Match(v.Trim()).Groups + { + Name = matches.Item("xrefName") .Value |> String.trim + Description = matches.Item("xrefDescription") .Value |> String.trim + Modifiers = matches.Item("xrefModifiers") .Value |> String.trim + } + + /// Returns the corresponding CvTerm of the DBXref with empty name. + member this.ToCvTerm() = { + Name = "" + Accession = this.Name + RefUri = + String.split ':' this.Name + |> Array.head + |> String.trim + } + /// Functions for working with DBXrefs. module DBXref = @@ -45,24 +66,10 @@ module DBXref = let trimComment (line : string) = line.Split('!').[0].Trim() - let private xrefRegex = - Text.RegularExpressions.Regex("""(?^([^"{])*)(\s?)(?\"(.*?)\")?(\s?)(?\{(.*?)}$)?""") - + [] let parseDBXref (v : string) = - let matches = xrefRegex.Match(v.Trim()).Groups - { - Name = matches.Item("xrefName").Value - Description = matches.Item("xrefDescription").Value - Modifiers = matches.Item("xrefModifiers").Value - } + DBXref.ofString v /// Creates a CvTerm (with an empty name) of a given DBXref. - let toCvTerm dbxref : CvTerm = - { - Name = "" - Accession = dbxref.Name - RefUri = - String.split ':' dbxref.Name - |> Array.head - |> String.trim - } \ No newline at end of file + let toCvTerm (dbxref : DBXref) = + dbxref.ToCvTerm() \ No newline at end of file diff --git a/tests/OBO.NET.Tests/DBXref.Tests.fs b/tests/OBO.NET.Tests/DBXref.Tests.fs new file mode 100644 index 0000000..afccbad --- /dev/null +++ b/tests/OBO.NET.Tests/DBXref.Tests.fs @@ -0,0 +1,35 @@ +namespace OBO.NET.Tests + + +open OBO.NET + +open Expecto +open ControlledVocabulary + + +module DBXref = + + [] + let dbxrefTests = + testList "DBXref" [ + + let testDBXref = DBXref.ofString """test:1 "testDesc" {testMod}""" + + testList "ofString" [ + testCase "returns correct DBXref" <| fun _ -> + let expected = {Name = "test:1"; Description = "\"testDesc\""; Modifiers = "{testMod}"} + Expect.equal testDBXref.Name expected.Name "Name does not match" + Expect.equal testDBXref.Description expected.Description "Description does not match" + Expect.equal testDBXref.Modifiers expected.Modifiers "Modifiers do not match" + ] + + testList "ToCvTerm" [ + testCase "returns correct CvTerm" <| fun _ -> + let actual = testDBXref.ToCvTerm() + let expected = CvTerm.create("test:1", "", "test") + Expect.equal actual.Accession expected.Accession "TANs are not equal" + Expect.equal actual.RefUri expected.RefUri "TSRs are not equal" + Expect.equal actual.Name expected.Name "Names are not equal" + ] + + ] \ No newline at end of file diff --git a/tests/OBO.NET.Tests/OBO.NET.Tests.fsproj b/tests/OBO.NET.Tests/OBO.NET.Tests.fsproj index 1883492..1613971 100644 --- a/tests/OBO.NET.Tests/OBO.NET.Tests.fsproj +++ b/tests/OBO.NET.Tests/OBO.NET.Tests.fsproj @@ -12,6 +12,7 @@ + @@ -32,6 +33,4 @@ - - From 477e1e3465144f15f5de881ac8630f61f226a6ce Mon Sep 17 00:00:00 2001 From: omaus Date: Tue, 4 Jun 2024 12:29:20 +0200 Subject: [PATCH 4/6] Add function to return OboTerm as CvTerm --- src/OBO.NET/OboTerm.fs | 18 ++++++++++++++++-- tests/OBO.NET.Tests/OboTerm.Tests.fs | 11 +++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/OBO.NET/OboTerm.fs b/src/OBO.NET/OboTerm.fs index a3d6f74..c5c5930 100644 --- a/src/OBO.NET/OboTerm.fs +++ b/src/OBO.NET/OboTerm.fs @@ -3,10 +3,12 @@ open DBXref open TermSynonym -open ARCtrl.ISA - open System +open ARCtrl.ISA +open ControlledVocabulary +open FSharpAux + /// Models the entities in an OBO Ontology. type OboTerm = @@ -540,6 +542,18 @@ type OboTerm = static member getRelatedTermIds (term : OboTerm) = term.GetRelatedTermIds() + /// Returns the corresponding CvTerm of the OboTerm. + member this.ToCvTerm() = + let tsr = + String.split ':' this.Id + |> Array.head + |> String.trim + CvTerm.create(this.Id, this.Name, tsr) + + /// Returns the corresponding CvTerm of the given OboTerm. + static member toCvTerm (term : OboTerm) = + term.ToCvTerm() + /// Representation of a the relation an OboTerm can have with other OboTerms. type TermRelation<'a> = diff --git a/tests/OBO.NET.Tests/OboTerm.Tests.fs b/tests/OBO.NET.Tests/OboTerm.Tests.fs index 3b401f1..be5abba 100644 --- a/tests/OBO.NET.Tests/OboTerm.Tests.fs +++ b/tests/OBO.NET.Tests/OboTerm.Tests.fs @@ -2,10 +2,13 @@ namespace OBO.NET.Tests open Expecto open OBO.NET +open ControlledVocabulary module OboTermTests = + let testTerm1 = OboTerm.Create("test:001", Name = "TestTerm1") + [] let oboTermTest = testList "OboTerm" [ @@ -35,4 +38,12 @@ module OboTermTests = ] Expect.sequenceEqual actual expected "" ] + testList "ToCvTerm" [ + testCase "returns correct CvTerm" <| fun _ -> + let actual = OboTerm.toCvTerm testTerm1 + let expected = CvTerm.create("test:001", "TestTerm1", "test") + Expect.equal actual.RefUri expected.RefUri "TSRs are different" + Expect.equal actual.Name expected.Name "Names are different" + Expect.equal actual.Accession expected.Accession "TANs are different" + ] ] \ No newline at end of file From e3fc9d7b463958d6a9b1c645d3ff82dc15ab573b Mon Sep 17 00:00:00 2001 From: omaus Date: Tue, 4 Jun 2024 12:29:43 +0200 Subject: [PATCH 5/6] Add functions to check for and return equivalence among terms --- playground.fsx | 52 +++++++++++++++++++----- src/OBO.NET/OboOntology.fs | 41 +++++++++++++++++++ tests/OBO.NET.Tests/OboOntology.Tests.fs | 22 +++++++++- 3 files changed, 102 insertions(+), 13 deletions(-) diff --git a/playground.fsx b/playground.fsx index ddeb251..1b3102f 100644 --- a/playground.fsx +++ b/playground.fsx @@ -28,17 +28,47 @@ let r = term1.Xrefs |> List.exists (fun x1 -> term2.Xrefs |> List.exists (fun x2 type OboOntology with - member this.AreTermsEquivalent(term1 : OboTerm, term2 : OboTerm) = - term1.Xrefs - |> List.exists ( - fun x1 -> - term2.Id = x1.Name - && - this.TreatXrefsAsEquivalents - |> List.exists (fun t -> term2.) - ) - - +// member this.AreTermsEquivalent(term1 : OboTerm, term2 : OboTerm) = +// term1.Xrefs +// |> List.exists ( +// fun x1 -> +// term2.Id = x1.Name +// && +// this.TreatXrefsAsEquivalents +// |> List.exists (fun t -> t = (term2.ToCvTerm()).RefUri) +// ) + + /// Returns all terms of the OboOntology that have equivalent terms in a given second OboOntology. + member this.ReturnAllEquivalentTerms(ontology : OboOntology) = + if List.exists (fun x -> x = ontology.Terms.Head.ToCvTerm().RefUri) this.TreatXrefsAsEquivalents then + this.Terms + |> Seq.filter ( + fun t -> + List.isEmpty t.Xrefs |> not + && + t.Xrefs + |> List.exists ( + fun x -> + ontology.Terms + |> List.exists ( + fun t2 -> + (DBXref.toCvTerm x).Accession = t2.Id + ) + ) + ) + else Seq.empty + +let testTerm1 = OboTerm.Create("test:001", Name = "Test1", Xrefs = [DBXref.parseDBXref "check:001"]) +let testOntology1 = OboOntology.Create([testTerm1], [], "", TreatXrefsAsEquivalents = ["check"]) +let testTerm2 = OboTerm.Create("check:001") + +testOntology1.AreTermsEquivalent(testTerm1, testTerm2) + +let testOntology2 = OboOntology.Create([testTerm2], [], "") + +testOntology1.ReturnAllEquivalentTerms testOntology2 + +DBXref.ofString """test:1 "testDesc" {testMod}""" // DEPRECATED diff --git a/src/OBO.NET/OboOntology.fs b/src/OBO.NET/OboOntology.fs index 5fd7894..f47ca4f 100644 --- a/src/OBO.NET/OboOntology.fs +++ b/src/OBO.NET/OboOntology.fs @@ -519,6 +519,47 @@ type OboOntology = static member getSynonyms term (onto : OboOntology) = onto.GetSynonyms term + /// Checks if the given terms are treated as equivalent in the OboOntology. + /// Note that term1 must be part of the OboOntology while term2 must be part of another ontology. + member this.AreTermsEquivalent(term1 : OboTerm, term2 : OboTerm) = + term1.Xrefs + |> List.exists ( + fun x1 -> + term2.Id = x1.Name + && + this.TreatXrefsAsEquivalents + |> List.exists (fun t -> t = (term2.ToCvTerm()).RefUri) + ) + + /// Checks if the given terms are treated as equivalent in the given OboOntology. + /// Note that term1 must be part of the given OboOntology while term2 must be part of another ontology. + static member areTermsEquivalent term1 term2 (onto : OboOntology) = + onto.AreTermsEquivalent(term1, term2) + + /// Returns all terms of the OboOntology that have equivalent terms in a given second OboOntology. + member this.ReturnAllEquivalentTerms(onto : OboOntology) = + if List.exists (fun x -> x = onto.Terms.Head.ToCvTerm().RefUri) this.TreatXrefsAsEquivalents then + this.Terms + |> Seq.filter ( + fun t -> + List.isEmpty t.Xrefs |> not + && + t.Xrefs + |> List.exists ( + fun x -> + onto.Terms + |> List.exists ( + fun t2 -> + (DBXref.toCvTerm x).Accession = t2.Id + ) + ) + ) + else Seq.empty + + /// Returns all terms of the first given OboOntology that have equivalent terms in the second given OboOntology. + static member returnAllEquivalentTerms (onto1 : OboOntology) onto2 = + onto1.ReturnAllEquivalentTerms(onto2) + type OboTermDef = { diff --git a/tests/OBO.NET.Tests/OboOntology.Tests.fs b/tests/OBO.NET.Tests/OboOntology.Tests.fs index 9003a66..06efe58 100644 --- a/tests/OBO.NET.Tests/OboOntology.Tests.fs +++ b/tests/OBO.NET.Tests/OboOntology.Tests.fs @@ -36,7 +36,8 @@ module OboOntologyTests = let testTerm4 = OboTerm.Create( "id:5", - Name = "testTerm4" + Name = "testTerm4", + Xrefs = [DBXref.ofString "check:1"] ) let testTerm5 = OboTerm.Create( @@ -44,6 +45,11 @@ module OboOntologyTests = Name = "testTerm5", Synonyms = [TermSynonym.parseSynonym None 0 "\"testTerm1\" EXACT []"; TermSynonym.parseSynonym None 1 "\"testTerm2\" BROAD []"; TermSynonym.parseSynonym None 2 "\"testTerm0\" NARROW []"] ) + let testTerm6 = + OboTerm.Create( + "check:1", + Name = "checkTerm1" + ) let testFile1Path = Path.Combine(__SOURCE_DIRECTORY__, "References", "CorrectHeaderTags.obo") let testFile2Path = Path.Combine(__SOURCE_DIRECTORY__, "References", "IncorrectHeaderTags.obo") @@ -125,7 +131,8 @@ module OboOntologyTests = Expect.equal (Option.map (fun o -> o.TypeDefs) testFile1) typedefsExpected "Terms did not match" ] - let testOntology = OboOntology.Create([testTerm1; testTerm2; testTerm3; testTerm4; testTerm5], [], "") + let testOntology = OboOntology.Create([testTerm1; testTerm2; testTerm3; testTerm4; testTerm5], [], "", TreatXrefsAsEquivalents = ["check"]) + let testOntology2 = OboOntology.Create([testTerm6], [], "") testList "GetRelatedTerms" [ testCase "returns correct related terms" <| fun _ -> @@ -171,4 +178,15 @@ module OboOntologyTests = let expected = seq {Exact, testTerm5, Some testTerm1; Broad, testTerm5, Some testTerm2; Narrow, testTerm5, None} Expect.sequenceEqual actual expected "is not equal" ] + + testList "AreTermsEquivalent" [ + testCase "checks equivalence correctly" <| fun _ -> + Expect.isTrue (testOntology.AreTermsEquivalent(testTerm4, testTerm6)) "is not equal" + ] + + testList "ReturnAllEquivalentTerms" [ + testCase "returns correct terms" <| fun _ -> + let actual = testOntology.ReturnAllEquivalentTerms(testOntology2) + Expect.equal (Seq.head actual).Id testTerm4.Id "is not equal" + ] ] \ No newline at end of file From 724ec353f9969608512e40fb3216ccba1b7bb55e Mon Sep 17 00:00:00 2001 From: omaus Date: Thu, 6 Jun 2024 11:16:47 +0200 Subject: [PATCH 6/6] Do requested changes --- tests/OBO.NET.Tests/OboOntology.Tests.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/OBO.NET.Tests/OboOntology.Tests.fs b/tests/OBO.NET.Tests/OboOntology.Tests.fs index 06efe58..47671b8 100644 --- a/tests/OBO.NET.Tests/OboOntology.Tests.fs +++ b/tests/OBO.NET.Tests/OboOntology.Tests.fs @@ -187,6 +187,6 @@ module OboOntologyTests = testList "ReturnAllEquivalentTerms" [ testCase "returns correct terms" <| fun _ -> let actual = testOntology.ReturnAllEquivalentTerms(testOntology2) - Expect.equal (Seq.head actual).Id testTerm4.Id "is not equal" + Expect.sequenceEqual actual (seq {testTerm4}) "is not equal" ] ] \ No newline at end of file