Merge remote-tracking branch 'origin/develop' into scoring-cleanup-three

This commit is contained in:
Quinn Dougherty 2022-06-23 11:34:03 -04:00
commit b74b83a2cb
11 changed files with 135 additions and 42 deletions

View File

@ -19,25 +19,38 @@ import {
} from "./DistributionVegaScales";
import { NumberShower } from "./NumberShower";
type DistributionChartProps = {
distribution: Distribution;
width?: number;
height: number;
export type DistributionPlottingSettings = {
/** Whether to show a summary of means, stdev, percentiles etc */
showSummary: boolean;
/** Whether to show the user graph controls (scale etc) */
showControls?: boolean;
showControls: boolean;
/** Set the x scale to be logarithmic by deault */
logX: boolean;
/** Set the y scale to be exponential by deault */
expY: boolean;
};
export type DistributionChartProps = {
distribution: Distribution;
width?: number;
height: number;
} & DistributionPlottingSettings;
export const DistributionChart: React.FC<DistributionChartProps> = ({
distribution,
height,
showSummary,
width,
showControls = false,
showControls,
logX,
expY,
}) => {
const [isLogX, setLogX] = React.useState(false);
const [isExpY, setExpY] = React.useState(false);
const [isLogX, setLogX] = React.useState(logX);
const [isExpY, setExpY] = React.useState(expY);
React.useEffect(() => setLogX(logX), [logX]);
React.useEffect(() => setExpY(expY), [expY]);
const shape = distribution.pointSet();
const [sized] = useSize((size) => {
if (shape.tag === "Error") {
@ -63,6 +76,7 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
return (
<div style={{ width: widthProp }}>
{!(isLogX && massBelow0) ? (
<Vega
spec={spec}
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
@ -70,6 +84,11 @@ export const DistributionChart: React.FC<DistributionChartProps> = ({
height={height}
actions={false}
/>
) : (
<ErrorAlert heading="Log Domain Error">
Cannot graph distribution with negative values on logarithmic scale.
</ErrorAlert>
)}
<div className="flex justify-center">
{showSummary && <SummaryTable distribution={distribution} />}
</div>
@ -126,7 +145,7 @@ export const CheckBox: React.FC<CheckBoxProps> = ({
<span title={tooltip}>
<input
type="checkbox"
value={value + ""}
checked={value}
onChange={() => onChange(!value)}
disabled={disabled}
className="form-checkbox"

View File

@ -2,6 +2,7 @@ import * as React from "react";
import { lambdaValue, environment, runForeign } from "@quri/squiggle-lang";
import { FunctionChart1Dist } from "./FunctionChart1Dist";
import { FunctionChart1Number } from "./FunctionChart1Number";
import { DistributionPlottingSettings } from "./DistributionChart";
import { ErrorAlert, MessageAlert } from "./Alert";
export type FunctionChartSettings = {
@ -13,6 +14,7 @@ export type FunctionChartSettings = {
interface FunctionChartProps {
fn: lambdaValue;
chartSettings: FunctionChartSettings;
distributionPlotSettings: DistributionPlottingSettings;
environment: environment;
height: number;
}
@ -21,6 +23,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
fn,
chartSettings,
environment,
distributionPlotSettings,
height,
}) => {
if (fn.parameters.length > 1) {
@ -53,6 +56,7 @@ export const FunctionChart: React.FC<FunctionChartProps> = ({
chartSettings={chartSettings}
environment={environment}
height={height}
distributionPlotSettings={distributionPlotSettings}
/>
);
case "number":

View File

@ -13,7 +13,10 @@ import {
} from "@quri/squiggle-lang";
import { createClassFromSpec } from "react-vega";
import * as percentilesSpec from "../vega-specs/spec-percentiles.json";
import { DistributionChart } from "./DistributionChart";
import {
DistributionChart,
DistributionPlottingSettings,
} from "./DistributionChart";
import { NumberShower } from "./NumberShower";
import { ErrorAlert } from "./Alert";
@ -44,6 +47,7 @@ export type FunctionChartSettings = {
interface FunctionChart1DistProps {
fn: lambdaValue;
chartSettings: FunctionChartSettings;
distributionPlotSettings: DistributionPlottingSettings;
environment: environment;
height: number;
}
@ -150,6 +154,7 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
fn,
chartSettings,
environment,
distributionPlotSettings,
height,
}) => {
let [mouseOverlay, setMouseOverlay] = React.useState(0);
@ -175,7 +180,7 @@ export const FunctionChart1Dist: React.FC<FunctionChart1DistProps> = ({
distribution={mouseItem.value.value}
width={400}
height={50}
showSummary={false}
{...distributionPlotSettings}
/>
) : null;

View File

@ -37,6 +37,10 @@ export interface SquiggleChartProps {
showTypes?: boolean;
/** Whether to show graph controls (scale etc)*/
showControls?: boolean;
/** Set the x scale to be logarithmic by deault */
logX?: boolean;
/** Set the y scale to be exponential by deault */
expY?: boolean;
}
const defaultOnChange = () => {};
@ -53,6 +57,8 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
width,
showTypes = false,
showControls = false,
logX = false,
expY = false,
chartSettings = defaultChartSettings,
}) => {
const { result } = useSquiggle({
@ -67,14 +73,20 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
return <SquiggleErrorAlert error={result.value} />;
}
let distributionPlotSettings = {
showControls,
showSummary,
logX,
expY,
};
return (
<SquiggleItem
expression={result.value}
width={width}
height={height}
showSummary={showSummary}
distributionPlotSettings={distributionPlotSettings}
showTypes={showTypes}
showControls={showControls}
chartSettings={chartSettings}
environment={environment ?? defaultEnvironment}
/>

View File

@ -54,6 +54,10 @@ export interface SquiggleEditorProps {
showControls?: boolean;
/** Whether to show a summary table */
showSummary?: boolean;
/** Whether to log the x coordinate on distribution charts */
logX?: boolean;
/** Whether to exp the y coordinate on distribution charts */
expY?: boolean;
}
export const SquiggleEditor: React.FC<SquiggleEditorProps> = ({
@ -69,8 +73,14 @@ export const SquiggleEditor: React.FC<SquiggleEditorProps> = ({
showTypes = false,
showControls = false,
showSummary = false,
logX = false,
expY = false,
}: SquiggleEditorProps) => {
const [code, setCode] = useState(initialSquiggleString);
React.useEffect(
() => setCode(initialSquiggleString),
[initialSquiggleString]
);
const { result, observableRef } = useSquiggle({
code,
@ -86,6 +96,13 @@ export const SquiggleEditor: React.FC<SquiggleEditorProps> = ({
count: diagramCount,
};
const distributionPlotSettings = {
showControls,
showSummary,
logX,
expY,
};
return (
<div ref={observableRef}>
<SquiggleContainer>
@ -95,9 +112,8 @@ export const SquiggleEditor: React.FC<SquiggleEditorProps> = ({
expression={result.value}
width={width}
height={200}
showSummary={showSummary}
distributionPlotSettings={distributionPlotSettings}
showTypes={showTypes}
showControls={showControls}
chartSettings={chartSettings}
environment={environment ?? defaultEnvironment}
/>
@ -136,6 +152,10 @@ export const SquigglePartial: React.FC<SquigglePartialProps> = ({
jsImports = defaultImports,
}: SquigglePartialProps) => {
const [code, setCode] = useState(initialSquiggleString);
React.useEffect(
() => setCode(initialSquiggleString),
[initialSquiggleString]
);
const { result, observableRef } = useSquigglePartial({
code,

View File

@ -5,7 +5,10 @@ import {
declaration,
} from "@quri/squiggle-lang";
import { NumberShower } from "./NumberShower";
import { DistributionChart } from "./DistributionChart";
import {
DistributionChart,
DistributionPlottingSettings,
} from "./DistributionChart";
import { FunctionChart, FunctionChartSettings } from "./FunctionChart";
function getRange<a>(x: declaration<a>) {
@ -61,12 +64,9 @@ export interface SquiggleItemProps {
expression: squiggleExpression;
width?: number;
height: number;
/** Whether to show a summary of statistics for distributions */
showSummary: boolean;
distributionPlotSettings: DistributionPlottingSettings;
/** Whether to show type information */
showTypes: boolean;
/** Whether to show users graph controls (scale etc) */
showControls: boolean;
/** Settings for displaying functions */
chartSettings: FunctionChartSettings;
/** Environment for further function executions */
@ -77,9 +77,8 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
expression,
width,
height,
showSummary,
distributionPlotSettings,
showTypes = false,
showControls = false,
chartSettings,
environment,
}) => {
@ -104,10 +103,9 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
) : null}
<DistributionChart
distribution={expression.value}
{...distributionPlotSettings}
height={height}
width={width}
showSummary={showSummary}
showControls={showControls}
/>
</VariableBox>
);
@ -155,11 +153,10 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
expression={r}
width={width !== undefined ? width - 20 : width}
height={50}
distributionPlotSettings={distributionPlotSettings}
showTypes={showTypes}
showControls={showControls}
chartSettings={chartSettings}
environment={environment}
showSummary={showSummary}
/>
</div>
</div>
@ -181,8 +178,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
width={width !== undefined ? width - 20 : width}
height={height / 3}
showTypes={showTypes}
showSummary={showSummary}
showControls={showControls}
distributionPlotSettings={distributionPlotSettings}
chartSettings={chartSettings}
environment={environment}
/>
@ -220,6 +216,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
<FunctionChart
fn={expression.value}
chartSettings={chartSettings}
distributionPlotSettings={distributionPlotSettings}
height={height}
environment={{
sampleCount: environment.sampleCount / 10,
@ -234,6 +231,7 @@ export const SquiggleItem: React.FC<SquiggleItemProps> = ({
<FunctionChart
fn={expression.value.fn}
chartSettings={getChartSettings(expression.value)}
distributionPlotSettings={distributionPlotSettings}
height={height}
environment={{
sampleCount: environment.sampleCount / 10,

View File

@ -32,6 +32,10 @@ interface PlaygroundProps {
showControls?: boolean;
/** Whether to show the summary table in the playground */
showSummary?: boolean;
/** Whether to log the x coordinate on distribution charts */
logX?: boolean;
/** Whether to exp the y coordinate on distribution charts */
expY?: boolean;
/** If code is set, component becomes controlled */
code?: string;
onCodeChange?(expr: string): void;
@ -72,6 +76,8 @@ const schema = yup
showControls: yup.boolean(),
showSummary: yup.boolean(),
showEditor: yup.boolean(),
logX: yup.boolean(),
expY: yup.boolean(),
showSettingsPage: yup.boolean().default(false),
diagramStart: yup
.number()
@ -204,6 +210,8 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
showTypes = false,
showControls = false,
showSummary = false,
logX = false,
expY = false,
code: controlledCode,
onCodeChange,
onSettingsChange,
@ -221,10 +229,12 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
sampleCount: 1000,
xyPointLength: 1000,
chartHeight: 150,
showTypes: showTypes,
showControls: showControls,
showSummary: showSummary,
showEditor: showEditor,
showTypes,
showControls,
logX,
expY,
showSummary,
showEditor,
leftSizePercent: 50,
showSettingsPage: false,
diagramStart: 0,
@ -320,6 +330,16 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
<div className="pt-8">
<HeadedSection title="Distribution Display Settings">
<div className="space-y-2">
<Checkbox
register={register}
name="logX"
label="Show x scale logarithmically"
/>
<Checkbox
register={register}
name="expY"
label="Show y scale exponentially"
/>
<Checkbox
register={register}
name="showControls"
@ -410,6 +430,8 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
showTypes={vars.showTypes}
showControls={vars.showControls}
showSummary={vars.showSummary}
logX={vars.logX}
expY={vars.expY}
bindings={defaultBindings}
jsImports={imports}
/>

View File

@ -14,4 +14,16 @@ describe("Combining Continuous and Discrete Distributions", () => {
), // Multiply distribution by -1
true,
)
makeTest(
"keep order of xs when first number is discrete and adding",
AlgebraicShapeCombination.isOrdered(
AlgebraicShapeCombination.combineShapesContinuousDiscrete(
#Add,
{xs: [0., 1.], ys: [1., 1.]},
{xs: [1.], ys: [1.]},
~discretePosition=First,
),
), // 1 + distribution
true,
)
})

View File

@ -57,6 +57,7 @@
"moduleserve": "^0.9.1",
"nyc": "^15.1.0",
"peggy": "^2.0.1",
"prettier": "^2.7.1",
"reanalyze": "^2.23.0",
"rescript-fast-check": "^1.1.1",
"ts-jest": "^27.1.4",

View File

@ -214,7 +214,7 @@ let combineShapesContinuousDiscrete = (
// When this operation is flipped (like 1 - normal(5, 2)) then the
// x axis coordinates would all come out the wrong order. So we need
// to fill them out in the opposite direction
let index = discretePosition == First ? t1n - 1 - i : i
let index = discretePosition == First && op == #Subtract ? t1n - 1 - i : i
Belt.Array.set(
dxyShape,
index,

View File

@ -4351,7 +4351,7 @@
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.0.9":
"@types/react@*", "@types/react@^18.0.1", "@types/react@^18.0.9":
version "18.0.14"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.14.tgz#e016616ffff51dba01b04945610fe3671fdbe06d"
integrity sha512-x4gGuASSiWmo0xjDLpm5mPb52syZHJx02VKbqUKdLmKtAwIh63XClGsiTI1K6DO5q7ox4xAsQrU+Gl3+gGXF9Q==
@ -14635,7 +14635,7 @@ react-vega@^7.5.1:
prop-types "^15.8.1"
vega-embed "^6.5.1"
react@^18.1.0:
react@^18.0.0, react@^18.1.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==