Skip to content

Commit

Permalink
re-add TableTransform xd
Browse files Browse the repository at this point in the history
  • Loading branch information
kMutagene committed Jul 24, 2023
1 parent 96e9fa5 commit 89a58cb
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 9 deletions.
14 changes: 10 additions & 4 deletions src/ArcGraphModel.IO/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
"FSharp.Core": "4.3.4"
}
},
"Fable.Core": {
"type": "Transitive",
"resolved": "4.0.0",
"contentHash": "crDLkyN4xADgnCqIneMUGVDo2oS92W4oufbIH/jwc8Fk7nIH6pS/Ds1rBB4R1jUfU1WM1k9GEPa4Up8cNj5VYw=="
},
"FSharp.FGL": {
"type": "Transitive",
"resolved": "0.0.2",
Expand Down Expand Up @@ -53,10 +58,11 @@
},
"FsSpreadsheet": {
"type": "Transitive",
"resolved": "2.0.2",
"contentHash": "4KdG85i/FGWRdV0PLqWaKoAOtXV0nTGs3bszRUds3x+aP91cRkKZg6/eKGAhTzKTyPHezAYBoOpzPwwN6miu8Q==",
"resolved": "3.1.0",
"contentHash": "ZBFN/UHnY5SvNTI4YB++saHRqwFlO/agYm/FzraW+uT/iNWz3DuHVDdFfL70a4Ngmtkntond23JBbV66NJhxbw==",
"dependencies": {
"FSharp.Core": "6.0.6"
"FSharp.Core": "6.0.6",
"Fable.Core": "4.0.0"
}
},
"Microsoft.NETCore.Platforms": {
Expand All @@ -70,7 +76,7 @@
"FSharp.Core": "[6.0.7, )",
"FSharp.FGL.ArrayAdjacencyGraph": "[0.0.2, 0.0.2]",
"FSharpAux.Core": "[2.0.0, 2.0.0]",
"FsSpreadsheet": "[2.0.2, 2.0.2]"
"FsSpreadsheet": "[3.1.0, 3.1.0]"
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/ArcGraphModel/ArcGraphModel.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
<Compile Include="CvTokens\UserParam.fs" />
<Compile Include="CvTokens\CvObject.fs" />
<Compile Include="CvTokens\CvContainer.fs" />
<Compile Include="TableTransform.fs" />
<Compile Include="Terms.fs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FSharp.FGL.ArrayAdjacencyGraph" Version="[0.0.2]" />
<PackageReference Include="FSharpAux.Core" Version="[2.0.0]" />
<PackageReference Include="FsSpreadsheet" Version="[2.0.2]" />
<PackageReference Include="FsSpreadsheet" Version="[3.1.0]" />
</ItemGroup>

<PropertyGroup>
Expand Down
213 changes: 213 additions & 0 deletions src/ArcGraphModel/TableTransform.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
namespace ArcGraphModel

open FSharpAux
open FsSpreadsheet
open FSharp.FGL
open FSharp.FGL.ArrayAdjacencyGraph


module List = // remove as soon as this is available in next F#Aux NuGet release
let map4 (mapping : 'T -> 'T -> 'T -> 'T -> 'U) (list1 : 'T list) (list2 : 'T list) (list3 : 'T list) (list4 : 'T list) =
if list1.Length <> list2.Length || list1.Length <> list3.Length || list1.Length <> list4.Length then
failwithf "The input lists have different lengths.\n\tlist1.Length = %i; list2.Length = %i; list3.Length = %i; list4.Length = %i" list1.Length list2.Length list3.Length list4.Length
let rec loop acc nl1 nl2 nl3 nl4 =
match nl1, nl2, nl3, nl4 with
| h1 :: t1, h2 :: t2, h3 :: t3, h4 :: t4 ->
loop (mapping h1 h2 h3 h4 :: acc) t1 t2 t3 t4
| _ -> List.rev acc
loop [] list1 list2 list3 list4

let inline transposeOrdinary (lists : seq<'T list>) =
if lists |> Seq.forall (fun t -> t.Length <> (Seq.head lists).Length) then
failwith "Input lists have different lengths."
List.init (Seq.head lists).Length (
fun i ->
List.init (Seq.length lists) (
fun j -> (Seq.item j lists)[i]
)
)


/// <summary>
/// Functions to work with FsTables into graph-based models.
/// </summary>
module TableTransform =

// -----
// TYPES
// -----

/// <summary>
/// Modelling of the different types of nodes / Building Blocks.
/// </summary>
type NodeType =
| Source
| Sink
| ProtocolRef


// ------
// VALUES
// ------

/// <summary>
/// The header names of the columns containing Node-related Building Blocks.
/// </summary>
let nodeColumnNames = [
"Source Name"
"Sample Name"
"Raw Data File"
"Derived Data File"
"Protocol Type"
"Protocol REF"
]


// ---------
// FUNCTIONS
// ---------

/// <summary>
/// Takes an FsWorkbook and returns all Annotation Tables it contains.
/// </summary>
let getAnnotationTables workbook =
let tables = FsWorkbook.getTables workbook
tables |> List.filter (fun t -> String.contains "annotationTable" t.Name)

/// <summary>
/// Returns all data cells from a given header cell by using a given FsCellsCollection.
/// </summary>
let getDataCellsOf (fcc : FsCellsCollection) (headerCell : FsCell) =
FsCellsCollection.getCellsInColumn headerCell.ColumnNumber fcc
|> Seq.toList
|> List.skip 1

/// <summary>
/// Takes a list of header cells and an FsCellsCollections and returns a list of CvParams according to the information from the FsCells.
/// If `crStart` is true, it is assumed that the first header cell is a Term containing header cell of a Building Block.
///
/// This function should only be used for parsing edges, i.e., Term-related Building Blocks.
/// </summary>
let parseEdges crStart (*(table : FsTable)*) (fcc : FsCellsCollection) (cl : FsCell list) =
//let empty() = FsCell.createEmpty ()
//let getTableFieldOf (table : FsTable) (cell : FsCell) =
// table.Fields(fcc) |> ignore

let rec loop roundOne (cells : FsCell list) =
[
match cells with
| a :: b :: c :: d :: rest when roundOne && (String.startsWith "Unit" b.Value) ->
// a = Value/Name header, b = Unit header, c = TermSourceRef header, d = TermAccessionNumber header
//let tfa = FsTableField(a.Value, a.ColumnNumber, )
//FsTableField.getDataCells fcc true
let dataCellsVal = getDataCellsOf fcc a
let dataCellsUnt = getDataCellsOf fcc b
let dataCellsTsr = getDataCellsOf fcc c
let dataCellsTan = getDataCellsOf fcc d
let cvPars =
List.map4 (
fun (vl : FsCell) unt tan tsr ->
let valTerm = CvUnit(tan.Value, vl.Value, tsr.Value)
CvParam(d.Value, a.Value, c.Value, WithCvUnitAccession (unt.Value, valTerm))
) dataCellsVal dataCellsUnt dataCellsTan dataCellsTsr
yield! cvPars
yield! loop false rest
| a :: b :: c :: rest when roundOne ->
// a = Value/Name header, b = TermSourceRef header, c = TermAccessionNumber header
let dataCellsVal = getDataCellsOf fcc a
let dataCellsTsr = getDataCellsOf fcc b
let dataCellsTan = getDataCellsOf fcc c
let cvPars =
(dataCellsVal, dataCellsTsr, dataCellsTan)
|||> List.map3 (
fun vl tsr tan ->
let valTerm = CvTerm(tan.Value, vl.Value, tsr.Value)
CvParam(c.Value, a.Value, b.Value, CvValue valTerm)
)
yield! cvPars
yield! loop false rest
| a :: b :: rest ->
match roundOne with
| true ->
// a = Value/Name header, b = TermSourceRef header (assumed, could also be TermAccessionNumber header if TSR column is missing)
let dataCellsVal = getDataCellsOf fcc a
let dataCellsTsr = getDataCellsOf fcc b
let cvPars =
(dataCellsVal, dataCellsTsr)
||> List.map2 (
fun vl tsr ->
let valTerm = CvTerm("(n/a)", vl.Value, tsr.Value)
CvParam("n/a", a.Value, b.Value, CvValue valTerm)
)
yield! cvPars
yield! loop false rest
| false ->
// a = TermSourceRef header, b = TermAccessionNumber header
let dataCellsTsr = getDataCellsOf fcc a
let dataCellsTan = getDataCellsOf fcc b
let cvPars =
(dataCellsTsr, dataCellsTan)
||> List.map2 (
fun tsr tan ->
let valTerm = CvTerm(tan.Value, "n/a", tsr.Value)
CvParam(b.Value, "(n/a)", a.Value, CvValue valTerm)
)
yield! cvPars
yield! loop false rest
| a :: [] ->
match roundOne with
| true ->
// a = Value/Name header
let dataCellsVal = getDataCellsOf fcc a
let cvPars =
dataCellsVal
|> List.map (
fun vl ->
// use this if ParamValue shall be CvValue instead of mere Value
//let valTerm = CvTerm("(n/a)", vl.Value, "(n/a)")
CvParam("(n/a)", a.Value, "(n/a)", Value vl.Value)
)
yield! cvPars
| false ->
// a = TermSourceRef header (assumed, could also be TermAccessionNumber header if TSR column is missing)
let dataCellsTsr = getDataCellsOf fcc a
let cvPars =
dataCellsTsr
|> List.map (
fun tsr ->
CvParam("(n/a)", "(n/a)", tsr.Value, Value "(n/a)")
)
yield! cvPars
| [] -> ()
]
loop crStart cl

/// <summary>
/// Takes a header cells and an FsCellsCollections and returns a list of CvParams according to the information from the FsCells.
///
/// This function should only be used for parsing nodes, i.e., input-, output-, and featured columns.
/// </summary>
let parseNode fcc headerCell =
let dataCellsVal = getDataCellsOf fcc headerCell
dataCellsVal
|> List.map (
fun dc ->
//UserParam(headerCell.Value, ParamValue.Value dc.Value)
CvParam("(n/a)", headerCell.Value, "(n/a)", ParamValue.Value dc.Value)
)

/// <summary>
/// Takes a CvParam and returns the type of Node it contains.
/// </summary>
let getNodeType (cvPar : #IParamBase) =
//let castedCvPar = cvPar :?> CvParam<string> // debatable approach
//let v = Param.getCvName castedCvPar
let v = CvBase.getCvName cvPar
match v with
| "Source Name" -> Source
| "Sample Name"
| "Raw Data File"
| "Derived Data File" -> Sink
| "Protocol REF"
| "Protocol Type" -> ProtocolRef
| _ -> failwith $"HeaderCell {v} cannot be parsed to any NodeType."
14 changes: 10 additions & 4 deletions src/ArcGraphModel/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
},
"FsSpreadsheet": {
"type": "Direct",
"requested": "[2.0.2, 2.0.2]",
"resolved": "2.0.2",
"contentHash": "4KdG85i/FGWRdV0PLqWaKoAOtXV0nTGs3bszRUds3x+aP91cRkKZg6/eKGAhTzKTyPHezAYBoOpzPwwN6miu8Q==",
"requested": "[3.1.0, 3.1.0]",
"resolved": "3.1.0",
"contentHash": "ZBFN/UHnY5SvNTI4YB++saHRqwFlO/agYm/FzraW+uT/iNWz3DuHVDdFfL70a4Ngmtkntond23JBbV66NJhxbw==",
"dependencies": {
"FSharp.Core": "6.0.6"
"FSharp.Core": "6.0.6",
"Fable.Core": "4.0.0"
}
},
"NETStandard.Library": {
Expand All @@ -53,6 +54,11 @@
"FSharp.Core": "4.3.4"
}
},
"Fable.Core": {
"type": "Transitive",
"resolved": "4.0.0",
"contentHash": "crDLkyN4xADgnCqIneMUGVDo2oS92W4oufbIH/jwc8Fk7nIH6pS/Ds1rBB4R1jUfU1WM1k9GEPa4Up8cNj5VYw=="
},
"FSharp.FGL": {
"type": "Transitive",
"resolved": "0.0.2",
Expand Down

0 comments on commit 89a58cb

Please sign in to comment.