Logo ProcessCore

Tabular Views Over Process Graphs

ProcessCore.Table exposes ISA-like table views over a process graph. A table groups processes by name, and each row is backed by a live Process.

dataset.Tables groups processes with the same name. Here both processes become rows in one Growth table.

let tableNames =
    dataset.Tables.TableNames
    |> Seq.toList

tableNames
["Growth"]
let growth = dataset.Tables.GetTable("Growth")

let initialShape =
    [ "rows", growth.RowCount
      "columns", growth.ColumnCount ]

initialShape
[("rows", 2); ("columns", 6)]

Headers and cells are typed. They preserve whether a column represents input/output, protocol metadata, or annotation values.

let headers =
    growth.Headers
    |> Seq.map (sprintf "%A")
    |> Seq.toList

headers
["Input Source"; "ProtocolREF"; "Component ProcessCore.DefinedTerm";
 "Parameter ProcessCore.DefinedTerm"; "Factor ProcessCore.DefinedTerm";
 "Output Sample"]
let firstRow =
    growth.GetRow(0)
    |> Seq.map (sprintf "%A")
    |> Seq.toList

firstRow
["FreeText "Base culture""; "FreeText "Growth""; "FreeText "chamber-1"";
 "Unitized ("7", "day", None)"; "Unitized ("25", "degree Celsius", None)";
 "FreeText "Leaf sample RT""]

Adding an annotation column writes Annotation objects into the appropriate graph slot. Parameter columns go to Process.ParameterValue.

growth.AddColumn(
    CompositeHeader.Parameter(DefinedTerm("light intensity")),
    ResizeArray([
        CompositeCell.Unitized("120", "umol m-2 s-1", None)
        CompositeCell.Unitized("150", "umol m-2 s-1", None)
    ])
)

let processParameters =
    growth.Processes
    |> Seq.map (fun p ->
        p.ParameterValue
        |> Seq.map (fun pv -> pv.Name + "=" + pv.ValueWithUnitText)
        |> Seq.toList)
    |> Seq.toList

processParameters
[["duration=7 day"; "light intensity=120 umol m-2 s-1"];
 ["duration=7 day"; "light intensity=150 umol m-2 s-1"]]

Adding a row creates a new Process in both the table and the parent dataset. Empty cells use the table's current headers as a template.

growth.AppendRow()

let afterAppend =
    [ "table rows", growth.RowCount
      "dataset processes", dataset.Processes.Count ]

afterAppend
[("table rows", 3); ("dataset processes", 3)]

The table is a view, not a detached copy. Querying the dataset after a table edit sees the edited process graph.

let allParameterNames =
    dataset.AllAnnotations()
    |> Seq.map (fun pv -> pv.Name)
    |> Seq.distinct
    |> Seq.toList

allParameterNames
["duration"; "light intensity"; "growth chamber"; "temperature"]

What To Use When

Task

API

List tables

dataset.Tables.GetTables()

Open a named table

dataset.Tables.GetTable(name)

Inspect column roles

table.Headers, table.Columns

Read a row

table.GetRow(index)

Add annotation columns

table.AddColumn

Add rows/processes

table.AddRow, table.AppendRow

Edit the graph through cells

table.UpdateRow

namespace ProcessCore
namespace ProcessCore.Table
val sample: name: string -> Sample
val name: string
Multiple items
type Sample = inherit DynamicObj new: name: string * ?additionalType: string * ?additionalProperty: Annotation seq -> Sample member AddAdditionalProperty: pv: Annotation -> unit member AllAnnotations: ?scope: ResizeArray<Process> -> ResizeArray<Annotation> member AllConnectedNodes: ?scope: ResizeArray<Process> -> ResizeArray<IONode> member AllConnectedProcesses: ?scope: ResizeArray<Process> -> ResizeArray<Process> member ConnectedData: ?scope: ResizeArray<Process> -> ResizeArray<Data> member ConnectedSamples: ?scope: ResizeArray<Process> -> ResizeArray<Sample> member DownstreamAnnotations: ?recipeName: string * ?scope: ResizeArray<Process> -> ResizeArray<Annotation> member DownstreamData: ?scope: ResizeArray<Process> -> ResizeArray<Data> ...
<summary> Input or output biological, chemical, or digital sample in the process graph. bioschemas.org/Sample </summary>

--------------------
new: name: string * ?additionalType: string * ?additionalProperty: Annotation seq -> Sample
val source: name: string -> Sample
val growthProcess: inputName: string -> outputName: string -> temperature: string -> Process
val inputName: string
val outputName: string
val temperature: string
val protocol: Recipe
Multiple items
type Recipe = inherit DynamicObj new: ?name: string * ?description: string * ?version: string * ?url: string * ?intendedUse: DefinedTerm * ?additionalType: string * ?parameters: FormalParameter seq * ?components: Annotation seq * ?additionalProperty: Annotation seq -> Recipe member AddAdditionalProperty: pv: Annotation -> unit member AddComponent: pv: Annotation -> unit member AddParameter: fp: FormalParameter -> unit override Equals: obj: obj -> bool override GetHashCode: unit -> int member RemoveAdditionalProperty: pv: Annotation -> unit member RemoveComponent: pv: Annotation -> unit member RemoveParameter: fp: FormalParameter -> unit ...
<summary> Description of a planned procedure. bioschemas.org/LabProtocol </summary>

--------------------
new: ?name: string * ?description: string * ?version: string * ?url: string * ?intendedUse: DefinedTerm * ?additionalType: string * ?parameters: FormalParameter seq * ?components: Annotation seq * ?additionalProperty: Annotation seq -> Recipe
property Recipe.Name: string option with get, set
union case Option.Some: Value: 'T -> Option<'T>
member Recipe.AddComponent: pv: Annotation -> unit
Multiple items
type Annotation = inherit DynamicObj new: name: string * ?value: string * ?unit: string * ?nameTAN: string * ?valueTAN: string * ?unitTAN: string * ?additionalType: string * ?instanceOf: FormalParameter -> Annotation override Equals: obj: obj -> bool override GetHashCode: unit -> int member NameEquals: term: DefinedTerm -> bool member AdditionalType: string option with get, set member InstanceOf: FormalParameter option with get, set member Name: string with get, set member NameTAN: string option with get, set member NameText: string ...
<summary> Extensible key-value-unit triple. Primary extension mechanism of ProcessCore. schema.org/PropertyValue </summary>

--------------------
new: name: string * ?value: string * ?unit: string * ?nameTAN: string * ?valueTAN: string * ?unitTAN: string * ?additionalType: string * ?instanceOf: FormalParameter -> Annotation
val output: Sample
member Sample.AddAdditionalProperty: pv: Annotation -> unit
type unit = Unit
val p: Process
Multiple items
type Process = inherit DynamicObj new: name: string * ?executesRecipe: Recipe * ?additionalType: string * ?input: IONode * ?output: IONode * ?parameterValue: Annotation seq -> Process member AddParameterValue: pv: Annotation -> unit member AnnotationsByName: name: string -> ResizeArray<Annotation> member CanonicalizeAllNodes: ds: Dataset -> unit member ClearInput: unit -> unit member ClearOutput: unit -> unit override Equals: obj: obj -> bool override GetHashCode: unit -> int member GetParameterValue: name: string -> Annotation ...
<summary> Core transformation node. Connects inputs to outputs by executing a recipe. bioschemas.org/LabProcess </summary>

--------------------
new: name: string * ?executesRecipe: Recipe * ?additionalType: string * ?input: IONode * ?output: IONode * ?parameterValue: Annotation seq -> Process
property Process.ExecutesRecipe: Recipe option with get, set
member Process.SetInputSample: m: Sample -> unit
member Process.SetOutputSample: m: Sample -> unit
member Process.AddParameterValue: pv: Annotation -> unit
val dataset: Dataset
Multiple items
type Dataset = inherit DynamicObj new: identifier: string * ?title: string * ?description: string * ?additionalType: string * ?license: string * ?datePublished: string * ?dateCreated: string * ?dateModified: string * ?processes: Process seq * ?hasPart: Dataset seq * ?dataFiles: Data seq * ?agents: Agent seq * ?citations: ScholarlyArticle seq * ?dataContexts: DataContext seq * ?additionalProperty: Annotation seq -> Dataset member AddAdditionalProperty: pv: Annotation -> unit member AddAgent: agent: Agent -> unit member AddCitation: article: ScholarlyArticle -> unit member AddDataContext: dataContext: DataContext -> unit member AddDataFile: data: Data -> unit member AddPart: child: Dataset -> unit member AddProcess: proc: Process -> unit member AllAgents: unit -> ResizeArray<Agent> ...
<summary> Container and context for data, processes, administrative metadata, and datamap entries. schema.org/Dataset </summary>

--------------------
new: identifier: string * ?title: string * ?description: string * ?additionalType: string * ?license: string * ?datePublished: string * ?dateCreated: string * ?dateModified: string * ?processes: Process seq * ?hasPart: Dataset seq * ?dataFiles: Data seq * ?agents: Agent seq * ?citations: ScholarlyArticle seq * ?dataContexts: DataContext seq * ?additionalProperty: Annotation seq -> Dataset
member Dataset.AddProcess: proc: Process -> unit
val tableNames: string list
property Dataset.Tables: Tables with get
<summary> A live tabular view of all processes in this dataset, grouped by process name. </summary>
property Tables.TableNames: ResizeArray<string> with get
<summary> Names of all tables in order. </summary>
module Seq from Microsoft.FSharp.Collections
val toList: source: 'T seq -> 'T list
val growth: Table
member Tables.GetTable: name: string -> Table
val initialShape: (string * int) list
property Table.RowCount: int with get
<summary> Number of visible rows; every row is exactly one process. </summary>
property Table.ColumnCount: int with get
<summary> Number of columns (derived from current process state). </summary>
val headers: string list
property Table.Headers: ResizeArray<CompositeHeader> with get
<summary> Derive headers from the current process state. </summary>
val map: mapping: ('T -> 'U) -> source: 'T seq -> 'U seq
val sprintf: format: Printf.StringFormat<'T> -> 'T
val firstRow: string list
member Table.GetRow: rowIndex: int -> ResizeArray<CompositeCell>
member Table.AddColumn: header: CompositeHeader * ?cells: ResizeArray<CompositeCell> -> unit
type CompositeHeader = | Parameter of DefinedTerm | Characteristic of DefinedTerm | Factor of DefinedTerm | Component of DefinedTerm | ProtocolREF | ProtocolType | ProtocolDescription | ProtocolUri | ProtocolVersion | Performer ... override ToString: unit -> string member TryIOType: unit -> IOType option member TryInput: unit -> IOType option member TryOutput: unit -> IOType option member GetColumnAccessionShort: string member GetFeaturedColumnAccession: string member IsCvParamColumn: bool member IsDataColumn: bool member IsFeaturedColumn: bool member IsIOType: bool ...
<summary> Typed column header. Carries the column role and, for annotation columns, the ontology term identifying what is being described. </summary>
union case CompositeHeader.Parameter: DefinedTerm -> CompositeHeader
Multiple items
type DefinedTerm = inherit DynamicObj new: name: string * ?tan: string * ?inDefinedTermSet: string -> DefinedTerm override Equals: obj: obj -> bool override GetHashCode: unit -> int member SemanticallyEquals: other: DefinedTerm -> bool member TermAccessionShort: unit -> string member TryGetTSR: unit -> string option member InDefinedTermSet: string option with get, set member Name: string with get, set member TAN: string option with get, set
<summary> Ontology annotation referencing a term in a controlled vocabulary or ontology. schema.org/DefinedTerm </summary>

--------------------
new: name: string * ?tan: string * ?inDefinedTermSet: string -> DefinedTerm
type ResizeArray<'T> = System.Collections.Generic.List<'T>
type CompositeCell = | FreeText of string | Term of name: string * tan: string option | Unitized of value: string * unitName: string * unitTAN: string option | Data of Data
<summary> Typed cell value. </summary>
union case CompositeCell.Unitized: value: string * unitName: string * unitTAN: string option -> CompositeCell
<summary> Numeric value with unit term </summary>
union case Option.None: Option<'T>
val processParameters: string list list
property Table.Processes: ResizeArray<Process> with get
<summary> The underlying process nodes this table projects. </summary>
property Process.ParameterValue: ResizeArray<Annotation> with get
val pv: Annotation
property Annotation.Name: string with get, set
property Annotation.ValueWithUnitText: string with get
member Table.AppendRow: ?cells: ResizeArray<CompositeCell> -> unit
val afterAppend: (string * int) list
property Dataset.Processes: ResizeArray<Process> with get
property System.Collections.Generic.List.Count: int with get
val allParameterNames: string list
member Dataset.AllAnnotations: ?recipeName: string -> ResizeArray<Annotation>
val distinct: source: 'T seq -> 'T seq (requires equality)

Type something to start searching.