diff --git a/packages/components/src/components/DistPlusChart.tsx b/packages/components/src/components/DistPlusChart.tsx
deleted file mode 100644
index 02f2fabd..00000000
--- a/packages/components/src/components/DistPlusChart.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import * as React from "react";
-import _ from "lodash";
-import type { Spec } from "vega";
-import type {
- DistPlus,
-} from "@quri/squiggle-lang";
-import { createClassFromSpec } from "react-vega";
-import * as chartSpecification from "../vega-specs/spec-distributions.json";
-
-let SquiggleVegaChart = createClassFromSpec({
- spec: chartSpecification as Spec,
-});
-
-export const DistPlusChart: React.FC<{
- distPlus: DistPlus;
- width: number;
- height: number;
-}> = ({ distPlus, width, height }) => {
- let shape = distPlus.pointSetDist;
- if (shape.tag === "Continuous") {
- let xyShape = shape.value.xyShape;
- let totalY = xyShape.ys.reduce((a, b) => a + b);
- let total = 0;
- let cdf = xyShape.ys.map((y) => {
- total += y;
- return total / totalY;
- });
- let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y]) => ({
- cdf: (c * 100).toFixed(2) + "%",
- x: x,
- y: y,
- }));
-
- return (
-
- );
- } else if (shape.tag === "Discrete") {
- let xyShape = shape.value.xyShape;
- let totalY = xyShape.ys.reduce((a, b) => a + b);
- let total = 0;
- let cdf = xyShape.ys.map((y) => {
- total += y;
- return total / totalY;
- });
- let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y]) => ({
- cdf: (c * 100).toFixed(2) + "%",
- x: x,
- y: y,
- }));
-
- return ;
- } else if (shape.tag === "Mixed") {
- let discreteShape = shape.value.discrete.xyShape;
- let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
-
- let discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
- let continuousShape = shape.value.continuous.xyShape;
- let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
-
- interface labeledPoint {
- x: number;
- y: number;
- type: "discrete" | "continuous";
- }
-
- let markedDisPoints: labeledPoint[] = discretePoints.map(([x, y]) => ({
- x: x,
- y: y,
- type: "discrete",
- }));
- let markedConPoints: labeledPoint[] = continuousPoints.map(([x, y]) => ({
- x: x,
- y: y,
- type: "continuous",
- }));
-
- let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), "x");
-
- let totalContinuous = 1 - totalDiscrete;
- let totalY = continuousShape.ys.reduce((a: number, b: number) => a + b);
-
- let total = 0;
- let cdf = sortedPoints.map((point: labeledPoint) => {
- if (point.type === "discrete") {
- total += point.y;
- return total;
- } else if (point.type === "continuous") {
- total += (point.y / totalY) * totalContinuous;
- return total;
- }
- });
-
- interface cdfLabeledPoint {
- cdf: string;
- x: number;
- y: number;
- type: "discrete" | "continuous";
- }
- let cdfLabeledPoint: cdfLabeledPoint[] = _.zipWith(
- cdf,
- sortedPoints,
- (c: number, point: labeledPoint) => ({
- ...point,
- cdf: (c * 100).toFixed(2) + "%",
- })
- );
- let continuousValues = cdfLabeledPoint.filter(
- (x) => x.type === "continuous"
- );
- let discreteValues = cdfLabeledPoint.filter((x) => x.type === "discrete");
-
- return (
-
- );
- }
-};
\ No newline at end of file
diff --git a/packages/components/src/components/DistributionChart.tsx b/packages/components/src/components/DistributionChart.tsx
new file mode 100644
index 00000000..502adc8c
--- /dev/null
+++ b/packages/components/src/components/DistributionChart.tsx
@@ -0,0 +1,38 @@
+import * as React from "react";
+import _ from "lodash";
+import type { Spec } from "vega";
+import type {
+ Distribution,
+} from "@quri/squiggle-lang";
+import { distributionErrorToString } from '@quri/squiggle-lang';
+import { createClassFromSpec } from "react-vega";
+import * as chartSpecification from "../vega-specs/spec-distributions.json";
+
+let SquiggleVegaChart = createClassFromSpec({
+ spec: chartSpecification as Spec,
+});
+
+type DistributionChartProps = {
+ distribution: Distribution;
+ width: number;
+ height: number;
+}
+
+export const DistributionChart: React.FC = ({ distribution, width, height }: DistributionChartProps) => {
+ console.log("Making shape")
+ let shape = distribution.shape();
+ console.log(shape)
+ if (shape.tag === "Ok") {
+ return (
+
+ );
+ }
+ else{
+ return <> {distributionErrorToString(shape.value)} >;
+ }
+};
diff --git a/packages/components/src/components/FunctionChart.tsx b/packages/components/src/components/FunctionChart.tsx
index 7625b2da..e93e8bd9 100644
--- a/packages/components/src/components/FunctionChart.tsx
+++ b/packages/components/src/components/FunctionChart.tsx
@@ -1,10 +1,10 @@
import * as React from "react";
import _ from "lodash";
import type { Spec } from "vega";
-import type { DistPlus } from "@quri/squiggle-lang";
+import type { Distribution, errorValue, result } from "@quri/squiggle-lang";
import { createClassFromSpec } from "react-vega";
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
-import { DistPlusChart } from "./DistPlusChart";
+import { DistributionChart } from "./DistributionChart";
import { Error } from "./Error";
let SquigglePercentilesChart = createClassFromSpec({
@@ -13,36 +13,38 @@ let SquigglePercentilesChart = createClassFromSpec({
type distPlusFn = (
a: number
-) => { tag: "Ok"; value: DistPlus } | { tag: "Error"; value: string };
+) => result
-const _rangeByCount = (start, stop, count) => {
+const _rangeByCount = (start: number, stop: number, count: number) => {
const step = (stop - start) / (count - 1);
const items = _.range(start, stop, step);
const result = items.concat([stop]);
return result;
};
+function unwrap( x: result): a {
+ if(x.tag === "Ok"){
+ return x.value
+ }
+}
export const FunctionChart: React.FC<{
distPlusFn: distPlusFn;
diagramStart: number;
diagramStop: number;
diagramCount: number;
}> = ({ distPlusFn, diagramStart, diagramStop, diagramCount }) => {
- let [mouseOverlay, setMouseOverlay] = React.useState(NaN);
+ let [mouseOverlay, setMouseOverlay] = React.useState(0);
function handleHover(...args) {
setMouseOverlay(args[1]);
}
- function handleOut(...args) {
+ function handleOut() {
setMouseOverlay(NaN);
}
const signalListeners = { mousemove: handleHover, mouseout: handleOut };
- let percentileArray = [
- 0.01, 0.05, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99,
- ];
let mouseItem = distPlusFn(mouseOverlay);
let showChart =
mouseItem.tag === "Ok" ? (
-
+
) : (
<>>
);
@@ -56,22 +58,21 @@ export const FunctionChart: React.FC<{
})
.filter((x) => x !== null)
.map(({ x, value }) => {
- let percentiles = getPercentiles(percentileArray, value);
return {
x: x,
- p1: percentiles[0],
- p5: percentiles[1],
- p10: percentiles[2],
- p20: percentiles[3],
- p30: percentiles[4],
- p40: percentiles[5],
- p50: percentiles[6],
- p60: percentiles[7],
- p70: percentiles[8],
- p80: percentiles[9],
- p90: percentiles[10],
- p95: percentiles[11],
- p99: percentiles[12],
+ p1: unwrap(value.inv(0.01)),
+ p5: unwrap(value.inv(0.05)),
+ p10: unwrap(value.inv(0.12)),
+ p20: unwrap(value.inv(0.20)),
+ p30: unwrap(value.inv(0.30)),
+ p40: unwrap(value.inv(0.40)),
+ p50: unwrap(value.inv(0.50)),
+ p60: unwrap(value.inv(0.60)),
+ p70: unwrap(value.inv(0.70)),
+ p80: unwrap(value.inv(0.80)),
+ p90: unwrap(value.inv(0.90)),
+ p95: unwrap(value.inv(0.95)),
+ p99: unwrap(value.inv(0.99)),
};
});
@@ -101,88 +102,3 @@ export const FunctionChart: React.FC<{
);
};
-function getPercentiles(percentiles: number[], t: DistPlus) {
- if (t.pointSetDist.tag === "Discrete") {
- let total = 0;
- let maxX = _.max(t.pointSetDist.value.xyShape.xs);
- let bounds = percentiles.map((_) => maxX);
- _.zipWith(
- t.pointSetDist.value.xyShape.xs,
- t.pointSetDist.value.xyShape.ys,
- (x, y) => {
- total += y;
- percentiles.forEach((v, i) => {
- if (total > v && bounds[i] === maxX) {
- bounds[i] = x;
- }
- });
- }
- );
- return bounds;
- } else if (t.pointSetDist.tag === "Continuous") {
- let total = 0;
- let maxX = _.max(t.pointSetDist.value.xyShape.xs);
- let totalY = _.sum(t.pointSetDist.value.xyShape.ys);
- let bounds = percentiles.map((_) => maxX);
- _.zipWith(
- t.pointSetDist.value.xyShape.xs,
- t.pointSetDist.value.xyShape.ys,
- (x, y) => {
- total += y / totalY;
- percentiles.forEach((v, i) => {
- if (total > v && bounds[i] === maxX) {
- bounds[i] = x;
- }
- });
- }
- );
- return bounds;
- } else if (t.pointSetDist.tag === "Mixed") {
- let discreteShape = t.pointSetDist.value.discrete.xyShape;
- let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
-
- let discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
- let continuousShape = t.pointSetDist.value.continuous.xyShape;
- let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
-
- interface labeledPoint {
- x: number;
- y: number;
- type: "discrete" | "continuous";
- }
-
- let markedDisPoints: labeledPoint[] = discretePoints.map(([x, y]) => ({
- x: x,
- y: y,
- type: "discrete",
- }));
- let markedConPoints: labeledPoint[] = continuousPoints.map(([x, y]) => ({
- x: x,
- y: y,
- type: "continuous",
- }));
-
- let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), "x");
-
- let totalContinuous = 1 - totalDiscrete;
- let totalY = continuousShape.ys.reduce((a: number, b: number) => a + b);
-
- let total = 0;
- let maxX = _.max(sortedPoints.map((x) => x.x));
- let bounds = percentiles.map((_) => maxX);
- sortedPoints.map((point: labeledPoint) => {
- if (point.type === "discrete") {
- total += point.y;
- } else if (point.type === "continuous") {
- total += (point.y / totalY) * totalContinuous;
- }
- percentiles.forEach((v, i) => {
- if (total > v && bounds[i] === maxX) {
- bounds[i] = total;
- }
- });
- return total;
- });
- return bounds;
- }
-}
diff --git a/packages/components/src/components/SquiggleChart.tsx b/packages/components/src/components/SquiggleChart.tsx
index f5dc5667..ded0a96a 100644
--- a/packages/components/src/components/SquiggleChart.tsx
+++ b/packages/components/src/components/SquiggleChart.tsx
@@ -1,14 +1,12 @@
import * as React from "react";
import _ from "lodash";
-import { run } from "@quri/squiggle-lang";
+import { run, errorValueToString } from "@quri/squiggle-lang";
import type {
- SamplingInputs,
+ samplingParams,
exportEnv,
- exportDistribution,
} from "@quri/squiggle-lang";
import { NumberShower } from "./NumberShower";
-import { DistPlusChart } from "./DistPlusChart";
-import { FunctionChart } from "./FunctionChart";
+import { DistributionChart } from "./DistributionChart";
import { Error } from "./Error";
export interface SquiggleChartProps {
@@ -39,8 +37,6 @@ export const SquiggleChart: React.FC = ({
squiggleString = "",
sampleCount = 1000,
outputXYPoints = 1000,
- kernelWidth,
- pointDistLength = 1000,
diagramStart = 0,
diagramStop = 10,
diagramCount = 20,
@@ -49,43 +45,35 @@ export const SquiggleChart: React.FC = ({
width = 500,
height = 60,
}: SquiggleChartProps) => {
- let samplingInputs: SamplingInputs = {
+ let samplingInputs: samplingParams = {
sampleCount: sampleCount,
- outputXYPoints: outputXYPoints,
- kernelWidth: kernelWidth,
- pointDistLength: pointDistLength,
+ xyPointLength: outputXYPoints
};
let result = run(squiggleString, samplingInputs, environment);
+ console.log(result)
if (result.tag === "Ok") {
- let environment = result.value.environment;
- let exports = result.value.exports;
onEnvChange(environment);
- let chartResults = exports.map((chartResult: exportDistribution) => {
- if (chartResult["NAME"] === "Float") {
- return ;
- } else if (chartResult["NAME"] === "DistPlus") {
- return (
-
- );
- } else if (chartResult.NAME === "Function") {
- return (
-
- );
- }
- });
- return <>{chartResults}>;
+ let chartResult = result.value;
+ if (chartResult.tag === "number") {
+ return ;
+ } else if (chartResult.tag === "distribution") {
+ console.log("Is a distribution")
+ return (
+
+ );
+ console.log("NOT THIS LINE")
+ }
+ else {
+ console.log("Is a distribution")
+ return {"We don't currently have a viewer for this type: " + chartResult.tag};
+ }
} else if (result.tag === "Error") {
// At this point, we came across an error. What was our error?
- return {result.value};
+ return {errorValueToString(result.value)};
}
};
diff --git a/packages/squiggle-lang/src/js/index.ts b/packages/squiggle-lang/src/js/index.ts
index 923303ef..35fa0537 100644
--- a/packages/squiggle-lang/src/js/index.ts
+++ b/packages/squiggle-lang/src/js/index.ts
@@ -4,8 +4,8 @@ import type {
exportDistribution,
} from "../rescript/ProgramEvaluator.gen";
export type { exportEnv, exportDistribution };
-import { genericDist, samplingParams, evaluate, expressionValue, errorValue, distributionError } from "../rescript/TypescriptInterface.gen";
-export { makeSampleSetDist } from "../rescript/TypescriptInterface.gen";
+import { genericDist, samplingParams, evaluate, expressionValue, errorValue, distributionError, toPointSet, continuousShape, discreteShape, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
+export { makeSampleSetDist, errorValueToString, distributionErrorToString } from "../rescript/TypescriptInterface.gen";
import {
Constructors_mean,
Constructors_sample,
@@ -32,19 +32,14 @@ import {
Constructors_pointwiseLogarithm,
Constructors_pointwisePower,
} from "../rescript/Distributions/DistributionOperation/DistributionOperation.gen";
+export type {samplingParams, errorValue}
-export type SamplingInputs = {
- readonly sampleCount?: number;
- readonly outputXYPoints?: number;
- readonly kernelWidth?: number;
- readonly pointDistLength?: number
-};
export let defaultSamplingInputs: samplingParams = {
sampleCount: 10000,
xyPointLength: 10000
};
-type result =
+export type result =
| {
tag: "Ok";
value: a;
@@ -65,6 +60,10 @@ export function resultMap(
}
}
+function Ok(x: a): result {
+ return {"tag": "Ok", value: x}
+}
+
type tagged = {tag: a, value: b}
function tag(x: a, y: b) : tagged{
@@ -97,9 +96,6 @@ function createTsExport(x: expressionValue, sampEnv: samplingParams): squiggleEx
return tag("number", x.value);
case "EvRecord":
return tag("record", _.mapValues(x.value, x => createTsExport(x, sampEnv)))
-
-
-
}
}
@@ -108,6 +104,19 @@ export function resultExn(r: result): a | c {
return r.value;
}
+export type point = { x: number, y: number}
+
+export type shape = {
+ continuous: point[]
+ discrete: point[]
+}
+
+function shapePoints(x : continuousShape | discreteShape): point[]{
+ let xs = x.xyShape.xs;
+ let ys = x.xyShape.ys;
+ return _.zipWith(xs, ys, (x, y) => ({x, y}))
+}
+
export class Distribution {
t: genericDist;
env: samplingParams;
@@ -148,6 +157,34 @@ export class Distribution {
);
}
+ shape() : result {
+ let pointSet = toPointSet(this.t, {xyPointLength: this.env.xyPointLength, sampleCount: this.env.sampleCount}, null);
+ if(pointSet.tag === "Ok"){
+ let distribution = pointSet.value;
+ if(distribution.tag === "Continuous"){
+ return Ok({
+ continuous: shapePoints(distribution.value),
+ discrete: []
+ })
+ }
+ else if(distribution.tag === "Discrete"){
+ return Ok({
+ discrete: shapePoints(distribution.value),
+ continuous: []
+ })
+ }
+ else if(distribution.tag === "Mixed"){
+ return Ok({
+ discrete: shapePoints(distribution.value.discrete),
+ continuous: shapePoints(distribution.value.continuous)
+ })
+ }
+ }
+ else {
+ return pointSet
+ }
+ }
+
toPointSet(): result {
return this.mapResultDist(
Constructors_toPointSet({ env: this.env }, this.t)
@@ -170,8 +207,14 @@ export class Distribution {
return this.mapResultDist(Constructors_inspect({ env: this.env }, this.t));
}
- toString(): result {
- return Constructors_toString({ env: this.env }, this.t);
+ toString(): string {
+ let result = Constructors_toString({ env: this.env }, this.t);
+ if(result.tag === "Ok"){
+ result.value
+ }
+ else {
+ return distributionErrorToString(result.value)
+ }
}
toSparkline(n: number): result {
diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi
index 4565ec14..bd6755fd 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi
+++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist.resi
@@ -21,6 +21,7 @@ let toFloatOperation: (
~distToFloatOperation: Operation.distToFloatOperation,
) => result
+@genType
let toPointSet: (
t,
~xyPointLength: int,
diff --git a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res
index 96e7d3f8..4d2ba9b6 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/GenericDist/GenericDist_Types.res
@@ -10,10 +10,21 @@ type error =
| DistributionVerticalShiftIsInvalid
| Other(string)
+@genType
module Error = {
type t = error
let fromString = (s: string): t => Other(s)
+
+ @genType
+ let toString = (x: t) => {
+ switch x {
+ | NotYetImplemented => "Not Yet Implemented"
+ | Unreachable => "Unreachable"
+ | DistributionVerticalShiftIsInvalid => "Distribution Vertical Shift Is Invalid"
+ | Other(s) => s
+ }
+ }
let resultStringToResultError: result<'a, string> => result<'a, error> = n =>
n->E.R2.errMap(r => r->fromString->Error)
@@ -51,6 +62,7 @@ module Operation = {
| #Sample
]
+ @genType
type pointsetXSelection = [#Linear | #ByWeight]
type toDist =
diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res
index 3b689453..3bd22018 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/Discrete.res
@@ -214,4 +214,4 @@ module T = Dist({
let getMeanOfSquares = t => t |> shapeMap(XYShape.T.square) |> mean
XYShape.Analysis.getVarianceDangerously(t, mean, getMeanOfSquares)
}
-})
\ No newline at end of file
+})
diff --git a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetTypes.res b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetTypes.res
index 2d7947c0..4de2e880 100644
--- a/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetTypes.res
+++ b/packages/squiggle-lang/src/rescript/Distributions/PointSetDist/PointSetTypes.res
@@ -19,6 +19,7 @@ type interpolationStrategy = XYShape.interpolationStrategy;
type extrapolationStrategy = XYShape.extrapolationStrategy;
type interpolator = XYShape.extrapolationStrategy;
+@genType
type rec continuousShape = {
xyShape: xyShape,
interpolation: interpolationStrategy,
@@ -26,12 +27,14 @@ type rec continuousShape = {
integralCache: option,
}
+@genType
type discreteShape = {
xyShape: xyShape,
integralSumCache: option,
integralCache: option,
}
+@genType
type mixedShape = {
continuous: continuousShape,
discrete: discreteShape,
diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res
index 666f5476..d0c85d59 100644
--- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res
+++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_ErrorValue.res
@@ -8,6 +8,7 @@ type errorValue =
type t = errorValue
+@genType
let errorToString = err =>
switch err {
| REArrayIndexNotFound(msg, index) => `${msg}: ${Js.String.make(index)}`
diff --git a/packages/squiggle-lang/src/rescript/TypescriptInterface.res b/packages/squiggle-lang/src/rescript/TypescriptInterface.res
index c52dd8a7..a706bdd2 100644
--- a/packages/squiggle-lang/src/rescript/TypescriptInterface.res
+++ b/packages/squiggle-lang/src/rescript/TypescriptInterface.res
@@ -36,3 +36,21 @@ type expressionValue = Reducer_Expression.expressionValue
@genType
type errorValue = Reducer_ErrorValue.errorValue
+
+@genType
+let toPointSet = GenericDist.toPointSet
+
+@genType
+type mixedShape = PointSetTypes.mixedShape
+
+@genType
+type discreteShape = PointSetTypes.discreteShape
+
+@genType
+type continuousShape = PointSetTypes.continuousShape
+
+@genType
+let errorValueToString = Reducer_ErrorValue.errorToString
+
+@genType
+let distributionErrorToString = GenericDist_Types.Error.toString