-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolve Xrefs equivalence #36
Changes from all commits
f19426f
2e583a5
50645d7
477e1e3
e3fc9d7
6c89bdf
724ec35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,40 @@ | ||
namespace OBO.NET | ||
|
||
|
||
open FSharpAux | ||
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("""(?<xrefName>^([^"{])*)(\s?)(?<xrefDescription>\"(.*?)\")?(\s?)(?<xrefModifiers>\{(.*?)}$)?""") | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this reliable? Will all TAN have this shape? Just curious, i don't know the answer myself There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The OBO Flat File Format section defines it this way, but with SHOULD. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nvm., String.split ':' "klsdklsd"
val it: string[] = [|"klsdklsd"|] Therefore, no need to do anything here, and I'm fine with this output for IDs that don't follow the format recommendations. |
||
|> Array.head | ||
|> String.trim | ||
} | ||
|
||
|
||
/// Functions for working with DBXrefs. | ||
module DBXref = | ||
|
@@ -37,16 +61,15 @@ 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() | ||
|
||
let private xrefRegex = | ||
Text.RegularExpressions.Regex("""(?<xrefName>^([^"{])*)(\s?)(?<xrefDescription>\"(.*?)\")?(\s?)(?<xrefModifiers>\{(.*?)}$)?""") | ||
|
||
[<Obsolete "Use `DBXref.ofString` instead">] | ||
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 : DBXref) = | ||
dbxref.ToCvTerm() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -519,6 +519,47 @@ type OboOntology = | |
static member getSynonyms term (onto : OboOntology) = | ||
onto.GetSynonyms term | ||
|
||
/// <summary>Checks if the given terms are treated as equivalent in the OboOntology.</summary> | ||
/// <remarks>Note that term1 must be part of the OboOntology while term2 must be part of another ontology.</remarks> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is fine for now, but i think we should eventually either add a check here or add item accession to the terms in the ontology, e.g. ontology["termName"] should return the relevant term, so this method just needs to be Requiring one term being from the ontology without checking/enforcing it screams for unintended behavior IMO, but as said, fine for now |
||
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) | ||
) | ||
|
||
/// <summary>Checks if the given terms are treated as equivalent in the given OboOntology.</summary> | ||
/// <remarks>Note that term1 must be part of the given OboOntology while term2 must be part of another ontology.</remarks> | ||
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 = | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,10 +3,12 @@ | |
open DBXref | ||
open TermSynonym | ||
|
||
open ARCtrl.ISA | ||
|
||
open System | ||
|
||
open ARCtrl.ISA | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. out of curiosity, where is this reference needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are IsaOntologyAnnotation functions that use this. I think it's mainly used in ISA.NET and some subsequent projects but that was more like @HLWeil 's business. |
||
open ControlledVocabulary | ||
open FSharpAux | ||
|
||
|
||
/// Models the entities in an OBO Ontology. | ||
type OboTerm = | ||
|
@@ -335,7 +337,7 @@ | |
propertyValues builtIn createdBy creationDate | ||
|
||
| "xref" | "xref_analog" | "xref_unk" -> | ||
let v = (split.[1..] |> String.concat ": ") |> parseDBXref | ||
Check warning on line 340 in src/OBO.NET/OboTerm.fs GitHub Actions / build-and-test-linux
|
||
OboTerm.fromLines verbose en (lineNumber + 1) | ||
id name isAnonymous altIds definition comment subsets synonyms (v::xrefs) isA | ||
intersectionOf unionOf disjointFrom relationships isObsolete replacedby consider | ||
|
@@ -540,6 +542,18 @@ | |
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> = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
namespace OBO.NET.Tests | ||
|
||
|
||
open OBO.NET | ||
|
||
open Expecto | ||
open ControlledVocabulary | ||
|
||
|
||
module DBXref = | ||
|
||
[<Tests>] | ||
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" | ||
] | ||
|
||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand why you are mixing static members and instance members here, is there a need for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instance members are only possible on an already existing object. The
ofString
method creates a DBXref object.