plot.js (6972B)
1 import { REArgumentError, REOther } from "../errors/messages.js"; 2 import { makeDefinition } from "../library/registry/fnDefinition.js"; 3 import { frArray, frBool, frDict, frDist, frDistOrNumber, frLambda, frNumber, frOptional, frScale, frString, } from "../library/registry/frTypes.js"; 4 import { FnFactory, parseDistFromDistOrNumber, } from "../library/registry/helpers.js"; 5 import { vPlot } from "../value/index.js"; 6 const maker = new FnFactory({ 7 nameSpace: "Plot", 8 requiresNamespace: true, 9 }); 10 const defaultScale = { type: "linear" }; 11 function createScale(scale, domain) { 12 if (scale && scale.min && scale.max) { 13 return scale; 14 } 15 if (scale) { 16 if (scale.min === undefined && scale.max !== undefined) { 17 throw new REArgumentError("Scale max set without min. Must set either both or neither."); 18 } 19 if (scale.min !== undefined && scale.max === undefined) { 20 throw new REArgumentError("Scale min set without max. Must set either both or neither."); 21 } 22 } 23 if (!domain || domain.value.type !== "NumericRange") { 24 return scale ?? defaultScale; 25 } 26 if (scale) { 27 return { 28 ...scale, 29 min: scale.min ?? domain.value.min, 30 max: scale.max ?? domain.value.max, 31 }; 32 } 33 else { 34 return { type: "linear", min: domain.value.min, max: domain.value.max }; 35 } 36 } 37 function extractDomainFromOneArgFunction(fn) { 38 const counts = fn.parameterCounts(); 39 if (!counts.includes(1)) { 40 throw new REOther(`Plots only work with functions that have one parameter. This function only supports ${fn.parameterCountString()} parameters.`); 41 } 42 let domain; 43 if (fn.type === "UserDefinedLambda") { 44 domain = fn.parameters[0]?.domain; 45 } 46 else { 47 domain = undefined; 48 } 49 return domain; 50 } 51 export const library = [ 52 maker.make({ 53 name: "dists", 54 output: "Plot", 55 examples: [ 56 `Plot.dists({ 57 dists: [{ name: "dist", value: normal(0, 1) }], 58 xScale: Scale.symlog(), 59 })`, 60 ], 61 definitions: [ 62 makeDefinition([ 63 frDict([ 64 "dists", 65 frArray(frDict(["name", frString], ["value", frDistOrNumber])), 66 ], ["xScale", frOptional(frScale)], ["yScale", frOptional(frScale)], ["title", frOptional(frString)], ["showSummary", frOptional(frBool)]), 67 ], ([{ dists, xScale, yScale, title, showSummary }]) => { 68 const distributions = []; 69 dists.forEach(({ name, value }) => { 70 distributions.push({ 71 name, 72 distribution: parseDistFromDistOrNumber(value), 73 }); 74 }); 75 return vPlot({ 76 type: "distributions", 77 distributions, 78 xScale: xScale ?? defaultScale, 79 yScale: yScale ?? defaultScale, 80 title: title ?? undefined, 81 showSummary: showSummary ?? true, 82 }); 83 }), 84 ], 85 }), 86 maker.make({ 87 name: "dist", 88 output: "Plot", 89 examples: [ 90 `Plot.dist({ 91 dist: normal(0, 1), 92 xScale: Scale.symlog(), 93 })`, 94 ], 95 definitions: [ 96 makeDefinition([ 97 frDict(["dist", frDist], ["xScale", frOptional(frScale)], ["yScale", frOptional(frScale)], ["title", frOptional(frString)], ["showSummary", frOptional(frBool)]), 98 ], ([{ dist, xScale, yScale, title, showSummary }]) => { 99 return vPlot({ 100 type: "distributions", 101 distributions: [{ distribution: dist }], 102 xScale: xScale ?? defaultScale, 103 yScale: yScale ?? defaultScale, 104 title: title ?? undefined, 105 showSummary: showSummary ?? true, 106 }); 107 }), 108 ], 109 }), 110 maker.make({ 111 name: "numericFn", 112 output: "Plot", 113 examples: [ 114 `Plot.numericFn({ fn: {|x|x*x}, xScale: Scale.linear({ min: 3, max: 5 }), yScale: Scale.log({ tickFormat: ".2s" }) })`, 115 ], 116 definitions: [ 117 makeDefinition([ 118 frDict(["fn", frLambda], ["xScale", frOptional(frScale)], ["yScale", frOptional(frScale)], ["title", frOptional(frString)], ["points", frOptional(frNumber)]), 119 ], ([{ fn, xScale, yScale, title, points }]) => { 120 const domain = extractDomainFromOneArgFunction(fn); 121 return vPlot({ 122 type: "numericFn", 123 fn, 124 xScale: createScale(xScale, domain), 125 yScale: yScale ?? defaultScale, 126 points: points ?? undefined, 127 title: title ?? undefined, 128 }); 129 }), 130 ], 131 }), 132 maker.make({ 133 name: "distFn", 134 output: "Plot", 135 examples: [ 136 `Plot.distFn({ fn: {|x|uniform(x, x+1)}, xScale: Scale.linear({ min: 3, max: 5}), yScale: Scale.log({ tickFormat: ".2s" }) })`, 137 ], 138 definitions: [ 139 makeDefinition([ 140 frDict(["fn", frLambda], ["xScale", frOptional(frScale)], ["yScale", frOptional(frScale)], ["distXScale", frOptional(frScale)], ["title", frOptional(frString)], ["points", frOptional(frNumber)]), 141 ], ([{ fn, xScale, yScale, distXScale, title, points }]) => { 142 const domain = extractDomainFromOneArgFunction(fn); 143 return vPlot({ 144 type: "distFn", 145 fn, 146 xScale: createScale(xScale, domain), 147 yScale: yScale ?? defaultScale, 148 distXScale: distXScale ?? yScale ?? defaultScale, 149 title: title ?? undefined, 150 points: points ?? undefined, 151 }); 152 }), 153 ], 154 }), 155 maker.make({ 156 name: "scatter", 157 output: "Plot", 158 examples: [ 159 `Plot.scatter({ xDist: 2 to 5, yDist: SampleSet.fromDist(1 to 3) })`, 160 `Plot.scatter({ xDist: 2 to 5, yDist: SampleSet.fromDist(1 to 3), xScale: Scale.symlog(), yScale: Scale.symlog() })`, 161 ], 162 definitions: [ 163 makeDefinition([ 164 frDict(["xDist", frDist], ["yDist", frDist], ["xScale", frOptional(frScale)], ["yScale", frOptional(frScale)], ["title", frOptional(frString)]), 165 ], ([{ xDist, yDist, xScale, yScale, title }]) => { 166 return vPlot({ 167 type: "scatter", 168 xDist, 169 yDist, 170 xScale: xScale ?? defaultScale, 171 yScale: yScale ?? defaultScale, 172 title: title ?? undefined, 173 }); 174 }), 175 ], 176 }), 177 ]; 178 //# sourceMappingURL=plot.js.map