Skip to content

Commit

Permalink
Merge pull request #402 from nextstrain/392-precalc-lat-longs
Browse files Browse the repository at this point in the history
Precalculate deme and transmission data
  • Loading branch information
colinmegill authored Jul 21, 2017
2 parents 56230b2 + 009d4e0 commit 3c7756e
Show file tree
Hide file tree
Showing 3 changed files with 452 additions and 205 deletions.
127 changes: 82 additions & 45 deletions src/components/map/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,34 @@ import React from "react";
import d3 from "d3";
import { connect } from "react-redux";
import Card from "../framework/card";
import {changeDateFilter} from "../../actions/treeProperties";

import { numericToCalendar, calendarToNumeric } from "../../util/dateHelpers";
import setupLeaflet from "../../util/leaflet";
import setupLeafletPlugins from "../../util/leaflet-plugins";
import {drawDemesAndTransmissions, updateOnMoveEnd, updateVisibility} from "../../util/mapHelpers";
import { drawDemesAndTransmissions, updateOnMoveEnd, updateVisibility } from "../../util/mapHelpers";
import { enableAnimationDisplay, animationWindowWidth, animationTick, twoColumnBreakpoint } from "../../util/globals";
import computeResponsive from "../../util/computeResponsive";
import {getLatLongs} from "../../util/mapHelpersLatLong";
import { modifyURLquery } from "../../util/urlHelpers";
import { MAP_ANIMATION_PLAY_PAUSE_BUTTON } from "../../actions/types.js";
import {
createDemeAndTransmissionData,
updateDemeAndTransmissionDataColAndVis,
updateDemeAndTransmissionDataLatLong
} from "../../util/mapHelpersLatLong";

import { changeDateFilter } from "../../actions/treeProperties";
import {
CHANGE_ANIMATION_START,
CHANGE_ANIMATION_TIME,
CHANGE_ANIMATION_CUMULATIVE,
MAP_ANIMATION_PLAY_PAUSE_BUTTON
} from "../../actions/types.js";

@connect((state) => {
return {
// datasetGuid: state.tree.datasetGuid,
absoluteDateMin: state.controls.absoluteDateMin,
absoluteDateMax: state.controls.absoluteDateMax,
treeVersion: state.tree.version,
treeLoaded: state.tree.loaded,
splitTreeAndMap: state.controls.splitTreeAndMap,
Expand All @@ -36,10 +50,8 @@ import { MAP_ANIMATION_PLAY_PAUSE_BUTTON } from "../../actions/types.js";
mapTriplicate: state.controls.mapTriplicate,
dateMin: state.controls.dateMin,
dateMax: state.controls.dateMax,
absoluteDateMin: state.controls.absoluteDateMin,
absoluteDateMax: state.controls.absoluteDateMax,
dateScale: state.controls.dateScale,
dateFormat: state.controls.dateFormat
dateFormat: state.controls.dateFormat,
};
})

Expand All @@ -48,12 +60,14 @@ class Map extends React.Component {
super(props);
this.state = {
map: null,
demes: false,
latLongs: null,
d3DOMNode: null,
d3elems: null,
// datasetGuid: null,
responsive: null,
demeData: null,
transmissionData: null,
demeIndices: null,
transmissionIndices: null
};
}
static contextTypes = {
Expand Down Expand Up @@ -86,7 +100,6 @@ class Map extends React.Component {
this.maybeSetupD3DOMNode(); /* attaches the D3 SVG DOM node to the Leaflet DOM node, only done once */
this.maybeDrawDemesAndTransmissions(prevProps); /* it's the first time, or they were just removed because we changed dataset or colorby or resolution */
this.maybeUpdateDemesAndTransmissions(prevProps); /* every time we change something like colorBy */
// this.maybeAnimateDemesAndTransmissions();
}
maybeCreateLeafletMap() {
/* first time map, this sets up leaflet */
Expand Down Expand Up @@ -156,7 +169,7 @@ class Map extends React.Component {

const mapIsDrawn = !!this.state.map;
const allDataPresent = !!(this.props.metadata && this.props.treeLoaded && this.state.responsive && this.state.d3DOMNode);
const demesAbsent = !this.state.demes;
const demesTransmissionsComputed = !this.state.demeData && !this.state.transmissionData;

/* if at any point we change dataset and app doesn't remount, we'll need these again */
// const newColorScale = this.props.colorScale.version !== prevProps.colorScale.version;
Expand All @@ -169,7 +182,7 @@ class Map extends React.Component {
// this.props.datasetGuid &&
mapIsDrawn &&
allDataPresent &&
demesAbsent
demesTransmissionsComputed
) {
/* data structures to feed to d3 latLongs = { tips: [{}, {}], transmissions: [{}, {}] } */
if (!this.state.boundsSet){ //we are doing the initial render -> set map to the range of the data
Expand All @@ -179,14 +192,32 @@ class Map extends React.Component {

this.state.map.setMaxBounds(this.getBounds())

const latLongs = this.latLongs(); /* no reference stored, we recompute this for now rather than updating in place */
const {
demeData,
transmissionData,
demeIndices,
transmissionIndices,
minTransmissionDate
} = createDemeAndTransmissionData(
this.props.nodes,
this.props.visibility,
this.props.geoResolution,
this.props.nodeColors,
this.props.mapTriplicate,
this.props.metadata,
this.state.map
);

// const latLongs = this.latLongs(demeData, transmissionData); /* no reference stored, we recompute this for now rather than updating in place */
const d3elems = drawDemesAndTransmissions(
latLongs,
demeData,
transmissionData,
this.state.d3DOMNode,
this.state.map,
this.props.nodes,
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMin),
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMax)
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMax),
minTransmissionDate
);

/* Set up leaflet events */
Expand All @@ -196,18 +227,20 @@ class Map extends React.Component {
// don't redraw on every rerender - need to seperately handle virus change redraw
this.setState({
boundsSet: true,
demes: true,
d3elems,
latLongs,
demeData,
transmissionData,
demeIndices,
transmissionIndices
});
}
}
maybeRemoveAllDemesAndTransmissions(nextProps) {
/* as of jul 7 2017, the constructor / omponentDidMount is NOT running
/* as of jul 7 2017, the constructor / componentDidMount is NOT running
on dataset change! */

/*
xx dataset change, remove all demes and transmissions d3 added
xx dataset change or resolution change, remove all demes and transmissions d3 added
xx we could also make this smoother: http://bl.ocks.org/alansmithy/e984477a741bc56db5a5
THE ABOVE IS NO LONGER TRUE: while App remounts, this is all getting nuked, so it doesn't matter.
Here's what we were doing and might do again:
Expand All @@ -220,7 +253,7 @@ class Map extends React.Component {

const mapIsDrawn = !!this.state.map;
const geoResolutionChanged = this.props.geoResolution !== nextProps.geoResolution;
const dataChanged = this.state.demes && (!nextProps.treeLoaded || this.props.treeVersion !== nextProps.treeVersion);
const dataChanged = (!nextProps.treeLoaded || this.props.treeVersion !== nextProps.treeVersion);

// (this.props.colorBy !== nextProps.colorBy ||
// this.props.visibilityVersion !== nextProps.visibilityVersion ||
Expand All @@ -232,17 +265,27 @@ class Map extends React.Component {
/* clear references to the demes and transmissions d3 added */
this.setState({
boundsSet: false,
demes: false,
d3elems: null,
latLongs: null,
demeData: null,
transmissionData: null,
demeIndices: null,
transmissionIndices: null
})
}
}
respondToLeafletEvent(leafletEvent) {
if (leafletEvent.type === "moveend") { /* zooming and panning */

updateDemeAndTransmissionDataLatLong(
this.state.demeData,
this.state.transmissionData,
this.state.map);

updateOnMoveEnd(
this.state.demeData,
this.state.transmissionData,
this.state.minTransmissionDate,
this.state.d3elems,
this.latLongs(),
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMin),
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMax),
this.props.nodes
Expand Down Expand Up @@ -273,41 +316,35 @@ class Map extends React.Component {
maybeUpdateDemesAndTransmissions(prevProps) {
/* nothing to update */
const noMap = !this.state.map;
const noDemes = !this.state.demes;
if (noMap || noDemes || !this.props.treeLoaded) { return; }
if (noMap || !this.props.treeLoaded) { return; }

if (
this.props.visibilityVersion !== prevProps.visibilityVersion ||
this.props.colorScaleVersion !== prevProps.colorScaleVersion
) {
const latLongs = this.latLongs(); /* can't run if noMap || noDemes */
if (latLongs === null) { return; }
updateDemeAndTransmissionDataColAndVis(
this.state.demeData,
this.state.transmissionData,
this.state.demeIndices,
this.state.transmissionIndices,
this.props.nodes,
this.props.visibility,
this.props.geoResolution,
this.props.nodeColors);
updateVisibility(
this.state.demeData,
this.state.transmissionData,
this.state.d3elems,
latLongs,
this.state.map,
this.props.nodes,
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMin),
calendarToNumeric(this.props.dateFormat, this.props.dateScale, this.props.dateMax),
this.props.nodes
this.state.minTransmissionDate
);
}

}
// maybeAnimateDemesAndTransmissions() {
// /* todo */
// }
latLongs() {
if (this.props.treeLoaded && this.state.map) {
return getLatLongs(
this.props.nodes,
this.props.visibility,
this.props.metadata,
this.state.map,
this.props.geoResolution,
this.props.mapTriplicate,
this.props.nodeColors,
);
}
return null;
}

getBounds() {
let southWest;
let northEast;
Expand Down
Loading

0 comments on commit 3c7756e

Please sign in to comment.