Skip to content

Commit

Permalink
dynamic colors by variable
Browse files Browse the repository at this point in the history
  • Loading branch information
hillalex committed Aug 1, 2024
1 parent 1b578eb commit 9af333f
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 34 deletions.
27 changes: 4 additions & 23 deletions app/RootContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ export interface PlotOptions {
export interface PlotConfig {
key: string
displayName: string
type: string,
lineColors?: any
fillColors?: any
type: string
}

export interface Model {
Expand Down Expand Up @@ -57,31 +55,14 @@ const biomarkerModel: Model = {
plots: [{
key: "pop_fits",
displayName: "Population fits",
type: "line",
lineColors: [
`rgba(204, 102, 119, 1)`,
`rgba(221, 204, 119, 1)`,
`rgba(136, 204, 238, 1)`,
`rgba(136, 34, 85, 1)`,
`rgba(68, 170, 153, 1)`,
`rgba(226, 226, 226, 1)`]
,
fillColors: [
`rgba(204, 102, 119, 0.3)`,
`rgba(221, 204, 119, 0.3)`,
`rgba(136, 204, 238, 0.3)`,
`rgba(136, 34, 85, 0.3)`,
`rgba(68, 170, 153, 0.3)`,
`rgba(226, 226, 226, 0.3)`

]
type: "line"
}],
variables: [{key: "titre_type", displayName: "Titre type"}]
}

export const initialState: AppState = {
models: [biomarkerModel],
selectedPlotOptions: {}
models: [biomarkerModel],
selectedPlotOptions: {}
}

export const RootContext = createContext<AppContext>({
Expand Down
1 change: 1 addition & 0 deletions app/components/ConfiguredPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface Props {
facetVariables: Covariate[],
traceVariables: Covariate[],
plot: PlotConfig
key: string
}

function Facet({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import Plot from 'react-plotly.js';
import {Covariate, PlotConfig} from "~/RootContext";
import {Covariate} from "~/RootContext";
import {interpolateBlues, interpolateOranges, interpolatePurples, interpolateGreens} from "d3-scale-chromatic";

interface Dat {
t: number
me: number
lo: number
hi: number

[index: string]: string | number
}

Expand All @@ -16,7 +18,6 @@ interface Props {
traces: { [k: string]: string[] }
value: string
parent: string
plot: PlotConfig
}

function showLegend(traces: Covariate[]) {
Expand All @@ -30,10 +31,50 @@ function permuteArrays(first, next, ...rest) {
return first.flatMap(a => next.map(b => [a, b].flat()));
}

export default function LocalPlot({data, traceVariables, traces, value, parent, plot}: Props) {
const colorFunctions = [
interpolateBlues,
interpolateOranges,
interpolatePurples,
interpolateGreens
]

function addOpacity(color) {
return color.replace(')', ', 0.3)').replace('rgb', 'rgba');
}

function getColors(traces, traceVariables, index, traceDefinition, numTraces) {
if (traceVariables.length == 0) {
const color = interpolateOranges(0.5);
return [color, addOpacity(color)]
}
if (traceVariables.length == 1) {
const color = colorFunctions[index](0.5)
return [color, addOpacity(color)]
}
if (traceVariables.length == 2) {
const firstTraceVariable = traceDefinition[0];
const levels = traces[traceVariables[0].key];
const levelIndex = levels.indexOf(firstTraceVariable);

const secondTraceVariable = traceDefinition[1];
const secondLevels = traces[traceVariables[1].key];
const secondLevelIndex = secondLevels.indexOf(secondTraceVariable);

const color = colorFunctions[levelIndex]((secondLevelIndex + 1) / secondLevels.length);
return [color, addOpacity(color)]
}
if (traceVariables.length > 2) {
// at this point the graph becomes quite unreadable anyway, so just let all traces
// be variations on a color scale
const color = colorFunctions[0]((index + 1) / numTraces)
return [color, addOpacity(color)]
}
}

export default function LinePlot({data, traceVariables, traces, value, parent}: Props) {

let traceDatasets = [data];
const traceDefinitions = permuteArrays(...traceVariables.map(v => traces[v.key]))
const traceDefinitions = permuteArrays(...traceVariables.map(v => traces[v.key]));

if (traceDefinitions.length > 0) {
traceDatasets = traceDefinitions.map(td =>
Expand All @@ -53,12 +94,13 @@ export default function LocalPlot({data, traceVariables, traces, value, parent,
const subsets = traceDatasets.map((dataset, i) => {
const times = dataset.map(d => d.t);
const seriesName = traceDefinitions.length > 0 ? traceDefinitions[i].join(" ") : "";
const color = getColors(traces, traceVariables, i, traceDefinitions[i], traceDatasets.length);
return [{
x: times,
y: dataset.map(d => d.lo),
name: seriesName,
line: {color: "transparent"},
marker: {color: plot.lineColors[i]},
marker: {color: color[0]},
showlegend: false,
legendgroup: i,
type: "scatter",
Expand All @@ -71,9 +113,9 @@ export default function LocalPlot({data, traceVariables, traces, value, parent,
type: 'scatter',
mode: 'lines',
fill: "tonexty",
fillcolor: plot.fillColors[i],
fillcolor: color[1],
showlegend: showLegend(traceVariables),
marker: {color: plot.lineColors[i]},
marker: {color: color[0]},
}, {
x: times,
y: dataset.map(d => d.hi),
Expand All @@ -84,7 +126,7 @@ export default function LocalPlot({data, traceVariables, traces, value, parent,
type: "scatter",
mode: "lines",
fill: "tonexty",
fillcolor: plot.fillColors[i],
fillcolor: color[1],
}]
}).flat();

Expand Down
11 changes: 9 additions & 2 deletions app/components/LocalPlot.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import {ClientOnly} from "remix-utils/client-only"
import Plot from "./LocalPlot.client";
import {Covariate, PlotConfig} from "~/RootContext";
import LinePlot from "./LinePlot.client";
import {createElement} from "react";

interface Dat {
[index: string]: string | number
}

function PlotByType(type: string, props: Props) {
if (type == "line") {
return createElement(LinePlot, props)
}
}

interface Props {
data: Dat[],
traceVariables: Covariate[]
Expand All @@ -17,6 +24,6 @@ interface Props {

export default function LocalPlot(props: Props) {
return <ClientOnly>
{() => (<Plot {...props} />)}
{() => PlotByType(props.plot.type, props)}
</ClientOnly>
}
2 changes: 1 addition & 1 deletion app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function Layout({children}: { children: React.ReactNode }) {
initialState as ReducerState<AppReducer>
);
const [status, selected] = useSelectedModel();
if (status == 200) {
if (status == 200 && selected) {
const {selectedModel, selectedRegressionModel} = selected;

const newState = {...appState}
Expand Down
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@remix-run/react": "^2.10.0",
"bootstrap": "^5.3.3",
"cross-env": "^7.0.3",
"d3-scale-chromatic": "^3.1.0",
"electron": "^31.1.0",
"express": "^4.19.2",
"isbot": "^4.4.0",
Expand Down

0 comments on commit 9af333f

Please sign in to comment.