Skip to content

Commit 4d636bf

Browse files
authored
Line styles (#126)
* Correct chart title * Rotate colors over experiments and their permutations + use dotted line for Td line + highlight on hover Fixes #124 * Make sounding observations black line and working hover highlight color * Remove console.log
1 parent 5944709 commit 4d636bf

File tree

5 files changed

+50
-25
lines changed

5 files changed

+50
-25
lines changed

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ const colors = [
5959
"#b0ab0b",
6060
];
6161

62-
const linestyles = ["none", "5,5", "10,10", "15,5,5,5", "20,10,5,5,5,10"];
63-
6462
interface FlatExperiment {
6563
label: string;
6664
color: string;
@@ -71,12 +69,13 @@ interface FlatExperiment {
7169

7270
// Create a derived store for looping over all outputs:
7371
const flatExperiments: () => FlatExperiment[] = createMemo(() => {
72+
let nextColor = 0;
7473
return experiments
7574
.filter((e) => e.output.running === false) // skip running experiments
76-
.flatMap((e, i) => {
75+
.flatMap((e) => {
7776
const reference: FlatExperiment = {
78-
color: colors[0],
79-
linestyle: linestyles[i % 5],
77+
color: colors[nextColor++ % 10],
78+
linestyle: "none",
8079
label: e.config.reference.name,
8180
config: e.config.reference,
8281
output: e.output.reference,
@@ -86,8 +85,8 @@ const flatExperiments: () => FlatExperiment[] = createMemo(() => {
8685
const output = e.output.permutations[j];
8786
return {
8887
label: `${e.config.reference.name}/${config.name}`,
89-
color: colors[(j + 1) % 10],
90-
linestyle: linestyles[i % 5],
88+
color: colors[nextColor++ % 10],
89+
linestyle: "none",
9190
config,
9291
output,
9392
};
@@ -146,7 +145,7 @@ export function TimeSeriesPlot({ analysis }: { analysis: TimeseriesAnalysis }) {
146145
{/* TODO: get label for yVariable from model config */}
147146
<ChartContainer>
148147
<Legend entries={chartData} />
149-
<Chart title="Vertical profile plot" formatX={formatSeconds}>
148+
<Chart title="Timeseries plot" formatX={formatSeconds}>
150149
<AxisBottom domain={xLim} label="Time [s]" />
151150
<AxisLeft domain={yLim} label={analysis.yVariable} />
152151
<For each={chartData()}>{(d) => Line(d)}</For>

apps/class-solid/src/components/plots/ChartContainer.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,19 @@ export function useChartContext() {
162162
}
163163
return context;
164164
}
165+
165166
export interface ChartData<T> {
166167
label: string;
167168
color: string;
168169
linestyle: string;
169170
data: T[];
170171
}
172+
173+
export function highlight(hex: string) {
174+
const g = 246; // gray level
175+
const b = (h: string, i: number) =>
176+
Math.round(Number.parseInt(h.slice(i, i + 2), 16) * 0.5 + g * 0.5)
177+
.toString(16)
178+
.padStart(2, "0");
179+
return `#${b(hex, 1)}${b(hex, 3)}${b(hex, 5)}`;
180+
}

apps/class-solid/src/components/plots/Line.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
import * as d3 from "d3";
22
import { createSignal } from "solid-js";
33
import type { ChartData } from "./ChartContainer";
4-
import { useChartContext } from "./ChartContainer";
4+
import { highlight, useChartContext } from "./ChartContainer";
55

66
export interface Point {
77
x: number;
88
y: number;
99
}
1010

1111
export function Line(d: ChartData<Point>) {
12-
const [chart, updateChart] = useChartContext();
12+
const [chart, _updateChart] = useChartContext();
1313
const [hovered, setHovered] = createSignal(false);
1414

1515
const l = d3.line<Point>(
1616
(d) => chart.scaleX(d.x),
1717
(d) => chart.scaleY(d.y),
1818
);
19+
20+
const stroke = () => (hovered() ? highlight(d.color) : d.color);
21+
1922
return (
2023
<path
2124
onMouseEnter={() => setHovered(true)}
2225
onMouseLeave={() => setHovered(false)}
2326
fill="none"
24-
stroke={d.color}
27+
stroke={stroke()}
2528
stroke-dasharray={d.linestyle}
26-
stroke-width={hovered() ? 5 : 3}
29+
stroke-width="3"
2730
d={l(d.data) || ""}
2831
>
2932
<title>{d.label}</title>

apps/class-solid/src/components/plots/skewTlogP.tsx

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import * as d3 from "d3";
33
import { For, createSignal } from "solid-js";
44
import { AxisBottom, AxisLeft } from "./Axes";
55
import type { ChartData, SupportedScaleTypes } from "./ChartContainer";
6-
import { Chart, ChartContainer, useChartContext } from "./ChartContainer";
6+
import {
7+
Chart,
8+
ChartContainer,
9+
highlight,
10+
useChartContext,
11+
} from "./ChartContainer";
712
import { Legend } from "./Legend";
813
interface SoundingRecord {
914
p: number;
@@ -108,28 +113,36 @@ function Sounding(data: ChartData<SoundingRecord>) {
108113
.x((d) => x(d.Td - 273.15) + (y(basep) - y(d.p)) / tan)
109114
.y((d) => y(d.p));
110115

116+
const titleT = () => `${data.label} T`;
117+
const titleTd = () => `${data.label} Td`;
118+
119+
const stroke = () => (hovered() ? highlight(data.color) : data.color);
120+
111121
return (
112122
<g
113123
onMouseEnter={() => setHovered(true)}
114124
onMouseLeave={() => setHovered(false)}
115125
>
116-
<title>{data.label}</title>
117126
<path
118127
d={temperatureLine(data.data) || ""}
119128
clip-path="url(#clipper)"
120-
stroke={data.color}
129+
stroke={stroke()}
121130
stroke-dasharray={data.linestyle}
122-
stroke-width={hovered() ? 5 : 3}
131+
stroke-width={3}
123132
fill="none"
124-
/>
133+
>
134+
<title>{titleT()}</title>
135+
</path>
125136
<path
126137
d={dewpointLine(data.data) || ""}
127138
clip-path="url(#clipper)"
128-
stroke={data.color}
129-
stroke-dasharray={data.linestyle}
130-
stroke-width={hovered() ? 5 : 3}
139+
stroke={stroke()}
140+
stroke-dasharray="5,5"
141+
stroke-width={3}
131142
fill="none"
132-
/>
143+
>
144+
<title>{titleTd()}</title>
145+
</path>
133146
</g>
134147
);
135148
}

apps/class-solid/src/lib/profiles.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ export function getThermodynamicProfiles(
186186
export function observationsForProfile(obs: Observation, variable = "theta") {
187187
return {
188188
label: obs.name,
189-
color: "red",
190-
linestyle: "3,10",
189+
color: "#000000",
190+
linestyle: "none",
191191
data: obs.height.map((h, i) => {
192192
const T = obs.temperature[i] + 273.15;
193193
const rh = obs.relativeHumidity[i];
@@ -213,7 +213,7 @@ export function observationsForSounding(obs: Observation) {
213213
return { p, T, Td };
214214
}),
215215
label: obs.name,
216-
color: "red",
217-
linestyle: "3,10",
216+
color: "#000000",
217+
linestyle: "none",
218218
};
219219
}

0 commit comments

Comments
 (0)