Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jameshadfield committed Jun 17, 2024
1 parent 9cf6128 commit ce33cbd
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,18 @@ import { entropyCreateState, genomeMap as createGenomeMap } from "../util/entrop
import { calcNodeColor } from "../util/colorHelpers";
import { calcColorScale, createVisibleLegendValues } from "../util/colorScale";
import { computeMatrixFromRawData, checkIfNormalizableFromRawData } from "../util/processFrequencies";
import { applyInViewNodesToTree } from "../actions/tree";
import { applyInViewNodesToTree } from "./tree";
import { validateScatterVariables } from "../util/scatterplotHelpers";
import { isColorByGenotype, decodeColorByGenotype, encodeColorByGenotype, decodeGenotypeFilters, encodeGenotypeFilters, getCdsFromGenotype } from "../util/getGenotype";
import { getTraitFromNode, getDivFromNode, collectGenotypeStates } from "../util/treeMiscHelpers";
import { collectAvailableTipLabelOptions } from "../components/controls/choose-tip-label";
import { hasMultipleGridPanels } from "./panelDisplay";
import { strainSymbolUrlString } from "../middleware/changeURL";

import { DatasetJson } from "../types/datasetJson";
import { MetadataState } from "../reducers/metadata";
import { ReduxRootState, AppDispatch } from "../store";

export const doesColorByHaveConfidence = (controlsState, colorBy) =>
controlsState.coloringsPresentOnTreeWithConfidence.has(colorBy);

Expand Down Expand Up @@ -118,8 +122,11 @@ const modifyStateViaURLQuery = (state, query) => {
if (query.animate) {
const params = query.animate.split(',');
// console.log("start animation!", params);
window.NEXTSTRAIN.animationStartPoint = calendarToNumeric(params[0]);
window.NEXTSTRAIN.animationEndPoint = calendarToNumeric(params[1]);
// TS TODO FIX
if ('NEXTSTRAIN' in window) {
(window.NEXTSTRAIN as any).animationStartPoint = calendarToNumeric(params[0]);
(window.NEXTSTRAIN as any).animationEndPoint = calendarToNumeric(params[1]);
}
state.dateMin = params[0];
state.dateMax = params[1];
state.dateMinNumeric = calendarToNumeric(params[0]);
Expand Down Expand Up @@ -380,7 +387,7 @@ const modifyControlsStateViaTree = (state, tree, treeToo, colorings) => {
state.coloringsPresentOnTree = new Set();
state.coloringsPresentOnTreeWithConfidence = new Set(); // subset of above

let coloringsToCheck = [];
let coloringsToCheck: string[] = [];
if (colorings) {
coloringsToCheck = Object.keys(colorings);
}
Expand Down Expand Up @@ -444,7 +451,7 @@ const modifyControlsStateViaTree = (state, tree, treeToo, colorings) => {
return state;
};

const checkAndCorrectErrorsInState = (state, metadata, genomeMap, query, tree, viewingNarrative) => {
const checkAndCorrectErrorsInState = (state, metadata: MetadataState, genomeMap, query, tree, viewingNarrative) => {
/* want to check that the (currently set) colorBy (state.colorBy) is valid,
* and fall-back to an available colorBy if not
*/
Expand Down Expand Up @@ -597,7 +604,8 @@ const checkAndCorrectErrorsInState = (state, metadata, genomeMap, query, tree, v
continue
}
/* delete filter names (e.g. country, region) which aren't observed on the tree */
if (!Object.keys(tree.totalStateCounts).includes(traitName) && traitName!==strainSymbol && traitName!==genotypeSymbol) {
// TS TODO - remove the following cast (and check code _was_ working as I thought it was...)
if (!Object.keys(tree.totalStateCounts).includes(traitName as string) && traitName!==strainSymbol && traitName!==genotypeSymbol) {
delete state.filters[traitName];
delete query[_queryKey(traitName)];
continue
Expand Down Expand Up @@ -734,8 +742,8 @@ const convertColoringsListToDict = (coloringsList) => {
*
* A lot of this is simply changing augur's snake_case to auspice's camelCase
*/
const createMetadataStateFromJSON = (json) => {
const metadata = {};
const createMetadataStateFromJSON = (json: DatasetJson): MetadataState => {
const metadata: MetadataState = {};
if (json.meta.colorings) {
metadata.colorings = convertColoringsListToDict(json.meta.colorings);
}
Expand Down Expand Up @@ -851,6 +859,18 @@ export const getNarrativePageFromQuery = (query, narrative) => {
return n;
};

/* TS TODO */
interface CreateStateArgs {
json: DatasetJson | false;
secondTreeDataset: any;
oldState: ReduxRootState | false;
narrativeBlocks: any; /* if in a narrative this argument is set */
mainTreeName: string | false;
secondTreeName: string | false;
query?: any;
dispatch: any; /* redux should define this for us... */
}

export const createStateFromQueryOrJSONs = ({
json = false, /* raw json data - completely nuke existing redux state */
secondTreeDataset = false,
Expand All @@ -860,8 +880,9 @@ export const createStateFromQueryOrJSONs = ({
secondTreeName = false,
query,
dispatch
}) => {
let tree, treeToo, entropy, controls, metadata, narrative, frequencies, measurements;
}: CreateStateArgs) => {
let tree, treeToo, entropy, controls, narrative, frequencies, measurements;
let metadata: MetadataState;
/* first task is to create metadata, entropy, controls & tree partial state */
if (json) {
/* create metadata state */
Expand Down Expand Up @@ -905,6 +926,8 @@ export const createStateFromQueryOrJSONs = ({
measurements = {...oldState.measurements};
controls = restoreQueryableStateToDefaults(controls);
controls = modifyStateViaMetadata(controls, metadata, entropy.genomeMap);
} else {
// can this _ever_ occur? If it does then `metadata` is undefined...
}

/* For the creation of state, we want to parse out URL query parameters
Expand Down Expand Up @@ -936,7 +959,7 @@ export const createStateFromQueryOrJSONs = ({


/* calculate colours if loading from JSONs or if the query demands change */
if (json || controls.colorBy !== oldState.controls.colorBy) {
if (json || controls.colorBy !== oldState?.controls.colorBy) { // TODO - why elvis operator not working here?
const colorScale = calcColorScale(controls.colorBy, controls, tree, treeToo, metadata);
const nodeColors = calcNodeColor(tree, colorScale);
controls.colorScale = colorScale;
Expand Down
40 changes: 36 additions & 4 deletions src/reducers/metadata.js → src/reducers/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
import { colorOptions } from "../util/globals";
import * as types from "../actions/types";
import { DatasetJsonRootSequence, DatasetJson, DatasetJsonMeta } from "../types/datasetJson";

/**
* A lot of to-dos here...
* Does it make sense to have two state types, a non-loaded one and
* a loaded one (discriminated type based on loaded: boolean) to give
* more assurances? Otherwise most properties are potential undefineds.
* (TS still helpful here tho)
*/
export interface MetadataState {
loaded: boolean;
rootSequence?: DatasetJsonRootSequence;
identicalGenomeMapAcrossBothTrees: boolean;
rootSequenceSecondTree?: DatasetJsonRootSequence;
colorOptions: any; // TODO XXX
colorings?: any; // TODO XXX
geoResolutions?: DatasetJsonMeta['geo_resolutions'];
buildUrl?: DatasetJsonMeta['build_url'] | false;
displayDefaults?: Record<string,any>; // TODO XXX
panels?: DatasetJsonMeta['panels'];
mainTreeNumTips?: number;
title?: DatasetJsonMeta['title'];
version?: DatasetJson['version'];
filters?: DatasetJsonMeta['filters'];
dataProvenance?: DatasetJsonMeta['data_provenance'];
maintainers?: DatasetJsonMeta['maintainers'];
description?: DatasetJsonMeta['description'];
updated?: DatasetJsonMeta['updated'];
}


/* The metadata reducer holds data that is
* (a) mostly derived from the dataset JSON
* (b) rarely changes
*/

const Metadata = (state = {
const Metadata = (state:MetadataState = {
loaded: false, /* see comment in the sequences reducer for explanation */
metadata: null,
// metadata: null,
rootSequence: undefined,
identicalGenomeMapAcrossBothTrees: false,
rootSequenceSecondTree: undefined,
colorOptions // this can't be removed as the colorScale currently runs before it should
}, action) => {
}, action): MetadataState => {
switch (action.type) {
case types.DATA_INVALID:
return Object.assign({}, state, {
Expand All @@ -22,6 +52,7 @@ const Metadata = (state = {
case types.URL_QUERY_CHANGE_WITH_COMPUTED_STATE:
case types.TREE_TOO_DATA:
case types.CLEAN_START:
console.log("incoming!", action.metadata)
return action.metadata;
case types.ADD_EXTRA_METADATA: {
const colorings = Object.assign({}, state.colorings, action.newColorings);
Expand Down Expand Up @@ -54,7 +85,8 @@ const Metadata = (state = {
}
};

function getBuildUrlFromGetAvailableJson(availableData) {
// TODO - can we replace the returned 'false' with 'undefined'?
function getBuildUrlFromGetAvailableJson(availableData): (false | undefined | string) {
if (!availableData) return undefined;
/* check if the current dataset is present in the getAvailable data
We currently parse the URL (pathname) for the current dataset but this
Expand Down
2 changes: 1 addition & 1 deletion src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ if (process.env.NODE_ENV !== 'production' && module.hot) {
}

// Infer types from the store.
export type RootState = ReturnType<typeof store.getState>
export type ReduxRootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

export default store;
Loading

0 comments on commit ce33cbd

Please sign in to comment.