mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-08 19:38:11 +08:00
force categorical treatment of user annotations (#1663)
This commit is contained in:
@@ -34,7 +34,8 @@ export const annotationCreateCategoryAction = (
|
|||||||
throw new Error("name collision on annotation category create");
|
throw new Error("name collision on annotation category create");
|
||||||
|
|
||||||
let initialValue;
|
let initialValue;
|
||||||
let categories;
|
let newSchema;
|
||||||
|
let ctor;
|
||||||
if (categoryToDuplicate) {
|
if (categoryToDuplicate) {
|
||||||
/* if we are duplicating a category, retrieve it */
|
/* if we are duplicating a category, retrieve it */
|
||||||
const catDupSchema = schema.annotations.obsByName[categoryToDuplicate];
|
const catDupSchema = schema.annotations.obsByName[categoryToDuplicate];
|
||||||
@@ -47,25 +48,33 @@ export const annotationCreateCategoryAction = (
|
|||||||
.fetch("obs", categoryToDuplicate);
|
.fetch("obs", categoryToDuplicate);
|
||||||
const col = catToDupDf.col(categoryToDuplicate);
|
const col = catToDupDf.col(categoryToDuplicate);
|
||||||
initialValue = col.asArray();
|
initialValue = col.asArray();
|
||||||
({ categories } = col.summarize());
|
const { categories } = col.summarizeCategorical();
|
||||||
// all user-created annotations must have the unassigned category
|
// all user-created annotations must have the unassigned category
|
||||||
if (!categories.includes(globals.unassignedCategoryLabel)) {
|
if (!categories.includes(globals.unassignedCategoryLabel)) {
|
||||||
categories.push(globals.unassignedCategoryLabel);
|
categories.push(globals.unassignedCategoryLabel);
|
||||||
}
|
}
|
||||||
|
ctor = initialValue.constructor;
|
||||||
|
newSchema = {
|
||||||
|
...catDupSchema,
|
||||||
|
name: newCategoryName,
|
||||||
|
categories,
|
||||||
|
writable: true,
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
/* else assign to the standard default value */
|
/* else assign to the standard default value */
|
||||||
initialValue = globals.unassignedCategoryLabel;
|
initialValue = globals.unassignedCategoryLabel;
|
||||||
categories = [globals.unassignedCategoryLabel];
|
ctor = Array;
|
||||||
|
newSchema = {
|
||||||
|
name: newCategoryName,
|
||||||
|
type: "categorical",
|
||||||
|
categories: [globals.unassignedCategoryLabel],
|
||||||
|
writable: true,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const obsCrossfilter = prevObsCrossfilter.addObsColumn(
|
const obsCrossfilter = prevObsCrossfilter.addObsColumn(
|
||||||
{
|
newSchema,
|
||||||
name: newCategoryName,
|
ctor,
|
||||||
type: "categorical",
|
|
||||||
categories,
|
|
||||||
writable: true,
|
|
||||||
},
|
|
||||||
Array,
|
|
||||||
initialValue
|
initialValue
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -90,10 +90,10 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
|
|||||||
If an array, it must be of same size as nObs and same type as Ctor
|
If an array, it must be of same size as nObs and same type as Ctor
|
||||||
*/
|
*/
|
||||||
colSchema.writable = true;
|
colSchema.writable = true;
|
||||||
const col = colSchema.name;
|
const colName = colSchema.name;
|
||||||
if (
|
if (
|
||||||
_getColumnSchema(this.schema, "obs", col) ||
|
_getColumnSchema(this.schema, "obs", colName) ||
|
||||||
this._cache.obs.hasCol(col)
|
this._cache.obs.hasCol(colName)
|
||||||
) {
|
) {
|
||||||
throw new Error("column already exists");
|
throw new Error("column already exists");
|
||||||
}
|
}
|
||||||
@@ -109,11 +109,9 @@ export default class AnnoMatrixLoader extends AnnoMatrix {
|
|||||||
} else {
|
} else {
|
||||||
data = new Ctor(this.nObs).fill(value);
|
data = new Ctor(this.nObs).fill(value);
|
||||||
}
|
}
|
||||||
o._cache.obs = this._cache.obs.withCol(col, data);
|
o._cache.obs = this._cache.obs.withCol(colName, data);
|
||||||
o.schema = addObsAnnoColumn(this.schema, col, {
|
_normalizeCategoricalSchema(colSchema, o._cache.obs.col(colName));
|
||||||
...colSchema,
|
o.schema = addObsAnnoColumn(this.schema, colName, colSchema);
|
||||||
writable: true,
|
|
||||||
});
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,12 @@ export function _isContinuousType(schema) {
|
|||||||
|
|
||||||
export function _normalizeCategoricalSchema(colSchema, col) {
|
export function _normalizeCategoricalSchema(colSchema, col) {
|
||||||
const { type, writable } = colSchema;
|
const { type, writable } = colSchema;
|
||||||
if (type === "string" || type === "boolean" || type === "categorical") {
|
if (
|
||||||
|
type === "string" ||
|
||||||
|
type === "boolean" ||
|
||||||
|
type === "categorical" ||
|
||||||
|
writable
|
||||||
|
) {
|
||||||
const categorySet = new Set(
|
const categorySet = new Set(
|
||||||
col.summarizeCategorical().categories.concat(colSchema.categories ?? [])
|
col.summarizeCategorical().categories.concat(colSchema.categories ?? [])
|
||||||
);
|
);
|
||||||
@@ -79,4 +84,5 @@ export function _normalizeCategoricalSchema(colSchema, col) {
|
|||||||
if (colSchema.categories) {
|
if (colSchema.categories) {
|
||||||
colSchema.categories = catLabelSort(writable, colSchema.categories);
|
colSchema.categories = catLabelSort(writable, colSchema.categories);
|
||||||
}
|
}
|
||||||
|
return colSchema;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class Continuous extends React.PureComponent {
|
|||||||
const allContinuousNames = schema.annotations.obs.columns
|
const allContinuousNames = schema.annotations.obs.columns
|
||||||
.filter((col) => col.type === "int32" || col.type === "float32")
|
.filter((col) => col.type === "int32" || col.type === "float32")
|
||||||
.filter((col) => col.name !== obsIndex)
|
.filter((col) => col.name !== obsIndex)
|
||||||
|
.filter((col) => !col.writable) // skip user annotations - they will be treated as categorical
|
||||||
.map((col) => col.name);
|
.map((col) => col.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ function topNCategories(colSchema, summary, N) {
|
|||||||
|
|
||||||
export function isSelectableCategoryName(schema, name) {
|
export function isSelectableCategoryName(schema, name) {
|
||||||
const { index } = schema.annotations.obs;
|
const { index } = schema.annotations.obs;
|
||||||
return name && name !== index && isCategoricalAnnotation(schema, name);
|
const colSchema = schema.annotations.obsByName[name];
|
||||||
|
return (
|
||||||
|
name &&
|
||||||
|
name !== index &&
|
||||||
|
(isCategoricalAnnotation(schema, name) || colSchema.writable)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function selectableCategoryNames(schema, names) {
|
export function selectableCategoryNames(schema, names) {
|
||||||
|
|||||||
Reference in New Issue
Block a user