@genspectrum/dashboard-components 0.17.1 → 0.18.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.
- package/custom-elements.json +3 -3
- package/dist/assets/{mutationOverTimeWorker-CPfQDLe6.js.map → mutationOverTimeWorker-ChQTFL68.js.map} +1 -1
- package/dist/components.d.ts +46 -46
- package/dist/components.js +304 -3960
- package/dist/components.js.map +1 -1
- package/dist/style.css +2 -3687
- package/dist/util.d.ts +46 -46
- package/package.json +5 -5
- package/src/preact/aggregatedData/aggregate.tsx +3 -3
- package/src/preact/components/clearable-select.tsx +1 -1
- package/src/preact/components/color-scale-selector-dropdown.tsx +1 -1
- package/src/preact/components/color-scale-selector.tsx +1 -1
- package/src/preact/components/confidence-interval-selector.tsx +1 -1
- package/src/preact/components/downshift-combobox.tsx +3 -3
- package/src/preact/components/fullscreen.tsx +6 -2
- package/src/preact/components/info.tsx +1 -1
- package/src/preact/components/mutation-type-selector.tsx +1 -1
- package/src/preact/components/percent-intput.tsx +3 -3
- package/src/preact/components/proportion-selector-dropdown.tsx +1 -1
- package/src/preact/components/scaling-selector.tsx +1 -1
- package/src/preact/components/select.tsx +1 -1
- package/src/preact/components/tabs.tsx +1 -1
- package/src/preact/dateRangeFilter/date-picker.tsx +1 -1
- package/src/preact/dateRangeFilter/date-range-filter.tsx +4 -4
- package/src/preact/mutationComparison/mutation-comparison.tsx +1 -1
- package/src/preact/mutationFilter/mutation-filter.tsx +1 -1
- package/src/preact/mutations/mutations.tsx +2 -2
- package/src/preact/mutationsOverTime/__mockData__/aminoAcidMutationsByDay.ts +3773 -2290
- package/src/preact/mutationsOverTime/__mockData__/byWeek.ts +3012 -948
- package/src/preact/mutationsOverTime/__mockData__/defaultMockData.ts +8799 -4406
- package/src/preact/mutationsOverTime/__mockData__/showsMessageWhenTooManyMutations.ts +1836 -0
- package/src/preact/mutationsOverTime/getFilteredMutationsOverTime.spec.ts +3 -1
- package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +56 -21
- package/src/preact/mutationsOverTime/mutations-over-time.tsx +3 -2
- package/src/preact/numberSequencesOverTime/number-sequences-over-time.tsx +1 -1
- package/src/preact/prevalenceOverTime/prevalence-over-time.tsx +1 -1
- package/src/preact/sequencesByLocation/sequences-by-location-map.tsx +1 -1
- package/src/preact/sequencesByLocation/sequences-by-location.tsx +3 -7
- package/src/preact/wastewater/mutationsOverTime/computeWastewaterMutationsOverTimeDataPerLocation.spec.ts +5 -5
- package/src/preact/wastewater/mutationsOverTime/computeWastewaterMutationsOverTimeDataPerLocation.ts +1 -3
- package/src/query/queryMutationsOverTime.spec.ts +28 -26
- package/src/query/queryMutationsOverTime.ts +20 -8
- package/src/styles/tailwind.css +14 -3
- package/src/web-components/input/gs-date-range-filter.stories.ts +2 -2
- package/src/web-components/input/gs-lineage-filter.stories.ts +1 -1
- package/src/web-components/input/gs-location-filter.stories.ts +1 -1
- package/src/web-components/input/gs-mutation-filter.stories.ts +1 -1
- package/src/web-components/input/gs-text-filter.stories.ts +1 -1
- package/standalone-bundle/assets/{mutationOverTimeWorker-CERZSdcA.js.map → mutationOverTimeWorker-jChgWnwp.js.map} +1 -1
- package/standalone-bundle/dashboard-components.js +5455 -5431
- package/standalone-bundle/dashboard-components.js.map +1 -1
- package/standalone-bundle/style.css +1 -1
|
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest';
|
|
|
2
2
|
|
|
3
3
|
import { BaseMutationOverTimeDataMap } from './MutationOverTimeData';
|
|
4
4
|
import { getFilteredMutationOverTimeData } from './getFilteredMutationsOverTimeData';
|
|
5
|
+
import { type MutationOverTimeMutationValue } from '../../query/queryMutationsOverTime';
|
|
5
6
|
import { type DeletionEntry, type SubstitutionEntry } from '../../types';
|
|
6
7
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
7
8
|
import { type TemporalClass } from '../../utils/temporalClass';
|
|
@@ -240,10 +241,11 @@ describe('getFilteredMutationOverTimeData', () => {
|
|
|
240
241
|
const someTemporal = yearMonthDay('2021-01-01');
|
|
241
242
|
const anotherTemporal = yearMonthDay('2021-02-02');
|
|
242
243
|
const someMutationOverTimeValue = {
|
|
244
|
+
type: 'value',
|
|
243
245
|
count: 1,
|
|
244
246
|
proportion: inFilter,
|
|
245
247
|
totalCount: 10,
|
|
246
|
-
};
|
|
248
|
+
} satisfies MutationOverTimeMutationValue;
|
|
247
249
|
|
|
248
250
|
function prepareMutationOverTimeData(
|
|
249
251
|
mutationEntries: (SubstitutionEntry<Substitution> | DeletionEntry<Deletion>)[],
|
|
@@ -3,12 +3,15 @@ import { type FunctionComponent } from 'preact';
|
|
|
3
3
|
import { useMemo, useState } from 'preact/hooks';
|
|
4
4
|
|
|
5
5
|
import { type MutationOverTimeDataMap } from './MutationOverTimeData';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
type MutationOverTimeMutationValue,
|
|
8
|
+
MUTATIONS_OVER_TIME_MIN_PROPORTION,
|
|
9
|
+
} from '../../query/queryMutationsOverTime';
|
|
7
10
|
import { type SequenceType } from '../../types';
|
|
8
11
|
import { type Deletion, type Substitution } from '../../utils/mutations';
|
|
9
12
|
import { type Temporal, type TemporalClass, toTemporalClass, YearMonthDayClass } from '../../utils/temporalClass';
|
|
10
13
|
import { AnnotatedMutation } from '../components/annotated-mutation';
|
|
11
|
-
import { type ColorScale,
|
|
14
|
+
import { type ColorScale, getColorWithinScale, getTextColorForScale } from '../components/color-scale-selector';
|
|
12
15
|
import Tooltip, { type TooltipPosition } from '../components/tooltip';
|
|
13
16
|
import { formatProportion } from '../shared/table/formatProportion';
|
|
14
17
|
import { type PageSizes, Pagination } from '../shared/tanstackTable/pagination';
|
|
@@ -187,38 +190,26 @@ const ProportionCell: FunctionComponent<{
|
|
|
187
190
|
</p>
|
|
188
191
|
<p>({timeIntervalDisplay(dateClass)})</p>
|
|
189
192
|
<p>{mutation.code}</p>
|
|
190
|
-
{value
|
|
191
|
-
<p>No data</p>
|
|
192
|
-
) : (
|
|
193
|
-
<>
|
|
194
|
-
<p>Proportion: {formatProportion(value.proportion)}</p>
|
|
195
|
-
{value.count !== null && value.totalCount !== null && (
|
|
196
|
-
<>
|
|
197
|
-
<p>
|
|
198
|
-
{value.count} / {totalCountWithCoverage(value.count, value.proportion)} with coverage
|
|
199
|
-
</p>
|
|
200
|
-
<p>{value.totalCount} in timeframe</p>
|
|
201
|
-
</>
|
|
202
|
-
)}
|
|
203
|
-
</>
|
|
204
|
-
)}
|
|
193
|
+
<TooltipValueDescription value={value} />
|
|
205
194
|
</div>
|
|
206
195
|
);
|
|
207
196
|
|
|
197
|
+
const proportion = value?.type === 'belowThreshold' ? 0 : value?.proportion;
|
|
198
|
+
|
|
208
199
|
return (
|
|
209
200
|
<div className={'py-1 w-full h-full'}>
|
|
210
201
|
<Tooltip content={tooltipContent} position={tooltipPosition}>
|
|
211
202
|
<div
|
|
212
203
|
style={{
|
|
213
|
-
backgroundColor:
|
|
214
|
-
color: getTextColorForScale(
|
|
204
|
+
backgroundColor: getColorWithinScale(proportion, colorScale),
|
|
205
|
+
color: getTextColorForScale(proportion, colorScale),
|
|
215
206
|
}}
|
|
216
207
|
className={`w-full h-full hover:font-bold text-xs group @container`}
|
|
217
208
|
>
|
|
218
209
|
{value === null ? (
|
|
219
|
-
<span className=
|
|
210
|
+
<span className='invisible'>No data</span>
|
|
220
211
|
) : (
|
|
221
|
-
<span className='invisible @[2rem]:visible'>{formatProportion(
|
|
212
|
+
<span className='invisible @[2rem]:visible'>{formatProportion(proportion ?? 0, 0)}</span>
|
|
222
213
|
)}
|
|
223
214
|
</div>
|
|
224
215
|
</Tooltip>
|
|
@@ -226,6 +217,50 @@ const ProportionCell: FunctionComponent<{
|
|
|
226
217
|
);
|
|
227
218
|
};
|
|
228
219
|
|
|
220
|
+
const TooltipValueDescription: FunctionComponent<{ value: MutationOverTimeMutationValue }> = ({ value }) => {
|
|
221
|
+
if (value === null) {
|
|
222
|
+
return <p>No data</p>;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const proportion =
|
|
226
|
+
value.type === 'belowThreshold'
|
|
227
|
+
? `<${formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)}`
|
|
228
|
+
: formatProportion(value.proportion);
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<>
|
|
232
|
+
<p>Proportion: {proportion}</p>
|
|
233
|
+
<TooltipValueCountsDescription value={value} />
|
|
234
|
+
</>
|
|
235
|
+
);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const TooltipValueCountsDescription: FunctionComponent<{
|
|
239
|
+
value: NonNullable<MutationOverTimeMutationValue>;
|
|
240
|
+
}> = ({ value }) => {
|
|
241
|
+
switch (value.type) {
|
|
242
|
+
case 'wastewaterValue':
|
|
243
|
+
return;
|
|
244
|
+
case 'belowThreshold':
|
|
245
|
+
return (
|
|
246
|
+
<>
|
|
247
|
+
<p>{value.totalCount} samples are in the timeframe</p>
|
|
248
|
+
<p>none or less than {formatProportion(MUTATIONS_OVER_TIME_MIN_PROPORTION)} have the mutation</p>
|
|
249
|
+
</>
|
|
250
|
+
);
|
|
251
|
+
case 'value':
|
|
252
|
+
return (
|
|
253
|
+
<>
|
|
254
|
+
<p>{value.totalCount} samples are in the timeframe</p>
|
|
255
|
+
<p>
|
|
256
|
+
{totalCountWithCoverage(value.count, value.proportion)} have coverage, of those {value.count}{' '}
|
|
257
|
+
have the mutation
|
|
258
|
+
</p>
|
|
259
|
+
</>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
229
264
|
function totalCountWithCoverage(count: number, proportion: number) {
|
|
230
265
|
if (count === 0) {
|
|
231
266
|
return 0;
|
|
@@ -240,7 +240,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
240
240
|
labelPrefix='Mean proportion'
|
|
241
241
|
/>
|
|
242
242
|
<CsvDownloadButton
|
|
243
|
-
className='
|
|
243
|
+
className='btn btn-xs'
|
|
244
244
|
getData={() => getDownloadData(filteredData)}
|
|
245
245
|
filename='mutations_over_time.csv'
|
|
246
246
|
/>
|
|
@@ -283,7 +283,8 @@ function getDownloadData(filteredData: MutationOverTimeDataMap) {
|
|
|
283
283
|
return filteredData.getFirstAxisKeys().map((mutation) => {
|
|
284
284
|
return dates.reduce(
|
|
285
285
|
(accumulated, date) => {
|
|
286
|
-
const
|
|
286
|
+
const value = filteredData.get(mutation, date);
|
|
287
|
+
const proportion = value?.type === 'value' || value?.type === 'wastewaterValue' ? value.proportion : '';
|
|
287
288
|
return {
|
|
288
289
|
...accumulated,
|
|
289
290
|
[date.dateString]: proportion,
|
|
@@ -167,7 +167,7 @@ const Toolbar = ({ activeTab, data, yAxisScaleType, setYAxisScaleType, originalC
|
|
|
167
167
|
/>
|
|
168
168
|
)}
|
|
169
169
|
<CsvDownloadButton
|
|
170
|
-
className='
|
|
170
|
+
className='btn btn-xs'
|
|
171
171
|
getData={() => getNumberOfSequencesOverTimeTableData(data, originalComponentProps.granularity)}
|
|
172
172
|
filename='number_of_sequences_over_time.csv'
|
|
173
173
|
/>
|
|
@@ -218,7 +218,7 @@ const Toolbar: FunctionComponent<ToolbarProps> = ({
|
|
|
218
218
|
/>
|
|
219
219
|
)}
|
|
220
220
|
<CsvDownloadButton
|
|
221
|
-
className='
|
|
221
|
+
className='btn btn-xs'
|
|
222
222
|
getData={() => getPrevalenceOverTimeTableData(data, granularity)}
|
|
223
223
|
filename='prevalence_over_time.csv'
|
|
224
224
|
/>
|
|
@@ -106,7 +106,7 @@ const DataMatchInformation: FunctionComponent<DataMatchInformationProps> = ({
|
|
|
106
106
|
|
|
107
107
|
return (
|
|
108
108
|
<Modal
|
|
109
|
-
buttonClassName='text-sm absolute bottom-0 px-1 z-
|
|
109
|
+
buttonClassName='text-sm absolute bottom-0 px-1 z-1001 bg-white rounded-sm border border-gray-200'
|
|
110
110
|
modalContent={
|
|
111
111
|
<>
|
|
112
112
|
<InfoHeadline1>Sequences By Location - Map View</InfoHeadline1>
|
|
@@ -149,15 +149,11 @@ type ToolbarProps = {
|
|
|
149
149
|
|
|
150
150
|
const Toolbar: FunctionComponent<ToolbarProps> = ({ originalComponentProps, tableData }) => {
|
|
151
151
|
return (
|
|
152
|
-
|
|
153
|
-
<CsvDownloadButton
|
|
154
|
-
className='mx-1 btn btn-xs'
|
|
155
|
-
getData={() => tableData}
|
|
156
|
-
filename='sequences_by_location.csv'
|
|
157
|
-
/>
|
|
152
|
+
<>
|
|
153
|
+
<CsvDownloadButton className='btn btn-xs' getData={() => tableData} filename='sequences_by_location.csv' />
|
|
158
154
|
<SequencesByLocationMapInfo originalComponentProps={originalComponentProps} />
|
|
159
155
|
<Fullscreen />
|
|
160
|
-
|
|
156
|
+
</>
|
|
161
157
|
);
|
|
162
158
|
};
|
|
163
159
|
|
|
@@ -59,10 +59,10 @@ describe('groupMutationDataByLocation', () => {
|
|
|
59
59
|
temporalCache.getYearMonthDay('2025-01-02'),
|
|
60
60
|
]);
|
|
61
61
|
expect(location1Data.getAsArray()).to.deep.equal([
|
|
62
|
-
[{
|
|
62
|
+
[{ type: 'wastewaterValue', proportion: 0.1 }, null],
|
|
63
63
|
[
|
|
64
|
-
{
|
|
65
|
-
{
|
|
64
|
+
{ type: 'wastewaterValue', proportion: 0.2 },
|
|
65
|
+
{ type: 'wastewaterValue', proportion: 0.3 },
|
|
66
66
|
],
|
|
67
67
|
]);
|
|
68
68
|
});
|
|
@@ -96,8 +96,8 @@ describe('groupMutationDataByLocation', () => {
|
|
|
96
96
|
expect(location1Data.getFirstAxisKeys()).to.deep.equal([mutation2, mutation3]);
|
|
97
97
|
expect(location1Data.getSecondAxisKeys()).to.deep.equal([temporalCache.getYearMonthDay('2025-01-01')]);
|
|
98
98
|
expect(location1Data.getAsArray()).to.deep.equal([
|
|
99
|
-
[{
|
|
100
|
-
[{
|
|
99
|
+
[{ type: 'wastewaterValue', proportion: 0.2 }],
|
|
100
|
+
[{ type: 'wastewaterValue', proportion: 0.3 }],
|
|
101
101
|
]);
|
|
102
102
|
});
|
|
103
103
|
|
package/src/preact/wastewater/mutationsOverTime/computeWastewaterMutationsOverTimeDataPerLocation.ts
CHANGED
|
@@ -33,9 +33,7 @@ export function groupMutationDataByLocation(data: WastewaterData, sequenceType:
|
|
|
33
33
|
map.set(
|
|
34
34
|
mutation.mutation,
|
|
35
35
|
row.date,
|
|
36
|
-
mutation.proportion !== null
|
|
37
|
-
? { proportion: mutation.proportion, count: null, totalCount: null }
|
|
38
|
-
: null,
|
|
36
|
+
mutation.proportion !== null ? { type: 'wastewaterValue', proportion: mutation.proportion } : null,
|
|
39
37
|
);
|
|
40
38
|
}
|
|
41
39
|
}
|
|
@@ -101,14 +101,14 @@ describe('queryMutationsOverTime', () => {
|
|
|
101
101
|
|
|
102
102
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
103
103
|
[
|
|
104
|
-
{ proportion: 0.4, count: 4, totalCount: 11 },
|
|
105
|
-
{
|
|
106
|
-
{
|
|
104
|
+
{ type: 'value', proportion: 0.4, count: 4, totalCount: 11 },
|
|
105
|
+
{ type: 'belowThreshold', totalCount: 12 },
|
|
106
|
+
{ type: 'belowThreshold', totalCount: 13 },
|
|
107
107
|
],
|
|
108
108
|
[
|
|
109
|
-
{ proportion: 0.1, count: 1, totalCount: 11 },
|
|
110
|
-
{ proportion: 0.2, count: 2, totalCount: 12 },
|
|
111
|
-
{ proportion: 0.3, count: 3, totalCount: 13 },
|
|
109
|
+
{ type: 'value', proportion: 0.1, count: 1, totalCount: 11 },
|
|
110
|
+
{ type: 'value', proportion: 0.2, count: 2, totalCount: 12 },
|
|
111
|
+
{ type: 'value', proportion: 0.3, count: 3, totalCount: 13 },
|
|
112
112
|
],
|
|
113
113
|
]);
|
|
114
114
|
|
|
@@ -251,8 +251,16 @@ describe('queryMutationsOverTime', () => {
|
|
|
251
251
|
});
|
|
252
252
|
|
|
253
253
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
254
|
-
[
|
|
255
|
-
|
|
254
|
+
[
|
|
255
|
+
{ type: 'value', proportion: 0.4, count: 4, totalCount: 11 },
|
|
256
|
+
null,
|
|
257
|
+
{ type: 'belowThreshold', totalCount: 13 },
|
|
258
|
+
],
|
|
259
|
+
[
|
|
260
|
+
{ type: 'value', proportion: 0.1, count: 1, totalCount: 11 },
|
|
261
|
+
null,
|
|
262
|
+
{ type: 'value', proportion: 0.3, count: 3, totalCount: 13 },
|
|
263
|
+
],
|
|
256
264
|
]);
|
|
257
265
|
|
|
258
266
|
const sequences = mutationOverTimeData.getFirstAxisKeys();
|
|
@@ -444,8 +452,8 @@ describe('queryMutationsOverTime', () => {
|
|
|
444
452
|
|
|
445
453
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
446
454
|
[
|
|
447
|
-
{ proportion: 0.2, count: 2, totalCount: 11 },
|
|
448
|
-
{ proportion: 0.3, count: 3, totalCount: 12 },
|
|
455
|
+
{ type: 'value', proportion: 0.2, count: 2, totalCount: 11 },
|
|
456
|
+
{ type: 'value', proportion: 0.3, count: 3, totalCount: 12 },
|
|
449
457
|
],
|
|
450
458
|
]);
|
|
451
459
|
|
|
@@ -536,8 +544,8 @@ describe('queryMutationsOverTime', () => {
|
|
|
536
544
|
|
|
537
545
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
538
546
|
[
|
|
539
|
-
{ proportion: 0.1, count: 1, totalCount: 11 },
|
|
540
|
-
{ proportion: 0.2, count: 2, totalCount: 12 },
|
|
547
|
+
{ type: 'value', proportion: 0.1, count: 1, totalCount: 11 },
|
|
548
|
+
{ type: 'value', proportion: 0.2, count: 2, totalCount: 12 },
|
|
541
549
|
],
|
|
542
550
|
]);
|
|
543
551
|
|
|
@@ -598,13 +606,7 @@ describe('queryMutationsOverTime', () => {
|
|
|
598
606
|
});
|
|
599
607
|
|
|
600
608
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
601
|
-
[
|
|
602
|
-
{
|
|
603
|
-
proportion: 0.2,
|
|
604
|
-
count: 2,
|
|
605
|
-
totalCount: 11,
|
|
606
|
-
},
|
|
607
|
-
],
|
|
609
|
+
[{ type: 'value', proportion: 0.2, count: 2, totalCount: 11 }],
|
|
608
610
|
]);
|
|
609
611
|
|
|
610
612
|
const sequences = mutationOverTimeData.getFirstAxisKeys();
|
|
@@ -693,12 +695,12 @@ describe('queryMutationsOverTime', () => {
|
|
|
693
695
|
|
|
694
696
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
695
697
|
[
|
|
696
|
-
{ proportion: 0.4, count: 4, totalCount: 11 },
|
|
697
|
-
{
|
|
698
|
+
{ type: 'value', proportion: 0.4, count: 4, totalCount: 11 },
|
|
699
|
+
{ type: 'belowThreshold', totalCount: 12 },
|
|
698
700
|
],
|
|
699
701
|
[
|
|
700
|
-
{ proportion: 0.1, count: 1, totalCount: 11 },
|
|
701
|
-
{ proportion: 0.2, count: 2, totalCount: 12 },
|
|
702
|
+
{ type: 'value', proportion: 0.1, count: 1, totalCount: 11 },
|
|
703
|
+
{ type: 'value', proportion: 0.2, count: 2, totalCount: 12 },
|
|
702
704
|
],
|
|
703
705
|
]);
|
|
704
706
|
|
|
@@ -741,7 +743,7 @@ describe('queryMutationsOverTime', () => {
|
|
|
741
743
|
expect(dates.length).toBe(0);
|
|
742
744
|
});
|
|
743
745
|
|
|
744
|
-
it('should fill with
|
|
746
|
+
it('should fill with "belowThreshold" if the mutation does not exist in a date range but count > 0', async () => {
|
|
745
747
|
const lapisFilter = { field1: 'value1', field2: 'value2' };
|
|
746
748
|
const dateField = 'dateField';
|
|
747
749
|
|
|
@@ -820,8 +822,8 @@ describe('queryMutationsOverTime', () => {
|
|
|
820
822
|
|
|
821
823
|
expect(mutationOverTimeData.getAsArray()).to.deep.equal([
|
|
822
824
|
[
|
|
823
|
-
{ proportion: 0.1, count: 1, totalCount: 11 },
|
|
824
|
-
{
|
|
825
|
+
{ type: 'value', proportion: 0.1, count: 1, totalCount: 11 },
|
|
826
|
+
{ type: 'belowThreshold', totalCount: 11 },
|
|
825
827
|
],
|
|
826
828
|
]);
|
|
827
829
|
});
|
|
@@ -34,13 +34,25 @@ export type MutationOverTimeData = {
|
|
|
34
34
|
totalCount: number;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
export type MutationOverTimeMutationValue =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
export type MutationOverTimeMutationValue =
|
|
38
|
+
| {
|
|
39
|
+
type: 'value';
|
|
40
|
+
proportion: number;
|
|
41
|
+
count: number;
|
|
42
|
+
totalCount: number;
|
|
43
|
+
}
|
|
44
|
+
| {
|
|
45
|
+
type: 'wastewaterValue';
|
|
46
|
+
proportion: number;
|
|
47
|
+
}
|
|
48
|
+
| {
|
|
49
|
+
type: 'belowThreshold';
|
|
50
|
+
totalCount: number | null;
|
|
51
|
+
}
|
|
52
|
+
| null;
|
|
42
53
|
|
|
43
54
|
const MAX_NUMBER_OF_GRID_COLUMNS = 200;
|
|
55
|
+
export const MUTATIONS_OVER_TIME_MIN_PROPORTION = 0.001;
|
|
44
56
|
|
|
45
57
|
export async function queryOverallMutationData({
|
|
46
58
|
lapisFilter,
|
|
@@ -204,7 +216,7 @@ function fetchAndPrepareDates<LapisDateField extends string>(
|
|
|
204
216
|
}
|
|
205
217
|
|
|
206
218
|
function fetchAndPrepareSubstitutionsOrDeletions(filter: LapisFilter, sequenceType: SequenceType) {
|
|
207
|
-
return new FetchSubstitutionsOrDeletionsOperator(filter, sequenceType,
|
|
219
|
+
return new FetchSubstitutionsOrDeletionsOperator(filter, sequenceType, MUTATIONS_OVER_TIME_MIN_PROPORTION);
|
|
208
220
|
}
|
|
209
221
|
|
|
210
222
|
export function serializeSubstitutionOrDeletion(mutation: Substitution | Deletion) {
|
|
@@ -248,6 +260,7 @@ export function groupByMutation(
|
|
|
248
260
|
|
|
249
261
|
if (dataArray.get(mutation, date) !== undefined) {
|
|
250
262
|
dataArray.set(mutation, date, {
|
|
263
|
+
type: 'value',
|
|
251
264
|
count: mutationEntry.count,
|
|
252
265
|
proportion: mutationEntry.proportion,
|
|
253
266
|
totalCount: mutationData.totalCount,
|
|
@@ -258,8 +271,7 @@ export function groupByMutation(
|
|
|
258
271
|
for (const firstAxisKey of dataArray.getFirstAxisKeys()) {
|
|
259
272
|
if (dataArray.get(firstAxisKey, date) === null) {
|
|
260
273
|
dataArray.set(firstAxisKey, date, {
|
|
261
|
-
|
|
262
|
-
proportion: 0,
|
|
274
|
+
type: 'belowThreshold',
|
|
263
275
|
totalCount: mutationData.totalCount,
|
|
264
276
|
});
|
|
265
277
|
}
|
package/src/styles/tailwind.css
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
@
|
|
2
|
-
|
|
3
|
-
@
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
@plugin "daisyui" {
|
|
4
|
+
themes: light --default;
|
|
5
|
+
}
|
|
6
|
+
@plugin "@iconify/tailwind4" {
|
|
7
|
+
prefixes: mdi, mdi-light;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@theme {
|
|
11
|
+
--container-2xs: 18rem;
|
|
12
|
+
--container-3xs: 16rem;
|
|
13
|
+
--container-4xs: 14rem;
|
|
14
|
+
}
|
|
@@ -78,7 +78,7 @@ export default meta;
|
|
|
78
78
|
export const Default: StoryObj<Required<DateRangeFilterProps>> = {
|
|
79
79
|
render: (args) =>
|
|
80
80
|
html` <gs-app lapis="${LAPIS_URL}">
|
|
81
|
-
<div class="max-w-
|
|
81
|
+
<div class="max-w-(--breakpoint-lg)">
|
|
82
82
|
<gs-date-range-filter
|
|
83
83
|
.dateRangeOptions=${args.dateRangeOptions}
|
|
84
84
|
.earliestDate=${args.earliestDate}
|
|
@@ -94,7 +94,7 @@ export const Default: StoryObj<Required<DateRangeFilterProps>> = {
|
|
|
94
94
|
export const TestRenderAttributesInHtmlInsteadOfUsingPropertyExpression: StoryObj<Required<DateRangeFilterProps>> = {
|
|
95
95
|
render: (args) =>
|
|
96
96
|
html` <gs-app lapis="${LAPIS_URL}">
|
|
97
|
-
<div class="max-w-
|
|
97
|
+
<div class="max-w-(--breakpoint-lg)">
|
|
98
98
|
<gs-date-range-filter
|
|
99
99
|
.dateRangeOptions=${args.dateRangeOptions}
|
|
100
100
|
earliestDate="${args.earliestDate}"
|
|
@@ -87,7 +87,7 @@ export default meta;
|
|
|
87
87
|
const Template: StoryObj<Required<LineageFilterProps>> = {
|
|
88
88
|
render: (args) => {
|
|
89
89
|
return html` <gs-app lapis="${LAPIS_URL}">
|
|
90
|
-
<div class="max-w-
|
|
90
|
+
<div class="max-w-(--breakpoint-lg)">
|
|
91
91
|
<gs-lineage-filter
|
|
92
92
|
.lapisField=${args.lapisField}
|
|
93
93
|
.lapisFilter=${args.lapisFilter}
|
|
@@ -67,7 +67,7 @@ export default meta;
|
|
|
67
67
|
const Template: StoryObj<LocationFilterProps> = {
|
|
68
68
|
render: (args) => {
|
|
69
69
|
return html` <gs-app lapis="${LAPIS_URL}">
|
|
70
|
-
<div class="max-w-
|
|
70
|
+
<div class="max-w-(--breakpoint-lg)">
|
|
71
71
|
<gs-location-filter
|
|
72
72
|
.fields=${args.fields}
|
|
73
73
|
.lapisFilter=${args.lapisFilter}
|
|
@@ -46,7 +46,7 @@ export default meta;
|
|
|
46
46
|
const Template: StoryObj<MutationFilterProps> = {
|
|
47
47
|
render: (args) => {
|
|
48
48
|
return html` <gs-app lapis="${LAPIS_URL}">
|
|
49
|
-
<div class="max-w-
|
|
49
|
+
<div class="max-w-(--breakpoint-lg)">
|
|
50
50
|
<gs-mutation-filter .initialValue=${args.initialValue} .width=${args.width}></gs-mutation-filter>
|
|
51
51
|
</div>
|
|
52
52
|
</gs-app>`;
|
|
@@ -86,7 +86,7 @@ export default meta;
|
|
|
86
86
|
export const Default: StoryObj<Required<TextFilterProps>> = {
|
|
87
87
|
render: (args) => {
|
|
88
88
|
return html` <gs-app lapis="${LAPIS_URL}">
|
|
89
|
-
<div class="max-w-
|
|
89
|
+
<div class="max-w-(--breakpoint-lg)">
|
|
90
90
|
<gs-text-filter
|
|
91
91
|
.lapisField=${args.lapisField}
|
|
92
92
|
.lapisFilter=${args.lapisFilter}
|