diff --git a/src/components/tree/infoPanels/click.js b/src/components/tree/infoPanels/click.js
index 8a4234999..619208482 100644
--- a/src/components/tree/infoPanels/click.js
+++ b/src/components/tree/infoPanels/click.js
@@ -6,7 +6,7 @@ import { getTraitFromNode, getFullAuthorInfoFromNode, getVaccineFromNode,
getAccessionFromNode, getUrlFromNode } from "../../../util/treeMiscHelpers";
import { MutationTable } from "./MutationTable";
import { lhsTreeId} from "../tree";
-import { nodeDisplayName } from "./helpers";
+import { nodeDisplayName, dateInfo } from "./helpers";
export const styles = {
container: {
@@ -174,20 +174,22 @@ const StrainName = ({children}) => (
);
const SampleDate = ({isTerminal, node, t}) => {
- const date = getTraitFromNode(node, "num_date");
+ const {date, dateRange, inferred, ambiguousDate} = dateInfo(node, isTerminal);
if (!date) return null;
- const dateUncertainty = getTraitFromNode(node, "num_date", {confidence: true});
- if (date && dateUncertainty && dateUncertainty[0] !== dateUncertainty[1]) {
- return (
- <>
- {item(t(isTerminal ? "Inferred collection date" : "Inferred date"), numericToCalendar(date))}
- {item(t("Date Confidence Interval"), `(${numericToCalendar(dateUncertainty[0])}, ${numericToCalendar(dateUncertainty[1])})`)}
- >
- );
- }
- /* internal nodes are always inferred, regardless of whether uncertainty bounds are present */
- return item(t(isTerminal ? "Collection date" : "Inferred date"), numericToCalendar(date));
+ const dateDescription = isTerminal ?
+ (inferred ? "Inferred collection date" : "Collection date") :
+ "Inferred date"; // hardcoded assumption that internal nodes are inferred
+
+ return (
+ <>
+ {item(t(dateDescription), date)}
+ {inferred && dateRange &&
+ item(t("Date Confidence Interval"), `(${dateRange.join(', ')})`)}
+ {ambiguousDate &&
+ item(t("Provided date"), ambiguousDate)}
+ >
+ )
};
const getTraitsToDisplay = (node) => {
diff --git a/src/components/tree/infoPanels/helpers.js b/src/components/tree/infoPanels/helpers.js
index 5a3bf824a..3c34e5d6d 100644
--- a/src/components/tree/infoPanels/helpers.js
+++ b/src/components/tree/infoPanels/helpers.js
@@ -21,3 +21,27 @@ export function nodeDisplayName(t, node, tipLabelKey, branch) {
/* TIP */
return tipLabel;
}
+
+export function dateInfo(node, isTerminal) {
+ const num_date = getTraitFromNode(node, "num_date");
+ if (!num_date) return {};
+
+ // Decide if the date is inferred and, if so, attempt to get the underlying ambiguous date (for tips)
+ let inferred, ambiguousDate;
+ const dateUncertainty = getTraitFromNode(node, "num_date", {confidence: true});
+ if (!isTerminal) {
+ inferred=true;
+ } else if (Object.hasOwn(node.node_attrs.num_date, "inferred")) {
+ inferred = node.node_attrs.num_date.inferred;
+ ambiguousDate = getTraitFromNode(node, "num_date", {raw: true});
+ } else {
+ inferred = dateUncertainty && dateUncertainty[0] !== dateUncertainty[1];
+ }
+
+ const dateRange = dateUncertainty ?
+ [numericToCalendar(dateUncertainty[0]), numericToCalendar(dateUncertainty[1])] :
+ undefined;
+ const date = numericToCalendar(num_date);
+
+ return {date, dateRange, inferred, ambiguousDate};
+}
diff --git a/src/components/tree/infoPanels/hover.js b/src/components/tree/infoPanels/hover.js
index 2ba7c5fc3..36db9ebac 100644
--- a/src/components/tree/infoPanels/hover.js
+++ b/src/components/tree/infoPanels/hover.js
@@ -8,7 +8,7 @@ import { getTraitFromNode, getDivFromNode, getVaccineFromNode,
import { isValueValid, strainSymbol } from "../../../util/globals";
import { formatDivergence, getIdxOfInViewRootNode } from "../phyloTree/helpers";
import { parseIntervalsOfNsOrGaps } from "./MutationTable";
-import { nodeDisplayName } from "./helpers";
+import { nodeDisplayName, dateInfo } from "./helpers";
export const InfoLine = ({name, value, padBelow=false}) => {
const renderValues = () => {
@@ -37,30 +37,27 @@ export const InfoLine = ({name, value, padBelow=false}) => {
* A React component to display information about the branch's time & divergence (where applicable)
* @param {Object} props
* @param {Object} props.node branch node currently highlighted
+ * @param {boolean} props.isTerminal
*/
-const BranchLength = ({node, t}) => {
+const BranchLength = ({node, t, isTerminal}) => {
const elements = []; // elements to render
const divergence = getDivFromNode(node);
- const numDate = getTraitFromNode(node, "num_date");
if (divergence) {
elements.push();
}
- if (numDate !== undefined) {
- const date = numericToCalendar(numDate);
- const numDateConfidence = getTraitFromNode(node, "num_date", {confidence: true});
- if (numDateConfidence && numDateConfidence[0] !== numDateConfidence[1]) {
- elements.push();
- const dateRange = [numericToCalendar(numDateConfidence[0]), numericToCalendar(numDateConfidence[1])];
- if (dateRange[0] !== dateRange[1]) {
- elements.push();
- }
- } else {
- elements.push();
+ const {date, dateRange, inferred, ambiguousDate} = dateInfo(node, isTerminal);
+ if (date) {
+ const dateDescription = inferred ? 'Inferred Date' : 'Date';
+ elements.push();
+ if (inferred && dateRange) {
+ elements.push();
+ }
+ if (ambiguousDate) {
+ elements.push();
}
}
-
return elements;
};
@@ -409,7 +406,7 @@ const HoverInfoPanel = ({
{tipLabelKey!==strainSymbol && }
-
+
{t("Click on tip to display more info")}
@@ -418,7 +415,7 @@ const HoverInfoPanel = ({
<>
-
+
{idxOfInViewRootNode === node.arrayIdx ? t('Click to zoom out to parent clade') : t('Click to zoom into clade')}
diff --git a/src/util/treeMiscHelpers.js b/src/util/treeMiscHelpers.js
index ef71a66c0..6960bd8c9 100644
--- a/src/util/treeMiscHelpers.js
+++ b/src/util/treeMiscHelpers.js
@@ -25,10 +25,10 @@ james hadfield, nov 2019.
* NOTE: do not use this for "div", "vaccine" or other traits set on `node_attrs`
* which don't share the same structure as traits. See the JSON spec for more details.
*/
-export const getTraitFromNode = (node, trait, {entropy=false, confidence=false}={}) => {
+export const getTraitFromNode = (node, trait, {entropy=false, confidence=false, raw=false}={}) => {
if (!node.node_attrs) return undefined;
- if (!entropy && !confidence) {
+ if (!entropy && !confidence && !raw) {
if (!node.node_attrs[trait]) {
if (trait === strainSymbol) return node.name;
return undefined;
@@ -42,6 +42,9 @@ export const getTraitFromNode = (node, trait, {entropy=false, confidence=false}=
} else if (confidence) {
if (node.node_attrs[trait]) return node.node_attrs[trait].confidence;
return undefined;
+ } else if (raw) {
+ if (node.node_attrs[trait]) return node.node_attrs[trait].raw_value;
+ return undefined;
}
return undefined;
};