diff --git a/.gitignore b/.gitignore
index ab19fbe..c7d2a30 100644
--- a/.gitignore
+++ b/.gitignore
@@ -349,4 +349,5 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
-**/TestResults/**
\ No newline at end of file
+**/TestResults/**
+tests/ARCtrl.Querymodel.Tests/playground_2.fsx
diff --git a/README.md b/README.md
index c6537b0..3c95f27 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
# ARCtrl.NET
-> **ARCtrl.NET** is the .NET IO implementation of [ARCtrl](https://github.com/nfdi4plants/ARCtrl)
-
-| Version | Downloads |
-| :--------|-----------:|
-|||
+This library functions as an IO wrapper for the [ARCtrl](https://github.com/nfdi4plants/ARCtrl) library in .NET.
+
+The documentation for the actual functions for manipulating the ARC datamodel can be found [here](https://github.com/nfdi4plants/ARCtrl/tree/main/docs/scripts_fsharp).
+
+## Usage
```fsharp
#r "nuget: ARCtrl.NET, 1.0.0-beta.2"
@@ -12,11 +12,32 @@
open ARCtrl.NET
open ARCtrl
-let arc = ARC.load(myArcPath)
-// work work work
+let arcPath = ""
+
+let arc = ARC.load(arcPath)
+
+let isa = arc.ISA.Value
-arc.Write(myArcPath)
+isa.InitStudy("MyStudy")
+
+arc.Write(arcPath)
```
-For documentation on manipulationh of the datamodel, see https://github.com/nfdi4plants/ARCtrl/tree/main/docs
+## Development
+
+`./build.cmd runtests`
+
+## ARCtrl.Querymodel
+
+```fsharp
+open ARCtrl
+open ARCtrl.QueryModel
+open ARCtrl.ISA
+
+let i = ArcInvestigation("Dummy Investigation")
+
+i.ArcTables.Values().WithName("Dummy Header").First.ValueText
+
+i.GetAssay("Dummy Assay").LastSamples
+```
\ No newline at end of file
diff --git a/src/ARCtrl.QueryModel/ArcTables.fs b/src/ARCtrl.QueryModel/ArcTables.fs
index 4fcf2de..bfad169 100644
--- a/src/ARCtrl.QueryModel/ArcTables.fs
+++ b/src/ARCtrl.QueryModel/ArcTables.fs
@@ -140,6 +140,7 @@ module ArcTables =
QNode(oname,ot,ps)
|> Some
)
+ |> ResizeArray.distinctBy (fun n -> n.Name)
/// Returns the names of all nodes for which the predicate reutrns true
static member getNodesBy (predicate : IOType -> bool) (ps : #ArcTables) =
@@ -209,6 +210,40 @@ module ArcTables =
loop (ArcTables.getFinalOutputs ps |> List.ofSeq) []
+ static member getPreviousNodesBy (node : string) (ps : #ArcTables) =
+
+ let rec collectBackwardNodes nodes =
+ let newNodes =
+ ps.Tables
+ |> Seq.collect (fun sheet ->
+ sheet.Rows
+ |> Seq.choose (fun r -> if List.contains r.Output nodes then Some r.Input else None)
+ )
+ |> Seq.toList
+ |> List.append nodes
+ |> List.distinct
+
+ if newNodes = nodes then nodes
+ else collectBackwardNodes newNodes
+
+ collectBackwardNodes [node]
+
+ static member getSucceedingNodesBy (node : string) (ps : #ArcTables) =
+ let rec collectForwardNodes nodes =
+ let newNodes =
+ ps.Tables
+ |> Seq.collect (fun sheet ->
+ sheet.Rows
+ |> Seq.choose (fun r -> if List.contains r.InputName nodes then Some r.OutputName else None)
+ )
+ |> Seq.toList
+ |> List.append nodes
+ |> List.distinct
+
+ if newNodes = nodes then nodes
+ else collectForwardNodes newNodes
+ collectForwardNodes [node]
+
/// Returns the names of all nodes processSequence, which are connected to the given node and for which the predicate returns true
static member getNodesOfBy (predicate : IOType -> bool) (node : string) (ps : #ArcTables) =
ArcTables.getSubTreeOf node ps
@@ -230,10 +265,9 @@ module ArcTables =
ps.Tables
|> ResizeArray.collect (fun p ->
p.Rows
- |> List.map (fun r -> r.Output,r)
- |> List.distinct
+ |> List.groupBy (fun r -> r.Output)
+ //|> List.map (fun (o,rs) -> o, rs |> List.map snd)
)
-
|> Map.ofSeq
let rec loop values lastState state =
if lastState = state then values
@@ -242,11 +276,16 @@ module ArcTables =
state
|> List.map (fun s ->
mappings.TryFind s
- |> Option.map (fun r -> r.Input,r.Values |> Seq.toList)
- |> Option.defaultValue (s,[])
+ |> Option.map (fun rs ->
+ rs
+ |> List.map (fun r -> r.Input,r.Values |> Seq.toList)
+ |> List.unzip
+ |> fun (s,vs) -> s, vs |> List.concat
+ )
+ |> Option.defaultValue ([],[])
)
|> List.unzip
- |> fun (s,vs) -> s, vs |> List.concat
+ |> fun (s,vs) -> s |> List.concat, vs |> List.concat
loop (newValues@values) state newState
loop [] [] [node]
|> ValueCollection
@@ -257,8 +296,7 @@ module ArcTables =
ps.Tables
|> ResizeArray.collect (fun p ->
p.Rows
- |> List.map (fun r -> r.Input,r)
- |> List.distinct
+ |> List.groupBy (fun r -> r.Input)
)
|> Map.ofSeq
@@ -269,96 +307,33 @@ module ArcTables =
state
|> List.map (fun s ->
mappings.TryFind s
- |> Option.map (fun r -> r.Output,r.Values |> Seq.toList)
- |> Option.defaultValue (s,[])
+ |> Option.map (fun rs ->
+ rs
+ |> List.map (fun r -> r.Output,r.Values |> Seq.toList)
+ |> List.unzip
+ |> fun (s,vs) -> s, vs |> List.concat
+ )
+ |> Option.defaultValue ([],[])
)
|> List.unzip
- |> fun (s,vs) -> s, vs |> List.concat
+ |> fun (s,vs) -> s |> List.concat, vs |> List.concat
loop (values@newValues) state newState
loop [] [] [sample]
|> ValueCollection
/// Returns a new ProcessSequence, with only the values from the processes that implement the given protocol
- static member onlyValuesOfProtocol (ps : #ArcTables) (protocolName : string option) =
- match protocolName with
- | Some pn ->
- ps.Tables
- |> ResizeArray.filter (fun t ->
- t.Name = pn
-
- //if s.Name = pn then
- // s
- //else
- // {s with Rows = s.Rows |> List.map (fun r -> {r with Vals = []})}
- )
- |> ArcTables
- | None -> ps.Tables |> ArcTables
-
- ///// Returns an IOValueCollection, where for each Value the closest inputs and outputs are used
- //member this.Nearest =
- // this.Tables
- // |> List.collect (fun sheet -> sheet.Values |> Seq.toList)
- // |> IOValueCollection
-
- ///// Returns an IOValueCollection, where for each Value the global inputs and closest outputs are used
- //member this.SinkNearest =
- // this.Sheets
- // |> List.collect (fun sheet ->
- // sheet.Rows
- // |> List.collect (fun r ->
-
- // ArcTables.getRootInputsOfBy (fun _ -> true) r.Input this
- // |> List.distinct
- // |> List.collect (fun inp ->
- // r.Vals
- // |> List.map (fun v ->
- // KeyValuePair((inp.Name,r.Output),v)
- // )
- // )
- // )
- // )
- // |> IOValueCollection
-
- ///// Returns an IOValueCollection, where for each Value the closest inputs and global outputs are used
- //member this.SourceNearest =
- // this.Sheets
- // |> List.collect (fun sheet ->
- // sheet.Rows
- // |> List.collect (fun r ->
-
- // ArcTables.getFinalOutputsOfBy (fun _ -> true) r.Output this
- // |> List.distinct
- // |> List.collect (fun out ->
- // r.Vals
- // |> List.map (fun v ->
- // KeyValuePair((r.Input,out.Name),v)
- // )
- // )
- // )
- // )
- // |> IOValueCollection
-
- ///// Returns an IOValueCollection, where for each Value the global inputs and outputs are used
- //member this.Global =
- // this.Sheets
- // |> List.collect (fun sheet ->
- // sheet.Rows
- // |> List.collect (fun r ->
- // let outs = ArcTables.getFinalOutputsOfBy (fun _ -> true) r.Output this |> List.distinct
- // let inps = ArcTables.getRootInputsOfBy (fun _ -> true) r.Input this |> List.distinct
- // outs
- // |> List.collect (fun out ->
- // inps
- // |> List.collect (fun inp ->
- // r.Vals
- // |> List.map (fun v ->
- // KeyValuePair((inp.Name,out.Name),v)
- // )
- // )
- // )
- // )
- // )
- // |> IOValueCollection
+ static member onlyValuesOfProtocol (ps : #ArcTables) (protocolName : string) =
+
+ ps.Tables
+ |> ResizeArray.filter (fun t ->
+ t.Name = protocolName
+
+ //if s.Name = pn then
+ // s
+ //else
+ // {s with Rows = s.Rows |> List.map (fun r -> {r with Vals = []})}
+ )
+ |> ArcTables
/// Returns the names of all nodes in the Process sequence
member this.NodesOf(node : QNode) =
@@ -492,7 +467,8 @@ module ArcTables =
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Values(?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Tables
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Tables
|> ResizeArray.collect (fun s ->
s.ISAValues.Values().Values
)
@@ -502,7 +478,8 @@ module ArcTables =
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Values(ontology : OntologyAnnotation, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Tables
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Tables
|> ResizeArray.collect (fun s -> s.ISAValues.Values().WithCategory(ontology).Values)
|> ValueCollection
@@ -510,7 +487,8 @@ module ArcTables =
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Values(name : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Tables
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Tables
|> ResizeArray.collect (fun s -> s.ISAValues.Values().WithName(name).Values)
|> ValueCollection
@@ -518,219 +496,231 @@ module ArcTables =
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Factors(?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Values().Factors()
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Values().Factors()
/// Returns all parameter values in the process sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Parameters(?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Values().Parameters()
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Values().Parameters()
/// Returns all characteristic values in the process sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Characteristics(?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Values().Characteristics()
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Values().Characteristics()
/// Returns all components in the process sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.Components(?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Values().Components()
+ let ps = if ProtocolName.IsSome then ArcTables.onlyValuesOfProtocol this ProtocolName.Value else this
+ ps.Values().Components()
- /// Returns all values in the process sequence, that are connected to the given node
- ///
- /// If a protocol name is given, returns only the values of the processes that implement this protocol
- member this.ValuesOf(node : string, ?ProtocolName : string) =
- let ps = ArcTables.onlyValuesOfProtocol this ProtocolName
- (ArcTables.getPreviousValuesOf ps node).Values @ (ArcTables.getSucceedingValuesOf ps node).Values
- |> ValueCollection
-
- /// Returns all values in the process sequence, that are connected to the given node
- ///
- /// If a protocol name is given, returns only the values of the processes that implement this protocol
- member this.ValuesOf(node : QNode, ?ProtocolName : string) =
- let ps = ArcTables.onlyValuesOfProtocol this ProtocolName
- (ArcTables.getPreviousValuesOf ps node.Name).Values @ (ArcTables.getSucceedingValuesOf ps node.Name).Values
- |> ValueCollection
- /// Returns all values in the process sequence, that are connected to the given node and come before it in the sequence
- ///
- /// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousValuesOf(node : string, ?ProtocolName) =
- let ps = ArcTables.onlyValuesOfProtocol this ProtocolName
- ArcTables.getPreviousValuesOf ps node
+ match ProtocolName with
+ | Some ps ->
+ let previousNodes = ArcTables.getPreviousNodesBy node this
+ let ps = ArcTables.onlyValuesOfProtocol this ps
+ previousNodes
+ |> Seq.collect (fun n ->
+ ps.PreviousValuesOf(n)
+ )
+ |> ValueCollection
+ | None ->
+ ArcTables.getPreviousValuesOf this node
+
+ member this.SucceedingValuesOf(node : string, ?ProtocolName) =
+ match ProtocolName with
+ | Some ps ->
+ let succeedingNodes = ArcTables.getSucceedingNodesBy node this
+ let ps = ArcTables.onlyValuesOfProtocol this ps
+ succeedingNodes
+ |> Seq.collect (fun n ->
+ ps.SucceedingValuesOf(n)
+ )
+ |> ValueCollection
+ | None ->
+ ArcTables.getSucceedingValuesOf this node
/// Returns all values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousValuesOf(node : QNode, ?ProtocolName) =
- let ps = ArcTables.onlyValuesOfProtocol this ProtocolName
- ArcTables.getPreviousValuesOf ps node.Name
+ this.PreviousValuesOf(node.Name, ?ProtocolName = ProtocolName)
/// Returns all values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
- member this.SucceedingValuesOf(node : string, ?ProtocolName) =
- let ps = ArcTables.onlyValuesOfProtocol this ProtocolName
- ArcTables.getSucceedingValuesOf ps node
+ member this.SucceedingValuesOf(node : QNode, ?ProtocolName) =
+ this.SucceedingValuesOf(node.Name, ?ProtocolName = ProtocolName)
- /// Returns all values in the process sequence, that are connected to the given node and come after it in the sequence
+ /// Returns all values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
- member this.SucceedingValuesOf(node : QNode, ?ProtocolName) =
- let ps = ArcTables.onlyValuesOfProtocol this ProtocolName
- ArcTables.getSucceedingValuesOf ps node.Name
+ member this.ValuesOf(node : string, ?ProtocolName : string) =
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Values @ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Values
+ |> ValueCollection
+
+ /// Returns all values in the process sequence, that are connected to the given node
+ ///
+ /// If a protocol name is given, returns only the values of the processes that implement this protocol
+ member this.ValuesOf(node : QNode, ?ProtocolName : string) =
+ this.ValuesOf(node.Name, ?ProtocolName = ProtocolName)
/// Returns all characteristic values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.CharacteristicsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Characteristics()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Characteristics()
/// Returns all characteristic values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.CharacteristicsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Characteristics()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Characteristics()
/// Returns all characteristic values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousCharacteristicsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Characteristics()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Characteristics()
/// Returns all characteristic values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousCharacteristicsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Characteristics()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Characteristics()
/// Returns all characteristic values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.SucceedingCharacteristicsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Characteristics()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Characteristics()
/// Returns all characteristic values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.SucceedingCharacteristicsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Characteristics()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Characteristics()
/// Returns all parameter values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.ParametersOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Parameters()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Parameters()
/// Returns all parameter values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.ParametersOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Parameters()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Parameters()
/// Returns all parameter values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousParametersOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Parameters()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Parameters()
/// Returns all parameter values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousParametersOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Parameters()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Parameters()
/// Returns all parameter values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.SucceedingParametersOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Parameters()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Parameters()
/// Returns all parameter values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.SucceedingParametersOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Parameters()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Parameters()
/// Returns all factor values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.FactorsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Factors()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Factors()
/// Returns all factor values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.FactorsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Factors()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Factors()
/// Returns all factor values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousFactorsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Factors()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Factors()
/// Returns all factor values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousFactorsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Factors()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Factors()
/// Returns all factor values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol and come after it in the sequence
member this.SucceedingFactorsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Factors()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Factors()
/// Returns all factor values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol and come after it in the sequence
member this.SucceedingFactorsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Factors()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Factors()
/// Returns all components values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.ComponentsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Components()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Components()
/// Returns all components values in the process sequence, that are connected to the given node
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.ComponentsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).ValuesOf(node).Components()
+ this.ValuesOf(node,?ProtocolName = ProtocolName).Components()
/// Returns all components values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousComponentsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Components()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Components()
/// Returns all components values in the process sequence, that are connected to the given node and come before it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.PreviousComponentsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).PreviousValuesOf(node).Components()
+ this.PreviousValuesOf(node,?ProtocolName = ProtocolName).Components()
/// Returns all components values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.SucceedingComponentsOf(node : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Components()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Components()
/// Returns all components values in the process sequence, that are connected to the given node and come after it in the sequence
///
/// If a protocol name is given, returns only the values of the processes that implement this protocol
member this.SucceedingComponentsOf(node : QNode, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).SucceedingValuesOf(node).Components()
+ this.SucceedingValuesOf(node,?ProtocolName = ProtocolName).Components()
member this.Contains(ontology : OntologyAnnotation, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Values().Contains ontology
+ this.Values(?ProtocolName = ProtocolName).Contains ontology
member this.Contains(name : string, ?ProtocolName) =
- (ArcTables.onlyValuesOfProtocol this ProtocolName).Values().Contains name
+ this.Values(?ProtocolName = ProtocolName).Contains name
/// Returns the names of all nodes in the Process sequence
member this.Nodes =
diff --git a/src/ARCtrl.QueryModel/Investigation.fs b/src/ARCtrl.QueryModel/Investigation.fs
index 4befdba..a773bbf 100644
--- a/src/ARCtrl.QueryModel/Investigation.fs
+++ b/src/ARCtrl.QueryModel/Investigation.fs
@@ -11,60 +11,18 @@ open System.Collections
[]
module ArcInvestigationExtensions =
- ///// Queryable representation of an ISA Investigation. Implements the QProcessSequence interface
- //type ArcInvestigation with
-
- // /// Returns the QStudy with the given name
- // member this.Study(studyName : string) =
- // this.Studies
- // |> List.find (fun s -> s.Identifier.Value = studyName)
-
- // /// Returns the nth QStudy
- // member this.Study(i : int) =
- // this.Studies
- // |> List.item i
-
- // /// Returns the QAssay with the given name (registered in the study with the given study name)
- // member this.Assay(assayName : string, ?StudyName : string) =
- // match StudyName with
- // | Some sn ->
- // this.Study(sn).Assay(assayName)
- // | None ->
- // this.Studies
- // |> List.collect (fun s -> s.Assays)
- // |> List.find (fun a -> a.FileName.Value.Contains assayName)
-
- // /// get the protocol or sheet (in ISATab logic) with the given name
- // member this.Protocol (sheetName : string) =
- // base.Protocol(sheetName, $"Assay \"{this.FileName}\"")
-
- // /// get the nth protocol or sheet (in ISATab logic)
- // member this.Protocol (index : int) =
- // base.Protocol(index, $"Assay \"{this.FileName}\"")
-
- // /// Returns the initial inputs final outputs of the assay, to which no processPoints
- // static member getRootInputs (investigation : QInvestigation) = QProcessSequence.getRootInputs investigation
-
- // /// Returns the final outputs of the investigation, which point to no further nodes
- // static member getFinalOutputs (investigation : QInvestigation) = QProcessSequence.getFinalOutputs investigation
-
- // /// Returns the initial inputs final outputs of the investigation, to which no processPoints
- // static member getRootInputOf (investigation : QInvestigation) (sample : string) = QProcessSequence.getRootInputsOfBy (fun _ -> true) sample investigation
-
- // /// Returns the final outputs of the investigation, which point to no further nodes
- // static member getFinalOutputsOf (investigation : QInvestigation) (sample : string) = QProcessSequence.getFinalOutputsOfBy (fun _ -> true) sample investigation
-
- // static member toString (rwa : QInvestigation) = JsonSerializer.Serialize(rwa,JsonExtensions.options)
-
- // static member toFile (path : string) (rwa:QInvestigation) =
- // File.WriteAllText(path,QInvestigation.toString rwa)
-
- // static member fromString (s:string) =
- // JsonSerializer.Deserialize(s,JsonExtensions.options)
-
- // static member fromFile (path : string) =
- // File.ReadAllText path
- // |> QInvestigation.fromString
+ /// Queryable representation of an ISA Investigation. Implements the QProcessSequence interface
+ type ArcInvestigation with
+
+ /// Returns the QStudy with the given name
+ member this.ArcTables
+ with get() : ArcTables =
+ seq {
+ for s in this.Studies do yield! s.Tables
+ for a in this.Assays do yield! a.Tables
+ }
+ |> ResizeArray
+ |> ArcTables
module Investigation =
diff --git a/src/ARCtrl.QueryModel/ResizeArray.fs b/src/ARCtrl.QueryModel/ResizeArray.fs
index 2684487..bd8927b 100644
--- a/src/ARCtrl.QueryModel/ResizeArray.fs
+++ b/src/ARCtrl.QueryModel/ResizeArray.fs
@@ -63,4 +63,14 @@ module ResizeArray =
for i in a do
if not (b.Contains(i)) then
b.Add(i)
+ b
+
+ let distinctBy f (a : ResizeArray<_>) =
+ let b = ResizeArray<_>()
+ let c = ResizeArray<_>()
+ for i in a do
+ let k = f i
+ if not (c.Contains(k)) then
+ c.Add(k)
+ b.Add(i)
b
\ No newline at end of file
diff --git a/src/ARCtrl.QueryModel/Value.fs b/src/ARCtrl.QueryModel/Value.fs
index b15381d..b331e50 100644
--- a/src/ARCtrl.QueryModel/Value.fs
+++ b/src/ARCtrl.QueryModel/Value.fs
@@ -172,11 +172,11 @@ module ISAValueExtensions =
this.TryUnit |> Option.map (fun u -> u.NameText)
/// Returns the value of the Value as string
- member this.ValueText = this.Value.AsName()
+ member this.ValueText = this.Value.Text
/// Returns the value of the Value as string if it exists, else returns None
member this.TryValueText =
- this.TryValue |> Option.map (fun v -> v.AsName())
+ this.TryValue |> Option.map (fun v -> v.Text)
/// Returns the value and unit of the Value as string
member this.ValueWithUnitText =
diff --git a/tests/ARCtrl.Querymodel.Tests/ARCtrl.Querymodel.Tests.fsproj b/tests/ARCtrl.Querymodel.Tests/ARCtrl.Querymodel.Tests.fsproj
index 530412b..dab8720 100644
--- a/tests/ARCtrl.Querymodel.Tests/ARCtrl.Querymodel.Tests.fsproj
+++ b/tests/ARCtrl.Querymodel.Tests/ARCtrl.Querymodel.Tests.fsproj
@@ -7,7 +7,7 @@
-
+
diff --git a/tests/ARCtrl.Querymodel.Tests/ArcTable.fs b/tests/ARCtrl.Querymodel.Tests/ArcTable.fs
deleted file mode 100644
index d91af9c..0000000
--- a/tests/ARCtrl.Querymodel.Tests/ArcTable.fs
+++ /dev/null
@@ -1,14 +0,0 @@
-module ArcTable.Tests
-
-open Expecto
-open System.Text.Json
-
-[]
-let testStuff =
-
- testList "ArcTable" [
- testCase "WillNotFail" (fun () ->
- Expect.isTrue true "Test if the test will test."
-
- )
- ]
\ No newline at end of file
diff --git a/tests/ARCtrl.Querymodel.Tests/Main.fs b/tests/ARCtrl.Querymodel.Tests/Main.fs
index 5875a34..075afdc 100644
--- a/tests/ARCtrl.Querymodel.Tests/Main.fs
+++ b/tests/ARCtrl.Querymodel.Tests/Main.fs
@@ -4,7 +4,7 @@ open Expecto
let all = testSequenced <| testList "All" [
- ArcTable.Tests.testStuff
+ TestARC.Tests.main
]
[]
diff --git a/tests/ARCtrl.Querymodel.Tests/TestARC.fs b/tests/ARCtrl.Querymodel.Tests/TestARC.fs
new file mode 100644
index 0000000..3b49ff9
--- /dev/null
+++ b/tests/ARCtrl.Querymodel.Tests/TestARC.fs
@@ -0,0 +1,165 @@
+module TestARC.Tests
+
+open Expecto
+open System.Text.Json
+open ARCtrl
+open ARCtrl.NET
+open ARCtrl.QueryModel
+open ARCtrl.ISA
+let testArcPath = __SOURCE_DIRECTORY__ + @"\TestObjects\TestArc"
+let testArc = ARC.load(testArcPath)
+
+
+let ArcTables_getNodes =
+ let isa = testArc.ISA.Value
+ testList "ARCTables_GetNodes" [
+ testCase "LastData" (fun () ->
+ let nodes = isa.ArcTables.LastData
+ let nodeNames = nodes |> List.map (fun n -> n.Name)
+ let expected = ["sampleOutCold.txt"; "sampleOutHeat.txt"]
+ Expect.sequenceEqual nodeNames expected "LastData of full sequence"
+ )
+ testCase "LastSamples" (fun () ->
+ let nodes = isa.ArcTables.LastSamples
+ let nodeNames = nodes |> List.map (fun n -> n.Name)
+ let expected = ["CC1_prep"; "CC2_prep"; "CC3_prep"; "Co1_prep"; "Co2_prep"; "Co3_prep"; "C1_prep"; "C2_prep"; "C3_prep"; "H1_prep"; "H2_prep"; "H3_prep"]
+ Expect.sequenceEqual expected nodeNames "LastSamples of full sequence"
+ )
+ testCase "LastNodes" (fun () ->
+ let nodes = isa.ArcTables.LastNodes
+ let nodeNames = nodes |> Seq.map (fun n -> n.Name)
+ let expected = ["sampleOutCold.txt"; "sampleOutHeat.txt"]
+ Expect.sequenceEqual nodeNames expected "LastData of full sequence"
+ )
+ testCase "RawData" (fun () ->
+ let nodes = isa.ArcTables.RawData
+ let nodeNames = nodes |> Seq.map (fun n -> n.Name)
+ let expected = ["CC1_measured";"CC2_measured";"CC3_measured";"Co1_measured";"Co2_measured";"Co3_measured";"C1_measured";"C2_measured";"C3_measured";"H1_measured";"H2_measured";"H3_measured"]
+ Expect.sequenceEqual nodeNames expected "RawData of full sequence"
+ )
+ testCase "LastRawData" (fun () ->
+ let nodes = isa.ArcTables.LastRawData
+ let nodeNames = nodes |> Seq.map (fun n -> n.Name)
+ let expected = ["CC1_measured";"CC2_measured";"CC3_measured";"Co1_measured";"Co2_measured";"Co3_measured";"C1_measured";"C2_measured";"C3_measured";"H1_measured";"H2_measured";"H3_measured"]
+ Expect.sequenceEqual nodeNames expected "RawData of full sequence"
+ )
+ testCase "FirstRawData" (fun () ->
+ let nodes = isa.ArcTables.FirstRawData
+ let nodeNames = nodes |> Seq.map (fun n -> n.Name)
+ let expected = ["CC1_measured";"CC2_measured";"CC3_measured";"Co1_measured";"Co2_measured";"Co3_measured";"C1_measured";"C2_measured";"C3_measured";"H1_measured";"H2_measured";"H3_measured"]
+ Expect.sequenceEqual nodeNames expected "RawData of full sequence"
+ )
+ ]
+
+let Assay_getNodes =
+ let isa = testArc.ISA.Value
+ testList "Assay_GetNodes" [
+
+ testCase "LastNodes" (fun () ->
+ let nodes = isa.GetAssay("MSEval_Heat").LastNodes
+ let nodeNames = nodes |> Seq.map (fun n -> n.Name)
+ let expected = ["sampleOutHeat.txt"]
+ Expect.sequenceEqual nodeNames expected "LastData of full sequence"
+ )
+ ]
+let Assay_ValuesOf =
+ let isa = testArc.ISA.Value
+ testList "Assay_ValuesOf" [
+
+ testCase "ValuesOfOutput_PooledOutput" (fun () ->
+ let values = isa.GetAssay("MSEval_Heat").ValuesOf("sampleOutHeat.txt").WithName("Column")
+ let valueValues = values |> Seq.map (fun n -> n.ValueText)
+ let expected = ["C1 Intensity";"C2 Intensity";"C3 Intensity";"H1 Intensity";"H2 Intensity";"H3 Intensity"]
+ Expect.sequenceEqual valueValues expected "Did not return all values correctly"
+ )
+ testCase "SucceedingValuesOfInput_PooledOutput" (fun () ->
+ let values = isa.GetAssay("MSEval_Heat").SucceedingValuesOf("C2_measured").WithName("Column")
+ let valueValues = values |> Seq.map (fun n -> n.ValueText)
+ let expected = ["C2 Intensity"]
+ Expect.sequenceEqual valueValues expected "Did not return the single value correctly"
+ )
+ testCase "PreviousValuesOfInput_PooledOutput" (fun () ->
+ let values = isa.GetAssay("MSEval_Heat").PreviousValuesOf("C2_measured").WithName("Column")
+ let valueValues = values |> Seq.map (fun n -> n.ValueText)
+ let expected = []
+ Expect.sequenceEqual valueValues expected "Should return no values"
+ )
+ testCase "ValuesOfInput_PooledOutput" (fun () ->
+ let values = isa.GetAssay("MSEval_Heat").ValuesOf("C2_measured").WithName("Column")
+ let valueValues = values |> Seq.map (fun n -> n.ValueText)
+ let expected = ["C2 Intensity"]
+ Expect.sequenceEqual valueValues expected "Did not return the single value correctly"
+ )
+
+ ]
+
+let ArcTables_ValueOf =
+ let isa = testArc.ISA.Value
+ testList "ArcTable_Values" [
+ testCase "ValuesOf_SpecificTable" (fun () ->
+ let nodeName = "sampleOutHeat.txt"
+ let protocolName = "MS"
+ let values = isa.ArcTables.ValuesOf(nodeName,protocolName)
+ let expectedTechRep =
+ ISAValue.Parameter (
+ ProcessParameterValue.create(
+ ProtocolParameter.fromString("technical replicate","MS","MS:1001808"),
+ Value.Ontology (OntologyAnnotation.fromString("1"))
+ )
+ )
+ let expectedInjVol =
+ ISAValue.Parameter (
+ ProcessParameterValue.create(
+ ProtocolParameter.fromString("injection volume setting","AFR","AFR:0001577"),
+ Value.Int 20,
+ OntologyAnnotation.fromString("microliter","UO","http://purl.obolibrary.org/obo/UO_0000101")
+ )
+ )
+ let expected =
+ [
+ expectedTechRep;expectedInjVol
+ expectedTechRep;expectedInjVol
+ expectedTechRep;expectedInjVol
+ expectedTechRep;expectedInjVol
+ expectedTechRep;expectedInjVol
+ expectedTechRep;expectedInjVol
+ ]
+ Expect.sequenceEqual values expected "Did not return correct values for specific table"
+ )
+ testCase "ValuesOf" (fun () ->
+ let nodeName = "sampleOutHeat.txt"
+
+ let valueHeaders =
+ isa.ArcTables.ValuesOf(nodeName).DistinctHeaderCategories()
+ |> Seq.map (fun x -> x.NameText)
+ let expected =
+ ["biological replicate";"organism";"temperature day";"pH";"technical replicate"; "injection volume setting";"analysis software";"Column"]
+ Expect.sequenceEqual valueHeaders expected "Did not return correct values for all table"
+ )
+ testCase "GetSpecificValue" (fun () ->
+ let rep1 = isa.ArcTables.ValuesOf("C1_measured").WithName("biological replicate").First.ValueText
+ Expect.equal rep1 "1" "Did not return correct value for specific table"
+ let rep2 = isa.ArcTables.ValuesOf("C2_measured").WithName("biological replicate").First.ValueText
+ Expect.equal rep2 "2" "Did not return correct value for specific table"
+ )
+ testCase "ValuesOf_SpecificTable_PooledOutput" (fun () ->
+ let vals = isa.ArcTables.ValuesOf("sampleOutHeat.txt","Growth").WithName("biological replicate").Values |> List.map (fun v -> v.ValueText)
+ Expect.sequenceEqual vals ["1";"2";"3";"1";"2";"3"] "Did not return correct values"
+ )
+ testCase "SpecificValue_SpecificTable_PooledOutput" (fun () ->
+ let vals = isa.ArcTables.ValuesOf("C2_prep","Growth").WithName("biological replicate").First.ValueText
+ Expect.equal vals "2" "Did not return correct value"
+ )
+ ]
+
+
+
+
+
+[]
+let main = testList "TestArcTests" [
+ ArcTables_getNodes
+ Assay_getNodes
+ Assay_ValuesOf
+ ArcTables_ValueOf
+]
\ No newline at end of file
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/.gitignore b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/.gitignore
new file mode 100644
index 0000000..25b86b4
--- /dev/null
+++ b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/.gitignore
@@ -0,0 +1,56 @@
+# ----- macos rules -----
+# taken from https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+# Icon must end with two \r
+Icon
+# Thumbnails
+._*
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+# ----- windows rules -----
+# taken from https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+# Dump file
+*.stackdump
+# Folder config file
+[Dd]esktop.ini
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+# Windows shortcuts
+*.lnk
+# ----- linux rules -----
+# taken from https://github.com/github/gitignore/blob/main/Global/Linux.gitignore
+*~
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+# KDE directory preferences
+.directory
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/dataset/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/dataset/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/dataset/sampleOutCold.txt b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/dataset/sampleOutCold.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/isa.assay.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/isa.assay.xlsx
new file mode 100644
index 0000000..4be47e0
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/isa.assay.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Cold/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/dataset/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/dataset/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/dataset/sampleOut.txt b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/dataset/sampleOut.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/isa.assay.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/isa.assay.xlsx
new file mode 100644
index 0000000..8e9fbe3
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/isa.assay.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MSEval_Heat/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/dataset/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/dataset/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/isa.assay.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/isa.assay.xlsx
new file mode 100644
index 0000000..d6b3983
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/isa.assay.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Cold/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/dataset/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/dataset/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/isa.assay.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/isa.assay.xlsx
new file mode 100644
index 0000000..625000e
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/isa.assay.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/MS_Heat/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/dataset/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/dataset/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/isa.assay.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/isa.assay.xlsx
new file mode 100644
index 0000000..d815857
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/isa.assay.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Cold/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/dataset/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/dataset/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/isa.assay.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/isa.assay.xlsx
new file mode 100644
index 0000000..a146f8e
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/isa.assay.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/assays/SamplePreparation_Heat/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/isa.investigation.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/isa.investigation.xlsx
new file mode 100644
index 0000000..df2024d
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/isa.investigation.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/runs/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/runs/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/isa.study.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/isa.study.xlsx
new file mode 100644
index 0000000..f1f8a20
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/isa.study.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/resources/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasColdTimeCourse/resources/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/README.md b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/isa.study.xlsx b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/isa.study.xlsx
new file mode 100644
index 0000000..e1f1210
Binary files /dev/null and b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/isa.study.xlsx differ
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/protocols/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/protocols/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/resources/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/studies/ChlamydomonasHeatTimeCourse/resources/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/workflows/.gitkeep b/tests/ARCtrl.Querymodel.Tests/TestObjects/TestArc/workflows/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/tests/ARCtrl.Querymodel.Tests/playground.fsx b/tests/ARCtrl.Querymodel.Tests/playground.fsx
new file mode 100644
index 0000000..01fd485
--- /dev/null
+++ b/tests/ARCtrl.Querymodel.Tests/playground.fsx
@@ -0,0 +1,117 @@
+#r "nuget: ARCtrl"
+#r @"bin\Release\net6.0\ARCtrl.NET.dll"
+#r @"bin\Release\net6.0\FSSpreadsheet.dll"
+#r @"bin\Release\net6.0\ARCtrl.Contract.dll"
+#r @"bin\Release\net6.0\ARCtrl.Querymodel.dll"
+#r @"bin\Release\net6.0\Fable.Core.dll"
+#r @"bin\Release\net6.0\OBO.NET.dll"
+
+
+open ARCtrl
+open ARCtrl.NET
+open ARCtrl.QueryModel
+open ARCtrl.ISA
+let testArcPath = __SOURCE_DIRECTORY__ + @"\TestObjects\TestArc"
+let testArc = ARC.load(testArcPath)
+
+let i = testArc.ISA.Value
+
+i.ArcTables.Data
+|> Seq.map (fun x -> x.Name)
+
+
+i.AssayCount
+i.StudyCount
+
+i.ArcTables.TableCount
+
+i.ArcTables.TableNames
+
+i.ArcTables.FirstRawData
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.LastSamples
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.FirstSamples
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.LastRawData
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.FirstProcessedData
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.LastProcessedData
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.Nodes
+|> List.map (fun x -> x.Name)
+|> List.length
+
+i.ArcTables.LastSamples
+|> List.map (fun x -> x.Name)
+
+i.ArcTables.LastNodes
+|> List.ofSeq
+|> List.map (fun x -> x.Name)
+
+let studies = i.StudyIdentifiers
+let heatAssays = i.Studies[0].RegisteredAssayIdentifiers |> List.ofSeq
+
+let coldAssays = i.Studies[1].RegisteredAssayIdentifiers |> List.ofSeq
+
+let lastsamplesOfFirstAssayH = i.GetAssay("SamplePreparation_Heat").LastSamples |> List.map (fun x -> x.Name)
+let lastsamplesOfFirstAssayC = i.GetAssay("SamplePreparation_Cold").LastSamples |> List.map (fun x -> x.Name)
+
+let lastNodesHeat = i.GetAssay("MSEval_Heat").LastNodes |> Seq.map (fun x -> x.Name) |> Array.ofSeq
+let lastSamplesHeat = i.GetAssay("MSEval_Heat").LastSamples |> List.map (fun x -> x.Name) |> Array.ofSeq
+
+let exampleLastSampleHeat = i.GetAssay("MSEval_Heat").LastSamples[0]
+let exampleLastSampleHeatName = i.GetAssay("MSEval_Heat").LastSamples[0].Name
+
+let prevNodes = exampleLastSampleHeat.Sources |> List.ofSeq |> List.map (fun x -> x.Name)
+
+exampleLastSampleHeat.PreviousParameters
+|> Seq.map (fun x -> x.Value)
+|> List.ofSeq
+
+// i.GetAssay("MSEval_Heat") |> List.map (fun x -> x.Name) |> Array.ofSeq
+let allValuesOfExampleAssayAndExampleNode =
+ i.GetAssay("MSEval_Heat").ValuesOf("sampleOutHeat.txt")
+ // |> Seq.toList
+ // |> List.map (fun x -> x.NameText)
+allValuesOfExampleAssayAndExampleNode
+|> Seq.map (fun x -> x.NameText)
+|> List.ofSeq
+
+exampleLastSampleHeat.Parameters
+|> Seq.toList
+|> List.map (fun x -> x.NameText)
+
+i.GetAssay("MS_Heat").ValuesOf("sampleOutHeat.txt")
+|> Seq.map (fun x -> x.NameText)
+|> List.ofSeq
+
+i.ArcTables.ValuesOf("sampleOutHeat.txt","MS")
+|> Seq.toList
+|> List.map (fun x -> x.NameText)
+
+i.GetAssay("MS_Heat").Values("MS")
+|> Seq.map (fun x -> x.NameText)
+|> List.ofSeq
+// let getBioRep (fN:QNode) =
+// match qi.ValuesOf(fN,ProtocolName = "Growth").WithName("biological replicate").Values.Head with
+// | QueryModel.ISAValue.Parameter x -> x.Value.Value.AsString
+// | _ -> failwith "no biorep please add"
+
+exampleLastSampleHeat.ParentProcessSequence.Nodes
+|> List.map (fun x -> x.Name)
+
+exampleLastSampleHeat.Nodes
+|> Seq.toList
+|> List.map (fun x -> x.Name)
+
+// exampleLastSampleHeat.
+// |> Seq.toList
+// |> List.map (fun x -> x.Name)