Skip to content

Commit

Permalink
feat: show count in "prevalence over time" table #18
Browse files Browse the repository at this point in the history
  • Loading branch information
fengelniederhammer committed Mar 8, 2024
1 parent aee3fea commit b547c11
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@ import { customElement, property } from 'lit/decorators.js';
import { html, LitElement } from 'lit';
import { Chart, registerables } from 'chart.js';
import { TemporalGranularity } from '../types';
import { addUnit, minusTemporal, Temporal } from '../temporal';
import { addUnit, minusTemporal } from '../temporal';
import { getMinMaxNumber } from '../utils';
import { getYAxisScale, ScaleType } from './container/component-scaling-selector';
import { LogitScale } from './charts/LogitScale';
import { PrevalenceOverTimeData } from '../query/queryPrevalenceOverTime';

@customElement('gs-prevalence-over-time-bubble-chart')
export class PrevalenceOverTimeBubbleChart extends LitElement {
@property({ type: Array })
data: {
displayName: string;
content: { dateRange: Temporal | null; prevalence: number; count: number; total: number }[];
}[] = [];
data: PrevalenceOverTimeData = [];

@property({ type: String })
granularity: TemporalGranularity = 'day';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import { customElement, property } from 'lit/decorators.js';
import { html, LitElement } from 'lit';
import { Chart, ChartConfiguration, registerables } from 'chart.js';
import { Temporal } from '../temporal';
import { getYAxisScale, ScaleType } from './container/component-scaling-selector';
import { LogitScale } from './charts/LogitScale';
import { PrevalenceOverTimeData } from '../query/queryPrevalenceOverTime';

@customElement('gs-prevalence-over-time-line-bar-chart')
export class PrevalenceOverTimeLineBarChart extends LitElement {
@property({ type: Array })
data: {
displayName: string;
content: { dateRange: Temporal | null; prevalence: number }[];
}[] = [];
data: PrevalenceOverTimeData = [];

@property()
type: 'line' | 'bar' = 'bar';
Expand Down
30 changes: 19 additions & 11 deletions components/src/components/prevalence-over-time-table.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { customElement, property } from 'lit/decorators.js';
import { html, LitElement } from 'lit';
import { html } from 'lit';
import { TemporalGranularity } from '../types';
import { Temporal } from '../temporal';
import { PrevalenceOverTimeData } from '../query/queryPrevalenceOverTime';
import { TailwindElement } from '../tailwind-element';

@customElement('gs-prevalence-over-time-table')
export class PrevalenceOverTimeTable extends LitElement {
export class PrevalenceOverTimeTable extends TailwindElement() {
@property({ type: Array })
data: {
displayName: string;
content: { dateRange: Temporal | null; prevalence: number }[];
}[] = [];
data: PrevalenceOverTimeData = [];

@property({ type: String })
granularity: TemporalGranularity = 'day';
Expand All @@ -20,15 +18,25 @@ export class PrevalenceOverTimeTable extends LitElement {
<thead>
<tr>
<th>${this.granularity}</th>
${this.data.map((d) => html`<th>${d.displayName}</th>`)}
${this.data.map(
(dataset) => html`
<th>${dataset.displayName} prevalence</th>
<th>${dataset.displayName} count</th>
`,
)}
</tr>
</thead>
<tbody>
${this.data[0].content.map(
(d, i) => html`
(row, rowNumber) => html`
<tr>
<td>${d.dateRange ?? 'Unknown'}</td>
${this.data.map((d2) => html`<td>${d2.content[i].prevalence.toFixed(4)}</td>`)}
<td>${row.dateRange ?? 'Unknown'}</td>
${this.data.map(
(dataset) => html`
<td>${dataset.content[rowNumber].prevalence.toFixed(4)}</td>
<td class="text-right">${dataset.content[rowNumber].count}</td>
`,
)}
</tr>
`,
)}
Expand Down
13 changes: 2 additions & 11 deletions components/src/components/prevalence-over-time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import './container/component-scaling-selector';
import { type NamedLapisFilter, TemporalGranularity } from '../types';
import { lapisContext } from '../lapis-context';
import { consume } from '@lit/context';
import { queryPrevalenceOverTime } from '../query/queryPrevalenceOverTime';
import { Temporal } from '../temporal';
import { PrevalenceOverTimeData, queryPrevalenceOverTime } from '../query/queryPrevalenceOverTime';
import { ScaleType } from './container/component-scaling-selector';

type View = 'bar' | 'line' | 'bubble' | 'table';
Expand Down Expand Up @@ -74,15 +73,7 @@ export class PrevalenceOverTime extends LitElement {
<h1>Prevalence over time</h1>
Loading...
`,
complete: (
// https://github.com/runem/lit-analyzer/issues/154
// lit-analyzer complains that the generic types don't match, although they do.
// it works, if we resolve the generic type here (TS will complain if the type here is wrong).
data: {
displayName: string;
content: { count: number; prevalence: number; total: number; dateRange: Temporal | null }[];
}[],
) => html`
complete: (data: PrevalenceOverTimeData) => html`
<h1>Prevalence over time</h1>
<gs-component-container>
Expand Down
33 changes: 22 additions & 11 deletions components/src/query/queryPrevalenceOverTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,27 @@ import { SlidingOperator } from '../operator/SlidingOperator';
import { DivisionOperator } from '../operator/DivisionOperator';
import { compareTemporal, generateAllInRange, getMinMaxTemporal, Temporal, TemporalCache } from '../temporal';

// https://github.com/runem/lit-analyzer/issues/154
// lit-analyzer complains that the generic types don't match in component props when using this type when inferred by
// Typescript, although they do.
// It works, if we resolve the generic type here manually.
export type PrevalenceOverTimeData = {
displayName: string;
content: { count: number; prevalence: number; total: number; dateRange: Temporal | null }[];
}[];

export function queryPrevalenceOverTime(
numerator: NamedLapisFilter | NamedLapisFilter[],
denominator: NamedLapisFilter,
numeratorFilter: NamedLapisFilter | NamedLapisFilter[],
denominatorFilter: NamedLapisFilter,
granularity: TemporalGranularity,
smoothingWindow: number,
lapis: string,
signal?: AbortSignal,
) {
const numerators = [];
if (Array.isArray(numerator)) {
numerators.push(...numerator);
} else {
numerators.push(numerator);
}
): Promise<PrevalenceOverTimeData> {
const numeratorFilters = makeArray(numeratorFilter);

const denominatorData = fetchAndPrepare(denominator, granularity, smoothingWindow);
const subQueries = numerators.map(async (namedLapisFilter) => {
const denominatorData = fetchAndPrepare(denominatorFilter, granularity, smoothingWindow);
const subQueries = numeratorFilters.map(async (namedLapisFilter) => {
const numeratorData = fetchAndPrepare(namedLapisFilter, granularity, smoothingWindow);
const divide = new DivisionOperator(
numeratorData,
Expand All @@ -45,6 +49,13 @@ export function queryPrevalenceOverTime(
return Promise.all(subQueries);
}

function makeArray<T>(arrayOrSingleItem: T | T[]) {
if (Array.isArray(arrayOrSingleItem)) {
return arrayOrSingleItem;
}
return [arrayOrSingleItem];
}

function fetchAndPrepare(filter: LapisFilter, granularity: TemporalGranularity, smoothingWindow: number) {
const fetchData = new FetchAggregatedOperator<{
date: string | null;
Expand Down

0 comments on commit b547c11

Please sign in to comment.