Skip to content

Commit 00e5b87

Browse files
committed
precompute all line plot arrays, but this is very slow
1 parent cd50647 commit 00e5b87

File tree

2 files changed

+94
-61
lines changed

2 files changed

+94
-61
lines changed

apps/class-solid/src/components/Analysis.tsx

Lines changed: 93 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -269,75 +269,60 @@ export function VerticalProfilePlot({
269269

270270
const showPlume = createMemo(() => isPlumeVariable(classVariable()));
271271

272-
const observations = () =>
273-
flatObservations().map((o) => observationsForProfile(o, classVariable()));
274-
275-
function extractLines<T extends Record<string, number[]>>(
276-
data: T,
277-
xvar: keyof T,
278-
yvar: keyof T,
279-
) {
280-
const xs = data[xvar] ?? [];
281-
const ys = data[yvar] ?? [];
282-
283-
const n = Math.min(xs.length, ys.length);
284-
285-
const result = new Array(n);
286-
for (let i = 0; i < n; i++) {
287-
result[i] = { x: xs[i], y: ys[i] };
288-
}
289-
290-
return result;
291-
}
292-
293-
const profileData = () =>
294-
flatExperiments().map((e) => {
272+
// Precalculate profile lines for classVariable() for all times
273+
const allProfileLines = () =>
274+
flatExperiments().flatMap((e) => {
295275
const { config, output, ...formatting } = e;
296276

297-
const targetTime = uniqueTimes()[analysis.time];
298-
const t = output?.timeseries.utcTime.indexOf(targetTime);
299-
300-
const profile =
301-
(t != null && t !== -1 && output?.profiles?.[t]) || noProfile;
277+
return uniqueTimes().map((time, tIndex) => {
278+
const profile = output?.profiles?.[tIndex] ?? noProfile;
302279

303-
return {
304-
...formatting,
305-
data: extractLines(profile, classVariable(), "z"),
306-
};
280+
return {
281+
...formatting,
282+
time,
283+
tIndex,
284+
data: extractLine(profile, classVariable(), "z"),
285+
};
286+
});
307287
});
308288

309-
const firePlumes = () =>
310-
flatExperiments().map((e) => {
289+
// Also precalculate plume lines
290+
const allPlumeLines = () =>
291+
flatExperiments().flatMap((e) => {
311292
const { config, output, ...formatting } = e;
312293

313-
const targetTime = uniqueTimes()[analysis.time];
314-
const t = output?.timeseries.utcTime.indexOf(targetTime);
315-
316-
const plume = (t != null && t !== -1 && output?.plumes?.[t]) || noPlume;
294+
return uniqueTimes().map((time, tIndex) => {
295+
const plume = output?.plumes?.[tIndex] ?? noPlume;
317296

318-
return {
319-
...formatting,
320-
linestyle: "4",
321-
data: extractLines(plume, classVariable() as PlumeVariable, "z"),
322-
};
297+
return {
298+
...formatting,
299+
time,
300+
tIndex,
301+
linestyle: "4",
302+
data: extractLine(plume, classVariable() as PlumeVariable, "z"),
303+
};
304+
});
323305
});
324-
325-
const allX = () => [
326-
...firePlumes().flatMap((p) => p.data.map((d) => d.x)),
327-
...profileDataForPlot().flatMap((p) => p.data.map((d) => d.x)),
328-
...observations().flatMap((obs) => obs.data.map((d) => d.x)),
329-
];
330-
const allY = () => [
331-
...firePlumes().flatMap((p) => p.data.map((d) => d.z)),
332-
...profileDataForPlot().flatMap((p) => p.data.map((d) => d.z)),
333-
...observations().flatMap((obs) => obs.data.map((d) => d.z)),
306+
307+
const observationLines = () =>
308+
flatObservations().map((o) => observationsForProfile(o, classVariable()));
309+
310+
const allLines = () => [
311+
...allPlumeLines(),
312+
...allProfileLines(),
313+
...observationLines(),
334314
];
335315

336-
const xLim = () => getNiceAxisLimits(allX(), 0);
337-
const yLim = () => [0, getNiceAxisLimits(allY(), 0)[1]] as [number, number];
316+
const limits = () => {
317+
const { xmin, xmax, ymin, ymax } = extractLimits(allLines());
318+
return { xLim: [xmin, xmax], yLim: [ymin, ymax] };
319+
};
320+
321+
const xLim = () => getNiceAxisLimits(limits().xLim);
322+
const yLim = () => getNiceAxisLimits(limits().yLim);
338323

339324
function chartData() {
340-
return [...profileData(), ...observations()];
325+
return [...allPlumeLines(), ...observationLines()];
341326
}
342327

343328
const [toggles, setToggles] = createStore<Record<string, boolean>>({});
@@ -356,33 +341,43 @@ export function VerticalProfilePlot({
356341
setResetPlot(analysis.id);
357342
}
358343

344+
const profilesAtSelectedTime = () => {
345+
const t = analysis.time;
346+
return allProfileLines().filter((line) => line.tIndex === t);
347+
};
348+
349+
const plumesAtSelectedTime = () => {
350+
const t = analysis.time;
351+
return allPlumeLines().filter((line) => line.tIndex === t);
352+
};
353+
359354
return (
360355
<>
361356
<div class="flex flex-col gap-2">
362357
<ChartContainer>
363358
<Legend
364-
entries={() => [...profileData(), ...observations()]}
359+
entries={() => [...profilesAtSelectedTime(), ...observationLines()]}
365360
toggles={toggles}
366361
onChange={toggleLine}
367362
/>
368363
<Chart id={analysis.id} title="Vertical profile plot">
369364
<AxisBottom domain={xLim} label={analysis.variable} />
370365
<AxisLeft domain={yLim} label="Height[m]" />
371-
<For each={profileDataForPlot()}>
366+
<For each={profilesAtSelectedTime()}>
372367
{(d) => (
373368
<Show when={toggles[d.label]}>
374369
<Line {...d} />
375370
</Show>
376371
)}
377372
</For>
378-
<For each={observations()}>
373+
<For each={observationLines()}>
379374
{(d) => (
380375
<Show when={toggles[d.label]}>
381376
<Line {...d} />
382377
</Show>
383378
)}
384379
</For>
385-
<For each={firePlumes()}>
380+
<For each={plumesAtSelectedTime()}>
386381
{(d) => (
387382
<Show when={toggles[d.label]}>
388383
<Show when={showPlume()}>
@@ -630,3 +625,41 @@ export function AnalysisCard(analysis: Analysis) {
630625
</Card>
631626
);
632627
}
628+
629+
// Helper functions
630+
631+
function extractLine<T extends Record<string, number[]>>(
632+
data: T,
633+
xvar: keyof T,
634+
yvar: keyof T,
635+
) {
636+
const xs = data[xvar] ?? [];
637+
const ys = data[yvar] ?? [];
638+
639+
const n = Math.min(xs.length, ys.length);
640+
641+
const result = new Array(n);
642+
for (let i = 0; i < n; i++) {
643+
result[i] = { x: xs[i], y: ys[i] };
644+
}
645+
646+
return result;
647+
}
648+
649+
function extractLimits(lines: { data: { x: number; y: number }[] }[]) {
650+
let xmin = Number.POSITIVE_INFINITY;
651+
let xmax = Number.NEGATIVE_INFINITY;
652+
let ymin = Number.POSITIVE_INFINITY;
653+
let ymax = Number.NEGATIVE_INFINITY;
654+
655+
for (const line of lines) {
656+
for (const p of line.data) {
657+
if (p.x < xmin) xmin = p.x;
658+
if (p.x > xmax) xmax = p.x;
659+
if (p.y < ymin) ymin = p.y;
660+
if (p.y > ymax) ymax = p.y;
661+
}
662+
}
663+
664+
return { xmin, xmax, ymin, ymax };
665+
}

packages/class/src/profiles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export const noProfile: ClassProfile = {
5656
export function generateProfiles(
5757
config: MixedLayerConfig & (WindConfig | NoWindConfig),
5858
output: ClassOutput,
59-
dz = 1,
59+
dz = 10,
6060
): ClassProfile {
6161
const { Rd, cp, g } = CONSTANTS;
6262
const { h, theta, qt, u, v, dtheta, dqt, du, dv } = output;

0 commit comments

Comments
 (0)