@genspectrum/dashboard-components 0.4.5 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +2 -2
  2. package/custom-elements.json +178 -102
  3. package/dist/dashboard-components.js +473 -289
  4. package/dist/dashboard-components.js.map +1 -1
  5. package/dist/genspectrum-components.d.ts +93 -57
  6. package/dist/style.css +53 -13
  7. package/package.json +5 -5
  8. package/src/preact/aggregatedData/aggregate-table.tsx +4 -2
  9. package/src/preact/dateRangeSelector/date-range-selector.tsx +3 -5
  10. package/src/preact/mutationComparison/mutation-comparison-venn.tsx +1 -1
  11. package/src/preact/mutationComparison/mutation-comparison.stories.tsx +18 -18
  12. package/src/preact/mutationComparison/mutation-comparison.tsx +6 -6
  13. package/src/preact/mutationComparison/queryMutationData.ts +4 -4
  14. package/src/preact/mutations/mutations.stories.tsx +3 -3
  15. package/src/preact/mutations/mutations.tsx +16 -6
  16. package/src/preact/mutations/queryMutations.ts +3 -3
  17. package/src/preact/prevalenceOverTime/__mockData__/{denominatorOneVariant.json → denominatorFilterOneDataset.json} +1 -1
  18. package/src/preact/prevalenceOverTime/__mockData__/{numeratorOneVariant.json → numeratorFilterOneDataset.json} +1 -1
  19. package/src/preact/prevalenceOverTime/prevalence-over-time-bar-chart.tsx +42 -5
  20. package/src/preact/prevalenceOverTime/prevalence-over-time-bubble-chart.tsx +26 -7
  21. package/src/preact/prevalenceOverTime/prevalence-over-time-line-chart.tsx +62 -28
  22. package/src/preact/prevalenceOverTime/prevalence-over-time.stories.tsx +26 -16
  23. package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +38 -11
  24. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage-chart.tsx +39 -7
  25. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.stories.tsx +10 -4
  26. package/src/preact/relativeGrowthAdvantage/relative-growth-advantage.tsx +19 -10
  27. package/src/preact/shared/charts/confideceInterval.ts +7 -2
  28. package/src/preact/shared/charts/getYAxisMax.ts +24 -0
  29. package/src/preact/shared/charts/getYAxisScale.ts +1 -3
  30. package/src/query/queryAggregateData.ts +3 -3
  31. package/src/query/queryInsertions.ts +7 -2
  32. package/src/query/querySubstitutionsOrDeletions.ts +2 -2
  33. package/src/web-components/input/gs-date-range-selector.tsx +1 -1
  34. package/src/web-components/input/gs-location-filter.tsx +1 -1
  35. package/src/web-components/input/gs-mutation-filter.tsx +1 -1
  36. package/src/web-components/input/gs-text-input.tsx +1 -1
  37. package/src/web-components/visualization/gs-aggregate.tsx +2 -2
  38. package/src/web-components/visualization/gs-mutation-comparison.stories.ts +12 -12
  39. package/src/web-components/visualization/gs-mutation-comparison.tsx +18 -19
  40. package/src/web-components/visualization/gs-mutations.stories.ts +4 -4
  41. package/src/web-components/visualization/gs-mutations.tsx +10 -11
  42. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +46 -35
  43. package/src/web-components/visualization/gs-prevalence-over-time.tsx +54 -20
  44. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +32 -18
  45. package/src/web-components/visualization/gs-relative-growth-advantage.tsx +51 -13
  46. /package/src/preact/mutationComparison/__mockData__/{nucleotideMutationsOtherVariant.json → nucleotideMutationsOtherDataset.json} +0 -0
  47. /package/src/preact/mutationComparison/__mockData__/{nucleotideMutationsSomeVariant.json → nucleotideMutationsSomeDataset.json} +0 -0
  48. /package/src/preact/prevalenceOverTime/__mockData__/{denominator.json → denominatorFilter.json} +0 -0
  49. /package/src/preact/prevalenceOverTime/__mockData__/{numeratorEG.json → numeratorFilterEG.json} +0 -0
  50. /package/src/preact/prevalenceOverTime/__mockData__/{numeratorJN1.json → numeratorFilterJN1.json} +0 -0
  51. /package/src/preact/relativeGrowthAdvantage/__mockData__/{denominator.json → denominatorFilter.json} +0 -0
  52. /package/src/preact/relativeGrowthAdvantage/__mockData__/{numerator.json → numeratorFilter.json} +0 -0
@@ -1,8 +1,8 @@
1
- import denominator from './__mockData__/denominator.json';
2
- import denominatorOneVariant from './__mockData__/denominatorOneVariant.json';
3
- import numeratorEG from './__mockData__/numeratorEG.json';
4
- import numeratorJN1 from './__mockData__/numeratorJN1.json';
5
- import numeratorOneVariant from './__mockData__/numeratorOneVariant.json';
1
+ import denominatorFilter from './__mockData__/denominatorFilter.json';
2
+ import denominatorOneDataset from './__mockData__/denominatorFilterOneDataset.json';
3
+ import numeratorFilterEG from './__mockData__/numeratorFilterEG.json';
4
+ import numeratorFilterJN1 from './__mockData__/numeratorFilterJN1.json';
5
+ import numeratorOneDataset from './__mockData__/numeratorFilterOneDataset.json';
6
6
  import { PrevalenceOverTime, type PrevalenceOverTimeProps } from './prevalence-over-time';
7
7
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
8
8
  import { LapisUrlContext } from '../LapisUrlContext';
@@ -33,6 +33,7 @@ export default {
33
33
  height: { control: 'text' },
34
34
  headline: { control: 'text' },
35
35
  pageSize: { control: 'object' },
36
+ yAxisMaxConfig: { control: 'object' },
36
37
  },
37
38
  };
38
39
 
@@ -40,8 +41,8 @@ const Template = {
40
41
  render: (args: PrevalenceOverTimeProps) => (
41
42
  <LapisUrlContext.Provider value={LAPIS_URL}>
42
43
  <PrevalenceOverTime
43
- numerator={args.numerator}
44
- denominator={args.denominator}
44
+ numeratorFilter={args.numeratorFilter}
45
+ denominatorFilter={args.denominatorFilter}
45
46
  granularity={args.granularity}
46
47
  smoothingWindow={args.smoothingWindow}
47
48
  views={args.views}
@@ -51,6 +52,7 @@ const Template = {
51
52
  headline={args.headline}
52
53
  lapisDateField={args.lapisDateField}
53
54
  pageSize={args.pageSize}
55
+ yAxisMaxConfig={args.yAxisMaxConfig}
54
56
  />
55
57
  </LapisUrlContext.Provider>
56
58
  ),
@@ -59,11 +61,11 @@ const Template = {
59
61
  export const TwoVariants = {
60
62
  ...Template,
61
63
  args: {
62
- numerator: [
64
+ numeratorFilter: [
63
65
  { displayName: 'EG', lapisFilter: { country: 'USA', pangoLineage: 'EG*', dateFrom: '2023-01-01' } },
64
66
  { displayName: 'JN.1', lapisFilter: { country: 'USA', pangoLineage: 'JN.1*', dateFrom: '2023-01-01' } },
65
67
  ],
66
- denominator: { country: 'USA', dateFrom: '2023-01-01' },
68
+ denominatorFilter: { country: 'USA', dateFrom: '2023-01-01' },
67
69
  granularity: 'month',
68
70
  smoothingWindow: 0,
69
71
  views: ['bar', 'line', 'bubble', 'table'],
@@ -73,6 +75,10 @@ export const TwoVariants = {
73
75
  headline: 'Prevalence over time',
74
76
  lapisDateField: 'date',
75
77
  pageSize: 10,
78
+ yAxisMaxConfig: {
79
+ linear: 1,
80
+ logarithmic: 1,
81
+ },
76
82
  },
77
83
  parameters: {
78
84
  fetchMock: {
@@ -90,7 +96,7 @@ export const TwoVariants = {
90
96
  },
91
97
  response: {
92
98
  status: 200,
93
- body: numeratorEG,
99
+ body: numeratorFilterEG,
94
100
  },
95
101
  },
96
102
  {
@@ -106,7 +112,7 @@ export const TwoVariants = {
106
112
  },
107
113
  response: {
108
114
  status: 200,
109
- body: numeratorJN1,
115
+ body: numeratorFilterJN1,
110
116
  },
111
117
  },
112
118
  {
@@ -121,7 +127,7 @@ export const TwoVariants = {
121
127
  },
122
128
  response: {
123
129
  status: 200,
124
- body: denominator,
130
+ body: denominatorFilter,
125
131
  },
126
132
  },
127
133
  ],
@@ -132,11 +138,11 @@ export const TwoVariants = {
132
138
  export const OneVariant = {
133
139
  ...Template,
134
140
  args: {
135
- numerator: {
141
+ numeratorFilter: {
136
142
  displayName: 'EG',
137
143
  lapisFilter: { country: 'USA', pangoLineage: 'BA.2.86*', dateFrom: '2023-10-01' },
138
144
  },
139
- denominator: { country: 'USA', dateFrom: '2023-10-01' },
145
+ denominatorFilter: { country: 'USA', dateFrom: '2023-10-01' },
140
146
  granularity: 'day',
141
147
  smoothingWindow: 7,
142
148
  views: ['bar', 'line', 'bubble', 'table'],
@@ -146,6 +152,10 @@ export const OneVariant = {
146
152
  headline: 'Prevalence over time',
147
153
  lapisDateField: 'date',
148
154
  pageSize: 10,
155
+ yAxisMaxConfig: {
156
+ linear: 1,
157
+ logarithmic: 1,
158
+ },
149
159
  },
150
160
  parameters: {
151
161
  fetchMock: {
@@ -163,7 +173,7 @@ export const OneVariant = {
163
173
  },
164
174
  response: {
165
175
  status: 200,
166
- body: numeratorOneVariant,
176
+ body: numeratorOneDataset,
167
177
  },
168
178
  },
169
179
  {
@@ -178,7 +188,7 @@ export const OneVariant = {
178
188
  },
179
189
  response: {
180
190
  status: 200,
181
- body: denominatorOneVariant,
191
+ body: denominatorOneDataset,
182
192
  },
183
193
  },
184
194
  ],
@@ -21,6 +21,7 @@ import { ResizeContainer } from '../components/resize-container';
21
21
  import { ScalingSelector } from '../components/scaling-selector';
22
22
  import Tabs from '../components/tabs';
23
23
  import { type ConfidenceIntervalMethod } from '../shared/charts/confideceInterval';
24
+ import type { YAxisMaxConfig } from '../shared/charts/getYAxisMax';
24
25
  import { type ScaleType } from '../shared/charts/getYAxisScale';
25
26
  import { useQuery } from '../useQuery';
26
27
 
@@ -33,19 +34,20 @@ export interface PrevalenceOverTimeProps extends PrevalenceOverTimeInnerProps {
33
34
  }
34
35
 
35
36
  export interface PrevalenceOverTimeInnerProps {
36
- numerator: NamedLapisFilter | NamedLapisFilter[];
37
- denominator: LapisFilter;
37
+ numeratorFilter: NamedLapisFilter | NamedLapisFilter[];
38
+ denominatorFilter: LapisFilter;
38
39
  granularity: TemporalGranularity;
39
40
  smoothingWindow: number;
40
41
  views: View[];
41
42
  confidenceIntervalMethods: ConfidenceIntervalMethod[];
42
43
  lapisDateField: string;
43
44
  pageSize: boolean | number;
45
+ yAxisMaxConfig: YAxisMaxConfig;
44
46
  }
45
47
 
46
48
  export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
47
- numerator,
48
- denominator,
49
+ numeratorFilter,
50
+ denominatorFilter,
49
51
  granularity,
50
52
  smoothingWindow,
51
53
  views,
@@ -55,6 +57,7 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
55
57
  headline = 'Prevalence over time',
56
58
  lapisDateField,
57
59
  pageSize,
60
+ yAxisMaxConfig,
58
61
  }) => {
59
62
  const size = { height, width };
60
63
 
@@ -63,14 +66,15 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
63
66
  <ResizeContainer size={size}>
64
67
  <Headline heading={headline}>
65
68
  <PrevalenceOverTimeInner
66
- numerator={numerator}
67
- denominator={denominator}
69
+ numeratorFilter={numeratorFilter}
70
+ denominatorFilter={denominatorFilter}
68
71
  granularity={granularity}
69
72
  smoothingWindow={smoothingWindow}
70
73
  views={views}
71
74
  confidenceIntervalMethods={confidenceIntervalMethods}
72
75
  lapisDateField={lapisDateField}
73
76
  pageSize={pageSize}
77
+ yAxisMaxConfig={yAxisMaxConfig}
74
78
  />
75
79
  </Headline>
76
80
  </ResizeContainer>
@@ -79,20 +83,29 @@ export const PrevalenceOverTime: FunctionComponent<PrevalenceOverTimeProps> = ({
79
83
  };
80
84
 
81
85
  export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeInnerProps> = ({
82
- numerator,
83
- denominator,
86
+ numeratorFilter,
87
+ denominatorFilter,
84
88
  granularity,
85
89
  smoothingWindow,
86
90
  views,
87
91
  confidenceIntervalMethods,
88
92
  lapisDateField,
89
93
  pageSize,
94
+ yAxisMaxConfig,
90
95
  }) => {
91
96
  const lapis = useContext(LapisUrlContext);
92
97
 
93
98
  const { data, error, isLoading } = useQuery(
94
- () => queryPrevalenceOverTime(numerator, denominator, granularity, smoothingWindow, lapis, lapisDateField),
95
- [lapis, numerator, denominator, granularity, smoothingWindow],
99
+ () =>
100
+ queryPrevalenceOverTime(
101
+ numeratorFilter,
102
+ denominatorFilter,
103
+ granularity,
104
+ smoothingWindow,
105
+ lapis,
106
+ lapisDateField,
107
+ ),
108
+ [lapis, numeratorFilter, denominatorFilter, granularity, smoothingWindow],
96
109
  );
97
110
 
98
111
  if (isLoading) {
@@ -114,6 +127,7 @@ export const PrevalenceOverTimeInner: FunctionComponent<PrevalenceOverTimeInnerP
114
127
  granularity={granularity}
115
128
  confidenceIntervalMethods={confidenceIntervalMethods}
116
129
  pageSize={pageSize}
130
+ yAxisMaxConfig={yAxisMaxConfig}
117
131
  />
118
132
  );
119
133
  };
@@ -124,6 +138,7 @@ type PrevalenceOverTimeTabsProps = {
124
138
  granularity: TemporalGranularity;
125
139
  confidenceIntervalMethods: ConfidenceIntervalMethod[];
126
140
  pageSize: boolean | number;
141
+ yAxisMaxConfig: YAxisMaxConfig;
127
142
  };
128
143
 
129
144
  const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = ({
@@ -132,6 +147,7 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
132
147
  granularity,
133
148
  confidenceIntervalMethods,
134
149
  pageSize,
150
+ yAxisMaxConfig,
135
151
  }) => {
136
152
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
137
153
  const [confidenceIntervalMethod, setConfidenceIntervalMethod] = useState<ConfidenceIntervalMethod>(
@@ -148,6 +164,7 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
148
164
  data={data}
149
165
  yAxisScaleType={yAxisScaleType}
150
166
  confidenceIntervalMethod={confidenceIntervalMethod}
167
+ yAxisMaxConfig={yAxisMaxConfig}
151
168
  />
152
169
  ),
153
170
  };
@@ -159,13 +176,20 @@ const PrevalenceOverTimeTabs: FunctionComponent<PrevalenceOverTimeTabsProps> = (
159
176
  data={data}
160
177
  yAxisScaleType={yAxisScaleType}
161
178
  confidenceIntervalMethod={confidenceIntervalMethod}
179
+ yAxisMaxConfig={yAxisMaxConfig}
162
180
  />
163
181
  ),
164
182
  };
165
183
  case 'bubble':
166
184
  return {
167
185
  title: 'Bubble',
168
- content: <PrevalenceOverTimeBubbleChart data={data} yAxisScaleType={yAxisScaleType} />,
186
+ content: (
187
+ <PrevalenceOverTimeBubbleChart
188
+ data={data}
189
+ yAxisScaleType={yAxisScaleType}
190
+ yAxisMaxConfig={yAxisMaxConfig}
191
+ />
192
+ ),
169
193
  };
170
194
  case 'table':
171
195
  return {
@@ -245,3 +269,6 @@ const PrevalenceOverTimeInfo: FunctionComponent = () => {
245
269
  </Info>
246
270
  );
247
271
  };
272
+
273
+ export const maxInData = (data: PrevalenceOverTimeData) =>
274
+ Math.max(...data.flatMap((variant) => variant.content.map((dataPoint) => dataPoint.prevalence)));
@@ -5,7 +5,9 @@ import GsChart from '../components/chart';
5
5
  import { LogitScale } from '../shared/charts/LogitScale';
6
6
  import { singleGraphColorRGBByName } from '../shared/charts/colors';
7
7
  import { confidenceIntervalDataLabel } from '../shared/charts/confideceInterval';
8
+ import { getYAxisMax, type YAxisMaxConfig } from '../shared/charts/getYAxisMax';
8
9
  import { getYAxisScale, type ScaleType } from '../shared/charts/getYAxisScale';
10
+ import { formatProportion } from '../shared/table/formatProportion';
9
11
 
10
12
  interface RelativeGrowthAdvantageChartData {
11
13
  t: YearMonthDay[];
@@ -25,11 +27,17 @@ interface RelativeGrowthAdvantageChartData {
25
27
  interface RelativeGrowthAdvantageChartProps {
26
28
  data: RelativeGrowthAdvantageChartData;
27
29
  yAxisScaleType: ScaleType;
30
+ yAxisMaxConfig: YAxisMaxConfig;
28
31
  }
29
32
 
30
33
  Chart.register(...registerables, LogitScale);
31
34
 
32
- const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }: RelativeGrowthAdvantageChartProps) => {
35
+ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType, yAxisMaxConfig }: RelativeGrowthAdvantageChartProps) => {
36
+ const maxY =
37
+ yAxisScaleType !== 'logit'
38
+ ? getYAxisMax(Math.max(...data.proportion), yAxisMaxConfig?.[yAxisScaleType])
39
+ : undefined;
40
+
33
41
  const config: ChartConfiguration = {
34
42
  type: 'line',
35
43
  data: {
@@ -39,8 +47,9 @@ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }: RelativeGrowthAd
39
47
  options: {
40
48
  maintainAspectRatio: false,
41
49
  animation: false,
50
+
42
51
  scales: {
43
- y: getYAxisScale(yAxisScaleType),
52
+ y: { ...getYAxisScale(yAxisScaleType), max: maxY },
44
53
  },
45
54
  plugins: {
46
55
  legend: {
@@ -52,14 +61,37 @@ const RelativeGrowthAdvantageChart = ({ data, yAxisScaleType }: RelativeGrowthAd
52
61
  };
53
62
 
54
63
  return (
55
- <div className='flex flex-col h-full'>
64
+ <div className='flex h-full flex-col'>
65
+ <RelativeGrowthAdvantageDisplay
66
+ relativeAdvantage={data.params.fd.value}
67
+ relativeAdvantageLowerBound={data.params.fd.ciLower}
68
+ relativeAdvantageUpperBound={data.params.fd.ciUpper}
69
+ />
56
70
  <div className='flex-1'>
57
71
  <GsChart configuration={config} />
58
72
  </div>
59
- <p>
60
- Advantage: {(data.params.fd.value * 100).toFixed(2)}% ({(data.params.fd.ciLower * 100).toFixed(2)}% -{' '}
61
- {(data.params.fd.ciUpper * 100).toFixed(2)}%)
62
- </p>
73
+ </div>
74
+ );
75
+ };
76
+
77
+ const RelativeGrowthAdvantageDisplay = ({
78
+ relativeAdvantage,
79
+ relativeAdvantageLowerBound,
80
+ relativeAdvantageUpperBound,
81
+ }: {
82
+ relativeAdvantage: number;
83
+ relativeAdvantageLowerBound: number;
84
+ relativeAdvantageUpperBound: number;
85
+ }) => {
86
+ return (
87
+ <div class='mx-auto flex items-end flex-wrap'>
88
+ <span class='text-[#606060]'>Relative advantage:</span>
89
+ <div>
90
+ <span class='text-2xl ml-3'> {formatProportion(relativeAdvantage)} </span>
91
+ <span class='ml-2.5'>
92
+ ({formatProportion(relativeAdvantageLowerBound)} - {formatProportion(relativeAdvantageUpperBound)})
93
+ </span>
94
+ </div>
63
95
  </div>
64
96
  );
65
97
  };
@@ -1,5 +1,5 @@
1
- import denominator from './__mockData__/denominator.json';
2
- import numerator from './__mockData__/numerator.json';
1
+ import denominator from './__mockData__/denominatorFilter.json';
2
+ import numerator from './__mockData__/numeratorFilter.json';
3
3
  import { RelativeGrowthAdvantage, type RelativeGrowthAdvantageProps } from './relative-growth-advantage';
4
4
  import { AGGREGATED_ENDPOINT, LAPIS_URL } from '../../constants';
5
5
  import { LapisUrlContext } from '../LapisUrlContext';
@@ -21,6 +21,7 @@ export default {
21
21
  width: { control: 'text' },
22
22
  height: { control: 'text' },
23
23
  headline: { control: 'text' },
24
+ yAxisMaxConfig: { control: 'object' },
24
25
  },
25
26
  };
26
27
 
@@ -28,14 +29,15 @@ export const Primary = {
28
29
  render: (args: RelativeGrowthAdvantageProps) => (
29
30
  <LapisUrlContext.Provider value={LAPIS_URL}>
30
31
  <RelativeGrowthAdvantage
31
- numerator={args.numerator}
32
- denominator={args.denominator}
32
+ numeratorFilter={args.numeratorFilter}
33
+ denominatorFilter={args.denominatorFilter}
33
34
  generationTime={args.generationTime}
34
35
  views={args.views}
35
36
  width={args.width}
36
37
  height={args.height}
37
38
  headline={args.headline}
38
39
  lapisDateField={args.lapisDateField}
40
+ yAxisMaxConfig={args.yAxisMaxConfig}
39
41
  />
40
42
  </LapisUrlContext.Provider>
41
43
  ),
@@ -48,6 +50,10 @@ export const Primary = {
48
50
  height: '700px',
49
51
  headline: 'Relative growth advantage',
50
52
  lapisDateField: 'date',
53
+ yAxisMaxConfig: {
54
+ linear: 1,
55
+ logarithmic: 1,
56
+ },
51
57
  },
52
58
  parameters: {
53
59
  fetchMock: {
@@ -17,6 +17,7 @@ import { NoDataDisplay } from '../components/no-data-display';
17
17
  import { ResizeContainer } from '../components/resize-container';
18
18
  import { ScalingSelector } from '../components/scaling-selector';
19
19
  import Tabs from '../components/tabs';
20
+ import { type YAxisMaxConfig } from '../shared/charts/getYAxisMax';
20
21
  import { type ScaleType } from '../shared/charts/getYAxisScale';
21
22
  import { useQuery } from '../useQuery';
22
23
 
@@ -29,22 +30,24 @@ export interface RelativeGrowthAdvantageProps extends RelativeGrowthAdvantagePro
29
30
  }
30
31
 
31
32
  export interface RelativeGrowthAdvantagePropsInner {
32
- numerator: LapisFilter;
33
- denominator: LapisFilter;
33
+ numeratorFilter: LapisFilter;
34
+ denominatorFilter: LapisFilter;
34
35
  generationTime: number;
35
36
  views: View[];
36
37
  lapisDateField: string;
38
+ yAxisMaxConfig: YAxisMaxConfig;
37
39
  }
38
40
 
39
41
  export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageProps> = ({
40
42
  views,
41
43
  width,
42
44
  height,
43
- numerator,
44
- denominator,
45
+ numeratorFilter,
46
+ denominatorFilter,
45
47
  generationTime,
46
48
  headline = 'Relative growth advantage',
47
49
  lapisDateField,
50
+ yAxisMaxConfig,
48
51
  }) => {
49
52
  const size = { height, width };
50
53
 
@@ -54,10 +57,11 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
54
57
  <Headline heading={headline}>
55
58
  <RelativeGrowthAdvantageInner
56
59
  views={views}
57
- numerator={numerator}
58
- denominator={denominator}
60
+ numeratorFilter={numeratorFilter}
61
+ denominatorFilter={denominatorFilter}
59
62
  generationTime={generationTime}
60
63
  lapisDateField={lapisDateField}
64
+ yAxisMaxConfig={yAxisMaxConfig}
61
65
  />
62
66
  </Headline>
63
67
  </ResizeContainer>
@@ -66,18 +70,19 @@ export const RelativeGrowthAdvantage: FunctionComponent<RelativeGrowthAdvantageP
66
70
  };
67
71
 
68
72
  export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvantagePropsInner> = ({
69
- numerator,
70
- denominator,
73
+ numeratorFilter,
74
+ denominatorFilter,
71
75
  generationTime,
72
76
  views,
73
77
  lapisDateField,
78
+ yAxisMaxConfig,
74
79
  }) => {
75
80
  const lapis = useContext(LapisUrlContext);
76
81
  const [yAxisScaleType, setYAxisScaleType] = useState<ScaleType>('linear');
77
82
 
78
83
  const { data, error, isLoading } = useQuery(
79
- () => queryRelativeGrowthAdvantage(numerator, denominator, generationTime, lapis, lapisDateField),
80
- [lapis, numerator, denominator, generationTime, views],
84
+ () => queryRelativeGrowthAdvantage(numeratorFilter, denominatorFilter, generationTime, lapis, lapisDateField),
85
+ [lapis, numeratorFilter, denominatorFilter, generationTime, views],
81
86
  );
82
87
 
83
88
  if (isLoading) {
@@ -99,6 +104,7 @@ export const RelativeGrowthAdvantageInner: FunctionComponent<RelativeGrowthAdvan
99
104
  setYAxisScaleType={setYAxisScaleType}
100
105
  views={views}
101
106
  generationTime={generationTime}
107
+ yAxisMaxConfig={yAxisMaxConfig}
102
108
  />
103
109
  );
104
110
  };
@@ -109,6 +115,7 @@ type RelativeGrowthAdvantageTabsProps = {
109
115
  setYAxisScaleType: (scaleType: ScaleType) => void;
110
116
  views: View[];
111
117
  generationTime: number;
118
+ yAxisMaxConfig: YAxisMaxConfig;
112
119
  };
113
120
 
114
121
  const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabsProps> = ({
@@ -117,6 +124,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
117
124
  setYAxisScaleType,
118
125
  views,
119
126
  generationTime,
127
+ yAxisMaxConfig,
120
128
  }) => {
121
129
  const getTab = (view: View) => {
122
130
  switch (view) {
@@ -131,6 +139,7 @@ const RelativeGrowthAdvantageTabs: FunctionComponent<RelativeGrowthAdvantageTabs
131
139
  params: data.params,
132
140
  }}
133
141
  yAxisScaleType={yAxisScaleType}
142
+ yAxisMaxConfig={yAxisMaxConfig}
134
143
  />
135
144
  ),
136
145
  };
@@ -20,10 +20,15 @@ export function wilson95PercentConfidenceInterval(observed: number, sample: numb
20
20
  };
21
21
  }
22
22
 
23
- export const confidenceIntervalDataLabel = (value: number, lowerLimit: number, upperLimit: number, prefix?: string) => {
23
+ export const confidenceIntervalDataLabel = (
24
+ value: number,
25
+ lowerLimit?: number,
26
+ upperLimit?: number,
27
+ prefix?: string,
28
+ ) => {
24
29
  const label = prefix ? `${prefix}: ` : '';
25
30
 
26
- return `${label}${value.toFixed(3)} (${lowerLimit.toFixed(3)} - ${upperLimit.toFixed(3)})`;
31
+ return `${label}${value.toFixed(3)} (${lowerLimit?.toFixed(3)} - ${upperLimit?.toFixed(3)})`;
27
32
  };
28
33
 
29
34
  export type ConfidenceIntervalMethod = 'wilson' | 'none';
@@ -0,0 +1,24 @@
1
+ export interface YAxisMaxConfig {
2
+ linear?: AxisMax;
3
+ logarithmic?: AxisMax;
4
+ }
5
+
6
+ export type AxisMax = 'maxInData' | 'limitTo1' | number;
7
+
8
+ export const getYAxisMax = (maxInData: number, axisMax?: AxisMax) => {
9
+ if (!axisMax) {
10
+ return 1;
11
+ }
12
+
13
+ switch (axisMax) {
14
+ case 'limitTo1': {
15
+ return maxInData > 1 ? 1 : maxInData;
16
+ }
17
+ case 'maxInData': {
18
+ return maxInData;
19
+ }
20
+ default: {
21
+ return axisMax;
22
+ }
23
+ }
24
+ };
@@ -6,11 +6,9 @@ export function getYAxisScale(scaleType: ScaleType) {
6
6
  return { beginAtZero: true, type: 'linear' as const, min: 0, max: 1 };
7
7
  }
8
8
  case 'logarithmic': {
9
- return { type: 'logarithmic' as const };
9
+ return { type: 'logarithmic' as const, max: 1 };
10
10
  }
11
11
  case 'logit':
12
12
  return { type: 'logit' as const };
13
- default:
14
- return { beginAtZero: true, type: 'linear' as const };
15
13
  }
16
14
  }
@@ -8,7 +8,7 @@ export type AggregateData = (Record<string, string | null | number | boolean> &
8
8
  proportion: number;
9
9
  })[];
10
10
 
11
- const compareAscending = (a: string | null | number, b: string | null | number) => {
11
+ export const compareAscending = (a: string | null | number, b: string | null | number) => {
12
12
  if (typeof a === 'number' && typeof b === 'number') {
13
13
  return a - b;
14
14
  }
@@ -20,7 +20,7 @@ const compareAscending = (a: string | null | number, b: string | null | number)
20
20
  };
21
21
 
22
22
  export async function queryAggregateData(
23
- variant: LapisFilter,
23
+ lapisFilter: LapisFilter,
24
24
  fields: string[],
25
25
  lapis: string,
26
26
  initialSort: InitialSort = { field: 'count', direction: 'descending' },
@@ -31,7 +31,7 @@ export async function queryAggregateData(
31
31
  throw new Error(`InitialSort field not in fields. Valid fields are: ${validSortFields.join(', ')}`);
32
32
  }
33
33
 
34
- const fetchData = new FetchAggregatedOperator<Record<string, string | null | number>>(variant, fields);
34
+ const fetchData = new FetchAggregatedOperator<Record<string, string | null | number>>(lapisFilter, fields);
35
35
  const sortData = new SortOperator(fetchData, (a, b) => {
36
36
  return initialSort.direction === 'ascending'
37
37
  ? compareAscending(a[initialSort.field], b[initialSort.field])
@@ -2,8 +2,13 @@ import { FetchInsertionsOperator } from '../operator/FetchInsertionsOperator';
2
2
  import { SortOperator } from '../operator/SortOperator';
3
3
  import { type LapisFilter, type SequenceType } from '../types';
4
4
 
5
- export function queryInsertions(variant: LapisFilter, sequenceType: SequenceType, lapis: string, signal?: AbortSignal) {
6
- const fetchData = new FetchInsertionsOperator(variant, sequenceType);
5
+ export function queryInsertions(
6
+ lapisFilter: LapisFilter,
7
+ sequenceType: SequenceType,
8
+ lapis: string,
9
+ signal?: AbortSignal,
10
+ ) {
11
+ const fetchData = new FetchInsertionsOperator(lapisFilter, sequenceType);
7
12
  const sortData = new SortOperator(fetchData, (a, b) => {
8
13
  if (a.mutation.segment !== b.mutation.segment) {
9
14
  return (a.mutation.segment ?? '').localeCompare(b.mutation.segment ?? '');
@@ -3,12 +3,12 @@ import { SortOperator } from '../operator/SortOperator';
3
3
  import { type LapisFilter, type SequenceType } from '../types';
4
4
 
5
5
  export function querySubstitutionsOrDeletions(
6
- variant: LapisFilter,
6
+ lapisFilter: LapisFilter,
7
7
  sequenceType: SequenceType,
8
8
  lapis: string,
9
9
  signal?: AbortSignal,
10
10
  ) {
11
- const fetchData = new FetchSubstitutionsOrDeletionsOperator(variant, sequenceType, 0);
11
+ const fetchData = new FetchSubstitutionsOrDeletionsOperator(lapisFilter, sequenceType, 0);
12
12
  const sortData = new SortOperator(fetchData, (a, b) => {
13
13
  if (a.mutation.segment !== b.mutation.segment) {
14
14
  return (a.mutation.segment ?? '').localeCompare(b.mutation.segment ?? '');
@@ -91,7 +91,7 @@ export class DateRangeSelectorComponent extends PreactLitAdapter {
91
91
  /**
92
92
  * The width of the component.
93
93
  *
94
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
94
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
95
95
  */
96
96
  @property({ type: String })
97
97
  width: string = '100%';
@@ -54,7 +54,7 @@ export class LocationFilterComponent extends PreactLitAdapter {
54
54
  /**
55
55
  * The width of the component.
56
56
  *
57
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
57
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
58
58
  */
59
59
  @property({ type: String })
60
60
  width: string = '100%';
@@ -86,7 +86,7 @@ export class MutationFilterComponent extends PreactLitAdapter {
86
86
  /**
87
87
  * The width of the component.
88
88
  *
89
- * Visit https://genspectrum.github.io/dashboards/?path=/docs/components-size-of-components--docs for more information.
89
+ * Visit https://genspectrum.github.io/dashboard-components/?path=/docs/components-size-of-components--docs for more information.
90
90
  */
91
91
  @property({ type: String })
92
92
  width: string = '100%';