From c33f2dd8355934921cea16bd40696b3fa0b12ff5 Mon Sep 17 00:00:00 2001 From: Heinrich Lukas Weil Date: Mon, 14 Aug 2023 12:42:44 +0400 Subject: [PATCH] make ArcAssay TechnologyPlatform an ontology annotation and add helper functions #162 --- src/ISA/ISA/ArcTypes/ArcAssay.fs | 42 ++++++++++++++++--- tests/ISA/ISA.Tests/ArcAssay.Tests.fs | 36 ++++++++++++++-- tests/ISA/ISA.Tests/ArcInvestigation.Tests.fs | 12 +++--- tests/ISA/ISA.Tests/ArcJsonConversionTests.fs | 5 ++- tests/ISA/ISA.Tests/ArcStudy.Tests.fs | 4 +- 5 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/ISA/ISA/ArcTypes/ArcAssay.fs b/src/ISA/ISA/ArcTypes/ArcAssay.fs index 5e6708a8..85dcfb13 100644 --- a/src/ISA/ISA/ArcTypes/ArcAssay.fs +++ b/src/ISA/ISA/ArcTypes/ArcAssay.fs @@ -6,7 +6,7 @@ open ARCtrl.ISA.Aux // "MyAssay"; "assays/MyAssay/isa.assay.xlsx" [] -type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?technologyType : OntologyAnnotation, ?technologyPlatform : string, ?tables: ResizeArray, ?performers : Person [], ?comments : Comment []) = +type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?technologyType : OntologyAnnotation, ?technologyPlatform : OntologyAnnotation, ?tables: ResizeArray, ?performers : Person [], ?comments : Comment []) = let tables = defaultArg tables <| ResizeArray() let performers = defaultArg performers [||] let comments = defaultArg comments [||] @@ -21,20 +21,20 @@ type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?techno member val MeasurementType : OntologyAnnotation option = measurementType with get, set member val TechnologyType : OntologyAnnotation option = technologyType with get, set - member val TechnologyPlatform : string option = technologyPlatform with get, set + member val TechnologyPlatform : OntologyAnnotation option = technologyPlatform with get, set member val Tables : ResizeArray = tables with get, set member val Performers : Person [] = performers with get, set member val Comments : Comment [] = comments with get, set static member init (identifier : string) = ArcAssay(identifier) - static member create (identifier: string, ?measurementType : OntologyAnnotation, ?technologyType : OntologyAnnotation, ?technologyPlatform : string, ?tables: ResizeArray, ?performers : Person [], ?comments : Comment []) = + static member create (identifier: string, ?measurementType : OntologyAnnotation, ?technologyType : OntologyAnnotation, ?technologyPlatform : OntologyAnnotation, ?tables: ResizeArray, ?performers : Person [], ?comments : Comment []) = ArcAssay(identifier = identifier, ?measurementType = measurementType, ?technologyType = technologyType, ?technologyPlatform = technologyPlatform, ?tables =tables, ?performers = performers, ?comments = comments) static member make (identifier : string) (measurementType : OntologyAnnotation option) (technologyType : OntologyAnnotation option) - (technologyPlatform : string option) + (technologyPlatform : OntologyAnnotation option) (tables : ResizeArray) (performers : Person []) (comments : Comment []) = @@ -370,6 +370,36 @@ type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?techno comments=nextComments ) + /// This function creates a string containing the name and the ontology short-string of the given ontology annotation term + /// + /// TechnologyPlatforms are plain strings in ISA-JSON. + /// + /// This function allows us, to parse them as an ontology term. + static member composeTechnologyPlatform (tp : OntologyAnnotation) = + match tp.TANInfo with + | Some _ -> + $"{tp.NameText} ({tp.TermAccessionShort})" + | None -> + $"{tp.NameText}" + + /// This function parses the given string containing the name and the ontology short-string of the given ontology annotation term + /// + /// TechnologyPlatforms are plain strings in ISA-JSON. + /// + /// This function allows us, to parse them as an ontology term. + static member decomposeTechnologyPlatform (name : string) = + let pattern = """(?[^\(]+) \((?[^(]*:[^)]*)\)""" + + let r = System.Text.RegularExpressions.Regex.Match(name,pattern) + + + if r.Success then + let oa = (r.Groups.Item "ontology").Value |> OntologyAnnotation.fromTermAnnotation + let v = (r.Groups.Item "value").Value |> Value.fromString + {oa with Name = (Some (AnnotationValue.Text v.Text))} + else + OntologyAnnotation.fromString(termName = name) + /// Transform an ArcAssay to an ISA Json Assay. member this.ToAssay() : Assay = let processSeq = ArcTables(this.Tables).GetProcesses() @@ -388,7 +418,7 @@ type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?techno ?FileName = fileName, ?MeasurementType = this.MeasurementType, ?TechnologyType = this.TechnologyType, - ?TechnologyPlatform = this.TechnologyPlatform, + ?TechnologyPlatform = (this.TechnologyPlatform |> Option.map ArcAssay.composeTechnologyPlatform), ?DataFiles = (ProcessSequence.getData processSeq |> Option.fromValueWithDefault []), ?Materials = assayMaterials, ?CharacteristicCategories = (ProcessSequence.getCharacteristics processSeq |> Option.fromValueWithDefault []), @@ -408,7 +438,7 @@ type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?techno identifer, ?measurementType = (a.MeasurementType |> Option.map (fun x -> x.Copy())), ?technologyType = (a.TechnologyType |> Option.map (fun x -> x.Copy())), - ?technologyPlatform = a.TechnologyPlatform, + ?technologyPlatform = (a.TechnologyPlatform |> Option.map ArcAssay.decomposeTechnologyPlatform), ?tables = tables, ?comments = (a.Comments |> Option.map Array.ofList) ) \ No newline at end of file diff --git a/tests/ISA/ISA.Tests/ArcAssay.Tests.fs b/tests/ISA/ISA.Tests/ArcAssay.Tests.fs index 79081729..9d39d813 100644 --- a/tests/ISA/ISA.Tests/ArcAssay.Tests.fs +++ b/tests/ISA/ISA.Tests/ArcAssay.Tests.fs @@ -76,7 +76,7 @@ let private test_create = let identifier = "MyIdentifier" let oa_mt = OntologyAnnotation.fromString("measurement type") let oa_tt = OntologyAnnotation.fromString("technology type") - let technologyPlatform = "tp" + let technologyPlatform = OntologyAnnotation.fromString("tp") let tables = ResizeArray([ArcTable.init("MyTable1")]) let performers = Person.create(FirstName = "Kevin", LastName = "Frey") |> Array.singleton let comments = Comment.create("Comment Name") |> Array.singleton @@ -92,7 +92,7 @@ let private test_create = let identifier = "MyIdentifier" let oa_mt = OntologyAnnotation.fromString("measurement type") let oa_tt = OntologyAnnotation.fromString("technology type") - let technologyPlatform = "tp" + let technologyPlatform = OntologyAnnotation.fromString("tp") let tables = ResizeArray([ArcTable.init("MyTable1")]) let performers = Person.create(FirstName = "Kevin", LastName = "Frey") |> Array.singleton let comments = Comment.create("Comment Name") |> Array.singleton @@ -118,7 +118,7 @@ let private test_create = let identifier = "MyIdentifier" let measurementType = Some (OntologyAnnotation.fromString("Measurement Type")) let technologyType = Some (OntologyAnnotation.fromString("Technology Type")) - let technologyPlatform = Some "Technology Platform" + let technologyPlatform = Some (OntologyAnnotation.fromString("Technology Platform")) let tables = ResizeArray([ArcTable.init("Table 1")]) let performers = Person.create(FirstName = "John", LastName = "Doe") |> Array.singleton let comments = Comment.create("Comment 1") |> Array.singleton @@ -457,6 +457,35 @@ let private tests_updateTable = ) ] +let private tests_technologyPlatform = + testList "technologyPlatformTests" [ + let name = "MyOntology" + let tsr = "ABC" + let tan = "ABC:123" + let tp_Term = OntologyAnnotation.fromString(name,tsr,tan) + let tp_String = OntologyAnnotation.fromString(name) + testCase "compose Term" (fun () -> + let s = ArcAssay.composeTechnologyPlatform tp_Term + Expect.equal s $"{name} ({tan})" "Term was not correctly composed as string." + ) + testCase "decompose Term" (fun () -> + let s = ArcAssay.composeTechnologyPlatform tp_Term + let pt_new = ArcAssay.decomposeTechnologyPlatform s + Expect.equal pt_new.NameText name "NameText should match" + Expect.equal pt_new.TermAccessionShort tan "ShortTan should match" + ) + testCase "compose String" (fun () -> + let s = ArcAssay.composeTechnologyPlatform tp_String + Expect.equal s $"{name}" "String was not correctly composed as string." + ) + testCase "decompose String" (fun () -> + let s = ArcAssay.composeTechnologyPlatform tp_String + let pt_new = ArcAssay.decomposeTechnologyPlatform s + Expect.equal pt_new.NameText name "NameText should match" + Expect.isNone pt_new.TermAccessionNumber "TermAccessionNumber should be None" + Expect.equal pt_new.TermAccessionShort "" "ShortTan should match" + ) + ] let main = testList "ArcAssay" [ test_create @@ -467,4 +496,5 @@ let main = tests_UpdateTableAt tests_UpdateTable tests_updateTable + tests_technologyPlatform ] \ No newline at end of file diff --git a/tests/ISA/ISA.Tests/ArcInvestigation.Tests.fs b/tests/ISA/ISA.Tests/ArcInvestigation.Tests.fs index 2a68f260..5da0eddf 100644 --- a/tests/ISA/ISA.Tests/ArcInvestigation.Tests.fs +++ b/tests/ISA/ISA.Tests/ArcInvestigation.Tests.fs @@ -318,7 +318,7 @@ let tests_Assay = testList "CRUD Assay" [ testCase "by index" <| fun _ -> let i = createExampleInvestigation() let assay_ident = "New Assay" - let assay_techPlatform = "Assay Tech" + let assay_techPlatform = OntologyAnnotation.fromString("Assay Tech") let expected = ArcAssay(assay_ident, technologyPlatform = assay_techPlatform) i.AddAssayAt(0, expected) Expect.equal i.StudyCount 2 "StudyCount" @@ -329,7 +329,7 @@ let tests_Assay = testList "CRUD Assay" [ testCase "by identifier" <| fun _ -> let i = createExampleInvestigation() let assay_ident = "New Assay" - let assay_techPlatform = "Assay Tech" + let assay_techPlatform = OntologyAnnotation.fromString("Assay Tech") let expected = ArcAssay(assay_ident, technologyPlatform = assay_techPlatform) i.AddAssay("Study 1", expected) Expect.equal i.StudyCount 2 "StudyCount" @@ -342,7 +342,7 @@ let tests_Assay = testList "CRUD Assay" [ testCase "by index" <| fun _ -> let i = createExampleInvestigation() let assay_ident = "New Assay" - let assay_techPlatform = "Assay Tech" + let assay_techPlatform = OntologyAnnotation.fromString("Assay Tech") let expected = ArcAssay(assay_ident, technologyPlatform = assay_techPlatform) i.SetAssayAt("Study 1", 0, expected) Expect.equal i.StudyCount 2 "StudyCount" @@ -353,7 +353,7 @@ let tests_Assay = testList "CRUD Assay" [ testCase "by identifier" <| fun _ -> let i = createExampleInvestigation() let assay_ident = "New Assay" - let assay_techPlatform = "Assay Tech" + let assay_techPlatform = OntologyAnnotation.fromString("Assay Tech") let expected = ArcAssay(assay_ident, technologyPlatform = assay_techPlatform) i.SetAssay("Study 1", "Assay 2", expected) Expect.equal i.StudyCount 2 "StudyCount" @@ -373,7 +373,7 @@ let tests_Assay = testList "CRUD Assay" [ Expect.equal a.Identifier "Assay 2" "FileName" testCase "mutable propagation" <| fun _ -> let i = createExampleInvestigation() - let tech = Some "New Tech Stuff" + let tech = Some (OntologyAnnotation.fromString("New Tech Stuff")) let a = i.GetAssayAt("Study 1", 0) Expect.equal a.Identifier "Assay 1" "FileName" Expect.equal a.TechnologyPlatform None "TechnologyPlatform" @@ -383,7 +383,7 @@ let tests_Assay = testList "CRUD Assay" [ testCase "mutable propagation, copy" <| fun _ -> let i = createExampleInvestigation() let copy = createExampleInvestigation() - let tech = Some "New Tech Stuff" + let tech = Some (OntologyAnnotation.fromString("New Tech Stuff")) let a = i.GetAssayAt("Study 1", 0) Expect.equal a.Identifier "Assay 1" "FileName" Expect.equal a.TechnologyPlatform None "TechnologyPlatform" diff --git a/tests/ISA/ISA.Tests/ArcJsonConversionTests.fs b/tests/ISA/ISA.Tests/ArcJsonConversionTests.fs index f0f1cb0a..6d073bef 100644 --- a/tests/ISA/ISA.Tests/ArcJsonConversionTests.fs +++ b/tests/ISA/ISA.Tests/ArcJsonConversionTests.fs @@ -377,7 +377,8 @@ let private tests_arcAssay = let identifier = "MyIdentifier" let measurementType = OntologyAnnotation.fromString("Measurement Type") let technologyType = OntologyAnnotation.fromString("Technology Type") - let technologyPlatform = "Technology Platform" + let technologyPlatformString = "Technology Platform" + let technologyPlatform = OntologyAnnotation.fromString(technologyPlatformString) let t1 = singleRowSingleParam.Copy() let t2 = singleRowDataInputWithCharacteristic.Copy() |> fun t -> ArcTable.create(tableName2, t.Headers, t.Values) @@ -418,7 +419,7 @@ let private tests_arcAssay = Expect.equal assay.TechnologyType.Value technologyType "Assay technologyType should match" Expect.isSome assay.TechnologyPlatform "Assay should have technologyPlatform" - Expect.equal assay.TechnologyPlatform.Value technologyPlatform "Assay technologyPlatform should match" + Expect.equal assay.TechnologyPlatform.Value technologyPlatformString "Assay technologyPlatform should match" Expect.isSome assay.ProcessSequence "Assay should have processes" Expect.equal assay.ProcessSequence.Value.Length 2 "Should have 2 processes" diff --git a/tests/ISA/ISA.Tests/ArcStudy.Tests.fs b/tests/ISA/ISA.Tests/ArcStudy.Tests.fs index 67fd2732..937340cd 100644 --- a/tests/ISA/ISA.Tests/ArcStudy.Tests.fs +++ b/tests/ISA/ISA.Tests/ArcStudy.Tests.fs @@ -158,7 +158,7 @@ let tests_copy = let _study_identifier = "My Study" let _study_description = Some "Lorem Ipsum" let _assay_identifier = "My Assay" - let _assay_technologyPlatform = "Awesome Technology" + let _assay_technologyPlatform = OntologyAnnotation.fromString("Awesome Technology") let createTestStudy() = let s = ArcStudy(_study_identifier) s.Description <- _study_description @@ -198,7 +198,7 @@ let tests_copy = Expect.equal assay.TechnologyPlatform (Some _assay_technologyPlatform) "copy _assay_technologyPlatform" () testCase "test mutable fields on assay children" <| fun _ -> - let newTechnologyPlatform = Some "New TechnologyPlatform" + let newTechnologyPlatform = Some (OntologyAnnotation.fromString("New TechnologyPlatform")) let newTechnologyType = Some <| OntologyAnnotation.fromString("nice technology type") let study = createTestStudy() let copy = study.Copy()