Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

S date distribution #2588

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions packages/components/src/components/NumberShower.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ export function numberShow(number: number, precision = 2) {
export interface NumberShowerProps {
number: number;
precision?: number;
unitName?: string;
}

export const NumberShower: React.FC<NumberShowerProps> = ({
number,
precision = 2,
unitName,
}) => {
const numberWithPresentation = numberShow(number, precision);
return (
Expand All @@ -92,6 +94,7 @@ export const NumberShower: React.FC<NumberShowerProps> = ({
</span>
</span>
) : null}
{unitName && ` ${unitName}`}
</span>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ varVoid = ()
varArray = [1,2,3]
varLambda = {|e| "Test"}
varScale = Scale.symlog({ min: -2, max: 5})
varDuration = hours(3 to 10)
varDate = 2020year + years(5 to 10)

varDict = {fir: 1, secon: 2}

Expand Down
42 changes: 41 additions & 1 deletion packages/components/src/widgets/DateWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
import {
SDateNumber,
SqDateScale,
SqDistributionsPlot,
} from "@quri/squiggle-lang";
import { widgetRegistry } from "./registry.js";
export const CHART_TO_DIST_HEIGHT_ADJUSTMENT = 0.5;
import { generateDistributionPlotSettings } from "../components/PlaygroundSettings.js";
import { DistributionsChart } from "./DistWidget/DistributionsChart.js";

widgetRegistry.register("Date", {
Chart: (value) => value.value.toString(),
Preview(value) {
const dist = value.value.toMs();
const p05 = dist.inv(0.05);
const p95 = dist.inv(0.95);
const oneValue = p05 === p95;
const show = (f: number) => SDateNumber.fromMs(f).toString();

return oneValue ? (
show(p05)
) : (
<div>
{show(p05)}
<span className="mx-1 opacity-70">to</span>
{show(p95)}
</div>
);
},

Chart(value, settings) {
const plot = SqDistributionsPlot.create({
distribution: value.toDist(),
...generateDistributionPlotSettings(settings.distributionChartSettings),
xScale: SqDateScale.create({}),
});

return (
<DistributionsChart
plot={plot}
environment={value.context.project.getEnvironment()}
height={settings.chartHeight * CHART_TO_DIST_HEIGHT_ADJUSTMENT}
/>
);
},
});
4 changes: 2 additions & 2 deletions packages/components/src/widgets/DistWidget/SummaryTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { XIcon } from "@heroicons/react/solid/esm/index.js";
import {
Env,
result,
SDuration,
SDurationNumber,
SqDistribution,
SqDistributionError,
SqDistributionsPlot,
Expand Down Expand Up @@ -58,7 +58,7 @@ const SummaryTableRow: FC<SummaryTableRowProps> = ({
if (valueType == "date") {
// When dealing with dates, the standard deviation is a duration, not a date, so we need to format it differently
if (isRange) {
return SDuration.fromMs(number).toString();
return SDurationNumber.fromMs(number).toString();
} else {
return d3.timeFormat(tickFormat ?? DEFAULT_DATE_FORMAT)(
new Date(number)
Expand Down
63 changes: 62 additions & 1 deletion packages/components/src/widgets/DurationWidget.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,66 @@
import { widgetRegistry } from "./registry.js";
import {
Env,
SDurationNumber,
SqDistributionsPlot,
SqLinearScale,
} from "@quri/squiggle-lang";
export const CHART_TO_DIST_HEIGHT_ADJUSTMENT = 0.5;
import { generateDistributionPlotSettings } from "../components/PlaygroundSettings.js";
import { DistributionsChart } from "./DistWidget/DistributionsChart.js";
import { NumberShower } from "../index.js";

const env: Env = {
sampleCount: 1000,
xyPointLength: 1000,
};

widgetRegistry.register("Duration", {
Chart: (value) => value.toString(),
Preview(value) {
const dist = value.value.toMs();
const p05 = dist.inv(0.05);
const p95 = dist.inv(0.95);
const oneValue = p05 === p95;
const show = (f: number) => {
const unitWithValue = SDurationNumber.fromMs(f).toGreatestUnit();
return (
<NumberShower
number={unitWithValue.value}
unitName={unitWithValue.toUnitString()}
/>
);
};
return oneValue ? (
show(p05)
) : (
<div>
{show(p05)}
<span className="mx-1 opacity-70">to</span>
{show(p95)}
</div>
);
},
Chart(value, settings) {
const high = value.toDist().inv(env, 0.9);
if (high.ok) {
const unit = SDurationNumber.fromMs(high.value).toGreatestUnit();
const conversionFactor = SDurationNumber.fromMs(
high.value
).unitToConversionFactor(unit.unit);
const newDist = value.divideyByConstant(conversionFactor, env);
const plot = SqDistributionsPlot.create({
distribution: newDist.toDist(),
...generateDistributionPlotSettings(settings.distributionChartSettings),
xScale: SqLinearScale.create({ title: unit.toUnitString() }),
});

return (
<DistributionsChart
plot={plot}
environment={value.context.project.getEnvironment()}
height={settings.chartHeight * CHART_TO_DIST_HEIGHT_ADJUSTMENT}
/>
);
}
},
});
13 changes: 9 additions & 4 deletions packages/squiggle-lang/__tests__/reducer/frTypes_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
frAny,
frNumberOrString,
} from "../../src/library/registry/frTypes.js";
import { SDate } from "../../src/utility/SDate.js";
import { SDuration } from "../../src/utility/SDuration.js";
import { SDateDist } from "../../src/utility/SDate.js";
import { SDurationDist } from "../../src/utility/SDuration.js";
import { ImmutableMap } from "../../src/utility/immutableMap.js";

import {
Expand Down Expand Up @@ -50,14 +50,19 @@ test("frBool", () => {
});

test("frDate", () => {
const date = SDate.now();
const date = SDateDist.now();
const value = vDate(date);
expect(frDate.unpack(value)).toBe(date);
expect(frDate.pack(date)).toEqual(value);
});

test("frDuration", () => {
const duration = SDuration.fromMs(1234);
const dResult = Normal.make({ mean: 2, stdev: 5 });
if (!dResult.ok) {
throw new Error();
}

const duration = SDurationDist.fromMs(dResult.value);
const value = vDuration(duration);
expect(frDuration.unpack(value)).toBe(duration);
expect(frDuration.pack(duration)).toEqual(value);
Expand Down
77 changes: 31 additions & 46 deletions packages/squiggle-lang/src/fr/date.ts
Original file line number Diff line number Diff line change
@@ -1,102 +1,87 @@
import { REOther } from "../errors/messages.js";
import { DistError } from "../dist/DistError.js";
import { REDistributionError, REOther } from "../errors/messages.js";
import { result } from "../index.js";
import { makeDefinition } from "../library/registry/fnDefinition.js";
import {
frDate,
frDict,
frNumber,
frString,
frDuration,
frDateNumber,
} from "../library/registry/frTypes.js";
import {
FnFactory,
makeNumericComparisons,
} from "../library/registry/helpers.js";
import { SDate } from "../utility/SDate.js";
import { SDateNumber, SDateDist } from "../utility/SDate.js";
import { getExt, getExtFn } from "../utility/result.js";
import { DateRangeDomain } from "../value/domain.js";
import { vDate, vDomain, vNumber, vDuration } from "../value/index.js";
import { vDate, vDateNumber, vDomain, vDuration } from "../value/index.js";

const maker = new FnFactory({
nameSpace: "Date",
requiresNamespace: false,
});

const makeYearFn = makeDefinition([frNumber], ([year]) => {
const result = SDate.fromYear(year);
const result = SDateNumber.fromYear(year);
const value = getExtFn(result, (e) => new REOther(e));
return vDateNumber(value);
});
export function unpackDistResult<T>(result: result<T, DistError>): T {
if (!result.ok) {
throw new REOther(result.value);
throw new REDistributionError(result.value);
}
return vDate(result.value);
});

return result.value;
}
export const library = [
...makeNumericComparisons(
maker,
(d1, d2) => d1.smaller(d2),
(d1, d2) => d1.larger(d2),
(d1, d2) => d1.isEqual(d2),
frDate
frDateNumber
),
maker.make({
name: "make",
requiresNamespace: true,
examples: ['Date.make("2020-05-12")', "Date.make(2020, 5, 10)"],
output: "Date",
output: "DateNumber",
definitions: [
makeDefinition([frString], ([str]) => {
const result = SDate.fromString(str);
const result = SDateNumber.fromString(str);
if (!result.ok) {
throw new REOther(result.value);
}
return vDate(result.value);
return vDateNumber(result.value);
}),

makeDefinition([frNumber, frNumber, frNumber], ([yr, month, date]) => {
return vDate(SDate.fromYearMonthDay(yr, month, date));
return vDateNumber(SDateNumber.fromYearMonthDay(yr, month, date));
}),
],
}),
maker.fromDefinition("fromYear", makeYearFn),
maker.fromDefinition("fromUnit_year", makeYearFn),
// same name as used in date-fns
maker.make({
name: "fromUnixTime",
examples: ["Date.fromUnixTime(1589222400)"],
requiresNamespace: true,
output: "Date",
definitions: [
makeDefinition([frNumber], ([num]) => {
return vDate(SDate.fromUnixS(num));
}),
],
}),
maker.make({
name: "toUnixTime",
examples: ["Date.toUnixTime(Date.make(2020, 5, 12))"],
requiresNamespace: true,
output: "Number",
definitions: [
makeDefinition([frDate], ([date]) => {
return vNumber(date.toUnixS());
}),
],
}),
maker.make({
name: "subtract",
examples: ["Date.make(2020, 5, 12) - Date.make(2000, 1, 1)"],
output: "Duration",
definitions: [
makeDefinition([frDate, frDate], ([d1, d2]) =>
vDuration(d1.subtract(d2))
),
makeDefinition([frDate, frDate], ([d1, d2], { environment }) => {
const result = d1.subtract(d2, environment);
return vDuration(getExt(result));
}),
],
}),
maker.make({
name: "subtract",
examples: ["Date.make(2020, 5, 12) - 20years"],
output: "Date",
definitions: [
makeDefinition([frDate, frDuration], ([d1, d2]) =>
vDate(d1.subtractDuration(d2))
makeDefinition([frDate, frDuration], ([d1, d2], { environment }) =>
vDate(unpackDistResult(d1.subtractDuration(d2, environment)))
),
],
}),
Expand All @@ -108,11 +93,11 @@ export const library = [
],
output: "Date",
definitions: [
makeDefinition([frDate, frDuration], ([d1, d2]) =>
vDate(d1.addDuration(d2))
makeDefinition([frDate, frDuration], ([d1, d2], { environment }) =>
vDate(unpackDistResult(d1.addDuration(d2, environment)))
),
makeDefinition([frDuration, frDate], ([d1, d2]) =>
vDate(d2.addDuration(d1))
makeDefinition([frDuration, frDate], ([d1, d2], { environment }) =>
vDate(unpackDistResult(d2.addDuration(d1, environment)))
),
],
}),
Expand All @@ -123,7 +108,7 @@ export const library = [
examples: ["Date.rangeDomain({ min: 2000year, max: 2010year })"],
definitions: [
makeDefinition(
[frDict(["min", frDate], ["max", frDate])],
[frDict(["min", frDateNumber], ["max", frDateNumber])],
([{ min, max }]) => {
return vDomain(new DateRangeDomain(min, max));
}
Expand Down
4 changes: 2 additions & 2 deletions packages/squiggle-lang/src/fr/dist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function makeCIDist<K1 extends string, K2 extends string>(
return makeDefinition(
[frDict([lowKey, frNumber], [highKey, frNumber])],
([dict], { environment }) =>
twoVarSample(dict[lowKey], dict[highKey], environment, fn)
vDist(twoVarSample(dict[lowKey], dict[highKey], environment, fn))
);
}

Expand All @@ -45,7 +45,7 @@ function makeMeanStdevDist(
return makeDefinition(
[frDict(["mean", frNumber], ["stdev", frNumber])],
([{ mean, stdev }], { environment }) =>
twoVarSample(mean, stdev, environment, fn)
vDist(twoVarSample(mean, stdev, environment, fn))
);
}

Expand Down
Loading
Loading