-
Notifications
You must be signed in to change notification settings - Fork 0
Populate tooltips with summary data #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 22 commits
a22f84b
9d81a89
2a5b96f
596626c
7d19845
9d8bc1e
6413e19
2a310b9
330795c
e8afa2d
84a7c3f
2682e0c
6d4c022
5cfc536
a654ed6
7b8abd3
05db003
2b95c6a
c72cf02
4f06a32
be04d52
1a65432
2011864
f8272ab
9f3e4fb
cc1061a
4cbd8e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,39 +1,68 @@ | ||||||||
| import { useAppStore } from "@/stores/appStore"; | ||||||||
| import { useColorStore } from "@/stores/colorStore"; | ||||||||
| import { Axis, type PointWithMetadata } from "@/types"; | ||||||||
| import { useDataStore } from "@/stores/dataStore"; | ||||||||
| import { Axis, SummaryTableColumn, type PointWithMetadata } from "@/types"; | ||||||||
| import { dimensionOptionLabel } from "@/utils/options"; | ||||||||
| import sentenceCase from "@/utils/sentenceCase"; | ||||||||
|
|
||||||||
| export default () => { | ||||||||
| const colorStore = useColorStore(); | ||||||||
| const appStore = useAppStore(); | ||||||||
| const dataStore = useDataStore(); | ||||||||
|
|
||||||||
| // Generate HTML for tooltips on ridgeline plot points. | ||||||||
| // This callback is passed to skadi-chart, and is invoked when hovering over the chart. | ||||||||
| const tooltipCallback = (point: PointWithMetadata) => { | ||||||||
| if (!point.metadata) return ""; | ||||||||
|
|
||||||||
| const { strokeColor } = colorStore.getColorsForLine(point.metadata) | ||||||||
| const { colorDimension } = colorStore; | ||||||||
| const { colorAxis, colorDimension } = colorStore; | ||||||||
| const { dimensions } = appStore; | ||||||||
|
|
||||||||
| const rowOptionLabel = dimensionOptionLabel(colorDimension, point.metadata[colorStore.colorAxis]); | ||||||||
| const valueForColorDimension = point.metadata[colorAxis]; | ||||||||
|
|
||||||||
| const colorDimensionLabel = dimensionOptionLabel(colorDimension, valueForColorDimension); | ||||||||
| const rowOptionLabel = dimensionOptionLabel(dimensions.row, point.metadata[Axis.ROW]); | ||||||||
| const columnOptionLabel = dimensionOptionLabel(dimensions.column, point.metadata[Axis.COLUMN]); | ||||||||
|
|
||||||||
| const { summaryTableData } = dataStore; | ||||||||
|
|
||||||||
| const summaryDataRow = summaryTableData.find(d => { | ||||||||
| return Object.entries(dimensions).every(([axis, dim]) => { | ||||||||
| return !dim || d[dim] === point.metadata?.[axis as Axis]; | ||||||||
| }); | ||||||||
| }); | ||||||||
|
|
||||||||
| // NB regardless of whether log scale is enabled, the summary table data are expressed in non-log scale. | ||||||||
| const [median, mean, ciLower, ciUpper] = [ | ||||||||
| SummaryTableColumn.MEDIAN, | ||||||||
| SummaryTableColumn.MEAN, | ||||||||
| SummaryTableColumn.CI_LOWER, | ||||||||
| SummaryTableColumn.CI_UPPER, | ||||||||
| ].map(col => summaryDataRow?.[col]); | ||||||||
|
|
||||||||
| const includePositiveSign = ciLower && ciLower < 0; | ||||||||
| const ciLowerMaybeWithSign = ciLower?.toFixed(2); | ||||||||
| const ciUpperMaybeWithSign = `${includePositiveSign ? `${ciUpper && ciUpper > 0 ? '+' : ''}` : ''}${ciUpper?.toFixed(2)}`; | ||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be more readable as two lines rather than having a bunch of logic in the string format. Don't really need to say
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't do |
||||||||
|
|
||||||||
| return `<div class="tooltip text-xs flex flex-col gap-1 w-75"> | ||||||||
| <div class="flex gap-1 items-center"> | ||||||||
| <span style="color: ${strokeColor}; font-size: 1.3rem;">●</span> | ||||||||
| <span class="mt-1 flex flex-wrap gap-5"> | ||||||||
| <span> | ||||||||
| ${sentenceCase(colorDimension)}: <strong>${rowOptionLabel}</strong> | ||||||||
| </span> | ||||||||
| ${dimensions.column ? `<span> | ||||||||
| ${sentenceCase(dimensions.column)}: <strong>${columnOptionLabel}</strong> | ||||||||
| </span>` : ''} | ||||||||
| <div class="flex gap-1 h-6 items-center"> | ||||||||
| <span style="color: ${strokeColor}; font-size: 1.5rem;">●</span> | ||||||||
| <span class="mt-1"> | ||||||||
| ${sentenceCase(colorDimension)}: <strong>${colorDimensionLabel}</strong> | ||||||||
| </span> | ||||||||
| </div> | ||||||||
| <p>Tooltip content is TODO. VIMC-9196</p> | ||||||||
| ${dimensions.row !== colorDimension ? `<span> | ||||||||
| ${sentenceCase(dimensions.row)}: <strong>${rowOptionLabel}</strong> | ||||||||
| </span>` : ''} | ||||||||
| ${dimensions.column && dimensions.column !== colorDimension ? `<span> | ||||||||
| ${sentenceCase(dimensions.column)}: <strong>${columnOptionLabel}</strong> | ||||||||
| </span>` : ''} | ||||||||
| <p class="mt-1"> | ||||||||
| Median: <strong>${median?.toFixed(2)}</strong>, Mean: <strong>${mean?.toFixed(2)}</strong><br/> | ||||||||
| </p> | ||||||||
| <p> | ||||||||
| Will show the median/mean values and 95% confidence interval for the whole line. | ||||||||
| 95% confidence interval: <strong>${ciLowerMaybeWithSign}</strong> — <strong>${ciUpperMaybeWithSign}</strong> | ||||||||
| </p> | ||||||||
| </div>` | ||||||||
| } | ||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,21 +24,22 @@ export enum HistColumn { | |
| COUNTS = "Counts", | ||
| } | ||
|
|
||
| type DataRow = Record<string, string | number>; | ||
| export type SummaryTableDataRow = DataRow & { | ||
| [Dimension.DISEASE]: string; | ||
| [LocResolution.COUNTRY]?: string; | ||
| [LocResolution.SUBREGION]?: string; | ||
| }; | ||
| export type HistDataRow = DataRow & { | ||
| export enum SummaryTableColumn { | ||
| MEAN = "mean_value", | ||
| MEDIAN = "median_value", | ||
| CI_LOWER = "lower_95", | ||
| CI_UPPER = "upper_95", | ||
| } | ||
|
|
||
| type DataRow = Record<string, string | number> & { | ||
| [Dimension.DISEASE]: string; | ||
| [Dimension.ACTIVITY_TYPE]?: string; | ||
| [LocResolution.COUNTRY]?: string; | ||
| [LocResolution.SUBREGION]?: string; | ||
| [Dimension.LOCATION]?: string; | ||
| [HistColumn.LOWER_BOUND]: number; | ||
| [HistColumn.UPPER_BOUND]: number; | ||
| [HistColumn.COUNTS]: number; | ||
| }; | ||
| export type HistDataRow = DataRow & Record<HistColumn, number>; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why change the previous definition of HistDataRow? That seems clearer to me, and could use same approach to SummaryTableDataRow. It's a bit more verbose but also more readable. Also - this implies that the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wanted to put all the columns shared between both types of data file into the DataRow type. Maybe it was premature optimization! The optional columns:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm removing the 'DataRow' type and just tolerating the slight duplication |
||
| export type SummaryTableDataRow = DataRow & Record<SummaryTableColumn, number>; | ||
|
|
||
| export type Option = { label: string; value: string }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little inscrutable, maybe worth a comment - is this about right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a comment