Changed Samples to SamplesToShape
This commit is contained in:
parent
9b7f2f246d
commit
79d91bc69a
|
@ -14,12 +14,12 @@ describe("Lodash", () => {
|
||||||
describe("Lodash", () => {
|
describe("Lodash", () => {
|
||||||
makeTest(
|
makeTest(
|
||||||
"split",
|
"split",
|
||||||
Samples.T.splitContinuousAndDiscrete([|1.432, 1.33455, 2.0|]),
|
SamplesToShape.Internals.T.splitContinuousAndDiscrete([|1.432, 1.33455, 2.0|]),
|
||||||
([|1.432, 1.33455, 2.0|], E.FloatFloatMap.empty()),
|
([|1.432, 1.33455, 2.0|], E.FloatFloatMap.empty()),
|
||||||
);
|
);
|
||||||
makeTest(
|
makeTest(
|
||||||
"split",
|
"split",
|
||||||
Samples.T.splitContinuousAndDiscrete([|
|
SamplesToShape.Internals.T.splitContinuousAndDiscrete([|
|
||||||
1.432,
|
1.432,
|
||||||
1.33455,
|
1.33455,
|
||||||
2.0,
|
2.0,
|
||||||
|
@ -39,12 +39,12 @@ describe("Lodash", () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_, discrete) =
|
let (_, discrete) =
|
||||||
Samples.T.splitContinuousAndDiscrete(makeDuplicatedArray(10));
|
SamplesToShape.Internals.T.splitContinuousAndDiscrete(makeDuplicatedArray(10));
|
||||||
let toArr = discrete |> E.FloatFloatMap.toArray;
|
let toArr = discrete |> E.FloatFloatMap.toArray;
|
||||||
makeTest("splitMedium", toArr |> Belt.Array.length, 10);
|
makeTest("splitMedium", toArr |> Belt.Array.length, 10);
|
||||||
|
|
||||||
let (c, discrete) =
|
let (c, discrete) =
|
||||||
Samples.T.splitContinuousAndDiscrete(makeDuplicatedArray(500));
|
SamplesToShape.Internals.T.splitContinuousAndDiscrete(makeDuplicatedArray(500));
|
||||||
let toArr = discrete |> E.FloatFloatMap.toArray;
|
let toArr = discrete |> E.FloatFloatMap.toArray;
|
||||||
makeTest("splitMedium", toArr |> Belt.Array.length, 500);
|
makeTest("splitMedium", toArr |> Belt.Array.length, 500);
|
||||||
})
|
})
|
||||||
|
|
|
@ -60,7 +60,7 @@ let combineShapesUsingSampling =
|
||||||
let shape =
|
let shape =
|
||||||
samples
|
samples
|
||||||
|> E.O.fmap(
|
|> E.O.fmap(
|
||||||
Samples.T.fromSamples(
|
SamplesToShape.fromSamples(
|
||||||
~samplingInputs=evaluationParams.samplingInputs,
|
~samplingInputs=evaluationParams.samplingInputs,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
0
src/distPlus/renderers/ProgramRunner.re
Normal file
0
src/distPlus/renderers/ProgramRunner.re
Normal file
|
@ -1,154 +0,0 @@
|
||||||
module Types = {
|
|
||||||
type samplingStats = {
|
|
||||||
sampleCount: int,
|
|
||||||
outputXYPoints: int,
|
|
||||||
bandwidthXSuggested: float,
|
|
||||||
bandwidthUnitSuggested: float,
|
|
||||||
bandwidthXImplemented: float,
|
|
||||||
bandwidthUnitImplemented: float,
|
|
||||||
};
|
|
||||||
|
|
||||||
type outputs = {
|
|
||||||
continuousParseParams: option(samplingStats),
|
|
||||||
shape: option(DistTypes.shape),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module JS = {
|
|
||||||
[@bs.deriving abstract]
|
|
||||||
type distJs = {
|
|
||||||
xs: array(float),
|
|
||||||
ys: array(float),
|
|
||||||
};
|
|
||||||
|
|
||||||
let jsToDist = (d: distJs): DistTypes.xyShape => {
|
|
||||||
xs: xsGet(d),
|
|
||||||
ys: ysGet(d),
|
|
||||||
};
|
|
||||||
|
|
||||||
[@bs.module "./KdeLibrary.js"]
|
|
||||||
external samplesToContinuousPdf: (array(float), int, int) => distJs =
|
|
||||||
"samplesToContinuousPdf";
|
|
||||||
};
|
|
||||||
|
|
||||||
module KDE = {
|
|
||||||
let normalSampling = (samples, outputXYPoints, kernelWidth) => {
|
|
||||||
samples
|
|
||||||
|> JS.samplesToContinuousPdf(_, outputXYPoints, kernelWidth)
|
|
||||||
|> JS.jsToDist;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module T = {
|
|
||||||
type t = array(float);
|
|
||||||
|
|
||||||
let splitContinuousAndDiscrete = (sortedArray: t) => {
|
|
||||||
let continuous = [||];
|
|
||||||
let discrete = E.FloatFloatMap.empty();
|
|
||||||
Belt.Array.forEachWithIndex(
|
|
||||||
sortedArray,
|
|
||||||
(index, element) => {
|
|
||||||
let maxIndex = (sortedArray |> Array.length) - 1;
|
|
||||||
let possiblySimilarElements =
|
|
||||||
(
|
|
||||||
switch (index) {
|
|
||||||
| 0 => [|index + 1|]
|
|
||||||
| n when n == maxIndex => [|index - 1|]
|
|
||||||
| _ => [|index - 1, index + 1|]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|> Belt.Array.map(_, r => sortedArray[r]);
|
|
||||||
let hasSimilarElement =
|
|
||||||
Belt.Array.some(possiblySimilarElements, r => r == element);
|
|
||||||
hasSimilarElement
|
|
||||||
? E.FloatFloatMap.increment(element, discrete)
|
|
||||||
: {
|
|
||||||
let _ = Js.Array.push(element, continuous);
|
|
||||||
();
|
|
||||||
};
|
|
||||||
();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
(continuous, discrete);
|
|
||||||
};
|
|
||||||
|
|
||||||
let xWidthToUnitWidth = (samples, outputXYPoints, xWidth) => {
|
|
||||||
let xyPointRange = E.A.Sorted.range(samples) |> E.O.default(0.0);
|
|
||||||
let xyPointWidth = xyPointRange /. float_of_int(outputXYPoints);
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
let toShape = (~samples: t, ~samplingInputs: ExpressionTypes.ExpressionTree.samplingInputs, ()) => {
|
|
||||||
Array.fast_sort(compare, samples);
|
|
||||||
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples);
|
|
||||||
let length = samples |> E.A.length |> float_of_int;
|
|
||||||
let discrete: DistTypes.discreteShape =
|
|
||||||
discretePart
|
|
||||||
|> E.FloatFloatMap.fmap(r => r /. length)
|
|
||||||
|> E.FloatFloatMap.toArray
|
|
||||||
|> XYShape.T.fromZippedArray
|
|
||||||
|> Discrete.make;
|
|
||||||
|
|
||||||
let pdf =
|
|
||||||
continuousPart |> E.A.length > 5
|
|
||||||
? {
|
|
||||||
let _suggestedXWidth = Bandwidth.nrd0(continuousPart);
|
|
||||||
// todo: This does some recalculating from the last step.
|
|
||||||
let _suggestedUnitWidth =
|
|
||||||
suggestedUnitWidth(continuousPart, samplingInputs.outputXYPoints);
|
|
||||||
let usedWidth =
|
|
||||||
samplingInputs.kernelWidth |> E.O.default(_suggestedXWidth);
|
|
||||||
let usedUnitWidth =
|
|
||||||
xWidthToUnitWidth(
|
|
||||||
samples,
|
|
||||||
samplingInputs.outputXYPoints,
|
|
||||||
usedWidth,
|
|
||||||
);
|
|
||||||
let samplingStats: Types.samplingStats = {
|
|
||||||
sampleCount: samplingInputs.sampleCount,
|
|
||||||
outputXYPoints: samplingInputs.outputXYPoints,
|
|
||||||
bandwidthXSuggested: _suggestedXWidth,
|
|
||||||
bandwidthUnitSuggested: _suggestedUnitWidth,
|
|
||||||
bandwidthXImplemented: usedWidth,
|
|
||||||
bandwidthUnitImplemented: usedUnitWidth,
|
|
||||||
};
|
|
||||||
continuousPart
|
|
||||||
|> kde(
|
|
||||||
~samples=_,
|
|
||||||
~outputXYPoints=samplingInputs.outputXYPoints,
|
|
||||||
formatUnitWidth(usedUnitWidth),
|
|
||||||
)
|
|
||||||
|> Continuous.make
|
|
||||||
|> (r => Some((r, samplingStats)));
|
|
||||||
}
|
|
||||||
: None;
|
|
||||||
|
|
||||||
let shape =
|
|
||||||
MixedShapeBuilder.buildSimple(
|
|
||||||
~continuous=pdf |> E.O.fmap(fst),
|
|
||||||
~discrete=Some(discrete),
|
|
||||||
);
|
|
||||||
|
|
||||||
let samplesParse: Types.outputs = {
|
|
||||||
continuousParseParams: pdf |> E.O.fmap(snd),
|
|
||||||
shape,
|
|
||||||
};
|
|
||||||
|
|
||||||
samplesParse;
|
|
||||||
};
|
|
||||||
|
|
||||||
let fromSamples = (~samplingInputs, samples) => {
|
|
||||||
toShape(~samples, ~samplingInputs, ());
|
|
||||||
};
|
|
||||||
};
|
|
164
src/distPlus/renderers/samplesRenderer/SamplesToShape.re
Normal file
164
src/distPlus/renderers/samplesRenderer/SamplesToShape.re
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
module Internals = {
|
||||||
|
module Types = {
|
||||||
|
type samplingStats = {
|
||||||
|
sampleCount: int,
|
||||||
|
outputXYPoints: int,
|
||||||
|
bandwidthXSuggested: float,
|
||||||
|
bandwidthUnitSuggested: float,
|
||||||
|
bandwidthXImplemented: float,
|
||||||
|
bandwidthUnitImplemented: float,
|
||||||
|
};
|
||||||
|
|
||||||
|
type outputs = {
|
||||||
|
continuousParseParams: option(samplingStats),
|
||||||
|
shape: option(DistTypes.shape),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module JS = {
|
||||||
|
[@bs.deriving abstract]
|
||||||
|
type distJs = {
|
||||||
|
xs: array(float),
|
||||||
|
ys: array(float),
|
||||||
|
};
|
||||||
|
|
||||||
|
let jsToDist = (d: distJs): DistTypes.xyShape => {
|
||||||
|
xs: xsGet(d),
|
||||||
|
ys: ysGet(d),
|
||||||
|
};
|
||||||
|
|
||||||
|
[@bs.module "./KdeLibrary.js"]
|
||||||
|
external samplesToContinuousPdf: (array(float), int, int) => distJs =
|
||||||
|
"samplesToContinuousPdf";
|
||||||
|
};
|
||||||
|
|
||||||
|
module KDE = {
|
||||||
|
let normalSampling = (samples, outputXYPoints, kernelWidth) => {
|
||||||
|
samples
|
||||||
|
|> JS.samplesToContinuousPdf(_, outputXYPoints, kernelWidth)
|
||||||
|
|> JS.jsToDist;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
module T = {
|
||||||
|
type t = array(float);
|
||||||
|
|
||||||
|
let splitContinuousAndDiscrete = (sortedArray: t) => {
|
||||||
|
let continuous = [||];
|
||||||
|
let discrete = E.FloatFloatMap.empty();
|
||||||
|
Belt.Array.forEachWithIndex(
|
||||||
|
sortedArray,
|
||||||
|
(index, element) => {
|
||||||
|
let maxIndex = (sortedArray |> Array.length) - 1;
|
||||||
|
let possiblySimilarElements =
|
||||||
|
(
|
||||||
|
switch (index) {
|
||||||
|
| 0 => [|index + 1|]
|
||||||
|
| n when n == maxIndex => [|index - 1|]
|
||||||
|
| _ => [|index - 1, index + 1|]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> Belt.Array.map(_, r => sortedArray[r]);
|
||||||
|
let hasSimilarElement =
|
||||||
|
Belt.Array.some(possiblySimilarElements, r => r == element);
|
||||||
|
hasSimilarElement
|
||||||
|
? E.FloatFloatMap.increment(element, discrete)
|
||||||
|
: {
|
||||||
|
let _ = Js.Array.push(element, continuous);
|
||||||
|
();
|
||||||
|
};
|
||||||
|
();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
(continuous, discrete);
|
||||||
|
};
|
||||||
|
|
||||||
|
let xWidthToUnitWidth = (samples, outputXYPoints, xWidth) => {
|
||||||
|
let xyPointRange = E.A.Sorted.range(samples) |> E.O.default(0.0);
|
||||||
|
let xyPointWidth = xyPointRange /. float_of_int(outputXYPoints);
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let toShape =
|
||||||
|
(
|
||||||
|
~samples: Internals.T.t,
|
||||||
|
~samplingInputs: ExpressionTypes.ExpressionTree.samplingInputs,
|
||||||
|
(),
|
||||||
|
) => {
|
||||||
|
Array.fast_sort(compare, samples);
|
||||||
|
let (continuousPart, discretePart) = E.A.Sorted.Floats.split(samples);
|
||||||
|
let length = samples |> E.A.length |> float_of_int;
|
||||||
|
let discrete: DistTypes.discreteShape =
|
||||||
|
discretePart
|
||||||
|
|> E.FloatFloatMap.fmap(r => r /. length)
|
||||||
|
|> E.FloatFloatMap.toArray
|
||||||
|
|> XYShape.T.fromZippedArray
|
||||||
|
|> Discrete.make;
|
||||||
|
|
||||||
|
let pdf =
|
||||||
|
continuousPart |> E.A.length > 5
|
||||||
|
? {
|
||||||
|
let _suggestedXWidth = Bandwidth.nrd0(continuousPart);
|
||||||
|
// todo: This does some recalculating from the last step.
|
||||||
|
let _suggestedUnitWidth =
|
||||||
|
Internals.T.suggestedUnitWidth(
|
||||||
|
continuousPart,
|
||||||
|
samplingInputs.outputXYPoints,
|
||||||
|
);
|
||||||
|
let usedWidth =
|
||||||
|
samplingInputs.kernelWidth |> E.O.default(_suggestedXWidth);
|
||||||
|
let usedUnitWidth =
|
||||||
|
Internals.T.xWidthToUnitWidth(
|
||||||
|
samples,
|
||||||
|
samplingInputs.outputXYPoints,
|
||||||
|
usedWidth,
|
||||||
|
);
|
||||||
|
let samplingStats: Internals.Types.samplingStats = {
|
||||||
|
sampleCount: samplingInputs.sampleCount,
|
||||||
|
outputXYPoints: samplingInputs.outputXYPoints,
|
||||||
|
bandwidthXSuggested: _suggestedXWidth,
|
||||||
|
bandwidthUnitSuggested: _suggestedUnitWidth,
|
||||||
|
bandwidthXImplemented: usedWidth,
|
||||||
|
bandwidthUnitImplemented: usedUnitWidth,
|
||||||
|
};
|
||||||
|
continuousPart
|
||||||
|
|> Internals.T.kde(
|
||||||
|
~samples=_,
|
||||||
|
~outputXYPoints=samplingInputs.outputXYPoints,
|
||||||
|
Internals.T.formatUnitWidth(usedUnitWidth),
|
||||||
|
)
|
||||||
|
|> Continuous.make
|
||||||
|
|> (r => Some((r, samplingStats)));
|
||||||
|
}
|
||||||
|
: None;
|
||||||
|
|
||||||
|
let shape =
|
||||||
|
MixedShapeBuilder.buildSimple(
|
||||||
|
~continuous=pdf |> E.O.fmap(fst),
|
||||||
|
~discrete=Some(discrete),
|
||||||
|
);
|
||||||
|
|
||||||
|
let samplesParse: Internals.Types.outputs = {
|
||||||
|
continuousParseParams: pdf |> E.O.fmap(snd),
|
||||||
|
shape,
|
||||||
|
};
|
||||||
|
|
||||||
|
samplesParse;
|
||||||
|
};
|
||||||
|
|
||||||
|
let fromSamples = (~samplingInputs, samples) => {
|
||||||
|
toShape(~samples, ~samplingInputs, ());
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user