gene set summary progress (#2127)

* revert removal of cache control headers

* checkpoint work on revising summary route

* add summary query support to annoMatrix

* summarize route cleanup

* add mising file

* clean up summarize route

* add summary histogram

* update deps

* lint

* more lint

* lint

* manage crossfiler during gene set state changes

* remove obsolete debugging code

* correctly perform async watch in histogram

* better error handling
This commit is contained in:
Bruce Martin
2021-03-30 14:43:53 -07:00
committed by GitHub
parent bfb9e1edcc
commit ae30b66123
47 changed files with 28628 additions and 9109 deletions
+18 -26
View File
@@ -12,6 +12,7 @@ import {
import { indexEntireSchema } from "../util/stateManager/schemaHelpers";
import { _whereCacheGet, _whereCacheMerge } from "./whereCache";
import _shallowClone from "./clone";
import { _queryValidate, _queryCacheKey } from "./query";
const _dataframeCache = dataframeMemo(128);
@@ -181,7 +182,7 @@ export default class AnnoMatrix {
Returns a Promise for the query result, which will resolve to a dataframe.
Field must be one of the matrix fields: 'obs', 'var', 'X', 'emb'. Value
represents the underlying object upon which the query is occuring.
represents the underlying object upon which the query is occurring.
Query is one of:
* a string, representing a single column name from the field, eg,
@@ -197,12 +198,6 @@ export default class AnnoMatrix {
field/column, similar to a join. Currently only supported on the var
dimension, allowing query of X columns by var value (eg, gene name)
The query filter is a single value filter:
{ "field name": [
{name: "column name", values: [ list of values ]}
]}
One and only one value filter is allowed in a value query.
Examples:
1. Fetch the "n_genes" column the "obs":
@@ -220,7 +215,9 @@ export default class AnnoMatrix {
value "TYMP" in the var index.
fetch("X", {
where: {field: "var", column: this.schema.annotations.var.index, value: "TYMP"}
where: {
field: "var", column: this.schema.annotations.var.index, value: "TYMP"
}
})
In AnnData & Pandas DataFrame API, this is equivalent to:
@@ -410,6 +407,14 @@ export default class AnnoMatrix {
_subclassResponsibility();
}
getCacheKeys(field, query) {
/*
Return cache keys for columns associated with this query. May return
[unknown] if no keys are known (ie, nothing is or was cached).
*/
return _whereCacheGet(this._whereCache, this.schema, field, query);
}
/**
** Private interfaces below.
**/
@@ -427,6 +432,7 @@ export default class AnnoMatrix {
async _fetch(field, q) {
if (!AnnoMatrix.fields().includes(field)) return undefined;
const queries = Array.isArray(q) ? q : [q];
queries.forEach(_queryValidate);
/* find cached columns we need, and GC the rest */
const cachedColumns = this._resolveCachedQueries(field, queries);
@@ -507,7 +513,7 @@ export default class AnnoMatrix {
* obs, var and emb do not grow without bounds, and are needed constantly
for rendering.
a) There is no upside to GC'ing these in the base (loader)
b) The undo/redo cache can hold a large number in views, which is worht GC'ing
b) The undo/redo cache can hold a large number in views, which is worth GC'ing
* X is often much larger than memory, and the UI allows add/del from
this. Most of the GC potential is here in both the base and views.
@@ -522,7 +528,7 @@ export default class AnnoMatrix {
as much of the cache is pinned by that data structure.
*/
_gcField(field, isHot, pinnedColumns) {
const maxColumns = isHot ? 256 : 10; // maybe to aggessive?
const maxColumns = isHot ? 256 : 10; // maybe to aggressive?
const cache = this._cache[field];
if (cache.colIndex.size() < maxColumns) return; // trivial rejection
@@ -590,23 +596,18 @@ export default class AnnoMatrix {
called each time a query is performed, allowing the gc to update any bookkeeping
information. Currently, this is just a simple last-fetched timestamp, stored
in a Map.
Map objects preserve order of insertion. This is leveraged as a cheap way to
do LRU, by removing and re-inserting keys. IMPORTANT: the cleanup code assumes
the map insertion order is least-recently-used first.
*/
const cols = dataframe.colIndex.labels();
const { _gcInfo } = this;
const now = Date.now();
cols.forEach((c) => {
// gcInfo.delete(c);
_gcInfo.set(_columnCacheKey(field, c), now);
});
}
/**
Cloning sublcass protocol - we rely in cloning to preserve immutable
symantics while not causing races or other side effects in internal
Cloning subclass protocol - we rely in cloning to preserve immutable
semantics while not causing races or other side effects in internal
cache management.
Subclasses must override _cloneDeeper() if they have state which requires
@@ -639,15 +640,6 @@ export default class AnnoMatrix {
/*
private utility functions below
*/
function _queryCacheKey(field, query) {
if (typeof query === "object") {
const { field: queryField, column: queryColumn, value: queryValue } = query;
return `${field}/${queryField}/${queryColumn}/${queryValue}`;
}
return `${field}/${query}`;
}
function _columnCacheKey(field, column) {
return `${field}/${column}`;
}