@genspectrum/dashboard-components 0.13.5 → 0.13.7

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 (46) hide show
  1. package/custom-elements.json +29 -29
  2. package/dist/components.d.ts +15 -17
  3. package/dist/components.js +462 -285
  4. package/dist/components.js.map +1 -1
  5. package/dist/style.css +20 -5
  6. package/dist/util.d.ts +14 -14
  7. package/package.json +1 -1
  8. package/src/preact/components/downshift-combobox.tsx +2 -2
  9. package/src/preact/components/mutation-info.tsx +36 -0
  10. package/src/preact/components/tabs.tsx +3 -5
  11. package/src/preact/locationFilter/fetchAutocompletionList.spec.ts +13 -13
  12. package/src/preact/locationFilter/fetchAutocompletionList.ts +55 -19
  13. package/src/preact/locationFilter/location-filter.stories.tsx +1 -1
  14. package/src/preact/locationFilter/location-filter.tsx +18 -12
  15. package/src/preact/mutationComparison/mutation-comparison.tsx +26 -2
  16. package/src/preact/mutationFilter/ExampleMutation.tsx +68 -0
  17. package/src/preact/mutationFilter/mutation-filter-info.tsx +179 -112
  18. package/src/preact/mutationFilter/mutation-filter.tsx +10 -5
  19. package/src/preact/mutations/mutations.tsx +5 -23
  20. package/src/preact/mutationsOverTime/mutations-over-time-grid.tsx +26 -4
  21. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.stories.tsx +2 -6
  22. package/src/preact/wastewater/mutationsOverTime/wastewater-mutations-over-time.tsx +1 -1
  23. package/src/query/queryWastewaterMutationsOverTime.spec.ts +29 -1
  24. package/src/query/queryWastewaterMutationsOverTime.ts +30 -16
  25. package/src/web-components/{app.stories.ts → gs-app.stories.ts} +1 -1
  26. package/src/web-components/{app.ts → gs-app.ts} +2 -2
  27. package/src/web-components/index.ts +1 -1
  28. package/src/web-components/input/gs-date-range-selector.stories.ts +1 -1
  29. package/src/web-components/input/gs-lineage-filter.stories.ts +1 -1
  30. package/src/web-components/input/gs-location-filter.stories.ts +2 -2
  31. package/src/web-components/input/gs-mutation-filter.stories.ts +2 -2
  32. package/src/web-components/input/gs-text-input.stories.ts +1 -1
  33. package/src/web-components/visualization/gs-aggregate.stories.ts +1 -1
  34. package/src/web-components/visualization/gs-mutation-comparison.stories.ts +1 -1
  35. package/src/web-components/visualization/gs-mutations-over-time.stories.ts +1 -1
  36. package/src/web-components/visualization/gs-mutations.stories.ts +1 -1
  37. package/src/web-components/visualization/gs-number-sequences-over-time.stories.ts +1 -1
  38. package/src/web-components/visualization/gs-prevalence-over-time.stories.ts +1 -1
  39. package/src/web-components/visualization/gs-relative-growth-advantage.stories.ts +1 -1
  40. package/src/web-components/visualization/gs-sequences-by-location.stories.ts +1 -1
  41. package/src/web-components/visualization/gs-statistics.stories.ts +1 -1
  42. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.stories.ts +4 -1
  43. package/src/web-components/wastewaterVisualization/gs-wastewater-mutations-over-time.tsx +6 -2
  44. package/standalone-bundle/dashboard-components.js +5561 -5445
  45. package/standalone-bundle/dashboard-components.js.map +1 -1
  46. package/standalone-bundle/style.css +1 -1
@@ -550,7 +550,7 @@ var __decorateClass$g = (decorators, target, key, kind) => {
550
550
  return result;
551
551
  };
552
552
  const lapisUrlSchema = z$2.string().url();
553
- let App = class extends LitElement {
553
+ let AppComponent = class extends LitElement {
554
554
  constructor() {
555
555
  super(...arguments);
556
556
  this.lapis = "";
@@ -585,13 +585,13 @@ let App = class extends LitElement {
585
585
  __decorateClass$g([
586
586
  provide({ context: lapisContext }),
587
587
  n$1()
588
- ], App.prototype, "lapis", 2);
588
+ ], AppComponent.prototype, "lapis", 2);
589
589
  __decorateClass$g([
590
590
  provide({ context: referenceGenomeContext })
591
- ], App.prototype, "referenceGenome", 2);
592
- App = __decorateClass$g([
591
+ ], AppComponent.prototype, "referenceGenome", 2);
592
+ AppComponent = __decorateClass$g([
593
593
  t$3("gs-app")
594
- ], App);
594
+ ], AppComponent);
595
595
  function GsAppError(error) {
596
596
  return html` <div class="m-2 w-full alert alert-error">Error: ${error}</div>`;
597
597
  }
@@ -1628,6 +1628,25 @@ const LoadingDisplay = () => {
1628
1628
  }
1629
1629
  );
1630
1630
  };
1631
+ const SubstitutionsLink = () => /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Substitution", children: "substitutions" });
1632
+ const InsertionsLink = () => /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Insertion", children: "insertions" });
1633
+ const DeletionsLink = () => /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Deletion", children: "deletions" });
1634
+ const ProportionExplanation = () => /* @__PURE__ */ u$1(Fragment, { children: [
1635
+ /* @__PURE__ */ u$1(InfoHeadline2, { children: "Proportion calculation" }),
1636
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "The proportion of a mutation is calculated by dividing the number of sequences with the mutation by the total number of sequences with a non-ambiguous symbol at the position." }),
1637
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
1638
+ /* @__PURE__ */ u$1("b", { children: "Example:" }),
1639
+ " Assume we look at nucleotide mutations at position 5 where the reference has a T and assume there are 10 sequences in total:",
1640
+ /* @__PURE__ */ u$1("ul", { className: "list-disc list-inside ml-2", children: [
1641
+ /* @__PURE__ */ u$1("li", { children: "3 sequences have a C," }),
1642
+ /* @__PURE__ */ u$1("li", { children: "2 sequences have a T," }),
1643
+ /* @__PURE__ */ u$1("li", { children: "1 sequence has a G," }),
1644
+ /* @__PURE__ */ u$1("li", { children: "3 sequences have an N," }),
1645
+ /* @__PURE__ */ u$1("li", { children: "1 sequence has a Y (which means T or C)," })
1646
+ ] }),
1647
+ "then the proportion of the T5C mutation is 50%. The 4 sequences that have an N or Y are excluded from the calculation."
1648
+ ] })
1649
+ ] });
1631
1650
  function useFloatingUi(referenceRef, floatingRef, middleware, placement) {
1632
1651
  const cleanupRef = A$1(null);
1633
1652
  y(() => {
@@ -2022,13 +2041,13 @@ function useDisplayedSegments(sequenceType) {
2022
2041
  return h(displayedSegments);
2023
2042
  }
2024
2043
  const Tabs = ({ tabs, toolbar }) => {
2025
- var _a, _b;
2044
+ var _a;
2026
2045
  const [activeTab, setActiveTab] = h((_a = tabs[0]) == null ? void 0 : _a.title);
2027
2046
  const tabElements = /* @__PURE__ */ u$1("div", { className: "flex flex-row flex-wrap", children: tabs.map((tab) => {
2028
2047
  return /* @__PURE__ */ u$1(
2029
2048
  "button",
2030
2049
  {
2031
- className: `px-4 py-2 text-sm font-medium leading-5 transition-colors duration-150 ${activeTab === tab.title ? "border-b-2 border-gray-400" : "text-gray-600 hover:bg-gray-100 hover:text-gray-700"}`,
2050
+ className: `px-4 py-2 text-sm font-medium leading-5 transition-colors duration-150 ${activeTab === tab.title ? "border-b-2 border-gray-500" : "border-b border-gray-300 text-gray-600 hover:bg-gray-100 hover:text-gray-700"}`,
2032
2051
  onClick: () => {
2033
2052
  setActiveTab(tab.title);
2034
2053
  },
@@ -2043,13 +2062,7 @@ const Tabs = ({ tabs, toolbar }) => {
2043
2062
  tabElements,
2044
2063
  toolbar && /* @__PURE__ */ u$1("div", { className: "py-2 flex flex-wrap gap-y-1", children: toolbarElement })
2045
2064
  ] }),
2046
- /* @__PURE__ */ u$1(
2047
- "div",
2048
- {
2049
- className: `p-2 flex-grow overflow-scroll border-2 border-gray-100 rounded-b-md rounded-tr-md ${activeTab === ((_b = tabs[0]) == null ? void 0 : _b.title) ? "" : "rounded-tl-md"}`,
2050
- children: tabs.map((tab) => /* @__PURE__ */ u$1("div", { className: "h-full", hidden: activeTab !== tab.title, children: tab.content }, tab.title))
2051
- }
2052
- )
2065
+ /* @__PURE__ */ u$1("div", { className: `p-2 flex-grow overflow-scroll border-2 border-gray-100 rounded-b-md rounded-tr-md`, children: tabs.map((tab) => /* @__PURE__ */ u$1("div", { className: "h-full", hidden: activeTab !== tab.title, children: tab.content }, tab.title)) })
2053
2066
  ] });
2054
2067
  };
2055
2068
  function useQuery(fetchDataCallback, dependencies) {
@@ -2212,7 +2225,22 @@ const MutationComparisonInfo = ({ originalComponentProps }) => {
2212
2225
  const lapis = x$1(LapisUrlContext);
2213
2226
  return /* @__PURE__ */ u$1(Info, { children: [
2214
2227
  /* @__PURE__ */ u$1(InfoHeadline1, { children: "Info for mutation comparison" }),
2215
- /* @__PURE__ */ u$1(InfoParagraph, { children: "TODO: https://github.com/GenSpectrum/dashboard-components/issues/465" }),
2228
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
2229
+ "This displays ",
2230
+ /* @__PURE__ */ u$1(SubstitutionsLink, {}),
2231
+ " and ",
2232
+ /* @__PURE__ */ u$1(DeletionsLink, {}),
2233
+ " of several variants. It shows mutations where the proportion for any given variant falls within the range you can select in the component's toolbar."
2234
+ ] }),
2235
+ /* @__PURE__ */ u$1(ProportionExplanation, {}),
2236
+ originalComponentProps.views.includes(views.table) && /* @__PURE__ */ u$1(Fragment, { children: [
2237
+ /* @__PURE__ */ u$1(InfoHeadline2, { children: "Table View" }),
2238
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "The table view displays the proportion of mutations that appear in any of the variants." })
2239
+ ] }),
2240
+ originalComponentProps.views.includes(views.venn) && /* @__PURE__ */ u$1(Fragment, { children: [
2241
+ /* @__PURE__ */ u$1(InfoHeadline2, { children: "Venn Diagram View" }),
2242
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "The Venn diagram view illustrates which mutations overlap between the variants and which are exclusive to specific variants. Mutations overlap if their proportion falls within the selected range for two variants. If the proportion of a mutation is within the selected range for one variant but not for the other, the mutation is considered exclusive to that variant." })
2243
+ ] }),
2216
2244
  /* @__PURE__ */ u$1(InfoComponentCode, { componentName: "mutation-comparison", params: originalComponentProps, lapisUrl: lapis })
2217
2245
  ] });
2218
2246
  };
@@ -5162,6 +5190,9 @@ input.tab:checked + .tab-content,
5162
5190
  .gap-y-1 {
5163
5191
  row-gap: 0.25rem;
5164
5192
  }
5193
+ .overflow-visible {
5194
+ overflow: visible;
5195
+ }
5165
5196
  .overflow-scroll {
5166
5197
  overflow: scroll;
5167
5198
  }
@@ -5171,6 +5202,9 @@ input.tab:checked + .tab-content,
5171
5202
  .whitespace-nowrap {
5172
5203
  white-space: nowrap;
5173
5204
  }
5205
+ .text-nowrap {
5206
+ text-wrap: nowrap;
5207
+ }
5174
5208
  .break-words {
5175
5209
  overflow-wrap: break-word;
5176
5210
  }
@@ -5190,9 +5224,6 @@ input.tab:checked + .tab-content,
5190
5224
  border-bottom-right-radius: 0.375rem;
5191
5225
  border-bottom-left-radius: 0.375rem;
5192
5226
  }
5193
- .rounded-tl-md {
5194
- border-top-left-radius: 0.375rem;
5195
- }
5196
5227
  .rounded-tr-md {
5197
5228
  border-top-right-radius: 0.375rem;
5198
5229
  }
@@ -5202,6 +5233,9 @@ input.tab:checked + .tab-content,
5202
5233
  .border-2 {
5203
5234
  border-width: 2px;
5204
5235
  }
5236
+ .border-b {
5237
+ border-bottom-width: 1px;
5238
+ }
5205
5239
  .border-b-2 {
5206
5240
  border-bottom-width: 2px;
5207
5241
  }
@@ -5217,9 +5251,9 @@ input.tab:checked + .tab-content,
5217
5251
  --tw-border-opacity: 1;
5218
5252
  border-color: rgb(209 213 219 / var(--tw-border-opacity, 1));
5219
5253
  }
5220
- .border-gray-400 {
5254
+ .border-gray-500 {
5221
5255
  --tw-border-opacity: 1;
5222
- border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));
5256
+ border-color: rgb(107 114 128 / var(--tw-border-opacity, 1));
5223
5257
  }
5224
5258
  .border-slate-500 {
5225
5259
  --tw-border-opacity: 1;
@@ -5320,6 +5354,9 @@ input.tab:checked + .tab-content,
5320
5354
  .font-medium {
5321
5355
  font-weight: 500;
5322
5356
  }
5357
+ .font-semibold {
5358
+ font-weight: 600;
5359
+ }
5323
5360
  .leading-5 {
5324
5361
  line-height: 1.25rem;
5325
5362
  }
@@ -5466,6 +5503,12 @@ input.tab:checked + .tab-content,
5466
5503
  visibility: visible;
5467
5504
  }
5468
5505
  }
5506
+ @container (min-width: 6rem) {
5507
+
5508
+ .\\@\\[6rem\\]\\:visible {
5509
+ visibility: visible;
5510
+ }
5511
+ }
5469
5512
  @media (min-width: 640px) {
5470
5513
 
5471
5514
  .sm\\:max-w-5xl {
@@ -6075,31 +6118,16 @@ const MutationsInfo = ({ originalComponentProps }) => {
6075
6118
  return /* @__PURE__ */ u$1(Info, { children: [
6076
6119
  /* @__PURE__ */ u$1(InfoHeadline1, { children: "Mutations" }),
6077
6120
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
6078
- "This shows mutations of a variant. There are three types of mutations:",
6079
- " ",
6080
- /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Substitution", children: "substitutions" }),
6121
+ "This shows mutations of a variant. There are three types of mutations: ",
6122
+ /* @__PURE__ */ u$1(SubstitutionsLink, {}),
6081
6123
  ",",
6082
6124
  " ",
6083
- /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Deletion", children: "deletions" }),
6084
- " and",
6085
- " ",
6086
- /* @__PURE__ */ u$1(InfoLink, { href: "https://www.genome.gov/genetics-glossary/Insertion", children: "insertions" }),
6125
+ /* @__PURE__ */ u$1(DeletionsLink, {}),
6126
+ " and ",
6127
+ /* @__PURE__ */ u$1(InsertionsLink, {}),
6087
6128
  "."
6088
6129
  ] }),
6089
- /* @__PURE__ */ u$1(InfoHeadline2, { children: "Proportion calculation" }),
6090
- /* @__PURE__ */ u$1(InfoParagraph, { children: "The proportion of a mutation is calculated by dividing the number of sequences with the mutation by the total number of sequences with a non-ambiguous symbol at the position." }),
6091
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
6092
- /* @__PURE__ */ u$1("b", { children: "Example:" }),
6093
- " Assume we look at nucleotide mutations at position 5 where the reference has a T and assume there are 10 sequences in total:",
6094
- /* @__PURE__ */ u$1("ul", { className: "list-disc list-inside ml-2", children: [
6095
- /* @__PURE__ */ u$1("li", { children: "3 sequences have a C," }),
6096
- /* @__PURE__ */ u$1("li", { children: "2 sequences have a T," }),
6097
- /* @__PURE__ */ u$1("li", { children: "1 sequence has a G," }),
6098
- /* @__PURE__ */ u$1("li", { children: "3 sequences have an N," }),
6099
- /* @__PURE__ */ u$1("li", { children: "1 sequence has a Y (which means T or C)," })
6100
- ] }),
6101
- "then the proportion of the T5C mutation is 50%. The 4 sequences that have an N or Y are excluded from the calculation."
6102
- ] }),
6130
+ /* @__PURE__ */ u$1(ProportionExplanation, {}),
6103
6131
  /* @__PURE__ */ u$1(InfoComponentCode, { componentName: "mutations", params: originalComponentProps, lapisUrl: lapis })
6104
6132
  ] });
6105
6133
  };
@@ -9500,48 +9528,69 @@ const MutationsOverTimeGrid = ({
9500
9528
  gridTemplateRows: `repeat(${shownMutations.length}, 24px)`,
9501
9529
  gridTemplateColumns: `${MUTATION_CELL_WIDTH_REM}rem repeat(${dates.length}, minmax(0.05rem, 1fr))`
9502
9530
  },
9503
- children: shownMutations.map((mutation, rowIndex) => {
9504
- return /* @__PURE__ */ u$1(Fragment, { children: [
9505
- /* @__PURE__ */ u$1(
9506
- "div",
9507
- {
9508
- style: { gridRowStart: rowIndex + 1, gridColumnStart: 1 },
9509
- children: /* @__PURE__ */ u$1(MutationCell, { mutation })
9510
- },
9511
- `mutation-${mutation.toString()}`
9512
- ),
9513
- dates.map((date, columnIndex) => {
9514
- const value = data.get(mutation, date) ?? null;
9515
- const tooltipPosition = getTooltipPosition(
9516
- rowIndex,
9517
- shownMutations.length,
9518
- columnIndex,
9519
- dates.length
9520
- );
9521
- return /* @__PURE__ */ u$1(
9531
+ className: "text-center",
9532
+ children: [
9533
+ dates.map((date, columnIndex) => /* @__PURE__ */ u$1(
9534
+ "div",
9535
+ {
9536
+ className: "@container font-semibold",
9537
+ style: { gridRowStart: 1, gridColumnStart: columnIndex + 2 },
9538
+ children: /* @__PURE__ */ u$1("p", { ...styleGridHeader(columnIndex, dates), children: date.dateString })
9539
+ },
9540
+ date.dateString
9541
+ )),
9542
+ shownMutations.map((mutation, rowIndex) => {
9543
+ return /* @__PURE__ */ u$1(Fragment, { children: [
9544
+ /* @__PURE__ */ u$1(
9522
9545
  "div",
9523
9546
  {
9524
- style: { gridRowStart: rowIndex + 1, gridColumnStart: columnIndex + 2 },
9525
- children: /* @__PURE__ */ u$1(
9526
- ProportionCell,
9527
- {
9528
- value,
9529
- date,
9530
- mutation,
9531
- tooltipPosition,
9532
- colorScale
9533
- }
9534
- )
9547
+ style: { gridRowStart: rowIndex + 2, gridColumnStart: 1 },
9548
+ children: /* @__PURE__ */ u$1(MutationCell, { mutation })
9535
9549
  },
9536
- `${mutation.toString()}-${date.toString()}`
9537
- );
9538
- })
9539
- ] }, `fragment-${mutation.toString()}`);
9540
- })
9550
+ `mutation-${mutation.toString()}`
9551
+ ),
9552
+ dates.map((date, columnIndex) => {
9553
+ const value = data.get(mutation, date) ?? null;
9554
+ const tooltipPosition = getTooltipPosition(
9555
+ rowIndex,
9556
+ shownMutations.length,
9557
+ columnIndex,
9558
+ dates.length
9559
+ );
9560
+ return /* @__PURE__ */ u$1(
9561
+ "div",
9562
+ {
9563
+ style: { gridRowStart: rowIndex + 2, gridColumnStart: columnIndex + 2 },
9564
+ children: /* @__PURE__ */ u$1(
9565
+ ProportionCell,
9566
+ {
9567
+ value,
9568
+ date,
9569
+ mutation,
9570
+ tooltipPosition,
9571
+ colorScale
9572
+ }
9573
+ )
9574
+ },
9575
+ `${mutation.toString()}-${date.toString()}`
9576
+ );
9577
+ })
9578
+ ] }, `fragment-${mutation.toString()}`);
9579
+ })
9580
+ ]
9541
9581
  }
9542
9582
  )
9543
9583
  ] });
9544
9584
  };
9585
+ function styleGridHeader(columnIndex, dates) {
9586
+ if (columnIndex === 0) {
9587
+ return { className: "overflow-visible text-nowrap" };
9588
+ }
9589
+ if (columnIndex === dates.length - 1) {
9590
+ return { className: "overflow-visible text-nowrap", style: { direction: "rtl" } };
9591
+ }
9592
+ return { className: "invisible @[6rem]:visible" };
9593
+ }
9545
9594
  function getTooltipPosition(rowIndex, rows, columnIndex, columns) {
9546
9595
  const tooltipX = rowIndex < rows / 2 || rowIndex < 6 ? "bottom" : "top";
9547
9596
  const tooltipY = columnIndex < columns / 2 ? "start" : "end";
@@ -9578,7 +9627,7 @@ const ProportionCell = ({ value, mutation, date, tooltipPosition, colorScale })
9578
9627
  backgroundColor: getColorWithingScale(value == null ? void 0 : value.proportion, colorScale),
9579
9628
  color: getTextColorForScale(value == null ? void 0 : value.proportion, colorScale)
9580
9629
  },
9581
- className: `w-full h-full text-center hover:font-bold text-xs group @container`,
9630
+ className: `w-full h-full hover:font-bold text-xs group @container`,
9582
9631
  children: /* @__PURE__ */ u$1("span", { className: "invisible @[2rem]:visible", children: value === null ? "" : formatProportion(value.proportion, 0) })
9583
9632
  }
9584
9633
  ) }) });
@@ -9590,7 +9639,7 @@ const timeIntervalDisplay = (date) => {
9590
9639
  return `${date.firstDay.toString()} - ${date.lastDay.toString()}`;
9591
9640
  };
9592
9641
  const MutationCell = ({ mutation }) => {
9593
- return /* @__PURE__ */ u$1("div", { className: "text-center", children: mutation.code });
9642
+ return /* @__PURE__ */ u$1("div", { children: mutation.code });
9594
9643
  };
9595
9644
  const ColorScaleSelectorDropdown = ({
9596
9645
  colorScale,
@@ -11140,12 +11189,20 @@ async function queryWastewaterMutationsOverTime(lapis, lapisFilter, signal) {
11140
11189
  "aminoAcidMutationFrequency"
11141
11190
  ]);
11142
11191
  const data = (await fetchData.evaluate(lapis, signal)).content;
11143
- return data.map((row) => ({
11144
- location: row.location,
11145
- date: toTemporalClass(parseDateStringToTemporal(row.date, "day")),
11146
- nucleotideMutationFrequency: row.nucleotideMutationFrequency !== null ? transformMutations(JSON.parse(row.nucleotideMutationFrequency)) : [],
11147
- aminoAcidMutationFrequency: row.aminoAcidMutationFrequency !== null ? transformMutations(JSON.parse(row.aminoAcidMutationFrequency)) : []
11148
- }));
11192
+ return data.map((row) => {
11193
+ try {
11194
+ return {
11195
+ location: row.location,
11196
+ date: toTemporalClass(parseDateStringToTemporal(row.date, "day")),
11197
+ nucleotideMutationFrequency: row.nucleotideMutationFrequency !== null ? transformMutations(JSON.parse(row.nucleotideMutationFrequency)) : [],
11198
+ aminoAcidMutationFrequency: row.aminoAcidMutationFrequency !== null ? transformMutations(JSON.parse(row.aminoAcidMutationFrequency)) : []
11199
+ };
11200
+ } catch (e2) {
11201
+ throw new Error(
11202
+ `Failed to parse row of wastewater data: ${JSON.stringify(row)}: ${(e2 == null ? void 0 : e2.message) ?? "Unknown error"}`
11203
+ );
11204
+ }
11205
+ });
11149
11206
  }
11150
11207
  const mutationFrequencySchema = z$2.record(z$2.number().nullable());
11151
11208
  function transformMutations(input) {
@@ -11153,10 +11210,16 @@ function transformMutations(input) {
11153
11210
  if (!mutationFrequency.success) {
11154
11211
  throw new Error(`Failed to parse mutation frequency: ${mutationFrequency.error.message}`);
11155
11212
  }
11156
- return Object.entries(mutationFrequency.data).map(([key, value]) => ({
11157
- mutation: SubstitutionClass.parse(key),
11158
- proportion: value
11159
- }));
11213
+ return Object.entries(mutationFrequency.data).map(([key, value]) => {
11214
+ const mutation = SubstitutionClass.parse(key);
11215
+ if (mutation === null) {
11216
+ throw new Error(`Failed to parse mutation: "${key}"`);
11217
+ }
11218
+ return {
11219
+ mutation,
11220
+ proportion: value
11221
+ };
11222
+ });
11160
11223
  }
11161
11224
  async function computeWastewaterMutationsOverTimeDataPerLocation(lapis, lapisFilter, sequenceType, signal) {
11162
11225
  const data = await queryWastewaterMutationsOverTime(lapis, lapisFilter, signal);
@@ -11192,7 +11255,7 @@ const wastewaterMutationOverTimeSchema = z$2.object({
11192
11255
  sequenceType: sequenceTypeSchema,
11193
11256
  width: z$2.string(),
11194
11257
  height: z$2.string(),
11195
- maxNumberOfGridRows: z$2.number().optional()
11258
+ maxNumberOfGridRows: z$2.number()
11196
11259
  });
11197
11260
  const WastewaterMutationsOverTime = (componentProps) => {
11198
11261
  const { width, height } = componentProps;
@@ -11640,26 +11703,46 @@ async function fetchAutocompletionList({
11640
11703
  signal,
11641
11704
  lapisFilter
11642
11705
  }) {
11643
- const toAncestorInHierarchyOverwriteValues = Array(fields.length - 1).fill(0).map((_2, i2) => i2 + 1).map((i2) => fields.slice(i2).reduce((acc, field) => ({ ...acc, [field]: null }), {}));
11706
+ const helpersThatOverwriteAValueToItsAncestor = fields.map(
11707
+ (_2, i2) => fields.slice(i2 + 1).reduce((acc, field) => ({ ...acc, [field]: null }), {})
11708
+ );
11644
11709
  const fetchAggregatedOperator = new FetchAggregatedOperator(
11645
11710
  lapisFilter ?? {},
11646
11711
  fields
11647
11712
  );
11648
11713
  const data = (await fetchAggregatedOperator.evaluate(lapis, signal)).content;
11649
- const locationValues = data.map((entry) => fields.reduce((acc, field) => ({ ...acc, [field]: entry[field] }), {})).reduce((setOfAllHierarchies, entry) => {
11650
- setOfAllHierarchies.add(JSON.stringify(entry));
11651
- toAncestorInHierarchyOverwriteValues.forEach((overwriteValues) => {
11652
- setOfAllHierarchies.add(JSON.stringify({ ...entry, ...overwriteValues }));
11653
- });
11654
- return setOfAllHierarchies;
11655
- }, /* @__PURE__ */ new Set());
11656
- return [...locationValues].map((json) => JSON.parse(json)).sort(compareLocationEntries(fields)).map((entry) => fields.reduce((acc, field) => ({ ...acc, [field]: entry[field] ?? void 0 }), {}));
11714
+ const locationValues = data.map((entry) => ({
11715
+ value: fields.reduce((acc, field) => ({ ...acc, [field]: entry[field] }), {}),
11716
+ count: entry.count
11717
+ })).reduce((mapOfAllHierarchiesAndCounts, entry) => {
11718
+ return addValueAndAllAncestorsToMap(
11719
+ entry,
11720
+ helpersThatOverwriteAValueToItsAncestor,
11721
+ mapOfAllHierarchiesAndCounts
11722
+ );
11723
+ }, /* @__PURE__ */ new Map());
11724
+ return [...locationValues].map(([json, count]) => ({
11725
+ value: JSON.parse(json),
11726
+ count
11727
+ })).sort(compareLocationEntries(fields)).map(({ value, count }) => ({
11728
+ value: fields.reduce((acc, field) => ({ ...acc, [field]: value[field] ?? void 0 }), {}),
11729
+ count
11730
+ }));
11731
+ }
11732
+ function addValueAndAllAncestorsToMap({ value, count }, helpersThatOverwriteAValueToItsAncestor, mapOfAllHierarchiesAndCounts) {
11733
+ const keysOfAllHierarchyLevels = new Set(
11734
+ helpersThatOverwriteAValueToItsAncestor.map((overwriteValues) => ({ ...value, ...overwriteValues })).map((value2) => JSON.stringify(value2))
11735
+ );
11736
+ for (const key of keysOfAllHierarchyLevels) {
11737
+ mapOfAllHierarchiesAndCounts.set(key, (mapOfAllHierarchiesAndCounts.get(key) ?? 0) + count);
11738
+ }
11739
+ return mapOfAllHierarchiesAndCounts;
11657
11740
  }
11658
11741
  function compareLocationEntries(fields) {
11659
11742
  return (a2, b3) => {
11660
11743
  for (const field of fields) {
11661
- const valueA = a2[field];
11662
- const valueB = b3[field];
11744
+ const valueA = a2.value[field];
11745
+ const valueB = b3.value[field];
11663
11746
  if (valueA === valueB) {
11664
11747
  continue;
11665
11748
  }
@@ -14715,12 +14798,12 @@ function DownshiftCombobox({
14715
14798
  children: items.length > 0 ? items.map((item, index) => /* @__PURE__ */ u$1(
14716
14799
  "li",
14717
14800
  {
14718
- className: `${highlightedIndex === index ? "bg-blue-300" : ""} ${selectedItem !== null && itemToString2(selectedItem) === itemToString2(item) ? "font-bold" : ""} py-2 px-3 shadow-sm flex flex-col`,
14801
+ className: `${highlightedIndex === index ? "bg-blue-300" : ""} ${selectedItem !== null && itemToString2(selectedItem) === itemToString2(item) ? "font-bold" : ""} py-2 px-3 shadow-sm`,
14719
14802
  ...getItemProps({ item, index }),
14720
14803
  children: formatItemInList(item)
14721
14804
  },
14722
14805
  itemToString2(item)
14723
- )) : /* @__PURE__ */ u$1("li", { className: "py-2 px-3 shadow-sm flex flex-col", children: "No elements to select." })
14806
+ )) : /* @__PURE__ */ u$1("li", { className: "py-2 px-3 shadow-sm", children: "No elements to select." })
14724
14807
  }
14725
14808
  )
14726
14809
  ] });
@@ -14763,8 +14846,8 @@ const LocationSelector = ({
14763
14846
  return locationData.map((location) => toSelectItem(location, fields)).filter((item) => item !== void 0);
14764
14847
  }, [fields, locationData]);
14765
14848
  const selectedItem = T$1(() => {
14766
- return value !== void 0 ? toSelectItem(value, fields) : void 0;
14767
- }, [fields, value]);
14849
+ return value !== void 0 ? allItems.find((item) => item.description == concatenateLocation(value, fields)) : void 0;
14850
+ }, [fields, value, allItems]);
14768
14851
  return /* @__PURE__ */ u$1(
14769
14852
  DownshiftCombobox,
14770
14853
  {
@@ -14774,12 +14857,17 @@ const LocationSelector = ({
14774
14857
  createEvent: (item) => new LocationChangedEvent((item == null ? void 0 : item.lapisFilter) ?? emptyLocationFilter(fields)),
14775
14858
  itemToString: (item) => (item == null ? void 0 : item.label) ?? "",
14776
14859
  placeholderText,
14777
- formatItemInList: (item) => {
14778
- return /* @__PURE__ */ u$1(Fragment, { children: [
14860
+ formatItemInList: (item) => /* @__PURE__ */ u$1(Fragment, { children: [
14861
+ /* @__PURE__ */ u$1("p", { children: [
14779
14862
  /* @__PURE__ */ u$1("span", { children: item.label }),
14780
- /* @__PURE__ */ u$1("span", { className: "text-sm text-gray-500", children: item.description })
14781
- ] });
14782
- }
14863
+ /* @__PURE__ */ u$1("span", { className: "ml-2 text-gray-500", children: [
14864
+ "(",
14865
+ item.count,
14866
+ ")"
14867
+ ] })
14868
+ ] }),
14869
+ /* @__PURE__ */ u$1("span", { className: "text-sm text-gray-500", children: item.description })
14870
+ ] })
14783
14871
  }
14784
14872
  );
14785
14873
  };
@@ -14790,7 +14878,8 @@ function filterByInputValue$2(item, inputValue) {
14790
14878
  }
14791
14879
  return ((_a = item == null ? void 0 : item.label) == null ? void 0 : _a.toLowerCase().includes(inputValue.toLowerCase())) || (item == null ? void 0 : item.description.toLowerCase().includes(inputValue.toLowerCase()));
14792
14880
  }
14793
- function toSelectItem(locationFilter, fields) {
14881
+ function toSelectItem(locationEntry, fields) {
14882
+ const locationFilter = locationEntry.value;
14794
14883
  const concatenatedLocation = concatenateLocation(locationFilter, fields);
14795
14884
  const lastNonUndefinedField = [...fields].reverse().find((field) => locationFilter[field] !== void 0 && locationFilter[field] !== null);
14796
14885
  if (lastNonUndefinedField === void 0) {
@@ -14799,7 +14888,8 @@ function toSelectItem(locationFilter, fields) {
14799
14888
  return {
14800
14889
  lapisFilter: locationFilter,
14801
14890
  label: locationFilter[lastNonUndefinedField],
14802
- description: concatenatedLocation
14891
+ description: concatenatedLocation,
14892
+ count: locationEntry.count
14803
14893
  };
14804
14894
  }
14805
14895
  function concatenateLocation(locationFilter, fields) {
@@ -15013,48 +15103,218 @@ const ReferenceGenomesAwaiter = ({ children }) => {
15013
15103
  function isNotInitialized(referenceGenome) {
15014
15104
  return referenceGenome.nucleotideSequences.length === 0 && referenceGenome.genes.length === 0;
15015
15105
  }
15016
- const MutationFilterInfo = () => {
15106
+ const ExampleMutation = ({ sequenceType, mutationType }) => {
15017
15107
  const referenceGenome = x$1(ReferenceGenomeContext);
15018
- const firstGene = referenceGenome.genes[0].name;
15108
+ return /* @__PURE__ */ u$1("b", { children: getExampleMutation(referenceGenome, sequenceType, mutationType) });
15109
+ };
15110
+ function getExampleMutation(referenceGenome, sequenceType, mutationType) {
15111
+ switch (sequenceType) {
15112
+ case "amino acid": {
15113
+ if (referenceGenome.genes.length === 0) {
15114
+ return "";
15115
+ }
15116
+ const firstGene = referenceGenome.genes[0].name;
15117
+ switch (mutationType) {
15118
+ case "substitution":
15119
+ return `${firstGene}:57Q`;
15120
+ case "insertion":
15121
+ return `ins_${firstGene}:31:N`;
15122
+ }
15123
+ }
15124
+ // Issue of linter https://github.com/typescript-eslint/typescript-eslint/issues/3455
15125
+ // eslint-disable-next-line no-fallthrough
15126
+ case "nucleotide": {
15127
+ switch (referenceGenome.nucleotideSequences.length) {
15128
+ case 0: {
15129
+ return "";
15130
+ }
15131
+ case 1: {
15132
+ switch (mutationType) {
15133
+ case "substitution":
15134
+ return "23T";
15135
+ case "insertion":
15136
+ return "ins_1046:A";
15137
+ }
15138
+ }
15139
+ // Issue of linter https://github.com/typescript-eslint/typescript-eslint/issues/3455
15140
+ // eslint-disable-next-line no-fallthrough
15141
+ default: {
15142
+ const firstSegment = referenceGenome.nucleotideSequences[0].name;
15143
+ switch (mutationType) {
15144
+ case "substitution":
15145
+ return `${firstSegment}:23T`;
15146
+ case "insertion":
15147
+ return `ins_${firstSegment}:10462:A`;
15148
+ }
15149
+ }
15150
+ }
15151
+ }
15152
+ }
15153
+ }
15154
+ const MutationFilterInfo = () => {
15019
15155
  return /* @__PURE__ */ u$1(Info, { children: [
15020
15156
  /* @__PURE__ */ u$1(InfoHeadline1, { children: " Mutation Filter" }),
15021
15157
  /* @__PURE__ */ u$1(InfoParagraph, { children: "This component allows you to filter for mutations at specific positions." }),
15158
+ /* @__PURE__ */ u$1(QuickStart, {}),
15159
+ /* @__PURE__ */ u$1(NucleotideMutationsInfo, {}),
15160
+ /* @__PURE__ */ u$1(AminoAcidMutationsInfo, {}),
15161
+ /* @__PURE__ */ u$1(InsertionWildcards, {}),
15162
+ /* @__PURE__ */ u$1(MultipleMutations, {}),
15163
+ /* @__PURE__ */ u$1(AnyMutation, {}),
15164
+ /* @__PURE__ */ u$1(NoMutation, {})
15165
+ ] });
15166
+ };
15167
+ const QuickStart = () => {
15168
+ const referenceGenome = x$1(ReferenceGenomeContext);
15169
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15022
15170
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "Quickstart" }),
15023
15171
  /* @__PURE__ */ u$1(InfoParagraph, { children: /* @__PURE__ */ u$1("ul", { className: "list-disc list-inside", children: [
15024
- /* @__PURE__ */ u$1("li", { children: [
15172
+ referenceGenome.nucleotideSequences.length > 0 && /* @__PURE__ */ u$1("li", { children: [
15025
15173
  "Filter for nucleotide mutations:",
15026
15174
  " ",
15027
15175
  /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "substitution", sequenceType: "nucleotide" })
15028
15176
  ] }),
15029
- /* @__PURE__ */ u$1("li", { children: [
15177
+ referenceGenome.genes.length > 0 && /* @__PURE__ */ u$1("li", { children: [
15030
15178
  "Filter for amino acid mutations:",
15031
15179
  " ",
15032
- /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "insertion", sequenceType: "nucleotide" })
15180
+ /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "substitution", sequenceType: "amino acid" })
15033
15181
  ] }),
15034
- /* @__PURE__ */ u$1("li", { children: [
15182
+ referenceGenome.nucleotideSequences.length > 0 && /* @__PURE__ */ u$1("li", { children: [
15035
15183
  "Filter for nucleotide insertions:",
15036
15184
  " ",
15037
- /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "substitution", sequenceType: "amino acid" })
15185
+ /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "insertion", sequenceType: "nucleotide" })
15038
15186
  ] }),
15039
- /* @__PURE__ */ u$1("li", { children: [
15187
+ referenceGenome.genes.length > 0 && /* @__PURE__ */ u$1("li", { children: [
15040
15188
  "Filter for amino acid insertions:",
15041
15189
  " ",
15042
15190
  /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "insertion", sequenceType: "amino acid" })
15043
15191
  ] })
15044
15192
  ] }) }),
15045
- !isSingleSegmented(referenceGenome) && /* @__PURE__ */ u$1(InfoParagraph, { children: [
15193
+ referenceGenome.nucleotideSequences.length > 1 ? /* @__PURE__ */ u$1(InfoParagraph, { children: [
15046
15194
  "This organism has the following segments:",
15047
15195
  " ",
15048
15196
  referenceGenome.nucleotideSequences.map((gene) => gene.name).join(", "),
15049
15197
  "."
15050
- ] }),
15051
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
15198
+ ] }) : /* @__PURE__ */ u$1(InfoParagraph, { children: "This organism doesn't support nucleotide sequences." }),
15199
+ referenceGenome.genes.length !== 0 ? /* @__PURE__ */ u$1(InfoParagraph, { children: [
15052
15200
  "This organism has the following genes: ",
15053
15201
  referenceGenome.genes.map((gene) => gene.name).join(", "),
15054
15202
  "."
15055
- ] }),
15203
+ ] }) : /* @__PURE__ */ u$1(InfoParagraph, { children: "This organism doesn't support amino acid sequences." })
15204
+ ] });
15205
+ };
15206
+ const NucleotideMutationsInfo = () => {
15207
+ const referenceGenome = x$1(ReferenceGenomeContext);
15208
+ if (referenceGenome.nucleotideSequences.length === 0) {
15209
+ return null;
15210
+ }
15211
+ if (isSingleSegmented(referenceGenome)) {
15212
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15213
+ /* @__PURE__ */ u$1(InfoHeadline2, { children: "Nucleotide Mutations and Insertions" }),
15214
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
15215
+ "This organism is single-segmented. Thus, nucleotide mutations have the format",
15216
+ " ",
15217
+ /* @__PURE__ */ u$1("b", { children: "<position><base>" }),
15218
+ " or ",
15219
+ /* @__PURE__ */ u$1("b", { children: "<base_ref><position><base>" }),
15220
+ ". The",
15221
+ " ",
15222
+ /* @__PURE__ */ u$1("b", { children: "<base_ref>" }),
15223
+ " is the reference base at the position. It is optional. A ",
15224
+ /* @__PURE__ */ u$1("b", { children: "<base>" }),
15225
+ " ",
15226
+ "can be one of the four nucleotides ",
15227
+ /* @__PURE__ */ u$1("b", { children: "A" }),
15228
+ ", ",
15229
+ /* @__PURE__ */ u$1("b", { children: "T" }),
15230
+ ", ",
15231
+ /* @__PURE__ */ u$1("b", { children: "C" }),
15232
+ ", and ",
15233
+ /* @__PURE__ */ u$1("b", { children: "G" }),
15234
+ ". It can also be",
15235
+ " ",
15236
+ /* @__PURE__ */ u$1("b", { children: "-" }),
15237
+ " for deletion and ",
15238
+ /* @__PURE__ */ u$1("b", { children: "N" }),
15239
+ " for unknown. For example if the reference sequence is ",
15240
+ /* @__PURE__ */ u$1("b", { children: "A" }),
15241
+ " at position ",
15242
+ /* @__PURE__ */ u$1("b", { children: "23" }),
15243
+ " both: ",
15244
+ /* @__PURE__ */ u$1("b", { children: "23T" }),
15245
+ " and ",
15246
+ /* @__PURE__ */ u$1("b", { children: "A23T" }),
15247
+ " will yield the same results."
15248
+ ] }),
15249
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
15250
+ "Insertions can be searched for in the same manner, they just need to have ",
15251
+ /* @__PURE__ */ u$1("b", { children: "ins_" }),
15252
+ " appended to the start of the mutation. Example: ",
15253
+ /* @__PURE__ */ u$1("b", { children: "ins_1046:A" }),
15254
+ " would filter for sequences with an insertion of A between the positions 1046 and 1047 in the nucleotide sequence."
15255
+ ] })
15256
+ ] });
15257
+ }
15258
+ const firstSegment = referenceGenome.nucleotideSequences[0].name;
15259
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15056
15260
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "Nucleotide Mutations and Insertions" }),
15057
- isSingleSegmented(referenceGenome) ? /* @__PURE__ */ u$1(SingleSegmentedNucleotideMutationsInfo, {}) : /* @__PURE__ */ u$1(MultiSegmentedNucleotideMutationsInfo, {}),
15261
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
15262
+ "This organism is multi-segmented. Thus, nucleotide mutations have the format",
15263
+ " ",
15264
+ /* @__PURE__ */ u$1("b", { children: "<segment>:<position><base>" }),
15265
+ " or",
15266
+ " ",
15267
+ /* @__PURE__ */ u$1("b", { children: "<segment>:<base_ref><position><base>" }),
15268
+ ". ",
15269
+ /* @__PURE__ */ u$1("b", { children: "<base_ref>" }),
15270
+ " is the reference base at the position. It is optional. A ",
15271
+ /* @__PURE__ */ u$1("b", { children: "<base>" }),
15272
+ " can be one of the four nucleotides",
15273
+ " ",
15274
+ /* @__PURE__ */ u$1("b", { children: "A" }),
15275
+ ", ",
15276
+ /* @__PURE__ */ u$1("b", { children: "T" }),
15277
+ ", ",
15278
+ /* @__PURE__ */ u$1("b", { children: "C" }),
15279
+ ", and ",
15280
+ /* @__PURE__ */ u$1("b", { children: "G" }),
15281
+ ". It can also be ",
15282
+ /* @__PURE__ */ u$1("b", { children: "-" }),
15283
+ " for deletion and ",
15284
+ /* @__PURE__ */ u$1("b", { children: "N" }),
15285
+ " for unknown. For example if the reference sequence is ",
15286
+ /* @__PURE__ */ u$1("b", { children: "A" }),
15287
+ " at position ",
15288
+ /* @__PURE__ */ u$1("b", { children: "23" }),
15289
+ " both:",
15290
+ " ",
15291
+ /* @__PURE__ */ u$1("b", { children: [
15292
+ firstSegment,
15293
+ ":23T"
15294
+ ] }),
15295
+ " and ",
15296
+ /* @__PURE__ */ u$1("b", { children: [
15297
+ firstSegment,
15298
+ ":A23T"
15299
+ ] }),
15300
+ " will yield the same results."
15301
+ ] }),
15302
+ /* @__PURE__ */ u$1(InfoParagraph, { children: [
15303
+ "Insertions can be searched for in the same manner, they just need to have ",
15304
+ /* @__PURE__ */ u$1("b", { children: "ins_" }),
15305
+ " appended to the start of the mutation. Example: ",
15306
+ /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "insertion", sequenceType: "nucleotide" }),
15307
+ "."
15308
+ ] })
15309
+ ] });
15310
+ };
15311
+ const AminoAcidMutationsInfo = () => {
15312
+ const referenceGenome = x$1(ReferenceGenomeContext);
15313
+ if (referenceGenome.genes.length === 0) {
15314
+ return null;
15315
+ }
15316
+ const firstGene = referenceGenome.genes[0].name;
15317
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15058
15318
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "Amino Acid Mutations and Insertions" }),
15059
15319
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
15060
15320
  "An amino acid mutation has the format ",
@@ -15084,30 +15344,46 @@ const MutationFilterInfo = () => {
15084
15344
  " would filter for sequences with an insertion of N between positions 31 and 32 in the gene ",
15085
15345
  firstGene,
15086
15346
  "."
15087
- ] }),
15347
+ ] })
15348
+ ] });
15349
+ };
15350
+ const InsertionWildcards = () => {
15351
+ const referenceGenome = x$1(ReferenceGenomeContext);
15352
+ if (referenceGenome.nucleotideSequences.length === 0 && referenceGenome.genes.length === 0) {
15353
+ return null;
15354
+ }
15355
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15088
15356
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "Insertion Wildcards" }),
15089
15357
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
15090
- "This component supports insertion queries that contain wildcards ",
15358
+ "This component supports nucleotide and amino acid insertion queries that contain wildcards ",
15091
15359
  /* @__PURE__ */ u$1("b", { children: "?" }),
15092
15360
  ". For example",
15093
15361
  " ",
15094
15362
  /* @__PURE__ */ u$1("b", { children: [
15095
15363
  "ins_",
15096
- firstGene,
15097
- ":214:?EP?"
15364
+ exampleSegmentString(referenceGenome),
15365
+ "214:?",
15366
+ exampleWildcardInsertion(referenceGenome),
15367
+ "?"
15098
15368
  ] }),
15099
- " will match all cases where segment ",
15100
- /* @__PURE__ */ u$1("b", { children: firstGene }),
15101
- " has an insertion of ",
15102
- /* @__PURE__ */ u$1("b", { children: "EP" }),
15369
+ " ",
15370
+ "will match all cases where segment ",
15371
+ /* @__PURE__ */ u$1("b", { children: exampleSegment(referenceGenome) }),
15372
+ " has an insertion of",
15373
+ " ",
15374
+ /* @__PURE__ */ u$1("b", { children: exampleWildcardInsertion(referenceGenome) }),
15103
15375
  " between the positions ",
15104
15376
  /* @__PURE__ */ u$1("b", { children: "214" }),
15105
15377
  " and ",
15106
15378
  /* @__PURE__ */ u$1("b", { children: "215" }),
15107
15379
  " but also an insertion of other amino acids which include the ",
15108
15380
  /* @__PURE__ */ u$1("b", { children: "EP" }),
15109
- ", e.g. the insertion ",
15110
- /* @__PURE__ */ u$1("b", { children: "EPE" }),
15381
+ ", e.g. the insertion",
15382
+ " ",
15383
+ /* @__PURE__ */ u$1("b", { children: [
15384
+ exampleWildcardInsertion(referenceGenome),
15385
+ "T"
15386
+ ] }),
15111
15387
  " will be matched."
15112
15388
  ] }),
15113
15389
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
@@ -15115,13 +15391,47 @@ const MutationFilterInfo = () => {
15115
15391
  " ",
15116
15392
  /* @__PURE__ */ u$1("b", { children: [
15117
15393
  "ins_",
15118
- firstGene,
15119
- ":214:?"
15394
+ exampleSegmentString(referenceGenome),
15395
+ "214:?"
15120
15396
  ] }),
15121
15397
  " match any (but at least one) insertion between the positions 214 and 215."
15122
- ] }),
15398
+ ] })
15399
+ ] });
15400
+ };
15401
+ const exampleSegmentString = (referenceGenome) => {
15402
+ const segment = exampleSegment(referenceGenome);
15403
+ if (segment === "") {
15404
+ return "";
15405
+ }
15406
+ return `${segment}:`;
15407
+ };
15408
+ const exampleSegment = (referenceGenome) => {
15409
+ if (referenceGenome.genes.length > 0) {
15410
+ return `${referenceGenome.genes[0].name}`;
15411
+ }
15412
+ if (referenceGenome.nucleotideSequences.length > 1) {
15413
+ return `${referenceGenome.nucleotideSequences[0].name}`;
15414
+ }
15415
+ return "";
15416
+ };
15417
+ const exampleWildcardInsertion = (referenceGenome) => {
15418
+ if (referenceGenome.genes.length > 0) {
15419
+ return "EP";
15420
+ }
15421
+ if (referenceGenome.nucleotideSequences.length > 0) {
15422
+ return "CG";
15423
+ }
15424
+ return "";
15425
+ };
15426
+ const MultipleMutations = () => {
15427
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15123
15428
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "Multiple Mutations" }),
15124
- /* @__PURE__ */ u$1(InfoParagraph, { children: "Multiple mutation filters can be provided by adding one mutation after the other." }),
15429
+ /* @__PURE__ */ u$1(InfoParagraph, { children: "Multiple mutation filters can be provided by adding one mutation after the other." })
15430
+ ] });
15431
+ };
15432
+ const AnyMutation = () => {
15433
+ const referenceGenome = x$1(ReferenceGenomeContext);
15434
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15125
15435
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "Any Mutation" }),
15126
15436
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
15127
15437
  "To filter for any mutation at a given position you can omit the ",
@@ -15129,11 +15439,15 @@ const MutationFilterInfo = () => {
15129
15439
  ". Example:",
15130
15440
  " ",
15131
15441
  /* @__PURE__ */ u$1("b", { children: [
15132
- firstGene,
15133
- ":20"
15442
+ exampleSegmentString(referenceGenome),
15443
+ "20"
15134
15444
  ] }),
15135
15445
  "."
15136
- ] }),
15446
+ ] })
15447
+ ] });
15448
+ };
15449
+ const NoMutation = () => {
15450
+ return /* @__PURE__ */ u$1(Fragment, { children: [
15137
15451
  /* @__PURE__ */ u$1(InfoHeadline2, { children: "No Mutation" }),
15138
15452
  /* @__PURE__ */ u$1(InfoParagraph, { children: [
15139
15453
  "You can write a ",
@@ -15144,146 +15458,6 @@ const MutationFilterInfo = () => {
15144
15458
  ] })
15145
15459
  ] });
15146
15460
  };
15147
- const SingleSegmentedNucleotideMutationsInfo = () => {
15148
- return /* @__PURE__ */ u$1(Fragment, { children: [
15149
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
15150
- "This organism is single-segmented. Thus, nucleotide mutations have the format",
15151
- " ",
15152
- /* @__PURE__ */ u$1("b", { children: "<position><base>" }),
15153
- " or ",
15154
- /* @__PURE__ */ u$1("b", { children: "<base_ref><position><base>" }),
15155
- ". The",
15156
- " ",
15157
- /* @__PURE__ */ u$1("b", { children: "<base_ref>" }),
15158
- " is the reference base at the position. It is optional. A ",
15159
- /* @__PURE__ */ u$1("b", { children: "<base>" }),
15160
- " can be one of the four nucleotides ",
15161
- /* @__PURE__ */ u$1("b", { children: "A" }),
15162
- ", ",
15163
- /* @__PURE__ */ u$1("b", { children: "T" }),
15164
- ", ",
15165
- /* @__PURE__ */ u$1("b", { children: "C" }),
15166
- ", and ",
15167
- /* @__PURE__ */ u$1("b", { children: "G" }),
15168
- ". It can also be ",
15169
- /* @__PURE__ */ u$1("b", { children: "-" }),
15170
- " for deletion and ",
15171
- /* @__PURE__ */ u$1("b", { children: "N" }),
15172
- " for unknown. For example if the reference sequence is ",
15173
- /* @__PURE__ */ u$1("b", { children: "A" }),
15174
- " at position",
15175
- " ",
15176
- /* @__PURE__ */ u$1("b", { children: "23" }),
15177
- " both: ",
15178
- /* @__PURE__ */ u$1("b", { children: "23T" }),
15179
- " and ",
15180
- /* @__PURE__ */ u$1("b", { children: "A23T" }),
15181
- " will yield the same results."
15182
- ] }),
15183
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
15184
- "Insertions can be searched for in the same manner, they just need to have ",
15185
- /* @__PURE__ */ u$1("b", { children: "ins_" }),
15186
- " appended to the start of the mutation. Example: ",
15187
- /* @__PURE__ */ u$1("b", { children: "ins_1046:A" }),
15188
- " would filter for sequences with an insertion of A between the positions 1046 and 1047 in the nucleotide sequence."
15189
- ] })
15190
- ] });
15191
- };
15192
- const MultiSegmentedNucleotideMutationsInfo = () => {
15193
- const referenceGenome = x$1(ReferenceGenomeContext);
15194
- const firstSegment = referenceGenome.nucleotideSequences[0].name;
15195
- return /* @__PURE__ */ u$1(Fragment, { children: [
15196
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
15197
- "This organism is multi-segmented. Thus, nucleotide mutations have the format",
15198
- " ",
15199
- /* @__PURE__ */ u$1("b", { children: "<segment>:<position><base>" }),
15200
- " or",
15201
- " ",
15202
- /* @__PURE__ */ u$1("b", { children: "<segment>:<base_ref><position><base>" }),
15203
- ". ",
15204
- /* @__PURE__ */ u$1("b", { children: "<base_ref>" }),
15205
- " is the reference base at the position. It is optional. A ",
15206
- /* @__PURE__ */ u$1("b", { children: "<base>" }),
15207
- " can be one of the four nucleotides",
15208
- " ",
15209
- /* @__PURE__ */ u$1("b", { children: "A" }),
15210
- ", ",
15211
- /* @__PURE__ */ u$1("b", { children: "T" }),
15212
- ", ",
15213
- /* @__PURE__ */ u$1("b", { children: "C" }),
15214
- ", and ",
15215
- /* @__PURE__ */ u$1("b", { children: "G" }),
15216
- ". It can also be ",
15217
- /* @__PURE__ */ u$1("b", { children: "-" }),
15218
- " for deletion and ",
15219
- /* @__PURE__ */ u$1("b", { children: "N" }),
15220
- " for unknown. For example if the reference sequence is ",
15221
- /* @__PURE__ */ u$1("b", { children: "A" }),
15222
- " at position ",
15223
- /* @__PURE__ */ u$1("b", { children: "23" }),
15224
- " both:",
15225
- " ",
15226
- /* @__PURE__ */ u$1("b", { children: [
15227
- firstSegment,
15228
- ":23T"
15229
- ] }),
15230
- " and ",
15231
- /* @__PURE__ */ u$1("b", { children: [
15232
- firstSegment,
15233
- ":A23T"
15234
- ] }),
15235
- " will yield the same results."
15236
- ] }),
15237
- /* @__PURE__ */ u$1(InfoParagraph, { children: [
15238
- "Insertions can be searched for in the same manner, they just need to have ",
15239
- /* @__PURE__ */ u$1("b", { children: "ins_" }),
15240
- " appended to the start of the mutation. Example: ",
15241
- /* @__PURE__ */ u$1(ExampleMutation, { mutationType: "insertion", sequenceType: "nucleotide" }),
15242
- "."
15243
- ] })
15244
- ] });
15245
- };
15246
- const ExampleMutation = ({ sequenceType, mutationType }) => {
15247
- const referenceGenome = x$1(ReferenceGenomeContext);
15248
- const firstSegment = referenceGenome.nucleotideSequences[0].name;
15249
- const firstGene = referenceGenome.genes[0].name;
15250
- if (sequenceType === "amino acid") {
15251
- switch (mutationType) {
15252
- case "substitution":
15253
- return /* @__PURE__ */ u$1("b", { children: [
15254
- firstGene,
15255
- ":57Q"
15256
- ] });
15257
- case "insertion":
15258
- return /* @__PURE__ */ u$1("b", { children: [
15259
- "ins_",
15260
- firstGene,
15261
- ":31:N"
15262
- ] });
15263
- }
15264
- }
15265
- if (isSingleSegmented(referenceGenome)) {
15266
- switch (mutationType) {
15267
- case "substitution":
15268
- return /* @__PURE__ */ u$1("b", { children: "23T" });
15269
- case "insertion":
15270
- return /* @__PURE__ */ u$1("b", { children: "ins_1046:A" });
15271
- }
15272
- }
15273
- switch (mutationType) {
15274
- case "substitution":
15275
- return /* @__PURE__ */ u$1("b", { children: [
15276
- firstSegment,
15277
- ":23T"
15278
- ] });
15279
- case "insertion":
15280
- return /* @__PURE__ */ u$1("b", { children: [
15281
- "ins_",
15282
- firstSegment,
15283
- ":10462:A"
15284
- ] });
15285
- }
15286
- };
15287
15461
  const sequenceTypeFromSegment = (possibleSegment, referenceGenome) => {
15288
15462
  if (possibleSegment === void 0) {
15289
15463
  return isSingleSegmented(referenceGenome) ? "nucleotide" : void 0;
@@ -15527,9 +15701,12 @@ const MutationFilterSelector = ({ referenceGenome, setSelectedFilters, selectedF
15527
15701
  ] });
15528
15702
  };
15529
15703
  function getPlaceholder(referenceGenome) {
15530
- const segmentPrefix = referenceGenome.nucleotideSequences.length > 1 ? `${referenceGenome.nucleotideSequences[0].name}:` : "";
15531
- const firstGene = referenceGenome.genes[0].name;
15532
- return `Enter a mutation (e.g. ${segmentPrefix}A123T, ins_${segmentPrefix}123:AT, ${firstGene}:M123E, ins_${firstGene}:123:ME)`;
15704
+ const nucleotideSubstitution = getExampleMutation(referenceGenome, "nucleotide", "substitution");
15705
+ const nucleotideInsertion = getExampleMutation(referenceGenome, "nucleotide", "insertion");
15706
+ const aminoAcidSubstitution = getExampleMutation(referenceGenome, "amino acid", "substitution");
15707
+ const aminoAcidInsertion = getExampleMutation(referenceGenome, "amino acid", "insertion");
15708
+ const exampleMutations = [nucleotideSubstitution, nucleotideInsertion, aminoAcidSubstitution, aminoAcidInsertion].filter((example) => example !== "").join(", ");
15709
+ return `Enter a mutation (e.g. ${exampleMutations})`;
15533
15710
  }
15534
15711
  const backgroundColor = {
15535
15712
  aminoAcidMutations: singleGraphColorRGBByName("teal", 0.4),
@@ -15751,7 +15928,7 @@ LineageFilterComponent = __decorateClass([
15751
15928
  ], LineageFilterComponent);
15752
15929
  export {
15753
15930
  AggregateComponent,
15754
- App,
15931
+ AppComponent,
15755
15932
  DateRangeSelectorComponent,
15756
15933
  LineageFilterComponent,
15757
15934
  LocationFilterComponent,