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 LabProcess.

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 PropertyValue objects into the appropriate graph slot. Parameter columns go to LabProcess.ParameterValue.

growth.AddColumn(
    CompositeHeader.Parameter("light intensity", None),
    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
No value returned by any evaluator

Adding a row creates a new LabProcess 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.AllPropertyValues()
    |> Seq.map (fun pv -> pv.Name)
    |> Seq.distinct
    |> Seq.toList

allParameterNames
["duration"; "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 -> Material
val name: string
Multiple items
type Material = inherit DynamicObj new: name: string * ?additionalType: string * ?additionalProperty: PropertyValue seq -> Material member AddAdditionalProperty: pv: PropertyValue -> unit member AllConnectedNodes: ?scope: ResizeArray<LabProcess> -> ResizeArray<IONode> member AllConnectedProcesses: ?scope: ResizeArray<LabProcess> -> ResizeArray<LabProcess> member AllPropertyValues: ?scope: ResizeArray<LabProcess> -> ResizeArray<PropertyValue> member ConnectedData: ?scope: ResizeArray<LabProcess> -> ResizeArray<Data> member ConnectedMaterials: ?scope: ResizeArray<LabProcess> -> ResizeArray<Material> member DownstreamData: ?scope: ResizeArray<LabProcess> -> ResizeArray<Data> member DownstreamMaterials: ?scope: ResizeArray<LabProcess> -> ResizeArray<Material> ...
<summary> Input or output biological, chemical, or digital material in the process graph. bioschemas.org/Sample </summary>

--------------------
new: name: string * ?additionalType: string * ?additionalProperty: PropertyValue seq -> Material
val source: name: string -> Material
val growthProcess: inputName: string -> outputName: string -> temperature: string -> LabProcess
val inputName: string
val outputName: string
val temperature: string
val protocol: LabProtocol
Multiple items
type LabProtocol = inherit DynamicObj new: ?name: string * ?description: string * ?version: string * ?url: string * ?intendedUse: DefinedTerm * ?additionalType: string * ?parameters: FormalParameter seq * ?labEquipment: PropertyValue seq * ?additionalProperty: PropertyValue seq -> LabProtocol member AddAdditionalProperty: pv: PropertyValue -> unit member AddLabEquipment: pv: PropertyValue -> unit member AddParameter: fp: FormalParameter -> unit override Equals: obj: obj -> bool override GetHashCode: unit -> int member RemoveAdditionalProperty: pv: PropertyValue -> unit member RemoveLabEquipment: pv: PropertyValue -> 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 * ?labEquipment: PropertyValue seq * ?additionalProperty: PropertyValue seq -> LabProtocol
property LabProtocol.Name: string option with get, set
union case Option.Some: Value: 'T -> Option<'T>
member LabProtocol.AddLabEquipment: pv: PropertyValue -> unit
Multiple items
type PropertyValue = inherit DynamicObj new: name: string * ?value: string * ?unit: string * ?nameTAN: string * ?valueTAN: string * ?unitTAN: string * ?additionalType: string * ?instanceOf: FormalParameter -> PropertyValue override Equals: obj: obj -> bool override GetHashCode: unit -> int 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 member Unit: string option with get, set ...
<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 -> PropertyValue
val output: Material
member Material.AddAdditionalProperty: pv: PropertyValue -> unit
type unit = Unit
val p: LabProcess
Multiple items
type LabProcess = inherit DynamicObj new: name: string * ?executesProtocol: LabProtocol * ?additionalType: string * ?inputs: IONode seq * ?outputs: IONode seq * ?parameterValue: PropertyValue seq -> LabProcess member AddInput: node: IONode -> unit member AddInputData: d: Data -> unit member AddInputMaterial: m: Material -> unit member AddOutput: node: IONode -> unit member AddOutputData: d: Data -> unit member AddOutputMaterial: m: Material -> unit member AddParameterValue: pv: PropertyValue -> unit member CanonicalizeAllNodes: ds: Dataset -> unit ...
<summary> Core transformation node. Connects inputs to outputs via a protocol. bioschemas.org/LabProcess </summary>

--------------------
new: name: string * ?executesProtocol: LabProtocol * ?additionalType: string * ?inputs: IONode seq * ?outputs: IONode seq * ?parameterValue: PropertyValue seq -> LabProcess
property LabProcess.ExecutesProtocol: LabProtocol option with get, set
member LabProcess.AddInputMaterial: m: Material -> unit
member LabProcess.AddOutputMaterial: m: Material -> unit
member LabProcess.AddParameterValue: pv: PropertyValue -> unit
val dataset: Dataset
Multiple items
type Dataset = inherit DynamicObj new: identifier: string * ?name: string * ?description: string * ?additionalType: string * ?processes: LabProcess seq * ?hasPart: Dataset seq * ?additionalProperty: PropertyValue seq -> Dataset member AddAdditionalProperty: pv: PropertyValue -> unit member AddPart: child: Dataset -> unit member AddProcess: proc: LabProcess -> unit member AllConnectedNodes: node: IONode -> ResizeArray<IONode> member AllData: unit -> ResizeArray<Data> member AllMaterials: unit -> ResizeArray<Material> member AllNodes: unit -> ResizeArray<IONode> member AllProcesses: unit -> ResizeArray<LabProcess> ...
<summary> Container and context for data and processes. schema.org/Dataset </summary>

--------------------
new: identifier: string * ?name: string * ?description: string * ?additionalType: string * ?processes: LabProcess seq * ?hasPart: Dataset seq * ?additionalProperty: PropertyValue seq -> Dataset
member Dataset.AddProcess: proc: LabProcess -> 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 in the table projection. </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 ... 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 member IsSingleColumn: 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
union case Option.None: Option<'T>
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>
val processParameters: string list list
property Table.Processes: ResizeArray<LabProcess> with get
<summary> The underlying process nodes this table projects. </summary>
property LabProcess.ParameterValue: ResizeArray<PropertyValue> with get
val pv: PropertyValue
property PropertyValue.Name: string with get, set
property PropertyValue.ValueWithUnitText: string with get
member Table.AppendRow: ?cells: ResizeArray<CompositeCell> -> unit
val afterAppend: (string * int) list
property Dataset.Processes: ResizeArray<LabProcess> with get
property System.Collections.Generic.List.Count: int with get
val allParameterNames: string list
member Dataset.AllPropertyValues: ?protocolName: string -> ResizeArray<PropertyValue>
val distinct: source: 'T seq -> 'T seq (requires equality)

Type something to start searching.