Skip to content

Commit

Permalink
Initial hooks for scfind + tests for URL hook param formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
NickAkhmetov committed Jan 15, 2025
1 parent 65b64c4 commit de588cb
Show file tree
Hide file tree
Showing 14 changed files with 482 additions and 1 deletion.
61 changes: 61 additions & 0 deletions context/app/static/js/api/scfind/scfind.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { createScfindKey, annotationNamesToGetParams, SCFIND_BASE } from './utils';

describe('createScfindKey', () => {
function expectURLIsValid(key: string) {
expect(() => new URL(key)).not.toThrow();
}

it('should use the appropriate scfind base URL', () => {
const key = createScfindKey('endpoint', {});
expect(key).toContain(SCFIND_BASE);
expectURLIsValid(key);
});

it.each(['endpoint1', 'endpoint2', 'endpoint3', 'my-weird-endpoint'])(
'should use the appropriate provided endpoint',
(endpoint) => {
const key = createScfindKey(endpoint, {});
expect(key).toContain(endpoint);
expectURLIsValid(key);
},
);

it.each([
{
params: {
param1: 'value1',
param2: 'value2',
param3: undefined,
},
definedKeys: ['param1', 'param2'],
undefinedKeys: ['param3'],
},
])('should filter out undefined passed params', ({ params, definedKeys, undefinedKeys }) => {
const key = createScfindKey('endpoint', params);
definedKeys.forEach((k) => {
expect(key.includes(k));
});
undefinedKeys.forEach((k) => {
expect(!key.includes(k));
});
expectURLIsValid(key);
});
});

describe('annotationNamesToGetParams', () => {
it('should return undefined if annotationNames is undefined', () => {
expect(annotationNamesToGetParams(undefined)).toBeUndefined();
});

it.each([
{
obj: [
{ Organ: 'organ1', Tissue: 'tissue1' },
{ Organ: 'organ1', Tissue: 'tissue2' },
],
expected: '[{"Organ": "organ1", "Tissue": "tissue1"},{"Organ": "organ1", "Tissue": "tissue2"}]',
},
])('should format annotation names correctly', ({ obj, expected }) => {
expect(annotationNamesToGetParams(obj)).toBe(expected);
});
});
6 changes: 6 additions & 0 deletions context/app/static/js/api/scfind/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface AnnotationNames {
Organ: string;
Tissue: string;
}

export type AnnotationNamesList = AnnotationNames[];
61 changes: 61 additions & 0 deletions context/app/static/js/api/scfind/useCellTypeMarkers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { AnnotationNamesList } from './types';
import { createScfindKey, annotationNamesToGetParams } from './utils';

interface CellTypeMarkerInfo {
cellType: string;
f1: number;
fn: number;
fp: number;
genes: string;
precision: number;
recall: number;
tp: number;
}

interface CellTypeMarkersParams {
cellTypes: string | string[];
annotationNames: AnnotationNamesList;
backgroundCellTypes?: string[];
backgroundAnnotationNames?: AnnotationNamesList;
topK?: number;
sortField?: keyof CellTypeMarkerInfo;
includePrefix?: boolean;
}

type CellTypeMarkersKey = string;

interface CellTypeMarkersResponse {
cellTypeMarkers: CellTypeMarkerInfo[];
}

export function createCellTypeMarkersKey({
cellTypes,
annotationNames,
backgroundCellTypes,
backgroundAnnotationNames,
topK,
sortField,
includePrefix,
}: CellTypeMarkersParams): CellTypeMarkersKey {
return createScfindKey('cellTypeMarkers', {
cell_types: Array.isArray(cellTypes) ? cellTypes.join(',') : cellTypes,
annotation_names: annotationNames ? annotationNamesToGetParams(annotationNames) : undefined,
background_cell_types: Array.isArray(backgroundCellTypes) ? backgroundCellTypes.join(',') : backgroundCellTypes,
background_annotation_names: annotationNamesToGetParams(backgroundAnnotationNames),
top_k: topK ? topK.toString() : undefined,
include_prefix: includePrefix ? String(includePrefix) : undefined,
sort_field: sortField,
});
}

export default function useCellTypeMarkers({
topK = 10,
sortField = 'f1',
includePrefix = true,
...params
}: CellTypeMarkersParams) {
const key = createCellTypeMarkersKey({ topK, sortField, includePrefix, ...params });
return useSWR<CellTypeMarkersResponse, unknown, CellTypeMarkersKey>(key, (url) => fetcher({ url }));
}
25 changes: 25 additions & 0 deletions context/app/static/js/api/scfind/useCellTypeNames.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey, annotationNamesToGetParams } from './utils';
import { AnnotationNamesList } from './types';

type CellTypeNamesKey = string;

interface CellTypeNamesParams {
annotationNames: AnnotationNamesList;
}

interface CellTypeNamesResponse {
cellTypeNames: string[];
}

export function createCellTypeNamesKey(annotationNames?: AnnotationNamesList): CellTypeNamesKey {
return createScfindKey('cellTypeNames', {
annotation_names: annotationNames ? annotationNamesToGetParams(annotationNames) : undefined,
});
}

export default function useCellTypeNames({ annotationNames }: CellTypeNamesParams) {
const key = createCellTypeNamesKey(annotationNames);
return useSWR<CellTypeNamesResponse, unknown, CellTypeNamesKey>(key, (url) => fetcher({ url }));
}
45 changes: 45 additions & 0 deletions context/app/static/js/api/scfind/useEvaluateMarkers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey, annotationNamesToGetParams } from './utils';
import { AnnotationNamesList } from './types';

interface EvaluateMarkersParams {
geneList: string | string[];
cellTypes: string | string[];
annotationNames?: AnnotationNamesList;
backgroundCellTypes?: string[];
backgroundAnnotationNames?: AnnotationNamesList;
sortField?: string;
includePrefix?: boolean;
}

type EvaluateMarkersKey = string;

interface EvaluateMarkersResponse {
evaluateMarkers: unknown;
}

export function createCellTypeMarkersKey({
geneList,
cellTypes,
annotationNames,
backgroundCellTypes,
backgroundAnnotationNames,
sortField,
includePrefix,
}: EvaluateMarkersParams): EvaluateMarkersKey {
return createScfindKey('evaluateMarkers', {
gene_list: Array.isArray(geneList) ? geneList.join(',') : geneList,
cell_types: Array.isArray(cellTypes) ? cellTypes.join(',') : cellTypes,
annotation_names: annotationNamesToGetParams(annotationNames),
background_cell_types: Array.isArray(backgroundCellTypes) ? backgroundCellTypes.join(',') : backgroundCellTypes,
background_annotation_names: annotationNamesToGetParams(backgroundAnnotationNames),
sort_field: sortField,
include_prefix: includePrefix !== undefined ? String(includePrefix) : undefined,
});
}

export default function useEvaluateMarkers(params: EvaluateMarkersParams) {
const key = createCellTypeMarkersKey(params);
return useSWR<EvaluateMarkersResponse, unknown, EvaluateMarkersKey>(key, (url) => fetcher({ url }));
}
36 changes: 36 additions & 0 deletions context/app/static/js/api/scfind/useFindCellTypeSpecificities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey, annotationNamesToGetParams } from './utils';
import { AnnotationNamesList } from './types';

interface EvaluateMarkersParams {
geneList?: string | string[];
annotationNames?: AnnotationNamesList;
minCells?: number;
minFraction?: number;
}

type EvaluateMarkersKey = string;

interface EvaluateMarkersResponse {
evaluateMarkers: unknown;
}

export function createCellTypeSpecificitiesKey({
geneList,
annotationNames,
minCells,
minFraction,
}: EvaluateMarkersParams): EvaluateMarkersKey {
return createScfindKey('findCellTypeSpecificities', {
annotation_names: annotationNamesToGetParams(annotationNames),
gene_list: Array.isArray(geneList) ? geneList.join(',') : geneList,
min_cells: minCells ? String(minCells) : undefined,
min_fraction: minFraction ? String(minFraction) : undefined,
});
}

export default function useFindCellTypeSpecificities(params: EvaluateMarkersParams) {
const key = createCellTypeSpecificitiesKey(params);
return useSWR<EvaluateMarkersResponse, unknown, EvaluateMarkersKey>(key, (url) => fetcher({ url }));
}
36 changes: 36 additions & 0 deletions context/app/static/js/api/scfind/useFindGeneSignatures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey, annotationNamesToGetParams } from './utils';
import { AnnotationNamesList } from './types';

interface FindGeneSignaturesParams {
cellTypes?: string | string[];
annotationNames?: AnnotationNamesList;
minCells?: number;
minFraction?: number;
}

type FindGeneSignaturesKey = string;

interface FindGeneSignaturesResponse {
evaluateMarkers: unknown;
}

export function createFindGeneSignaturesKey({
cellTypes,
annotationNames,
minCells,
minFraction,
}: FindGeneSignaturesParams): FindGeneSignaturesKey {
return createScfindKey('findGeneSignatures', {
cell_types: Array.isArray(cellTypes) ? cellTypes.join(',') : cellTypes,
annotation_names: annotationNamesToGetParams(annotationNames),
min_cells: minCells ? String(minCells) : undefined,
min_fraction: minFraction ? String(minFraction) : undefined,
});
}

export default function useFindGeneSignatures(params: FindGeneSignaturesParams) {
const key = createFindGeneSignaturesKey(params);
return useSWR<FindGeneSignaturesResponse, unknown, FindGeneSignaturesKey>(key, (url) => fetcher({ url }));
}
36 changes: 36 additions & 0 deletions context/app/static/js/api/scfind/useFindHouseKeepingGenes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey, annotationNamesToGetParams } from './utils';
import { AnnotationNamesList } from './types';

interface FindHouseKeepingGenesParams {
cellTypes?: string | string[];
annotationNames?: AnnotationNamesList;
minRecall?: number;
maxGenes?: number;
}

type FindHouseKeepingGenesKey = string;

interface FindHouseKeepingGenesResponse {
findHouseKeepingGenes: unknown;
}

export function createFindHouseKeepingGenesKey({
cellTypes,
annotationNames,
minRecall,
maxGenes,
}: FindHouseKeepingGenesParams): FindHouseKeepingGenesKey {
return createScfindKey('findHouseKeepingGenes', {
cell_types: Array.isArray(cellTypes) ? cellTypes.join(',') : cellTypes,
annotation_names: annotationNamesToGetParams(annotationNames),
min_recall: minRecall ? String(minRecall) : undefined,
max_genes: maxGenes ? String(maxGenes) : undefined,
});
}

export default function useFindHouseKeepingGenes(params: FindHouseKeepingGenesParams) {
const key = createFindHouseKeepingGenesKey(params);
return useSWR<FindHouseKeepingGenesResponse, unknown, FindHouseKeepingGenesKey>(key, (url) => fetcher({ url }));
}
36 changes: 36 additions & 0 deletions context/app/static/js/api/scfind/useFindSimilarGenes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey, annotationNamesToGetParams } from './utils';
import { AnnotationNamesList } from './types';

interface FindSimilarGenesParams {
cellTypes?: string | string[];
annotationNames?: AnnotationNamesList;
minRecall?: number;
maxGenes?: number;
}

type FindSimilarGenesKey = string;

interface FindSimilarGenesResponse {
evaluateMarkers: unknown;
}

export function createFindSimilarGenesKey({
cellTypes,
annotationNames,
minRecall,
maxGenes,
}: FindSimilarGenesParams): FindSimilarGenesKey {
return createScfindKey('findSimilarGenes', {
cell_types: Array.isArray(cellTypes) ? cellTypes.join(',') : cellTypes,
annotation_names: annotationNamesToGetParams(annotationNames),
min_recall: minRecall ? String(minRecall) : undefined,
max_genes: maxGenes ? String(maxGenes) : undefined,
});
}

export default function useFindSimilarGenes(params: FindSimilarGenesParams) {
const key = createFindSimilarGenesKey(params);
return useSWR<FindSimilarGenesResponse, unknown, FindSimilarGenesKey>(key, (url) => fetcher({ url }));
}
29 changes: 29 additions & 0 deletions context/app/static/js/api/scfind/useFindTissueSpecificities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import useSWR from 'swr';
import { fetcher } from 'js/helpers/swr';
import { createScfindKey } from './utils';

interface FindTissueSpecificitiesParams {
geneList?: string | string[];
minCells?: number;
}

type FindTissueSpecificitiesKey = string;

interface FindTissueSpecificitiesResponse {
evaluateMarkers: unknown;
}

export function FindTissueSpecificitiesKey({
geneList,
minCells,
}: FindTissueSpecificitiesParams): FindTissueSpecificitiesKey {
return createScfindKey('findTissueSpecificities', {
gene_list: Array.isArray(geneList) ? geneList.join(',') : geneList,
min_cells: minCells ? String(minCells) : undefined,
});
}

export default function useFindTissueSpecificities(params: FindTissueSpecificitiesParams) {
const key = FindTissueSpecificitiesKey(params);
return useSWR<FindTissueSpecificitiesResponse, unknown, FindTissueSpecificitiesKey>(key, (url) => fetcher({ url }));
}
Loading

0 comments on commit de588cb

Please sign in to comment.