Adding render options and params
This commit is contained in:
		
							parent
							
								
									db78bc07f3
								
							
						
					
					
						commit
						e84cfd4c92
					
				|  | @ -15,12 +15,8 @@ let timeDist = | |||
|   ); | ||||
| 
 | ||||
| let setup = dist => | ||||
|   dist | ||||
|   |> DistPlusIngredients.toDistPlus( | ||||
|        ~sampleCount=2000, | ||||
|        ~outputXYPoints=1000, | ||||
|        ~truncateTo=Some(1000), | ||||
|      ) | ||||
|   RenderTypes.DistPlus.make(~distPlusIngredients=dist,()) | ||||
|   |> DistPlusIngredients.toDistPlus | ||||
|   |> E.O.React.fmapOrNull(distPlus => <DistPlusPlot distPlus />); | ||||
| 
 | ||||
| let simpleExample = (name, guesstimatorString) => | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ module KDE = { | |||
|     |> JS.jsToDist; | ||||
|   }; | ||||
| 
 | ||||
|   // Note: This was an experiment, but it didn't actually work that well. | ||||
|   let inGroups = (samples, outputXYPoints, kernelWidth, ~cuttoff=0.9, ()) => { | ||||
|     let partitionAt = | ||||
|       samples | ||||
|  | @ -88,33 +89,94 @@ module T = { | |||
|     (continuous, discrete); | ||||
|   }; | ||||
| 
 | ||||
|   let kde = (~samples, ~outputXYPoints) => { | ||||
|     let width = Bandwidth.nrd0(samples); | ||||
|   let xWidthToUnitWidth = (samples, outputXYPoints, xWidth) => { | ||||
|     let xyPointRange = E.A.Sorted.range(samples) |> E.O.default(0.0); | ||||
|     let xyPointWidth = xyPointRange /. float_of_int(outputXYPoints); | ||||
|     let kernelWidth = int_of_float(Jstat.max([|(width /. xyPointWidth), 1.0 |])); | ||||
|     KDE.normalSampling(samples, outputXYPoints, kernelWidth); | ||||
|     xWidth /. xyPointWidth; | ||||
|   }; | ||||
| 
 | ||||
|   let formatUnitWidth = w => Jstat.max([|w, 1.0|]) |> int_of_float; | ||||
| 
 | ||||
|   let suggestedUnitWidth = (samples, outputXYPoints) => { | ||||
|     let suggestedXWidth = Bandwidth.nrd0(samples); | ||||
|     xWidthToUnitWidth(samples, outputXYPoints, suggestedXWidth); | ||||
|   }; | ||||
| 
 | ||||
|   let kde = (~samples, ~outputXYPoints, width) => { | ||||
|     KDE.normalSampling(samples, outputXYPoints, width); | ||||
|   }; | ||||
| 
 | ||||
|   // todo: Figure out some way of doing this without having to integrate so many times. | ||||
|   let toShape = (~samples: t, ~outputXYPoints=3000, ~kernelWidth=10, ()) => { | ||||
|   let toShape = | ||||
|       (~samples: t, ~samplingInputs: RenderTypes.Sampling.Inputs.fInputs, ()) => { | ||||
|     Array.fast_sort(compare, samples); | ||||
|     let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples); | ||||
|     let length = samples |> E.A.length; | ||||
|     let lengthFloat = float_of_int(length); | ||||
|     let length = samples |> E.A.length |> float_of_int; | ||||
|     let discrete: DistTypes.xyShape = | ||||
|       discretePart | ||||
|       |> E.FloatFloatMap.fmap(r => r /. lengthFloat) | ||||
|       |> E.FloatFloatMap.fmap(r => r /. length) | ||||
|       |> E.FloatFloatMap.toArray | ||||
|       |> XYShape.T.fromZippedArray; | ||||
|     let pdf: DistTypes.xyShape = | ||||
| 
 | ||||
|     let pdf = | ||||
|       continuousPart |> E.A.length > 5 | ||||
|         ? { | ||||
|           continuousPart |> kde(~samples=_, ~outputXYPoints) | ||||
|           let _suggestedXWidth = Bandwidth.nrd0(continuousPart); | ||||
|           let _suggestedUnitWidth = | ||||
|             suggestedUnitWidth(continuousPart, samplingInputs.outputXYPoints); | ||||
|           let usedWidth = | ||||
|             samplingInputs.kernelWidth |> E.O.default(_suggestedXWidth); | ||||
|           let usedUnitWidth = | ||||
|             xWidthToUnitWidth( | ||||
|               samples, | ||||
|               samplingInputs.outputXYPoints, | ||||
|               usedWidth, | ||||
|             ); | ||||
|           let foo: RenderTypes.Sampling.samplingStats = { | ||||
|             sampleCount: samplingInputs.sampleCount, | ||||
|             outputXYPoints: samplingInputs.outputXYPoints, | ||||
|             bandwidthXSuggested: _suggestedXWidth, | ||||
|             bandwidthUnitSuggested: _suggestedUnitWidth, | ||||
|             bandwidthXImplemented: usedWidth, | ||||
|             bandwidthUnitImplemented: usedUnitWidth, | ||||
|           }; | ||||
|           continuousPart | ||||
|           |> kde( | ||||
|                ~samples=_, | ||||
|                ~outputXYPoints=samplingInputs.outputXYPoints, | ||||
|                formatUnitWidth(usedUnitWidth), | ||||
|              ) | ||||
|           |> Distributions.Continuous.make(`Linear) | ||||
|           |> (r => Some((r, foo))); | ||||
|         } | ||||
|         : {xs: [||], ys: [||]}; | ||||
|     let continuous = pdf |> Distributions.Continuous.make(`Linear); | ||||
|     let shape = MixedShapeBuilder.buildSimple(~continuous, ~discrete); | ||||
|     shape; | ||||
|         : None; | ||||
|     let shape = | ||||
|       MixedShapeBuilder.buildSimple( | ||||
|         ~continuous=pdf |> E.O.fmap(fst), | ||||
|         ~discrete, | ||||
|       ); | ||||
|     let samplesParse: RenderTypes.Sampling.outputs = { | ||||
|       continuousParseParams: pdf |> E.O.fmap(snd), | ||||
|       shape, | ||||
|     }; | ||||
|     samplesParse; | ||||
|   }; | ||||
| 
 | ||||
|   let fromGuesstimatorString = | ||||
|       ( | ||||
|         ~guesstimatorString, | ||||
|         ~samplingInputs=RenderTypes.Sampling.Inputs.empty, | ||||
|         (), | ||||
|       ) => { | ||||
|     let hasValidSamples = | ||||
|       Guesstimator.stringToSamples(guesstimatorString, 10) |> E.A.length > 0; | ||||
|     let samplingInputs = RenderTypes.Sampling.Inputs.toF(samplingInputs); | ||||
|     switch (hasValidSamples) { | ||||
|     | false => None | ||||
|     | true => | ||||
|       let samples = | ||||
|         Guesstimator.stringToSamples(guesstimatorString, samplingInputs.sampleCount); | ||||
|       Some(toShape(~samples, ~samplingInputs, ())); | ||||
|     }; | ||||
|   }; | ||||
| }; | ||||
|  | @ -26,7 +26,7 @@ type options = { | |||
|   sampleCount: int, | ||||
|   outputXYPoints: int, | ||||
|   truncateTo: option(int), | ||||
|   kernelWidth: int, | ||||
|   kernelWidth: option(float), | ||||
| }; | ||||
| 
 | ||||
| module Form = ReForm.Make(FormConfig); | ||||
|  | @ -111,6 +111,13 @@ module Styles = { | |||
|     ]); | ||||
| }; | ||||
| 
 | ||||
| type inputs = { | ||||
|   samplingInputs: RenderTypes.Sampling.inputs, | ||||
|   guesstimatorString: string, | ||||
|   length: int, | ||||
|   shouldTruncateSampledDistribution: int, | ||||
| }; | ||||
| 
 | ||||
| module DemoDist = { | ||||
|   [@react.component] | ||||
|   let make = (~guesstimatorString, ~domain, ~unit, ~options) => { | ||||
|  | @ -119,14 +126,24 @@ module DemoDist = { | |||
|       <div> | ||||
|         {switch (domain, unit, options) { | ||||
|          | (Some(domain), Some(unit), Some(options)) => | ||||
|            let distPlus = | ||||
|              DistPlusIngredients.make(~guesstimatorString, ~domain, ~unit, ()) | ||||
|              |> DistPlusIngredients.toDistPlus( | ||||
|                   ~sampleCount=options.sampleCount, | ||||
|                   ~outputXYPoints=options.outputXYPoints, | ||||
|                   ~truncateTo=options.truncateTo, | ||||
|                   ~kernelWidth=options.kernelWidth, | ||||
|            let distPlusIngredients = | ||||
|              DistPlusIngredients.make( | ||||
|                ~guesstimatorString, | ||||
|                ~domain, | ||||
|                ~unit, | ||||
|                (), | ||||
|              ); | ||||
|            let inputs = | ||||
|              RenderTypes.DistPlus.make( | ||||
|                ~samplingInputs={ | ||||
|                  sampleCount: Some(options.sampleCount), | ||||
|                  outputXYPoints: Some(options.outputXYPoints), | ||||
|                  kernelWidth: options.kernelWidth, | ||||
|                }, | ||||
|                ~distPlusIngredients, | ||||
|                (), | ||||
|              ); | ||||
|            let distPlus = DistPlusIngredients.toDistPlus(inputs); | ||||
|            switch (distPlus) { | ||||
|            | Some(distPlus) => <DistPlusPlot distPlus /> | ||||
|            | _ => | ||||
|  | @ -160,9 +177,9 @@ let make = () => { | |||
|         unitType: "UnspecifiedDistribution", | ||||
|         zero: MomentRe.momentNow(), | ||||
|         unit: "days", | ||||
|         sampleCount: "10000", | ||||
|         outputXYPoints: "500", | ||||
|         truncateTo: "100", | ||||
|         sampleCount: "30000", | ||||
|         outputXYPoints: "10000", | ||||
|         truncateTo: "1000", | ||||
|         kernelWidth: "5", | ||||
|       }, | ||||
|       (), | ||||
|  | @ -246,7 +263,7 @@ let make = () => { | |||
|         truncateTo: | ||||
|           int_of_float(truncateTo) > 0 | ||||
|             ? Some(int_of_float(truncateTo)) : None, | ||||
|         kernelWidth: kernelWidth |> int_of_float, | ||||
|         kernelWidth: kernelWidth == 0.0 ? None : Some(kernelWidth), | ||||
|       }) | ||||
|     | _ => None | ||||
|     }; | ||||
|  |  | |||
|  | @ -15,41 +15,34 @@ let applyTruncation = (truncateTo, distPlus) => | |||
|   | _ => None | ||||
|   }; | ||||
| 
 | ||||
|       // ~samplingInputs=RenderTypes.Sampling.Inputs.empty, | ||||
|       // ~truncateTo: option(int), | ||||
|       // t: distPlusIngredients, | ||||
| //Make truncation optional | ||||
| let toDistPlus = | ||||
|     ( | ||||
|       ~sampleCount=2000, | ||||
|       ~outputXYPoints=1500, | ||||
|       ~truncateTo=Some(300), | ||||
|       ~kernelWidth=5, | ||||
|       t: distPlusIngredients, | ||||
|       inputs:RenderTypes.DistPlus.inputs | ||||
|     ) | ||||
|     : option(distPlus) => { | ||||
|   let toDist = shape => | ||||
|     Distributions.DistPlus.make( | ||||
|       ~shape, | ||||
|       ~domain=t.domain, | ||||
|       ~unit=t.unit, | ||||
|       ~guesstimatorString=Some(t.guesstimatorString), | ||||
|       ~domain=inputs.distPlusIngredients.domain, | ||||
|       ~unit=inputs.distPlusIngredients.unit, | ||||
|       ~guesstimatorString=Some(inputs.distPlusIngredients.guesstimatorString), | ||||
|       (), | ||||
|     ) | ||||
|     |> Distributions.DistPlus.T.scaleToIntegralSum(~intendedSum=1.0); | ||||
|   let parsed1 = MathJsParser.fromString(t.guesstimatorString); | ||||
|   let shape = | ||||
|     switch (parsed1) { | ||||
|     | Ok(r) => | ||||
|       let shape = SymbolicDist.toShape(truncateTo |> E.O.default(10000), r); | ||||
|       Some(shape |> toDist); | ||||
|     | _ => | ||||
|       let fewSamples = Guesstimator.stringToSamples(t.guesstimatorString, 10); | ||||
|       if (fewSamples |> E.A.length > 0) { | ||||
|         let samples = | ||||
|           Guesstimator.stringToSamples(t.guesstimatorString, sampleCount); | ||||
|         let shape = | ||||
|           Samples.T.toShape(~samples, ~outputXYPoints, ~kernelWidth, ()); | ||||
|         shape |> E.O.fmap(toDist) |> applyTruncation(truncateTo); | ||||
|       } else { | ||||
|         None; | ||||
|       }; | ||||
|     }; | ||||
|     shape; | ||||
|     GuesstimatorToShape.run( | ||||
|       ~renderingInputs={ | ||||
|         guesstimatorString: inputs.distPlusIngredients.guesstimatorString, | ||||
|         shapeLength: inputs.recommendedLength, | ||||
|       }, | ||||
|       ~samplingInputs=inputs.samplingInputs, | ||||
|     ) | ||||
|     |> GuesstimatorToShape.getShape; | ||||
|   //TODO: Apply truncation | ||||
|   let foo = shape |> E.O.fmap(toDist); | ||||
|   foo; | ||||
| }; | ||||
							
								
								
									
										32
									
								
								src/distribution/GuesstimatorToShape.re
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/distribution/GuesstimatorToShape.re
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| let runSymbolic = | ||||
|     (renderingInputs: RenderTypes.primaryInputs) =>{ | ||||
|       let graph = MathJsParser.fromString(renderingInputs.guesstimatorString); | ||||
|       graph |> E.R.fmap(g => RenderTypes.Symbolic.make(g, SymbolicDist.toShape(renderingInputs.shapeLength,g))) | ||||
|     } | ||||
|    | ||||
| let getShape = (r: RenderTypes.Combined.outputs) => | ||||
|   switch (r.symbolic, r.sampling) { | ||||
|   | (Some(Ok({shape})), _) => Some(shape) | ||||
|   | (_, Some({shape})) => shape | ||||
|   | _ => None | ||||
|   }; | ||||
| 
 | ||||
| let run = | ||||
|     ( | ||||
|       ~renderingInputs: RenderTypes.primaryInputs, | ||||
|       ~samplingInputs: RenderTypes.Sampling.inputs, | ||||
|     ) | ||||
|     : RenderTypes.Combined.outputs => { | ||||
|   let symbolic = runSymbolic(renderingInputs); | ||||
|   let sampling = | ||||
|     switch (symbolic) { | ||||
|     | Ok(r) => None | ||||
|     | Error(r) => | ||||
|       Samples.T.fromGuesstimatorString( | ||||
|         ~guesstimatorString=renderingInputs.guesstimatorString, | ||||
|         ~samplingInputs, | ||||
|         (), | ||||
|       ) | ||||
|     }; | ||||
|   {symbolic: Some(symbolic), sampling}; | ||||
| }; | ||||
|  | @ -8,7 +8,8 @@ type assumptions = { | |||
|   discreteProbabilityMass: option(float), | ||||
| }; | ||||
| 
 | ||||
| let buildSimple = (~continuous, ~discrete): option(DistTypes.shape) => { | ||||
| let buildSimple = (~continuous: option(DistTypes.continuousShape), ~discrete): option(DistTypes.shape) => { | ||||
|   let continuous = continuous |> E.O.default(Distributions.Continuous.make(`Linear, {xs: [||], ys: [||]})) | ||||
|   let cLength = | ||||
|     continuous | ||||
|     |> Distributions.Continuous.getShape | ||||
|  |  | |||
							
								
								
									
										86
									
								
								src/distribution/RenderTypes.re
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/distribution/RenderTypes.re
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | |||
| type primaryInputs = { | ||||
|   guesstimatorString: string, | ||||
|   shapeLength: int, | ||||
| }; | ||||
| 
 | ||||
| module Sampling = { | ||||
|   type inputs = { | ||||
|     sampleCount: option(int), | ||||
|     outputXYPoints: option(int), | ||||
|     kernelWidth: option(float), | ||||
|   }; | ||||
|   type samplingStats = { | ||||
|     sampleCount: int, | ||||
|     outputXYPoints: int, | ||||
|     bandwidthXSuggested: float, | ||||
|     bandwidthUnitSuggested: float, | ||||
|     bandwidthXImplemented: float, | ||||
|     bandwidthUnitImplemented: float, | ||||
|   }; | ||||
|   type outputs = { | ||||
|     continuousParseParams: option(samplingStats), | ||||
|     shape: option(ProbExample.DistTypes.shape), | ||||
|   }; | ||||
|   module Inputs = { | ||||
|     let defaultSampleCount = 5000; | ||||
|     let defaultOutputXYPoints = 10000; | ||||
|     let empty = {sampleCount: None, outputXYPoints: None, kernelWidth: None}; | ||||
| 
 | ||||
|     type fInputs = { | ||||
|       sampleCount: int, | ||||
|       outputXYPoints: int, | ||||
|       kernelWidth: option(float), | ||||
|     }; | ||||
|     let toF = (i: inputs): fInputs => { | ||||
|       sampleCount: i.sampleCount |> E.O.default(defaultSampleCount), | ||||
|       outputXYPoints: i.outputXYPoints |> E.O.default(defaultOutputXYPoints), | ||||
|       kernelWidth: i.kernelWidth, | ||||
|     }; | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| module Symbolic = { | ||||
|   type inputs = {length: int}; | ||||
|   type outputs = { | ||||
|     graph: ProbExample.SymbolicDist.bigDist, | ||||
|     shape: ProbExample.DistTypes.shape, | ||||
|   }; | ||||
|   let make = (graph, shape) => {graph, shape}; | ||||
| }; | ||||
| 
 | ||||
| module Combined = { | ||||
|   type inputs = { | ||||
|     samplingInputs: Sampling.inputs, | ||||
|     symbolicInputs: Symbolic.inputs, | ||||
|     guesstimatorString: string, | ||||
|   }; | ||||
|   type outputs = { | ||||
|     symbolic: option(Belt.Result.t(Symbolic.outputs, string)), | ||||
|     sampling: option(Sampling.outputs), | ||||
|   }; | ||||
| }; | ||||
| 
 | ||||
| module DistPlus = { | ||||
|   let defaultRecommendedLength = 10000; | ||||
|   let defaultShouldTruncate = true; | ||||
|   type inputs = { | ||||
|     distPlusIngredients: DistTypes.distPlusIngredients, | ||||
|     samplingInputs: Sampling.inputs, | ||||
|     recommendedLength: int, | ||||
|     shouldTruncate: bool, | ||||
|   }; | ||||
|   let make = | ||||
|       ( | ||||
|         ~samplingInputs=Sampling.Inputs.empty, | ||||
|         ~recommendedLength=defaultRecommendedLength, | ||||
|         ~shouldTruncate=defaultShouldTruncate, | ||||
|         ~distPlusIngredients, | ||||
|         () | ||||
|       ) | ||||
|       : inputs => { | ||||
|     distPlusIngredients, | ||||
|     samplingInputs, | ||||
|     recommendedLength, | ||||
|     shouldTruncate, | ||||
|   }; | ||||
| }; | ||||
|  | @ -19,12 +19,8 @@ let propValue = (t: Prop.Value.t) => { | |||
|   | ConditionalArray(r) => "Array" |> ReasonReact.string | ||||
|   | DistPlusIngredients((r: DistTypes.distPlusIngredients)) => | ||||
|     let newDistribution = | ||||
|       DistPlusIngredients.toDistPlus( | ||||
|         ~sampleCount=1000, | ||||
|         ~outputXYPoints=2000, | ||||
|         ~truncateTo=Some(500), | ||||
|         r, | ||||
|       ); | ||||
|     RenderTypes.DistPlus.make(~distPlusIngredients=r, ~recommendedLength=1000, ~shouldTruncate=true,()) | ||||
|     |> DistPlusIngredients.toDistPlus | ||||
|     switch (newDistribution) { | ||||
|     | Some(distribution) => | ||||
|       <div> <DistPlusPlot distPlus=distribution /> </div> | ||||
|  |  | |||
|  | @ -110,6 +110,7 @@ module Model = { | |||
|   // TODO: Fixe number that integral is calculated for | ||||
|   let getGlobalCatastropheChance = dateTime => { | ||||
|     GlobalCatastrophe.makeI(MomentRe.momentNow()) | ||||
|     |> RenderTypes.DistPlus.make(~distPlusIngredients=_, ()) | ||||
|     |> DistPlusIngredients.toDistPlus | ||||
|     |> E.O.bind(_, Distributions.DistPlusTime.Integral.xToY(Time(dateTime))); | ||||
|   }; | ||||
|  |  | |||
|  | @ -245,6 +245,5 @@ let fromString = str => { | |||
|       } | ||||
|     ); | ||||
|   let value = E.R.bind(mathJsParse, MathAdtToDistDst.run); | ||||
|   Js.log4("fromString", mathJsToJson, mathJsParse, value); | ||||
|   value; | ||||
| }; | ||||
|  | @ -296,7 +296,7 @@ module PointwiseAddDistributionsWeighted = { | |||
|     let normalized = normalizeWeights(dists); | ||||
|     let continuous = normalized |> E.A.filter(((r,_)) => GenericSimple.contType(r) == `Continuous) |> continuousShape(_, sampleCount); | ||||
|     let discrete = normalized |> E.A.filter(((r,_)) => GenericSimple.contType(r) == `Discrete) |> discreteShape(_, sampleCount); | ||||
|     let shape = MixedShapeBuilder.buildSimple(~continuous, ~discrete); | ||||
|     let shape = MixedShapeBuilder.buildSimple(~continuous=Some(continuous), ~discrete); | ||||
|     shape |> E.O.toExt("") | ||||
|   }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user