diff --git a/src/Informedica.GenForm.Lib/DoseRule.fs b/src/Informedica.GenForm.Lib/DoseRule.fs index 9cef65b..e2b83e6 100644 --- a/src/Informedica.GenForm.Lib/DoseRule.fs +++ b/src/Informedica.GenForm.Lib/DoseRule.fs @@ -967,3 +967,20 @@ cannot map {r} |> Array.exists DoseLimit.useAdjust + let getNormDose (dr : DoseRule) = + dr.DoseLimits + |> Array.filter DoseLimit.isSubstanceLimit + |> Array.collect (fun dl -> + [| + if dl.NormPerTimeAdjust |> Option.isSome then + (dl.DoseLimitTarget, dl.NormPerTimeAdjust.Value) + |> NormPerTimeAdjust + |> Some + if dl.NormQuantityAdjust |> Option.isSome then + (dl.DoseLimitTarget, dl.NormQuantityAdjust.Value) + |> NormQuantityAdjust + |> Some + |] + ) + |> Array.choose id + |> Array.tryHead diff --git a/src/Informedica.GenForm.Lib/Types.fs b/src/Informedica.GenForm.Lib/Types.fs index aa25d46..a25c7f1 100644 --- a/src/Informedica.GenForm.Lib/Types.fs +++ b/src/Informedica.GenForm.Lib/Types.fs @@ -346,3 +346,8 @@ module Types = SolutionRules : SolutionRule [] } + + type NormDose = + | NormQuantityAdjust of LimitTarget * ValueUnit + | NormPerTimeAdjust of LimitTarget * ValueUnit + | NormRateAdjust of LimitTarget * ValueUnit diff --git a/src/Informedica.GenOrder.Lib/Api.fs b/src/Informedica.GenOrder.Lib/Api.fs index d2a036a..9a41d05 100644 --- a/src/Informedica.GenOrder.Lib/Api.fs +++ b/src/Informedica.GenOrder.Lib/Api.fs @@ -94,6 +94,9 @@ module Api = let increaseIncrements logger ord = Order.increaseIncrements logger 10N 50N ord + let setNormDose logger normDose ord = Order.solveNormDose logger normDose ord + + /// /// Evaluate a PrescriptionRule. The PrescriptionRule can result in /// multiple Orders, depending on the SolutionRules. @@ -111,6 +114,14 @@ module Api = |> Order.Dto.fromDto |> Order.solveMinMax false logger |> Result.bind (increaseIncrements logger) + |> Result.bind (fun ord -> + match pr.DoseRule |> DoseRule.getNormDose with + | Some nd -> + ord + |> Order.minIncrMaxToValues logger + |> setNormDose logger nd + | None -> Ok ord + ) |> function | Ok ord -> let ord = diff --git a/src/Informedica.GenOrder.Lib/Order.fs b/src/Informedica.GenOrder.Lib/Order.fs index 0bc0c3e..f043ca3 100644 --- a/src/Informedica.GenOrder.Lib/Order.fs +++ b/src/Informedica.GenOrder.Lib/Order.fs @@ -372,15 +372,37 @@ module Order = create qty ptm rte tot qty_adj ptm_adj rte_adj tot_adj + let setNormDose nd (dos: Dose) = + let qty_adj, ptm_adj = + match nd with + | Informedica.GenForm.Lib.Types.NormQuantityAdjust (_, vu) -> + dos.QuantityAdjust |> QuantityAdjust.setNearestValue vu, + dos.PerTimeAdjust + | Informedica.GenForm.Lib.Types.NormPerTimeAdjust (_, vu) -> + dos.QuantityAdjust, + dos.PerTimeAdjust |> PerTimeAdjust.setNearestValue vu + | _ -> dos.QuantityAdjust, dos.PerTimeAdjust + + let qty = dos.Quantity + let ptm = dos.PerTime + let rte = dos.Rate + let tot = dos.Total + let rte_adj = dos.RateAdjust + let tot_adj = dos.TotalAdjust + + create qty ptm rte tot qty_adj ptm_adj rte_adj tot_adj + + + let setDoseUnit du (dos : Dose) = - let qty = dos.Quantity |> Quantity.setDoseUnit du - let ptm = dos.PerTime |> PerTime.setDoseUnit du - let rte = dos.Rate |> Rate.setDoseUnit du - let tot = dos.Total |> Total.setDoseUnit du - let qty_adj = dos.QuantityAdjust |> QuantityAdjust.setDoseUnit du - let ptm_adj = dos.PerTimeAdjust |> PerTimeAdjust.setDoseUnit du - let rte_adj = dos.RateAdjust |> RateAdjust.setDoseUnit du - let tot_adj = dos.TotalAdjust |> TotalAdjust.setDoseUnit du + let qty = dos.Quantity |> Quantity.setFirstUnit du + let ptm = dos.PerTime |> PerTime.setFirstUnit du + let rte = dos.Rate |> Rate.setFirstUnit du + let tot = dos.Total |> Total.setFirstUnit du + let qty_adj = dos.QuantityAdjust |> QuantityAdjust.setFirstUnit du + let ptm_adj = dos.PerTimeAdjust |> PerTimeAdjust.setFirstUnit du + let rte_adj = dos.RateAdjust |> RateAdjust.setFirstUnit du + let tot_adj = dos.TotalAdjust |> TotalAdjust.setFirstUnit du create qty ptm rte tot qty_adj ptm_adj rte_adj tot_adj @@ -723,6 +745,16 @@ module Order = { itm with Dose = itm.Dose |> Dose.setDoseUnit du } + let setNormDose sn nd itm = + if itm + |> getName + |> Name.toStringList + |> List.exists ((=) sn) + |> not then itm + else + { itm with Dose = itm.Dose |> Dose.setNormDose nd } + + /// /// Create a string list from a Item where each string is /// a variable name with the value range and the Unit @@ -1108,6 +1140,12 @@ module Order = } + let setNormDose sn nd cmp = + { cmp with + Items = cmp.Items |> List.map (Item.setNormDose sn nd) + } + + /// /// Create a string list from a Component where each string is /// a variable name with the value range and the Unit @@ -1588,6 +1626,12 @@ module Order = } + let setNormDose sn nd orb = + { orb with + Components = orb.Components |> List.map (Component.setNormDose sn nd) + } + + module Print = @@ -2352,6 +2396,12 @@ module Order = } + let setNormDose sn nd ord = + { ord with + Orderable = ord.Orderable |> Orderable.setNormDose sn nd + } + + /// /// Map an Order to a list of Equations using a Product Equation /// mapping and a Sum Equation mapping @@ -2608,6 +2658,16 @@ module Order = |> Ok + let solveNormDose logger normDose ord = + match normDose with + | Informedica.GenForm.Lib.Types.NormQuantityAdjust (Informedica.GenForm.Lib.Types.SubstanceLimitTarget sn, _) + | Informedica.GenForm.Lib.Types.NormPerTimeAdjust (Informedica.GenForm.Lib.Types.SubstanceLimitTarget sn, _) -> + ord + |> setNormDose sn normDose + |> solveOrder false logger + | _ -> ord |> Ok + + let setDoseUnit sn du ord = { ord with Orderable = ord.Orderable |> Orderable.setDoseUnit sn du } diff --git a/src/Informedica.GenOrder.Lib/OrderVariable.fs b/src/Informedica.GenOrder.Lib/OrderVariable.fs index 1da9be4..573d7d2 100644 --- a/src/Informedica.GenOrder.Lib/OrderVariable.fs +++ b/src/Informedica.GenOrder.Lib/OrderVariable.fs @@ -265,6 +265,15 @@ module OrderVariable = } + let setNormDose vu (ovar: OrderVariable) = + { + ovar with + Variable = + ovar.Variable + |> Variable.setNearestValue vu + } + + /// /// Get the string representation of an OrderVariable. /// @@ -830,7 +839,7 @@ module OrderVariable = |> Quantity - let setDoseUnit u = toOrdVar >> setFirstUnit u >> Quantity + let setFirstUnit u = toOrdVar >> setFirstUnit u >> Quantity /// Turn a `Quantity` to a string @@ -912,7 +921,7 @@ module OrderVariable = |> PerTime - let setDoseUnit u = toOrdVar >> setFirstUnit u >> PerTime + let setFirstUnit u = toOrdVar >> setFirstUnit u >> PerTime /// Turn a `PerTime` to a string @@ -979,7 +988,7 @@ module OrderVariable = - let setDoseUnit u = toOrdVar >> setFirstUnit u >> Rate + let setFirstUnit u = toOrdVar >> setFirstUnit u >> Rate /// Turn a `Rate` to a string @@ -1052,7 +1061,7 @@ module OrderVariable = - let setDoseUnit u = toOrdVar >> setFirstUnit u >> Total + let setFirstUnit u = toOrdVar >> setFirstUnit u >> Total /// Turn a `Total` to a string @@ -1118,7 +1127,10 @@ module OrderVariable = |> QuantityAdjust - let setDoseUnit u = toOrdVar >> setFirstUnit u >> QuantityAdjust + let setFirstUnit u = toOrdVar >> setFirstUnit u >> QuantityAdjust + + + let setNearestValue vu = toOrdVar >> setNormDose vu >> QuantityAdjust /// Turn a `QuantityAdjust` to a string @@ -1197,7 +1209,10 @@ module OrderVariable = - let setDoseUnit u = toOrdVar >> setFirstUnit u >> PerTimeAdjust + let setFirstUnit u = toOrdVar >> setFirstUnit u >> PerTimeAdjust + + + let setNearestValue vu = toOrdVar >> setNormDose vu >> PerTimeAdjust let toString = toOrdVar >> (toString false) @@ -1271,7 +1286,7 @@ module OrderVariable = |> RateAdjust - let setDoseUnit u = toOrdVar >> setFirstUnit u >> RateAdjust + let setFirstUnit u = toOrdVar >> setFirstUnit u >> RateAdjust /// Turn a `RateAdjust` to a string @@ -1340,7 +1355,7 @@ module OrderVariable = |> TotalAdjust - let setDoseUnit u = toOrdVar >> setFirstUnit u >> TotalAdjust + let setFirstUnit u = toOrdVar >> setFirstUnit u >> TotalAdjust /// Turn a `TotalAdjust` to a string diff --git a/src/Informedica.GenOrder.Lib/Scripts/Api2.fsx b/src/Informedica.GenOrder.Lib/Scripts/Api2.fsx index b2c6d88..63fd52f 100644 --- a/src/Informedica.GenOrder.Lib/Scripts/Api2.fsx +++ b/src/Informedica.GenOrder.Lib/Scripts/Api2.fsx @@ -32,6 +32,7 @@ let calcTotal () = |> PrescriptionRule.get |> Array.collect (fun pr -> pr.DoseRule.Products + |> Array.filter (fun p -> p.Generic |> String.contains "/") |> Array.collect (fun p -> pr.DoseRule.Frequencies |> Option.map (ValueUnit.get >> fst) @@ -51,7 +52,12 @@ let calcTotal () = let calcTotal2 () = let dsrs = Informedica.GenForm.Lib.DoseRule.get () - |> Array.filter (fun dr -> dr.Products |> Array.length > 0) + |> Array.filter (fun dr -> + dr.Products |> Array.length > 0 && + dr.DoseType <> NoDoseType + ) +// |> Array.filter (fun p -> p.Generic |> String.contains "/") + let total1 = dsrs |> Array.collect (fun dr -> @@ -63,6 +69,7 @@ let calcTotal2 () = ) ) |> Array.length + dsrs |> Array.map (fun dr -> { dr with @@ -162,6 +169,7 @@ let run n pat = |> File.appendTextToFile path.Value + let getRule i pat = pat |> PrescriptionRule.get @@ -202,18 +210,18 @@ let pat = let pr = - Patient.newBorn + Patient.infant |> fun p -> { p with VenousAccess = [VenousAccess.CVL] Department = Some "ICK" Age = - Units.Time.day - |> ValueUnit.singleWithValue 2N + Units.Time.year + |> ValueUnit.singleWithValue 1N |> Some Weight = Units.Weight.kiloGram - |> ValueUnit.singleWithValue (3N) + |> ValueUnit.singleWithValue (10N) |> Some } //|> Api.scenarioResult |> Api.filter @@ -222,7 +230,7 @@ let pr = |> Array.item 0 //|> Api.evaluate (OrderLogger.logger.Logger) -Patient.teenager +Patient.infant |> fun p -> { p with VenousAccess = [] @@ -232,8 +240,8 @@ Patient.teenager //|> fun p -> { p with VenousAccess = CVL; AgeInDays = Some 0N } |> PrescriptionRule.get |> Array.item 0 //|> Api.evaluate (OrderLogger.logger.Logger) -//|> fun pr -> pr |> DrugOrder.createDrugOrder None //|> printfn "%A" -|> fun pr -> pr |> DrugOrder.createDrugOrder (pr.SolutionRules[0] |> Some) //|> printfn "%A" +|> fun pr -> pr |> DrugOrder.createDrugOrder None //|> printfn "%A" +//|> fun pr -> pr |> DrugOrder.createDrugOrder (pr.SolutionRules[0] |> Some) //|> printfn "%A" |> DrugOrder.toOrderDto |> Order.Dto.fromDto //|> Order.toString |> List.iter (printfn "%s") |> Order.Dto.toDto diff --git a/src/Informedica.GenOrder.Lib/Types.fs b/src/Informedica.GenOrder.Lib/Types.fs index b2054bf..09b4c09 100644 --- a/src/Informedica.GenOrder.Lib/Types.fs +++ b/src/Informedica.GenOrder.Lib/Types.fs @@ -312,6 +312,9 @@ module Types = type DoseType = Informedica.GenForm.Lib.Types.DoseType + type NormDose = Informedica.GenForm.Lib.Types.NormDose + + /// /// The representation of an order with a /// @@ -380,7 +383,6 @@ module Types = } - module Exceptions = type Message = diff --git a/src/Informedica.GenSolver.Lib/Variable.fs b/src/Informedica.GenSolver.Lib/Variable.fs index d760000..7ad01a7 100644 --- a/src/Informedica.GenSolver.Lib/Variable.fs +++ b/src/Informedica.GenSolver.Lib/Variable.fs @@ -1369,6 +1369,7 @@ module Variable = let convertToUnit u = mapValueUnit (ValueUnit.convertTo u) + let getUnit vr = if vr |> checkEqualUnitGroup then vr @@ -1557,6 +1558,7 @@ module Variable = Boolean.returnTrue + /// /// Checks whether a `BigRational` is between an optional /// **min** and an optional **max** @@ -2076,6 +2078,15 @@ module Variable = apply None None Option.none Option.none Option.none Option.none Option.none Option.none Option.none Some + let setNearestValue vu vr = + match vr |> getValSet with + | None -> vr + | Some vs -> + vs + |> ValueSet.map (ValueUnit.setNearestValue vu) + |> ValSet + + /// /// Checks whether a value is in a `ValueRange`. /// @@ -2601,7 +2612,6 @@ module Variable = /// <1N..3N] * <4N..5N> = <4N..15N> module MinMaxCalculator = - open MathNet.Numerics.LinearAlgebra open Utils.ValueUnit.Operators @@ -3385,6 +3395,14 @@ module Variable = } + let setNearestValue vu var = + { var with + Values = + var.Values + |> ValueRange.setNearestValue vu + } + + /// Get the unit of a Variable let getUnit var = var |> getValueRange |> ValueRange.getUnit diff --git a/src/Informedica.GenUnits.Lib/ValueUnit.fs b/src/Informedica.GenUnits.Lib/ValueUnit.fs index e449edd..68b5b5a 100644 --- a/src/Informedica.GenUnits.Lib/ValueUnit.fs +++ b/src/Informedica.GenUnits.Lib/ValueUnit.fs @@ -1927,6 +1927,8 @@ module Units = module ValueUnit = + open System.Net.NetworkInformation + //---------------------------------------------------------------------------- // Operator String functions @@ -3459,6 +3461,22 @@ module ValueUnit = let valueCount = getValue >> Array.length + let setNearestValue vu1 vu2 = + if vu1 |> valueCount <> 1 then vu2 + else + if vu1 >? vu2 || vu1 getBaseValue |> Array.head + let vs2 = vu2 |> getBaseValue + // find the nearest value in vs2 to vu1 + vs2 + |> Array.map (fun v -> (v, v - vu1 |> BigRational.Abs)) + |> Array.minBy snd + |> fun (v, _) -> + setSingleValue v vu2 + |> toUnit + + //---------------------------------------------------------------------------- // ValueUnit string functions //----------------------------------------------------------------------------