Skip to content

Commit

Permalink
Merge pull request #377 from nfdi4plants/datamap
Browse files Browse the repository at this point in the history
Rework datamap type
  • Loading branch information
HLWeil authored Jun 12, 2024
2 parents 8f5eaf1 + 0ead1eb commit 2951259
Show file tree
Hide file tree
Showing 12 changed files with 427 additions and 235 deletions.
1 change: 0 additions & 1 deletion .github/workflows/manage-issues.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ on:
types:
- opened
- reopened
- transferred

jobs:
label_issues:
Expand Down
1 change: 1 addition & 0 deletions src/Core/ARCtrl.Core.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<Compile Include="OntologyAnnotation.fs" />
<Compile Include="DataFile.fs" />
<Compile Include="Data.fs" />
<Compile Include="DataContext.fs" />
<Compile Include="Person.fs" />
<Compile Include="Publication.fs" />
<Compile Include="OntologySourceReference.fs" />
Expand Down
48 changes: 42 additions & 6 deletions src/Core/Data.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,28 @@ open ARCtrl
open ARCtrl.Helper
open Fable.Core

module DataAux =

let nameFromPathAndSelector (path : string) (selector : string) =
sprintf "%s#%s" path selector

let pathAndSelectorFromName (name : string) =
let parts = name.Split('#')
if parts.Length = 2 then
parts.[0], Some parts.[1]
else
name, None

[<AttachMembers>]
type Data(?id,?name,?dataType,?format,?selectorFormat,?comments) =
type Data(?id,?name : string,?dataType,?format,?selectorFormat,?comments) =

let mutable _id : URI option = id
let mutable _name : string option = name
let mutable _filePath,_selector =
match name with
| Some n ->
let p,s = DataAux.pathAndSelectorFromName n
Some p, s
| None -> None, None
let mutable _dataType : DataFile option = dataType
let mutable _format : string option = format
let mutable _selectorFormat : URI option = selectorFormat
Expand All @@ -19,8 +36,28 @@ type Data(?id,?name,?dataType,?format,?selectorFormat,?comments) =
and set(id) = _id <- id

member this.Name
with get() = _name
and set(name) = _name <- name
with get() =
match _filePath,_selector with
| Some p, Some s -> DataAux.nameFromPathAndSelector p s |> Some
| Some p, None -> p |> Some
| None, _ -> None
and set(name) =
match name with
| Some n ->
let p,s = DataAux.pathAndSelectorFromName n
_filePath <- Some p
_selector <- s
| None ->
_filePath <- None
_selector <- None

member this.FilePath
with get() = _filePath
and set(filePath) = _filePath <- filePath

member this.Selector
with get() = _selector
and set(selector) = _selector <- selector

member this.DataType
with get() = _dataType
Expand All @@ -36,8 +73,7 @@ type Data(?id,?name,?dataType,?format,?selectorFormat,?comments) =

member this.Comments
with get() = _comments
and set(comments) = _comments <- comments

and set(comments) = _comments <- comments

static member make id name dataType format selectorFormat comments =
Data(?id=id,?name=name,?dataType=dataType,?format=format,?selectorFormat=selectorFormat,?comments=comments)
Expand Down
74 changes: 74 additions & 0 deletions src/Core/DataContext.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
namespace ARCtrl

open ARCtrl
open ARCtrl.Helper
open Fable.Core

type DataContext(?id,?name : string,?dataType,?format,?selectorFormat, ?explication, ?unit, ?objectType, ?description, ?generatedBy, ?comments) =

inherit Data(?id = id,?name = name, ?dataType = dataType, ?format = format, ?selectorFormat = selectorFormat, ?comments = comments)

let mutable _explication : OntologyAnnotation option = explication
let mutable _unit : OntologyAnnotation option = unit
let mutable _objectType : OntologyAnnotation option = objectType
let mutable _description : string option = description
let mutable _generatedBy : string option = generatedBy

member this.Explication
with get() = _explication
and set(explication) = _explication <- explication

member this.Unit
with get() = _unit
and set(unit) = _unit <- unit

member this.ObjectType
with get() = _objectType
and set(objectType) = _objectType <- objectType

member this.Description
with get() = _description
and set(description) = _description <- description

member this.GeneratedBy
with get() = _generatedBy
and set(generatedBy) = _generatedBy <- generatedBy


member this.AsData() =
Data(?id = this.ID,?name = this.Name, ?dataType = this.DataType, ?format = this.Format, ?selectorFormat = this.SelectorFormat, comments = this.Comments)

member this.Copy() =
let copy = new DataContext()
copy.ID <- this.ID
copy.Name <- this.Name
copy.DataType <- this.DataType
copy.Format <- this.Format
copy.SelectorFormat <- this.SelectorFormat
copy.Explication <- this.Explication
copy.Unit <- this.Unit
copy.ObjectType <- this.ObjectType
copy.Description <- this.Description
copy.GeneratedBy <- this.GeneratedBy
copy.Comments <- this.Comments
copy

override this.GetHashCode() =
[|
HashCodes.boxHashOption this.ID
HashCodes.boxHashOption this.Name
HashCodes.boxHashOption this.DataType
HashCodes.boxHashOption this.Format
HashCodes.boxHashOption this.SelectorFormat
HashCodes.boxHashSeq this.Comments
HashCodes.boxHashOption this.Explication
HashCodes.boxHashOption this.Unit
HashCodes.boxHashOption this.ObjectType
HashCodes.boxHashOption this.Description
HashCodes.boxHashOption this.GeneratedBy
|]
|> HashCodes.boxHashArray
|> fun x -> x :?> int

override this.Equals(obj) =
HashCodes.hash this = HashCodes.hash obj
136 changes: 77 additions & 59 deletions src/Core/Table/DataMap.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ open Fable.Core

[<AttachMembers>]
module DataMapAux =

[<Literal>]
let dataMapName = "DataMap"

Expand Down Expand Up @@ -51,88 +51,106 @@ module DataMapAux =
let allowedHeaders =
[dataHeader; explicationHeader; unitHeader; objectTypeHeader; descriptionHeader; generatedByHeader]

let validate (headers : ResizeArray<CompositeHeader>) (values : System.Collections.Generic.Dictionary<int*int,CompositeCell>) (raiseException : bool) =
let headersAreValid =
headers
|> Seq.exists (fun h ->
let hasForeignHeader =
not (allowedHeaders |> List.exists (fun ah -> ah = h))
if raiseException && hasForeignHeader then
failwithf "Header %O is not allowed in DataMap" h
hasForeignHeader
)
let tableIsValid = ArcTableAux.SanityChecks.validate headers values raiseException
headersAreValid && tableIsValid

type DataMap(headers: ResizeArray<CompositeHeader>, values: System.Collections.Generic.Dictionary<int*int,CompositeCell>) =

let _ = DataMapAux.validate headers values true
let getOntologyColumn (f : DataContext -> OntologyAnnotation option) (dataContexts : ResizeArray<DataContext>) =
dataContexts
|> Seq.map (fun dc ->
match f dc with
| Some s -> CompositeCell.Term(s)
| None -> CompositeCell.emptyTerm
)
|> ResizeArray

let getStringColumn (f : DataContext -> string option) (dataContexts : ResizeArray<DataContext>) =
dataContexts
|> Seq.map (fun dc ->
match f dc with
| Some s -> CompositeCell.FreeText(s)
| None -> CompositeCell.emptyFreeText
)
|> ResizeArray

let setOntologyColumn (f : DataContext -> OntologyAnnotation option -> unit) (column : CompositeCell []) (dataContexts : ResizeArray<DataContext>) =
column
|> Seq.iteri (fun i cell ->
match cell with
| CompositeCell.Term s -> f (dataContexts.[i]) (Some s)
| _ -> ()
)

let table = ArcTable(DataMapAux.dataMapName, headers, values)
let mutable staticHash = 0
let setStringColumn (f : DataContext -> string option -> unit) (column : CompositeCell []) (dataContexts : ResizeArray<DataContext>) =
column
|> Seq.iteri (fun i cell ->
match cell with
| CompositeCell.FreeText s -> f (dataContexts.[i]) (Some s)
| _ -> ()
)

member this.Headers = table.Headers
member this.Values = table.Values
member this.StaticHash with get() = staticHash and set(value) = staticHash <- value
module SanityChecks =

let rowIndexInBoundaries (row : int) (dataContexts : ResizeArray<DataContext>) =
if row < 0 then
failwith "Row index must be greater or equal to 0."
if row >= dataContexts.Count then
failwith "Row index must be less than the number of rows."

static member init() = DataMap(ResizeArray(),Dictionary())
let lengthOfNewColumn (newColumn : CompositeCell []) (dataContexts : ResizeArray<DataContext>) =
if newColumn.Length <> dataContexts.Count then
failwith "Length of new column does not match length of data contexts."

member this.AddColumns(columns : CompositeColumn [], ?skipFillMissing : bool) =
columns |> Array.iter (fun c -> c.Validate(true) |> ignore)
table.AddColumns(columns, ?skipFillMissing = skipFillMissing)
DataMapAux.validate table.Headers table.Values true |> ignore
type DataMap(dataContexts : ResizeArray<DataContext>) =

let mutable staticHash = 0
let mutable dataContexts = dataContexts

static member addColumns (columns : CompositeColumn [], ?skipFillMissing : bool) =
fun (dm : DataMap) ->
let dm : DataMap = dm.Copy()
dm.AddColumns(columns, ?skipFillMissing = skipFillMissing)
dm
member this.StaticHash with get() = staticHash and set(value) = staticHash <- value

member this.DataContexts with get() = dataContexts

member this.Table = table
static member init() = DataMap(ResizeArray())

member this.TryGetCellAt (row: int, column: int) = table.TryGetCellAt(row, column)

member this.GetExplicationColumn() =
table.GetColumnByHeader(DataMapAux.explicationHeader)
member this.GetExplicationColumn() =
DataMapAux.getOntologyColumn (fun dc -> dc.Explication) dataContexts

member this.AddExplicationColumn(cells : CompositeCell []) =
table.AddColumn(DataMapAux.explicationHeader, cells)
member this.SetExplicationColumn(cells : CompositeCell []) =
DataMapAux.setOntologyColumn (fun dc oa -> dc.Explication <- oa) cells dataContexts

member this.GetUnitColumn() =
table.GetColumnByHeader(DataMapAux.unitHeader)
DataMapAux.getOntologyColumn (fun dc -> dc.Unit) dataContexts

member this.AddUnitColumn(cells : CompositeCell []) =
table.AddColumn(DataMapAux.unitHeader, cells)
member this.SetUnitColumn(cells : CompositeCell []) =
DataMapAux.setOntologyColumn (fun dc oa -> dc.Unit <- oa) cells dataContexts

member this.GetDataTypeColumn() =
table.GetColumnByHeader(DataMapAux.objectTypeHeader)
member this.GetObjectTypeColumn() =
DataMapAux.getOntologyColumn (fun dc -> dc.ObjectType) dataContexts

member this.AddDataTypeColumn(cells : CompositeCell []) =
table.AddColumn(DataMapAux.objectTypeHeader, cells)
member this.SetDataTypeColumn(cells : CompositeCell []) =
DataMapAux.setOntologyColumn (fun dc oa -> dc.ObjectType <- oa) cells dataContexts

member this.GetDescriptionColumn() =
table.GetColumnByHeader(DataMapAux.descriptionHeader)

member this.AddDescriptionColumn(cells : CompositeCell []) =
table.AddColumn(DataMapAux.descriptionHeader, cells)
DataMapAux.getStringColumn (fun dc -> dc.Description) dataContexts

member this.SetDescriptionColumn(cells : CompositeCell []) =
DataMapAux.setStringColumn (fun dc s -> dc.Description <- s) cells dataContexts

member this.GetRow(row: int, ?SkipValidation) = table.GetRow(row,?SkipValidation = SkipValidation)
member this.GetDataContext(row: int, ?SkipValidation) =
DataMapAux.SanityChecks.rowIndexInBoundaries row dataContexts
dataContexts.Item(row)

static member getRow(row: int, ?SkipValidation) =
fun (dm : DataMap) -> dm.GetRow(row,?SkipValidation = SkipValidation)
static member getDataContext(row: int, ?SkipValidation) =
fun (dm : DataMap) -> dm.GetDataContext(row,?SkipValidation = SkipValidation)

member this.Copy() =
DataMap(
ResizeArray(this.Headers),
Dictionary(this.Values)
dataContexts
|> Seq.map (fun dc -> dc.Copy())
|> ResizeArray
)

override this.Equals(obj) =
match obj with
| :? DataMap as dm ->
this.Table.Equals(dm.Table)
| _ -> false
HashCodes.hash this = HashCodes.hash obj

override this.GetHashCode() =
this.Table.GetHashCode()
dataContexts
|> HashCodes.boxHashSeq
|> fun x -> x :?> int
9 changes: 0 additions & 9 deletions src/Spreadsheet/AnnotationTable/CompositeCell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,6 @@ open ARCtrl
open ARCtrl.Helper
open FsSpreadsheet

//let fromFsCells (cells : list<FsCell>) : CompositeCell =
// let cellValues = cells |> List.map (fun c -> c.ValueAsString())
// match cellValues with
// | [v] -> CompositeCell.createFreeText v
// | [v1;v2;v3] -> CompositeCell.createTermFromString(v1,v2,v3)
// | [v1;v2;v3;v4] -> CompositeCell.createUnitizedFromString(v1,v2,v3,v4)
// | _ ->
// failwithf "Dafuq"

let termFromFsCells (tsrCol : int option) (tanCol : int option ) (cells : list<FsCell>) : CompositeCell=
let cellValues = cells |> List.map (fun c -> c.ValueAsString())
let tan = Option.map (fun i -> cellValues.[i]) tanCol
Expand Down
Loading

0 comments on commit 2951259

Please sign in to comment.