|
@@ -1,27 +1,31 @@
|
|
|
/**
|
|
|
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
|
|
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
|
|
*
|
|
|
* @author David Sehnal <david.sehnal@gmail.com>
|
|
|
*/
|
|
|
|
|
|
import { Queries, Structure, StructureQuery, StructureSymmetry } from '../../../mol-model/structure';
|
|
|
import { getAtomsTests } from '../query/atoms';
|
|
|
+import { CifWriter } from '../../../mol-io/writer/cif';
|
|
|
+import { QuerySchemas } from '../query/schemas';
|
|
|
|
|
|
export enum QueryParamType {
|
|
|
JSON,
|
|
|
String,
|
|
|
Integer,
|
|
|
- Float
|
|
|
+ Float,
|
|
|
+ Boolean
|
|
|
}
|
|
|
|
|
|
-export interface QueryParamInfo {
|
|
|
+export interface QueryParamInfo<T extends string | number = string | number> {
|
|
|
name: string,
|
|
|
type: QueryParamType,
|
|
|
description?: string,
|
|
|
required?: boolean,
|
|
|
defaultValue?: any,
|
|
|
exampleValues?: any[],
|
|
|
- validation?: (v: any) => void
|
|
|
+ validation?: (v: T) => void,
|
|
|
+ supportedValues?: string[]
|
|
|
}
|
|
|
|
|
|
export interface QueryDefinition<Params = any> {
|
|
@@ -30,11 +34,42 @@ export interface QueryDefinition<Params = any> {
|
|
|
exampleId: string, // default is 1cbs
|
|
|
query: (params: any, structure: Structure) => StructureQuery,
|
|
|
description: string,
|
|
|
- params: QueryParamInfo[],
|
|
|
+ jsonParams: QueryParamInfo[],
|
|
|
+ restParams: QueryParamInfo[],
|
|
|
structureTransform?: (params: any, s: Structure) => Promise<Structure>,
|
|
|
+ filter?: CifWriter.Category.Filter,
|
|
|
'@params': Params
|
|
|
}
|
|
|
|
|
|
+export const CommonQueryParamsInfo: QueryParamInfo[] = [
|
|
|
+ { name: 'model_nums', type: QueryParamType.String, description: `A comma-separated list of model ids (i.e. 1,2). If set, only include atoms with the corresponding '_atom_site.pdbx_PDB_model_num' field.` },
|
|
|
+ { name: 'encoding', type: QueryParamType.String, defaultValue: 'cif', description: `Determines the output encoding (text based 'CIF' or binary 'BCIF').`, supportedValues: ['cif', 'bcif'] },
|
|
|
+ { name: 'data_Source', type: QueryParamType.String, defaultValue: '', description: 'Allows to control how the provided data source ID maps to input file (as specified by the server instance config).' }
|
|
|
+];
|
|
|
+
|
|
|
+export interface CommonQueryParamsInfo {
|
|
|
+ model_nums?: number[],
|
|
|
+ encoding?: 'cif' | 'bcif',
|
|
|
+ data_source?: string
|
|
|
+}
|
|
|
+
|
|
|
+export const AtomSiteSchemaElement = {
|
|
|
+ label_entity_id: { type: QueryParamType.String },
|
|
|
+
|
|
|
+ label_asym_id: { type: QueryParamType.String },
|
|
|
+ auth_asym_id: { type: QueryParamType.String },
|
|
|
+
|
|
|
+ label_comp_id: { type: QueryParamType.String },
|
|
|
+ auth_comp_id: { type: QueryParamType.String },
|
|
|
+ label_seq_id: { type: QueryParamType.Integer },
|
|
|
+ auth_seq_id: { type: QueryParamType.Integer },
|
|
|
+ pdbx_PDB_ins_code: { type: QueryParamType.String },
|
|
|
+
|
|
|
+ label_atom_id: { type: QueryParamType.String },
|
|
|
+ auth_atom_id: { type: QueryParamType.String },
|
|
|
+ type_symbol: { type: QueryParamType.String }
|
|
|
+}
|
|
|
+
|
|
|
export interface AtomSiteSchemaElement {
|
|
|
label_entity_id?: string,
|
|
|
|
|
@@ -43,8 +78,8 @@ export interface AtomSiteSchemaElement {
|
|
|
|
|
|
label_comp_id?: string,
|
|
|
auth_comp_id?: string,
|
|
|
- label_seq_id?: string,
|
|
|
- auth_seq_id?: string,
|
|
|
+ label_seq_id?: number,
|
|
|
+ auth_seq_id?: number,
|
|
|
pdbx_PDB_ins_code?: string,
|
|
|
|
|
|
label_atom_id?: string,
|
|
@@ -54,13 +89,23 @@ export interface AtomSiteSchemaElement {
|
|
|
|
|
|
export type AtomSiteSchema = AtomSiteSchemaElement | AtomSiteSchemaElement[]
|
|
|
|
|
|
-const AtomSiteTestParams: QueryParamInfo = {
|
|
|
+const AtomSiteTestJsonParam: QueryParamInfo = {
|
|
|
name: 'atom_site',
|
|
|
type: QueryParamType.JSON,
|
|
|
description: 'Object or array of objects describing atom properties. Names are same as in wwPDB mmCIF dictionary of the atom_site category.',
|
|
|
exampleValues: [{ label_comp_id: 'ALA' }, { label_seq_id: 123, label_asym_id: 'A' }]
|
|
|
};
|
|
|
|
|
|
+export const AtomSiteTestRestParams = (function() {
|
|
|
+ const params: QueryParamInfo[] = [];
|
|
|
+ for (const k of Object.keys(AtomSiteSchemaElement)) {
|
|
|
+ const p = (AtomSiteSchemaElement as any)[k] as QueryParamInfo;
|
|
|
+ p.name = k;
|
|
|
+ params.push(p);
|
|
|
+ }
|
|
|
+ return params;
|
|
|
+})();
|
|
|
+
|
|
|
const RadiusParam: QueryParamInfo = {
|
|
|
name: 'radius',
|
|
|
type: QueryParamType.Float,
|
|
@@ -83,8 +128,9 @@ const QueryMap = {
|
|
|
'atoms': Q<{ atom_site: AtomSiteSchema }>({
|
|
|
niceName: 'Atoms',
|
|
|
description: 'Atoms satisfying the given criteria.',
|
|
|
- query: p => Queries.combinators.merge(getAtomsTests(p.atom_site).map(test => Queries.generators.atoms(test))),
|
|
|
- params: [ AtomSiteTestParams ]
|
|
|
+ query: p => Queries.combinators.merge(getAtomsTests(p).map(test => Queries.generators.atoms(test))),
|
|
|
+ jsonParams: [ AtomSiteTestJsonParam ],
|
|
|
+ restParams: AtomSiteTestRestParams
|
|
|
}),
|
|
|
'symmetryMates': Q<{ radius: number }>({
|
|
|
niceName: 'Symmetry Mates',
|
|
@@ -93,7 +139,7 @@ const QueryMap = {
|
|
|
structureTransform(p, s) {
|
|
|
return StructureSymmetry.builderSymmetryMates(s, p.radius).run();
|
|
|
},
|
|
|
- params: [ RadiusParam ]
|
|
|
+ jsonParams: [ RadiusParam ]
|
|
|
}),
|
|
|
'assembly': Q<{ name: string }>({
|
|
|
niceName: 'Assembly',
|
|
@@ -102,7 +148,7 @@ const QueryMap = {
|
|
|
structureTransform(p, s) {
|
|
|
return StructureSymmetry.buildAssembly(s, '' + (p.name || '1')).run();
|
|
|
},
|
|
|
- params: [{
|
|
|
+ jsonParams: [{
|
|
|
name: 'name',
|
|
|
type: QueryParamType.String,
|
|
|
defaultValue: '1',
|
|
@@ -110,11 +156,11 @@ const QueryMap = {
|
|
|
description: 'Assembly name.'
|
|
|
}]
|
|
|
}),
|
|
|
- 'residueInteraction': Q<{ atom_site: AtomSiteSchema, radius: number }>({
|
|
|
+ 'residueInteraction': Q<AtomSiteSchema & { radius: number }>({
|
|
|
niceName: 'Residue Interaction',
|
|
|
description: 'Identifies all residues within the given radius from the source residue. Takes crystal symmetry into account.',
|
|
|
query(p) {
|
|
|
- const tests = getAtomsTests(p.atom_site);
|
|
|
+ const tests = getAtomsTests(p);
|
|
|
const center = Queries.combinators.merge(tests.map(test => Queries.generators.atoms({
|
|
|
...test,
|
|
|
entityTest: test.entityTest
|
|
@@ -126,17 +172,21 @@ const QueryMap = {
|
|
|
structureTransform(p, s) {
|
|
|
return StructureSymmetry.builderSymmetryMates(s, p.radius).run();
|
|
|
},
|
|
|
- params: [ AtomSiteTestParams, RadiusParam ]
|
|
|
+ jsonParams: [ AtomSiteTestJsonParam, RadiusParam ],
|
|
|
+ restParams: [ ...AtomSiteTestRestParams, RadiusParam ],
|
|
|
+ filter: QuerySchemas.interaction
|
|
|
}),
|
|
|
- 'residueSurroundings': Q<{ atom_site: AtomSiteSchema, radius: number }>({
|
|
|
+ 'residueSurroundings': Q<AtomSiteSchema & { radius: number }>({
|
|
|
niceName: 'Residue Surroundings',
|
|
|
description: 'Identifies all residues within the given radius from the source residue.',
|
|
|
query(p) {
|
|
|
- const tests = getAtomsTests(p.atom_site);
|
|
|
+ const tests = getAtomsTests(p);
|
|
|
const center = Queries.combinators.merge(tests.map(test => Queries.generators.atoms(test)));
|
|
|
return Queries.modifiers.includeSurroundings(center, { radius: p.radius, wholeResidues: true });
|
|
|
},
|
|
|
- params: [ AtomSiteTestParams, RadiusParam ]
|
|
|
+ jsonParams: [ AtomSiteTestJsonParam, RadiusParam ],
|
|
|
+ restParams: [ ...AtomSiteTestRestParams, RadiusParam ],
|
|
|
+ filter: QuerySchemas.interaction
|
|
|
})
|
|
|
};
|
|
|
|
|
@@ -159,36 +209,45 @@ export const QueryList = (function () {
|
|
|
for (let q of QueryList) {
|
|
|
const m = q.definition;
|
|
|
m.name = q.name;
|
|
|
- m.params = m.params || [];
|
|
|
+ m.jsonParams = m.jsonParams || [];
|
|
|
+ m.restParams = m.restParams || m.jsonParams;
|
|
|
}
|
|
|
})();
|
|
|
|
|
|
-// function _normalizeQueryParams(params: { [p: string]: string }, paramList: QueryParamInfo[]): { [p: string]: string | number | boolean } {
|
|
|
-// const ret: any = {};
|
|
|
-// for (const p of paramList) {
|
|
|
-// const key = p.name;
|
|
|
-// const value = params[key];
|
|
|
-// if (typeof value === 'undefined' || (typeof value !== 'undefined' && value !== null && value['length'] === 0)) {
|
|
|
-// if (p.required) {
|
|
|
-// throw `The parameter '${key}' is required.`;
|
|
|
-// }
|
|
|
-// if (typeof p.defaultValue !== 'undefined') ret[key] = p.defaultValue;
|
|
|
-// } else {
|
|
|
-// switch (p.type) {
|
|
|
-// case QueryParamType.JSON: ret[key] = JSON.parse(value); break;
|
|
|
-// case QueryParamType.String: ret[key] = value; break;
|
|
|
-// case QueryParamType.Integer: ret[key] = parseInt(value); break;
|
|
|
-// case QueryParamType.Float: ret[key] = parseFloat(value); break;
|
|
|
-// }
|
|
|
-
|
|
|
-// if (p.validation) p.validation(ret[key]);
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// return ret;
|
|
|
-// }
|
|
|
-
|
|
|
-export function normalizeQueryParams(query: QueryDefinition, params: any) {
|
|
|
- return params;
|
|
|
- // return _normalizeQueryParams(params, query.params);
|
|
|
+function _normalizeQueryParams(params: { [p: string]: string }, paramList: QueryParamInfo[]): { [p: string]: string | number | boolean } {
|
|
|
+ const ret: any = {};
|
|
|
+ for (const p of paramList) {
|
|
|
+ const key = p.name;
|
|
|
+ const value = params[key];
|
|
|
+ if (typeof value === 'undefined' || (typeof value !== 'undefined' && value !== null && value['length'] === 0)) {
|
|
|
+ if (p.required) {
|
|
|
+ throw `The parameter '${key}' is required.`;
|
|
|
+ }
|
|
|
+ if (typeof p.defaultValue !== 'undefined') ret[key] = p.defaultValue;
|
|
|
+ } else {
|
|
|
+ switch (p.type) {
|
|
|
+ case QueryParamType.JSON: ret[key] = JSON.parse(value); break;
|
|
|
+ case QueryParamType.String: ret[key] = value; break;
|
|
|
+ case QueryParamType.Integer: ret[key] = parseInt(value); break;
|
|
|
+ case QueryParamType.Float: ret[key] = parseFloat(value); break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (p.validation) p.validation(ret[key]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+export function normalizeRestQueryParams(query: QueryDefinition, params: any) {
|
|
|
+ // return params;
|
|
|
+ return _normalizeQueryParams(params, query.restParams);
|
|
|
+}
|
|
|
+
|
|
|
+export function normalizeRestCommonParams(params: any): CommonQueryParamsInfo {
|
|
|
+ return {
|
|
|
+ model_nums: params.model_nums ? ('' + params.model_nums).split(',').map(n => n.trim()).filter(n => !!n).map(n => +n) : void 0,
|
|
|
+ data_source: params.data_source,
|
|
|
+ encoding: ('' + params.encoding).toLocaleLowerCase() === 'bcif' ? 'bcif' : 'cif'
|
|
|
+ };
|
|
|
}
|