diff --git a/.eslintrc.json b/.eslintrc.json index bef255fae52e4dccb7bd4ac7908ec12c3e47cf10..59a282f9d571c50f18536a375470abd79d266037 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -69,6 +69,7 @@ "no-trailing-spaces": "error", "no-unsafe-finally": "warn", "no-var": "error", - "spaced-comment": "error" + "spaced-comment": "error", + "semi": "warn" } } \ No newline at end of file diff --git a/src/apps/chem-comp-bond/create-table.ts b/src/apps/chem-comp-bond/create-table.ts index 6fbb74820ae5364bdb8eef651de9193c70d6a849..ef09d66cc33f6ebcda90bd9ab421a099e388804a 100644 --- a/src/apps/chem-comp-bond/create-table.ts +++ b/src/apps/chem-comp-bond/create-table.ts @@ -4,57 +4,57 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as argparse from 'argparse' -import * as util from 'util' -import * as path from 'path' -import * as fs from 'fs' -import * as zlib from 'zlib' -import fetch from 'node-fetch' -require('util.promisify').shim() -const readFile = util.promisify(fs.readFile) -const writeFile = util.promisify(fs.writeFile) - -import { Progress } from '../../mol-task' -import { Database, Table, DatabaseCollection } from '../../mol-data/db' -import { CIF } from '../../mol-io/reader/cif' -import { CifWriter } from '../../mol-io/writer/cif' -import { CCD_Schema } from '../../mol-io/reader/cif/schema/ccd' -import { SetUtils } from '../../mol-util/set' -import { DefaultMap } from '../../mol-util/map' +import * as argparse from 'argparse'; +import * as util from 'util'; +import * as path from 'path'; +import * as fs from 'fs'; +import * as zlib from 'zlib'; +import fetch from 'node-fetch'; +require('util.promisify').shim(); +const readFile = util.promisify(fs.readFile); +const writeFile = util.promisify(fs.writeFile); + +import { Progress } from '../../mol-task'; +import { Database, Table, DatabaseCollection } from '../../mol-data/db'; +import { CIF } from '../../mol-io/reader/cif'; +import { CifWriter } from '../../mol-io/writer/cif'; +import { CCD_Schema } from '../../mol-io/reader/cif/schema/ccd'; +import { SetUtils } from '../../mol-util/set'; +import { DefaultMap } from '../../mol-util/map'; import { mmCIF_chemCompBond_schema } from '../../mol-io/reader/cif/schema/mmcif-extras'; export async function ensureAvailable(path: string, url: string) { if (FORCE_DOWNLOAD || !fs.existsSync(path)) { - console.log(`downloading ${url}...`) - const data = await fetch(url) + console.log(`downloading ${url}...`); + const data = await fetch(url); if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR); } if (url.endsWith('.gz')) { - await writeFile(path, zlib.gunzipSync(await data.buffer())) + await writeFile(path, zlib.gunzipSync(await data.buffer())); } else { - await writeFile(path, await data.text()) + await writeFile(path, await data.text()); } - console.log(`done downloading ${url}`) + console.log(`done downloading ${url}`); } } export async function ensureDataAvailable() { - await ensureAvailable(CCD_PATH, CCD_URL) - await ensureAvailable(PVCD_PATH, PVCD_URL) + await ensureAvailable(CCD_PATH, CCD_URL); + await ensureAvailable(PVCD_PATH, PVCD_URL); } export async function readFileAsCollection<S extends Database.Schema>(path: string, schema: S) { - const parsed = await parseCif(await readFile(path, 'utf8')) - return CIF.toDatabaseCollection(schema, parsed.result) + const parsed = await parseCif(await readFile(path, 'utf8')); + return CIF.toDatabaseCollection(schema, parsed.result); } export async function readCCD() { - return readFileAsCollection(CCD_PATH, CCD_Schema) + return readFileAsCollection(CCD_PATH, CCD_Schema); } export async function readPVCD() { - return readFileAsCollection(PVCD_PATH, CCD_Schema) + return readFileAsCollection(PVCD_PATH, CCD_Schema); } async function parseCif(data: string | Uint8Array) { @@ -63,12 +63,12 @@ async function parseCif(data: string | Uint8Array) { const parsed = await comp.run(p => console.log(Progress.format(p)), 250); console.timeEnd('parse cif'); if (parsed.isError) throw parsed; - return parsed + return parsed; } export function getEncodedCif(name: string, database: Database<Database.Schema>, binary = false) { const encoder = CifWriter.createEncoder({ binary, encoderName: 'mol*' }); - CifWriter.Encoder.writeDatabase(encoder, name, database) + CifWriter.Encoder.writeDatabase(encoder, name, database); return encoder.getData(); } @@ -76,58 +76,58 @@ type CCB = Table<CCD_Schema['chem_comp_bond']> type CCA = Table<CCD_Schema['chem_comp_atom']> function ccbKey(compId: string, atomId1: string, atomId2: string) { - return atomId1 < atomId2 ? `${compId}:${atomId1}-${atomId2}` : `${compId}:${atomId2}-${atomId1}` + return atomId1 < atomId2 ? `${compId}:${atomId1}-${atomId2}` : `${compId}:${atomId2}-${atomId1}`; } function addChemCompBondToSet(set: Set<string>, ccb: CCB) { for (let i = 0, il = ccb._rowCount; i < il; ++i) { - set.add(ccbKey(ccb.comp_id.value(i), ccb.atom_id_1.value(i), ccb.atom_id_2.value(i))) + set.add(ccbKey(ccb.comp_id.value(i), ccb.atom_id_1.value(i), ccb.atom_id_2.value(i))); } - return set + return set; } function addChemCompAtomToSet(set: Set<string>, cca: CCA) { for (let i = 0, il = cca._rowCount; i < il; ++i) { - set.add(cca.atom_id.value(i)) + set.add(cca.atom_id.value(i)); } - return set + return set; } function checkAddingBondsFromPVCD(pvcd: DatabaseCollection<CCD_Schema>) { - const ccbSetByParent = DefaultMap<string, Set<string>>(() => new Set()) + const ccbSetByParent = DefaultMap<string, Set<string>>(() => new Set()); for (const k in pvcd) { - const { chem_comp, chem_comp_bond } = pvcd[k] + const { chem_comp, chem_comp_bond } = pvcd[k]; if (chem_comp_bond._rowCount) { - const parentIds = chem_comp.mon_nstd_parent_comp_id.value(0) + const parentIds = chem_comp.mon_nstd_parent_comp_id.value(0); if (parentIds.length === 0) { - const set = ccbSetByParent.getDefault(chem_comp.id.value(0)) - addChemCompBondToSet(set, chem_comp_bond) + const set = ccbSetByParent.getDefault(chem_comp.id.value(0)); + addChemCompBondToSet(set, chem_comp_bond); } else { for (let i = 0, il = parentIds.length; i < il; ++i) { - const parentId = parentIds[i] - const set = ccbSetByParent.getDefault(parentId) - addChemCompBondToSet(set, chem_comp_bond) + const parentId = parentIds[i]; + const set = ccbSetByParent.getDefault(parentId); + addChemCompBondToSet(set, chem_comp_bond); } } } } for (const k in pvcd) { - const { chem_comp, chem_comp_atom, chem_comp_bond } = pvcd[k] + const { chem_comp, chem_comp_atom, chem_comp_bond } = pvcd[k]; if (chem_comp_bond._rowCount) { - const parentIds = chem_comp.mon_nstd_parent_comp_id.value(0) + const parentIds = chem_comp.mon_nstd_parent_comp_id.value(0); if (parentIds.length > 0) { for (let i = 0, il = parentIds.length; i < il; ++i) { - const entryBonds = addChemCompBondToSet(new Set<string>(), chem_comp_bond) - const entryAtoms = addChemCompAtomToSet(new Set<string>(), chem_comp_atom) - const extraBonds = SetUtils.difference(ccbSetByParent.get(parentIds[i])!, entryBonds) + const entryBonds = addChemCompBondToSet(new Set<string>(), chem_comp_bond); + const entryAtoms = addChemCompAtomToSet(new Set<string>(), chem_comp_atom); + const extraBonds = SetUtils.difference(ccbSetByParent.get(parentIds[i])!, entryBonds); extraBonds.forEach(bk => { - const [a1, a2] = bk.split('|') + const [a1, a2] = bk.split('|'); if (entryAtoms.has(a1) && entryAtoms.has(a2)) { - console.error(`Adding all PVCD bonds would wrongly add bond ${bk} for ${k}`) + console.error(`Adding all PVCD bonds would wrongly add bond ${bk} for ${k}`); } - }) + }); } } } @@ -135,51 +135,51 @@ function checkAddingBondsFromPVCD(pvcd: DatabaseCollection<CCD_Schema>) { } async function createBonds() { - await ensureDataAvailable() - const ccd = await readCCD() - const pvcd = await readPVCD() + await ensureDataAvailable(); + const ccd = await readCCD(); + const pvcd = await readPVCD(); - const ccbSet = new Set<string>() + const ccbSet = new Set<string>(); - const comp_id: string[] = [] - const atom_id_1: string[] = [] - const atom_id_2: string[] = [] - const value_order: typeof mmCIF_chemCompBond_schema['value_order']['T'][] = [] - const pdbx_aromatic_flag: typeof mmCIF_chemCompBond_schema['pdbx_aromatic_flag']['T'][] = [] - const pdbx_stereo_config: typeof mmCIF_chemCompBond_schema['pdbx_stereo_config']['T'][] = [] - const molstar_protonation_variant: string[] = [] + const comp_id: string[] = []; + const atom_id_1: string[] = []; + const atom_id_2: string[] = []; + const value_order: typeof mmCIF_chemCompBond_schema['value_order']['T'][] = []; + const pdbx_aromatic_flag: typeof mmCIF_chemCompBond_schema['pdbx_aromatic_flag']['T'][] = []; + const pdbx_stereo_config: typeof mmCIF_chemCompBond_schema['pdbx_stereo_config']['T'][] = []; + const molstar_protonation_variant: string[] = []; function addBonds(compId: string, ccb: CCB, protonationVariant: boolean) { for (let i = 0, il = ccb._rowCount; i < il; ++i) { - const atomId1 = ccb.atom_id_1.value(i) - const atomId2 = ccb.atom_id_2.value(i) - const k = ccbKey(compId, atomId1, atomId2) + const atomId1 = ccb.atom_id_1.value(i); + const atomId2 = ccb.atom_id_2.value(i); + const k = ccbKey(compId, atomId1, atomId2); if (!ccbSet.has(k)) { - atom_id_1.push(atomId1) - atom_id_2.push(atomId2) - comp_id.push(compId) - value_order.push(ccb.value_order.value(i)) - pdbx_aromatic_flag.push(ccb.pdbx_aromatic_flag.value(i)) - pdbx_stereo_config.push(ccb.pdbx_stereo_config.value(i)) - molstar_protonation_variant.push(protonationVariant ? 'Y' : 'N') - ccbSet.add(k) + atom_id_1.push(atomId1); + atom_id_2.push(atomId2); + comp_id.push(compId); + value_order.push(ccb.value_order.value(i)); + pdbx_aromatic_flag.push(ccb.pdbx_aromatic_flag.value(i)); + pdbx_stereo_config.push(ccb.pdbx_stereo_config.value(i)); + molstar_protonation_variant.push(protonationVariant ? 'Y' : 'N'); + ccbSet.add(k); } } } // check adding bonds from PVCD - checkAddingBondsFromPVCD(pvcd) + checkAddingBondsFromPVCD(pvcd); // add bonds from PVCD for (const k in pvcd) { - const { chem_comp, chem_comp_bond } = pvcd[k] + const { chem_comp, chem_comp_bond } = pvcd[k]; if (chem_comp_bond._rowCount) { - const parentIds = chem_comp.mon_nstd_parent_comp_id.value(0) + const parentIds = chem_comp.mon_nstd_parent_comp_id.value(0); if (parentIds.length === 0) { - addBonds(chem_comp.id.value(0), chem_comp_bond, false) + addBonds(chem_comp.id.value(0), chem_comp_bond, false); } else { for (let i = 0, il = parentIds.length; i < il; ++i) { - addBonds(parentIds[i], chem_comp_bond, true) + addBonds(parentIds[i], chem_comp_bond, true); } } } @@ -187,43 +187,43 @@ async function createBonds() { // add bonds from CCD for (const k in ccd) { - const { chem_comp, chem_comp_bond } = ccd[k] + const { chem_comp, chem_comp_bond } = ccd[k]; if (chem_comp_bond._rowCount) { - addBonds(chem_comp.id.value(0), chem_comp_bond, false) + addBonds(chem_comp.id.value(0), chem_comp_bond, false); } } const bondTable = Table.ofArrays(mmCIF_chemCompBond_schema, { comp_id, atom_id_1, atom_id_2, value_order, pdbx_aromatic_flag, pdbx_stereo_config, molstar_protonation_variant - }) + }); const bondDatabase = Database.ofTables( TABLE_NAME, { chem_comp_bond: mmCIF_chemCompBond_schema }, { chem_comp_bond: bondTable } - ) + ); - return bondDatabase + return bondDatabase; } async function run(out: string, binary = false) { - const bonds = await createBonds() + const bonds = await createBonds(); - const cif = getEncodedCif(TABLE_NAME, bonds, binary) + const cif = getEncodedCif(TABLE_NAME, bonds, binary); if (!fs.existsSync(path.dirname(out))) { fs.mkdirSync(path.dirname(out)); } - writeFile(out, cif) + writeFile(out, cif); } -const TABLE_NAME = 'CHEM_COMP_BONDS' +const TABLE_NAME = 'CHEM_COMP_BONDS'; -const DATA_DIR = path.join(__dirname, '..', '..', '..', 'build/data') -const CCD_PATH = path.join(DATA_DIR, 'components.cif') -const PVCD_PATH = path.join(DATA_DIR, 'aa-variants-v1.cif') -const CCD_URL = 'http://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif' -const PVCD_URL = 'http://ftp.wwpdb.org/pub/pdb/data/monomers/aa-variants-v1.cif' +const DATA_DIR = path.join(__dirname, '..', '..', '..', 'build/data'); +const CCD_PATH = path.join(DATA_DIR, 'components.cif'); +const PVCD_PATH = path.join(DATA_DIR, 'aa-variants-v1.cif'); +const CCD_URL = 'http://ftp.wwpdb.org/pub/pdb/data/monomers/components.cif'; +const PVCD_URL = 'http://ftp.wwpdb.org/pub/pdb/data/monomers/aa-variants-v1.cif'; const parser = new argparse.ArgumentParser({ addHelp: true, @@ -247,6 +247,6 @@ interface Args { } const args: Args = parser.parseArgs(); -const FORCE_DOWNLOAD = args.forceDownload +const FORCE_DOWNLOAD = args.forceDownload; -run(args.out, args.binary) +run(args.out, args.binary); diff --git a/src/apps/cif2bcif/converter.ts b/src/apps/cif2bcif/converter.ts index b1cf3308971ad3fdf41782e923933df6d515d605..8ee2b236341393fc75bd76bf22484bf15d03b528 100644 --- a/src/apps/cif2bcif/converter.ts +++ b/src/apps/cif2bcif/converter.ts @@ -5,11 +5,11 @@ * @author Sebastian Bittrich <sebastian.bittrich@rcsb.org> */ -import { CIF, CifCategory, getCifFieldType, CifField, CifFile } from '../../mol-io/reader/cif' -import { CifWriter, EncodingStrategyHint } from '../../mol-io/writer/cif' -import * as util from 'util' -import * as fs from 'fs' -import * as zlib from 'zlib' +import { CIF, CifCategory, getCifFieldType, CifField, CifFile } from '../../mol-io/reader/cif'; +import { CifWriter, EncodingStrategyHint } from '../../mol-io/writer/cif'; +import * as util from 'util'; +import * as fs from 'fs'; +import * as zlib from 'zlib'; import { Progress, Task, RuntimeContext } from '../../mol-task'; import { classifyFloatArray, classifyIntArray } from '../../mol-io/common/binary-cif'; import { BinaryEncodingProvider } from '../../mol-io/writer/cif/encoder/binary'; @@ -27,7 +27,7 @@ const unzipAsync = util.promisify<zlib.InputType, Buffer>(zlib.unzip); async function readFile(ctx: RuntimeContext, filename: string): Promise<ReaderResult<CifFile>> { const isGz = /\.gz$/i.test(filename); if (filename.match(/\.bcif/)) { - let input = await readFileAsync(filename) + let input = await readFileAsync(filename); if (isGz) input = await unzipAsync(input); return await CIF.parseBinary(new Uint8Array(input)).runInContext(ctx); } else { @@ -101,7 +101,7 @@ export default function convert(path: string, asText = false, hints?: EncodingSt const cat = b.categories[c]; const fields: CifWriter.Field[] = []; for (const f of cat.fieldNames) { - fields.push(classify(f, cat.getField(f)!)) + fields.push(classify(f, cat.getField(f)!)); current++; if (ctx.shouldUpdate) await ctx.update({ message: 'Encoding...', current, max: maxProgress }); } diff --git a/src/apps/cif2bcif/index.ts b/src/apps/cif2bcif/index.ts index e6987c9cf51da9e1839b1f7d6f0d6fefd42176ce..c3b278d6f7532eec5b8c937aa0e9d479dc9811b2 100644 --- a/src/apps/cif2bcif/index.ts +++ b/src/apps/cif2bcif/index.ts @@ -5,11 +5,11 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as argparse from 'argparse' -import * as util from 'util' -import * as fs from 'fs' -import * as zlib from 'zlib' -import convert from './converter' +import * as argparse from 'argparse'; +import * as util from 'util'; +import * as fs from 'fs'; +import * as zlib from 'zlib'; +import convert from './converter'; require('util.promisify').shim(); @@ -32,7 +32,7 @@ async function write(outPath: string, res: Uint8Array) { } function run(args: Args) { - process(args.src, args.out, args.config, args.filter) + process(args.src, args.out, args.config, args.filter); } const parser = new argparse.ArgumentParser({ @@ -63,5 +63,5 @@ interface Args { const args: Args = parser.parseArgs(); if (args) { - run(args) + run(args); } \ No newline at end of file diff --git a/src/apps/cifschema/index.ts b/src/apps/cifschema/index.ts index 479192198c741b8d009b7b39c3fa8a6a1a54b290..b20754ce80ed6fc707a7fcc6891b0b7d8cb4abec 100644 --- a/src/apps/cifschema/index.ts +++ b/src/apps/cifschema/index.ts @@ -4,177 +4,177 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as argparse from 'argparse' -import * as fs from 'fs' -import * as path from 'path' -import fetch from 'node-fetch' - -import { parseCsv } from '../../mol-io/reader/csv/parser' -import { CifFrame, CifBlock } from '../../mol-io/reader/cif' -import parseText from '../../mol-io/reader/cif/text/parser' -import { generateSchema } from './util/cif-dic' -import { generate } from './util/generate' -import { Filter, Database } from './util/schema' -import { parseImportGet } from './util/helper' +import * as argparse from 'argparse'; +import * as fs from 'fs'; +import * as path from 'path'; +import fetch from 'node-fetch'; + +import { parseCsv } from '../../mol-io/reader/csv/parser'; +import { CifFrame, CifBlock } from '../../mol-io/reader/cif'; +import parseText from '../../mol-io/reader/cif/text/parser'; +import { generateSchema } from './util/cif-dic'; +import { generate } from './util/generate'; +import { Filter, Database } from './util/schema'; +import { parseImportGet } from './util/helper'; function getDicVersion(block: CifBlock) { - return block.categories.dictionary.getField('version')!.str(0) + return block.categories.dictionary.getField('version')!.str(0); } function getDicNamespace(block: CifBlock) { - return block.categories.dictionary.getField('namespace')!.str(0) + return block.categories.dictionary.getField('namespace')!.str(0); } async function runGenerateSchemaMmcif(name: string, fieldNamesPath: string, typescript = false, out: string, moldbImportPath: string, addAliases: boolean) { - await ensureMmcifDicAvailable() + await ensureMmcifDicAvailable(); const mmcifDic = await parseText(fs.readFileSync(MMCIF_DIC_PATH, 'utf8')).run(); - if (mmcifDic.isError) throw mmcifDic + if (mmcifDic.isError) throw mmcifDic; - await ensureIhmDicAvailable() + await ensureIhmDicAvailable(); const ihmDic = await parseText(fs.readFileSync(IHM_DIC_PATH, 'utf8')).run(); - if (ihmDic.isError) throw ihmDic + if (ihmDic.isError) throw ihmDic; - await ensureCarbBranchDicAvailable() + await ensureCarbBranchDicAvailable(); const carbBranchDic = await parseText(fs.readFileSync(CARB_BRANCH_DIC_PATH, 'utf8')).run(); - if (carbBranchDic.isError) throw carbBranchDic + if (carbBranchDic.isError) throw carbBranchDic; - await ensureCarbCompDicAvailable() + await ensureCarbCompDicAvailable(); const carbCompDic = await parseText(fs.readFileSync(CARB_COMP_DIC_PATH, 'utf8')).run(); - if (carbCompDic.isError) throw carbCompDic + if (carbCompDic.isError) throw carbCompDic; - const mmcifDicVersion = getDicVersion(mmcifDic.result.blocks[0]) - const ihmDicVersion = getDicVersion(ihmDic.result.blocks[0]) - const carbDicVersion = 'draft' - const version = `Dictionary versions: mmCIF ${mmcifDicVersion}, IHM ${ihmDicVersion}, CARB ${carbDicVersion}.` + const mmcifDicVersion = getDicVersion(mmcifDic.result.blocks[0]); + const ihmDicVersion = getDicVersion(ihmDic.result.blocks[0]); + const carbDicVersion = 'draft'; + const version = `Dictionary versions: mmCIF ${mmcifDicVersion}, IHM ${ihmDicVersion}, CARB ${carbDicVersion}.`; - const frames: CifFrame[] = [...mmcifDic.result.blocks[0].saveFrames, ...ihmDic.result.blocks[0].saveFrames, ...carbBranchDic.result.blocks[0].saveFrames, ...carbCompDic.result.blocks[0].saveFrames] - const schema = generateSchema(frames) + const frames: CifFrame[] = [...mmcifDic.result.blocks[0].saveFrames, ...ihmDic.result.blocks[0].saveFrames, ...carbBranchDic.result.blocks[0].saveFrames, ...carbCompDic.result.blocks[0].saveFrames]; + const schema = generateSchema(frames); - await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases) + await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases); } async function runGenerateSchemaCifCore(name: string, fieldNamesPath: string, typescript = false, out: string, moldbImportPath: string, addAliases: boolean) { - await ensureCifCoreDicAvailable() + await ensureCifCoreDicAvailable(); const cifCoreDic = await parseText(fs.readFileSync(CIF_CORE_DIC_PATH, 'utf8')).run(); - if (cifCoreDic.isError) throw cifCoreDic + if (cifCoreDic.isError) throw cifCoreDic; - const cifCoreDicVersion = getDicVersion(cifCoreDic.result.blocks[0]) - const version = `Dictionary versions: CifCore ${cifCoreDicVersion}.` + const cifCoreDicVersion = getDicVersion(cifCoreDic.result.blocks[0]); + const version = `Dictionary versions: CifCore ${cifCoreDicVersion}.`; - const frames: CifFrame[] = [...cifCoreDic.result.blocks[0].saveFrames] - const imports = await resolveImports(frames, DIC_DIR) - const schema = generateSchema(frames, imports) + const frames: CifFrame[] = [...cifCoreDic.result.blocks[0].saveFrames]; + const imports = await resolveImports(frames, DIC_DIR); + const schema = generateSchema(frames, imports); - await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases) + await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases); } async function resolveImports(frames: CifFrame[], baseDir: string): Promise<Map<string, CifFrame[]>> { - const imports = new Map<string, CifFrame[]>() + const imports = new Map<string, CifFrame[]>(); for (const d of frames) { if ('import' in d.categories) { - const importGet = parseImportGet(d.categories['import'].getField('get')!.str(0)) + const importGet = parseImportGet(d.categories['import'].getField('get')!.str(0)); for (const g of importGet) { - const { file } = g - if (!file) continue - if (imports.has(file)) continue + const { file } = g; + if (!file) continue; + if (imports.has(file)) continue; const dic = await parseText(fs.readFileSync(path.join(baseDir, file), 'utf8')).run(); - if (dic.isError) throw dic + if (dic.isError) throw dic; - imports.set(file, [...dic.result.blocks[0].saveFrames]) + imports.set(file, [...dic.result.blocks[0].saveFrames]); } } } - return imports + return imports; } async function runGenerateSchemaDic(name: string, dicPath: string, fieldNamesPath: string, typescript = false, out: string, moldbImportPath: string, addAliases: boolean) { const dic = await parseText(fs.readFileSync(dicPath, 'utf8')).run(); - if (dic.isError) throw dic + if (dic.isError) throw dic; - const dicVersion = getDicVersion(dic.result.blocks[0]) - const dicName = getDicNamespace(dic.result.blocks[0]) - const version = `Dictionary versions: ${dicName} ${dicVersion}.` + const dicVersion = getDicVersion(dic.result.blocks[0]); + const dicName = getDicNamespace(dic.result.blocks[0]); + const version = `Dictionary versions: ${dicName} ${dicVersion}.`; - const frames: CifFrame[] = [...dic.result.blocks[0].saveFrames] - const imports = await resolveImports(frames, path.dirname(dicPath)) - const schema = generateSchema(frames, imports) + const frames: CifFrame[] = [...dic.result.blocks[0].saveFrames]; + const imports = await resolveImports(frames, path.dirname(dicPath)); + const schema = generateSchema(frames, imports); - await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases) + await runGenerateSchema(name, version, schema, fieldNamesPath, typescript, out, moldbImportPath, addAliases); } async function runGenerateSchema(name: string, version: string, schema: Database, fieldNamesPath: string, typescript = false, out: string, moldbImportPath: string, addAliases: boolean) { - const filter = fieldNamesPath ? await getFieldNamesFilter(fieldNamesPath) : undefined - const output = typescript ? generate(name, version, schema, filter, moldbImportPath, addAliases) : JSON.stringify(schema, undefined, 4) + const filter = fieldNamesPath ? await getFieldNamesFilter(fieldNamesPath) : undefined; + const output = typescript ? generate(name, version, schema, filter, moldbImportPath, addAliases) : JSON.stringify(schema, undefined, 4); if (out) { - fs.writeFileSync(out, output) + fs.writeFileSync(out, output); } else { - console.log(output) + console.log(output); } } async function getFieldNamesFilter(fieldNamesPath: string): Promise<Filter> { - const fieldNamesStr = fs.readFileSync(fieldNamesPath, 'utf8') + const fieldNamesStr = fs.readFileSync(fieldNamesPath, 'utf8'); const parsed = await parseCsv(fieldNamesStr, { noColumnNames: true }).run(); - if (parsed.isError) throw parser.error + if (parsed.isError) throw parser.error; const csvFile = parsed.result; - const fieldNamesCol = csvFile.table.getColumn('0') - if (!fieldNamesCol) throw 'error getting fields columns' - const fieldNames = fieldNamesCol.toStringArray() + const fieldNamesCol = csvFile.table.getColumn('0'); + if (!fieldNamesCol) throw 'error getting fields columns'; + const fieldNames = fieldNamesCol.toStringArray(); - const filter: Filter = {} + const filter: Filter = {}; fieldNames.forEach((name, i) => { - const [ category, field ] = name.split('.') + const [ category, field ] = name.split('.'); // console.log(category, field) - if (!filter[ category ]) filter[ category ] = {} - filter[ category ][ field ] = true - }) - return filter + if (!filter[ category ]) filter[ category ] = {}; + filter[ category ][ field ] = true; + }); + return filter; } -async function ensureMmcifDicAvailable() { await ensureDicAvailable(MMCIF_DIC_PATH, MMCIF_DIC_URL) } -async function ensureIhmDicAvailable() { await ensureDicAvailable(IHM_DIC_PATH, IHM_DIC_URL) } -async function ensureCarbBranchDicAvailable() { await ensureDicAvailable(CARB_BRANCH_DIC_PATH, CARB_BRANCH_DIC_URL) } -async function ensureCarbCompDicAvailable() { await ensureDicAvailable(CARB_COMP_DIC_PATH, CARB_COMP_DIC_URL) } +async function ensureMmcifDicAvailable() { await ensureDicAvailable(MMCIF_DIC_PATH, MMCIF_DIC_URL); } +async function ensureIhmDicAvailable() { await ensureDicAvailable(IHM_DIC_PATH, IHM_DIC_URL); } +async function ensureCarbBranchDicAvailable() { await ensureDicAvailable(CARB_BRANCH_DIC_PATH, CARB_BRANCH_DIC_URL); } +async function ensureCarbCompDicAvailable() { await ensureDicAvailable(CARB_COMP_DIC_PATH, CARB_COMP_DIC_URL); } async function ensureCifCoreDicAvailable() { - await ensureDicAvailable(CIF_CORE_DIC_PATH, CIF_CORE_DIC_URL) - await ensureDicAvailable(CIF_CORE_ENUM_PATH, CIF_CORE_ENUM_URL) - await ensureDicAvailable(CIF_CORE_ATTR_PATH, CIF_CORE_ATTR_URL) + await ensureDicAvailable(CIF_CORE_DIC_PATH, CIF_CORE_DIC_URL); + await ensureDicAvailable(CIF_CORE_ENUM_PATH, CIF_CORE_ENUM_URL); + await ensureDicAvailable(CIF_CORE_ATTR_PATH, CIF_CORE_ATTR_URL); } async function ensureDicAvailable(dicPath: string, dicUrl: string) { if (FORCE_DIC_DOWNLOAD || !fs.existsSync(dicPath)) { - const name = dicUrl.substr(dicUrl.lastIndexOf('/') + 1) - console.log(`downloading ${name}...`) - const data = await fetch(dicUrl) + const name = dicUrl.substr(dicUrl.lastIndexOf('/') + 1); + console.log(`downloading ${name}...`); + const data = await fetch(dicUrl); if (!fs.existsSync(DIC_DIR)) { fs.mkdirSync(DIC_DIR); } - fs.writeFileSync(dicPath, await data.text()) - console.log(`done downloading ${name}`) + fs.writeFileSync(dicPath, await data.text()); + console.log(`done downloading ${name}`); } } -const DIC_DIR = path.resolve(__dirname, '../../../build/dics/') -const MMCIF_DIC_PATH = `${DIC_DIR}/mmcif_pdbx_v50.dic` -const MMCIF_DIC_URL = 'http://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic' -const IHM_DIC_PATH = `${DIC_DIR}/ihm-extension.dic` -const IHM_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/IHM-dictionary/master/ihm-extension.dic' -const CARB_BRANCH_DIC_PATH = `${DIC_DIR}/entity_branch-extension.dic` -const CARB_BRANCH_DIC_URL = 'https://raw.githubusercontent.com/pdbxmmcifwg/carbohydrate-extension/master/dict/entity_branch-extension.dic' -const CARB_COMP_DIC_PATH = `${DIC_DIR}/chem_comp-extension.dic` -const CARB_COMP_DIC_URL = 'https://raw.githubusercontent.com/pdbxmmcifwg/carbohydrate-extension/master/dict/chem_comp-extension.dic' - -const CIF_CORE_DIC_PATH = `${DIC_DIR}/cif_core.dic` -const CIF_CORE_DIC_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/cif_core.dic' -const CIF_CORE_ENUM_PATH = `${DIC_DIR}/templ_enum.cif` -const CIF_CORE_ENUM_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/templ_enum.cif' -const CIF_CORE_ATTR_PATH = `${DIC_DIR}/templ_attr.cif` -const CIF_CORE_ATTR_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/templ_attr.cif' +const DIC_DIR = path.resolve(__dirname, '../../../build/dics/'); +const MMCIF_DIC_PATH = `${DIC_DIR}/mmcif_pdbx_v50.dic`; +const MMCIF_DIC_URL = 'http://mmcif.wwpdb.org/dictionaries/ascii/mmcif_pdbx_v50.dic'; +const IHM_DIC_PATH = `${DIC_DIR}/ihm-extension.dic`; +const IHM_DIC_URL = 'https://raw.githubusercontent.com/ihmwg/IHM-dictionary/master/ihm-extension.dic'; +const CARB_BRANCH_DIC_PATH = `${DIC_DIR}/entity_branch-extension.dic`; +const CARB_BRANCH_DIC_URL = 'https://raw.githubusercontent.com/pdbxmmcifwg/carbohydrate-extension/master/dict/entity_branch-extension.dic'; +const CARB_COMP_DIC_PATH = `${DIC_DIR}/chem_comp-extension.dic`; +const CARB_COMP_DIC_URL = 'https://raw.githubusercontent.com/pdbxmmcifwg/carbohydrate-extension/master/dict/chem_comp-extension.dic'; + +const CIF_CORE_DIC_PATH = `${DIC_DIR}/cif_core.dic`; +const CIF_CORE_DIC_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/cif_core.dic'; +const CIF_CORE_ENUM_PATH = `${DIC_DIR}/templ_enum.cif`; +const CIF_CORE_ENUM_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/templ_enum.cif'; +const CIF_CORE_ATTR_PATH = `${DIC_DIR}/templ_attr.cif`; +const CIF_CORE_ATTR_URL = 'https://raw.githubusercontent.com/COMCIFS/cif_core/master/templ_attr.cif'; const parser = new argparse.ArgumentParser({ addHelp: true, @@ -231,44 +231,44 @@ interface Args { } const args: Args = parser.parseArgs(); -const FORCE_DIC_DOWNLOAD = args.forceDicDownload +const FORCE_DIC_DOWNLOAD = args.forceDicDownload; switch (args.preset) { case 'mmCIF': - args.name = 'mmCIF' - args.dic = 'mmCIF' - args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/mmcif-field-names.csv') - break + args.name = 'mmCIF'; + args.dic = 'mmCIF'; + args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/mmcif-field-names.csv'); + break; case 'CCD': - args.name = 'CCD' - args.dic = 'mmCIF' - args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/ccd-field-names.csv') - break + args.name = 'CCD'; + args.dic = 'mmCIF'; + args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/ccd-field-names.csv'); + break; case 'BIRD': - args.name = 'BIRD' - args.dic = 'mmCIF' - args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/bird-field-names.csv') - break + args.name = 'BIRD'; + args.dic = 'mmCIF'; + args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/bird-field-names.csv'); + break; case 'CifCore': - args.name = 'CifCore' - args.dic = 'CifCore' - args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/cif-core-field-names.csv') - break + args.name = 'CifCore'; + args.dic = 'CifCore'; + args.fieldNamesPath = path.resolve(__dirname, '../../../data/cif-field-names/cif-core-field-names.csv'); + break; } if (args.name) { - const typescript = args.targetFormat === 'typescript-molstar' + const typescript = args.targetFormat === 'typescript-molstar'; if (args.dicPath) { runGenerateSchemaDic(args.name, args.dicPath, args.fieldNamesPath, typescript, args.out, args.moldataImportPath, args.addAliases).catch(e => { - console.error(e) - }) + console.error(e); + }); } else if (args.dic === 'mmCIF') { runGenerateSchemaMmcif(args.name, args.fieldNamesPath, typescript, args.out, args.moldataImportPath, args.addAliases).catch(e => { - console.error(e) - }) + console.error(e); + }); } else if (args.dic === 'CifCore') { runGenerateSchemaCifCore(args.name, args.fieldNamesPath, typescript, args.out, args.moldataImportPath, args.addAliases).catch(e => { - console.error(e) - }) + console.error(e); + }); } } diff --git a/src/apps/cifschema/util/cif-dic.ts b/src/apps/cifschema/util/cif-dic.ts index 0fd9318731f554c1978a440c3ba39227c4f44885..b2979a67c7a2abbc78abb23e34067edfe3d91ccc 100644 --- a/src/apps/cifschema/util/cif-dic.ts +++ b/src/apps/cifschema/util/cif-dic.ts @@ -4,9 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Database, Column, EnumCol, StrCol, IntCol, ListCol, FloatCol, CoordCol, MatrixCol, VectorCol } from './schema' -import { parseImportGet } from './helper' -import * as Data from '../../../mol-io/reader/cif/data-model' +import { Database, Column, EnumCol, StrCol, IntCol, ListCol, FloatCol, CoordCol, MatrixCol, VectorCol } from './schema'; +import { parseImportGet } from './helper'; +import * as Data from '../../../mol-io/reader/cif/data-model'; import { CifFrame } from '../../../mol-io/reader/cif/data-model'; export function getFieldType(type: string, description: string, values?: string[], container?: string): Column { @@ -21,7 +21,7 @@ export function getFieldType(type: string, description: string, values?: string[ case 'uchar3': case 'uchar1': case 'boolean': - return values && values.length ? EnumCol(values, 'str', description) : StrCol(description) + return values && values.length ? EnumCol(values, 'str', description) : StrCol(description); case 'aliasname': case 'name': case 'idname': @@ -56,19 +56,19 @@ export function getFieldType(type: string, description: string, values?: string[ case 'symop': case 'exp_data_doi': case 'asym_id': - return StrCol(description) + return StrCol(description); case 'int': case 'non_negative_int': case 'positive_int': - return values && values.length ? EnumCol(values, 'int', description) : IntCol(description) + return values && values.length ? EnumCol(values, 'int', description) : IntCol(description); case 'float': - return FloatCol(description) + return FloatCol(description); case 'ec-type': case 'ucode-alphanum-csv': case 'id_list': - return ListCol('str', ',', description) + return ListCol('str', ',', description); case 'id_list_spc': - return ListCol('str', ' ', description) + return ListCol('str', ' ', description); // cif case 'Text': @@ -82,28 +82,28 @@ export function getFieldType(type: string, description: string, values?: string[ case 'Datetime': case 'Tag': case 'Implied': - return wrapContainer('str', ',', description, container) + return wrapContainer('str', ',', description, container); case 'Real': - return wrapContainer('float', ',', description, container) + return wrapContainer('float', ',', description, container); case 'Integer': - return wrapContainer('int', ',', description, container) + return wrapContainer('int', ',', description, container); } - console.log(`unknown type '${type}'`) - return StrCol(description) + console.log(`unknown type '${type}'`); + return StrCol(description); } function ColFromType(type: 'int' | 'str' | 'float' | 'coord', description: string): Column { switch (type) { - case 'int': return IntCol(description) - case 'str': return StrCol(description) - case 'float': return FloatCol(description) - case 'coord': return CoordCol(description) + case 'int': return IntCol(description); + case 'str': return StrCol(description); + case 'float': return FloatCol(description); + case 'coord': return CoordCol(description); } } function wrapContainer(type: 'int' | 'str' | 'float' | 'coord', separator: string, description: string, container?: string) { - return container && container === 'List' ? ListCol(type, separator, description) : ColFromType(type, description) + return container && container === 'List' ? ListCol(type, separator, description) : ColFromType(type, description); } type FrameCategories = { [category: string]: Data.CifFrame } @@ -117,107 +117,107 @@ interface FrameData { type Imports = Map<string, CifFrame[]> function getImportFrames(d: Data.CifFrame, imports: Imports) { - const frames: Data.CifFrame[] = [] - if (!('import' in d.categories)) return frames + const frames: Data.CifFrame[] = []; + if (!('import' in d.categories)) return frames; - const importGet = parseImportGet(d.categories['import'].getField('get')!.str(0)) + const importGet = parseImportGet(d.categories['import'].getField('get')!.str(0)); for (const g of importGet) { - const { file, save } = g + const { file, save } = g; if (!file || !save) { - console.warn(`missing 'save' or 'file' for import in '${d.header}'`) - continue + console.warn(`missing 'save' or 'file' for import in '${d.header}'`); + continue; } - const importFrames = imports.get(file) + const importFrames = imports.get(file); if (!importFrames) { - console.warn(`missing '${file}' entry in imports`) - continue + console.warn(`missing '${file}' entry in imports`); + continue; } - const importSave = importFrames.find(id => id.header.toLowerCase() === save.toLowerCase()) + const importSave = importFrames.find(id => id.header.toLowerCase() === save.toLowerCase()); if (!importSave) { - console.warn(`missing '${save}' save frame in '${file}'`) - continue + console.warn(`missing '${save}' save frame in '${file}'`); + continue; } - frames.push(importSave) + frames.push(importSave); } - return frames + return frames; } /** get field from given or linked category */ function getField(category: string, field: string, d: Data.CifFrame, imports: Imports, ctx: FrameData): Data.CifField|undefined { - const { categories, links } = ctx - const cat = d.categories[category] + const { categories, links } = ctx; + const cat = d.categories[category]; if (cat) { - return cat.getField(field) + return cat.getField(field); } else if (d.header in links) { - const linkName = links[d.header] + const linkName = links[d.header]; if (linkName in categories) { - return getField(category, field, categories[linkName], imports, ctx) + return getField(category, field, categories[linkName], imports, ctx); } else { // console.log(`link '${linkName}' not found`) } } else { - const importFrames = getImportFrames(d, imports) + const importFrames = getImportFrames(d, imports); for (const idf of importFrames) { - return getField(category, field, idf, imports, ctx) + return getField(category, field, idf, imports, ctx); } } } function getEnums(d: Data.CifFrame, imports: Imports, ctx: FrameData) { - const value = getField('item_enumeration', 'value', d, imports, ctx) - const enums: string[] = [] + const value = getField('item_enumeration', 'value', d, imports, ctx); + const enums: string[] = []; if (value) { for (let i = 0; i < value.rowCount; ++i) { - enums.push(value.str(i)) + enums.push(value.str(i)); // console.log(value.str(i)) } - return enums + return enums; } else { // console.log(`item_enumeration.value not found for '${d.header}'`) } } function getContainer(d: Data.CifFrame, imports: Imports, ctx: FrameData) { - const value = getField('type', 'container', d, imports, ctx) - return value ? value.str(0) : undefined + const value = getField('type', 'container', d, imports, ctx); + return value ? value.str(0) : undefined; } function getCode(d: Data.CifFrame, imports: Imports, ctx: FrameData): [string, string[] | undefined, string | undefined ] | undefined { - const code = getField('item_type', 'code', d, imports, ctx) || getField('type', 'contents', d, imports, ctx) + const code = getField('item_type', 'code', d, imports, ctx) || getField('type', 'contents', d, imports, ctx); if (code) { - return [ code.str(0), getEnums(d, imports, ctx), getContainer(d, imports, ctx) ] + return [ code.str(0), getEnums(d, imports, ctx), getContainer(d, imports, ctx) ]; } else { - console.log(`item_type.code or type.contents not found for '${d.header}'`) + console.log(`item_type.code or type.contents not found for '${d.header}'`); } } function getSubCategory(d: Data.CifFrame, imports: Imports, ctx: FrameData): string | undefined { - const value = getField('item_sub_category', 'id', d, imports, ctx) + const value = getField('item_sub_category', 'id', d, imports, ctx); if (value) { - return value.str(0) + return value.str(0); } } function getDescription(d: Data.CifFrame, imports: Imports, ctx: FrameData): string | undefined { - const value = getField('item_description', 'description', d, imports, ctx) || getField('description', 'text', d, imports, ctx) + const value = getField('item_description', 'description', d, imports, ctx) || getField('description', 'text', d, imports, ctx); if (value) { // trim (after newlines) and remove references to square brackets return value.str(0).trim() .replace(/(\r\n|\r|\n)([ \t]+)/g, '\n') .replace(/(\[[1-3]\])+ element/, 'elements') - .replace(/(\[[1-3]\])+/, '') + .replace(/(\[[1-3]\])+/, ''); } } function getAliases(d: Data.CifFrame, imports: Imports, ctx: FrameData): string[] | undefined { - const value = getField('item_aliases', 'alias_name', d, imports, ctx) || getField('alias', 'definition_id', d, imports, ctx) - return value ? value.toStringArray().map(v => v.substr(1)) : undefined + const value = getField('item_aliases', 'alias_name', d, imports, ctx) || getField('alias', 'definition_id', d, imports, ctx); + return value ? value.toStringArray().map(v => v.substr(1)) : undefined; } -const reMatrixField = /\[[1-3]\]\[[1-3]\]/ -const reVectorField = /\[[1-3]\]/ +const reMatrixField = /\[[1-3]\]\[[1-3]\]/; +const reVectorField = /\[[1-3]\]/; const FORCE_INT_FIELDS = [ '_atom_site.id', @@ -245,8 +245,8 @@ const FORCE_MATRIX_FIELDS_MAP: { [k: string]: string } = { 'atom_site_aniso.U_23_su': 'U_su', 'atom_site_aniso.U_13_su': 'U_su', 'atom_site_aniso.U_12_su': 'U_su', -} -const FORCE_MATRIX_FIELDS = Object.keys(FORCE_MATRIX_FIELDS_MAP) +}; +const FORCE_MATRIX_FIELDS = Object.keys(FORCE_MATRIX_FIELDS_MAP); const EXTRA_ALIASES: Database['aliases'] = { 'atom_site_aniso.U': [ @@ -256,7 +256,7 @@ const EXTRA_ALIASES: Database['aliases'] = { 'atom_site_aniso_U_esd', 'atom_site_anisotrop_U_esd', ], -} +}; const COMMA_SEPARATED_LIST_FIELDS = [ '_atom_site.pdbx_struct_group_id', @@ -294,7 +294,7 @@ const SPACE_SEPARATED_LIST_FIELDS = [ const SEMICOLON_SEPARATED_LIST_FIELDS = [ '_chem_comp.pdbx_synonyms' // GLYCERIN; PROPANE-1,2,3-TRIOL -] +]; /** * Useful when a dictionary extension will add enum values to an existing dictionary. @@ -303,173 +303,173 @@ const SEMICOLON_SEPARATED_LIST_FIELDS = [ */ const EXTRA_ENUM_VALUES: { [k: string]: string[] } = { -} +}; export function generateSchema(frames: CifFrame[], imports: Imports = new Map()): Database { - const tables: Database['tables'] = {} - const aliases: Database['aliases'] = { ...EXTRA_ALIASES } + const tables: Database['tables'] = {}; + const aliases: Database['aliases'] = { ...EXTRA_ALIASES }; - const categories: FrameCategories = {} - const links: FrameLinks = {} - const ctx = { categories, links } + const categories: FrameCategories = {}; + const links: FrameLinks = {}; + const ctx = { categories, links }; // get category metadata frames.forEach(d => { // category definitions in mmCIF start with '_' and don't include a '.' // category definitions in cifCore don't include a '.' - if (d.header[0] === '_' || d.header.includes('.')) return - const categoryName = d.header.toLowerCase() + if (d.header[0] === '_' || d.header.includes('.')) return; + const categoryName = d.header.toLowerCase(); // console.log(d.header, d.categoryNames, d.categories) - let descriptionField: Data.CifField | undefined - const categoryKeyNames = new Set<string>() + let descriptionField: Data.CifField | undefined; + const categoryKeyNames = new Set<string>(); if ('category' in d.categories && 'category_key' in d.categories) { - const category = d.categories['category'] - const categoryKey = d.categories['category_key'] + const category = d.categories['category']; + const categoryKey = d.categories['category_key']; if (categoryKey) { - const categoryKey_names = categoryKey.getField('name') + const categoryKey_names = categoryKey.getField('name'); if (categoryKey_names) { for (let i = 0, il = categoryKey_names.rowCount; i < il; ++i) { - categoryKeyNames.add(categoryKey_names.str(i)) + categoryKeyNames.add(categoryKey_names.str(i)); } } } - descriptionField = category.getField('description') + descriptionField = category.getField('description'); if (categoryKeyNames.size === 0) { - console.log(`no key given for category '${categoryName}'`) + console.log(`no key given for category '${categoryName}'`); } } if ('description' in d.categories) { - descriptionField = d.categories['description'].getField('text') + descriptionField = d.categories['description'].getField('text'); } - let description = '' + let description = ''; if (descriptionField) { description = descriptionField.str(0).trim() - .replace(/(\r\n|\r|\n)([ \t]+)/g, '\n') // remove padding after newlines + .replace(/(\r\n|\r|\n)([ \t]+)/g, '\n'); // remove padding after newlines } else { - console.log(`no description given for category '${categoryName}'`) + console.log(`no description given for category '${categoryName}'`); } - tables[categoryName] = { description, key: categoryKeyNames, columns: {} } + tables[categoryName] = { description, key: categoryKeyNames, columns: {} }; // console.log('++++++++++++++++++++++++++++++++++++++++++') // console.log('name', categoryName) // console.log('desc', description) // console.log('key', categoryKeyNames) - }) + }); // build list of links between categories frames.forEach(d => { - if (d.header[0] !== '_' && !d.header.includes('.')) return - categories[d.header] = d - const item_linked = d.categories['item_linked'] + if (d.header[0] !== '_' && !d.header.includes('.')) return; + categories[d.header] = d; + const item_linked = d.categories['item_linked']; if (item_linked) { - const child_name = item_linked.getField('child_name') - const parent_name = item_linked.getField('parent_name') + const child_name = item_linked.getField('child_name'); + const parent_name = item_linked.getField('parent_name'); if (child_name && parent_name) { for (let i = 0; i < item_linked.rowCount; ++i) { - const childName = child_name.str(i) - const parentName = parent_name.str(i) + const childName = child_name.str(i); + const parentName = parent_name.str(i); if (childName in links && links[childName] !== parentName) { - console.log(`${childName} linked to ${links[childName]}, ignoring link to ${parentName}`) + console.log(`${childName} linked to ${links[childName]}, ignoring link to ${parentName}`); } - links[childName] = parentName + links[childName] = parentName; } } } - }) + }); // get field data Object.keys(categories).forEach(fullName => { - const d = categories[fullName] + const d = categories[fullName]; if (!d) { - console.log(`'${fullName}' not found, moving on`) - return + console.log(`'${fullName}' not found, moving on`); + return; } - const categoryName = d.header.substring(d.header[0] === '_' ? 1 : 0, d.header.indexOf('.')) - const itemName = d.header.substring(d.header.indexOf('.') + 1) - let fields: { [k: string]: Column } + const categoryName = d.header.substring(d.header[0] === '_' ? 1 : 0, d.header.indexOf('.')); + const itemName = d.header.substring(d.header.indexOf('.') + 1); + let fields: { [k: string]: Column }; if (categoryName in tables) { - fields = tables[categoryName].columns - tables[categoryName].key.add(itemName) + fields = tables[categoryName].columns; + tables[categoryName].key.add(itemName); } else if (categoryName.toLowerCase() in tables) { // take case from category name in 'field' data as it is better if data is from cif dictionaries - tables[categoryName] = tables[categoryName.toLowerCase()] - fields = tables[categoryName].columns + tables[categoryName] = tables[categoryName.toLowerCase()]; + fields = tables[categoryName].columns; } else { - console.log(`category '${categoryName}' has no metadata`) - fields = {} + console.log(`category '${categoryName}' has no metadata`); + fields = {}; tables[categoryName] = { description: '', key: new Set(), columns: fields - } + }; } - const itemAliases = getAliases(d, imports, ctx) - if (itemAliases) aliases[`${categoryName}.${itemName}`] = itemAliases + const itemAliases = getAliases(d, imports, ctx); + if (itemAliases) aliases[`${categoryName}.${itemName}`] = itemAliases; - const description = getDescription(d, imports, ctx) || '' + const description = getDescription(d, imports, ctx) || ''; // need to use regex to check for matrix or vector items // as sub_category assignment is missing for some entries - const subCategory = getSubCategory(d, imports, ctx) + const subCategory = getSubCategory(d, imports, ctx); if (subCategory === 'cartesian_coordinate' || subCategory === 'fractional_coordinate') { - fields[itemName] = CoordCol(description) + fields[itemName] = CoordCol(description); } else if (FORCE_INT_FIELDS.includes(d.header)) { - fields[itemName] = IntCol(description) - console.log(`forcing int: ${d.header}`) + fields[itemName] = IntCol(description); + console.log(`forcing int: ${d.header}`); } else if (FORCE_MATRIX_FIELDS.includes(d.header)) { - fields[itemName] = FloatCol(description) - fields[FORCE_MATRIX_FIELDS_MAP[d.header]] = MatrixCol(3, 3, description) - console.log(`forcing matrix: ${d.header}`) + fields[itemName] = FloatCol(description); + fields[FORCE_MATRIX_FIELDS_MAP[d.header]] = MatrixCol(3, 3, description); + console.log(`forcing matrix: ${d.header}`); } else if (subCategory === 'matrix') { - fields[itemName.replace(reMatrixField, '')] = MatrixCol(3, 3, description) + fields[itemName.replace(reMatrixField, '')] = MatrixCol(3, 3, description); } else if (subCategory === 'vector') { - fields[itemName.replace(reVectorField, '')] = VectorCol(3, description) + fields[itemName.replace(reVectorField, '')] = VectorCol(3, description); } else { if (itemName.match(reMatrixField)) { - fields[itemName.replace(reMatrixField, '')] = MatrixCol(3, 3, description) - console.log(`${d.header} should have 'matrix' _item_sub_category.id`) + fields[itemName.replace(reMatrixField, '')] = MatrixCol(3, 3, description); + console.log(`${d.header} should have 'matrix' _item_sub_category.id`); } else if (itemName.match(reVectorField)) { - fields[itemName.replace(reVectorField, '')] = VectorCol(3, description) - console.log(`${d.header} should have 'vector' _item_sub_category.id`) + fields[itemName.replace(reVectorField, '')] = VectorCol(3, description); + console.log(`${d.header} should have 'vector' _item_sub_category.id`); } else { - const code = getCode(d, imports, ctx) + const code = getCode(d, imports, ctx); if (code) { let fieldType = getFieldType(code[0], description, code[1], code[2]); if (fieldType.type === 'str') { if (COMMA_SEPARATED_LIST_FIELDS.includes(d.header)) { - fieldType = ListCol('str', ',', description) - console.log(`forcing comma separated: ${d.header}`) + fieldType = ListCol('str', ',', description); + console.log(`forcing comma separated: ${d.header}`); } else if (SPACE_SEPARATED_LIST_FIELDS.includes(d.header)) { - fieldType = ListCol('str', ' ', description) - console.log(`forcing space separated: ${d.header}`) + fieldType = ListCol('str', ' ', description); + console.log(`forcing space separated: ${d.header}`); } else if (SEMICOLON_SEPARATED_LIST_FIELDS.includes(d.header)) { - fieldType = ListCol('str', ';', description) - console.log(`forcing space separated: ${d.header}`) + fieldType = ListCol('str', ';', description); + console.log(`forcing space separated: ${d.header}`); } } if (d.header in EXTRA_ENUM_VALUES) { if (fieldType.type === 'enum') { - fieldType.values.push(...EXTRA_ENUM_VALUES[d.header]) + fieldType.values.push(...EXTRA_ENUM_VALUES[d.header]); } else { - console.warn(`expected enum: ${d.header}`) + console.warn(`expected enum: ${d.header}`); } } - fields[itemName] = fieldType + fields[itemName] = fieldType; } else { - fields[itemName] = StrCol(description) + fields[itemName] = StrCol(description); // console.log(`could not determine code for '${d.header}'`) } } } - }) + }); - return { tables, aliases } + return { tables, aliases }; } diff --git a/src/apps/cifschema/util/generate.ts b/src/apps/cifschema/util/generate.ts index 5024811cd9ab0bfc05f359388a745d886f8f02ee..86bfd65dcc7bd7d0c187d0ce28edac83bad0a772 100644 --- a/src/apps/cifschema/util/generate.ts +++ b/src/apps/cifschema/util/generate.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Database, Filter, Column } from './schema' -import { indentString } from '../../../mol-util/string' +import { Database, Filter, Column } from './schema'; +import { indentString } from '../../../mol-util/string'; import { FieldPath } from '../../../mol-io/reader/cif/schema'; function header (name: string, info: string, moldataImportPath: string) { @@ -19,133 +19,133 @@ function header (name: string, info: string, moldataImportPath: string) { import { Database, Column } from '${moldataImportPath}/db' -import Schema = Column.Schema` +import Schema = Column.Schema`; } function footer (name: string) { return ` export type ${name}_Schema = typeof ${name}_Schema; -export interface ${name}_Database extends Database<${name}_Schema> {}` +export interface ${name}_Database extends Database<${name}_Schema> {}`; } function getTypeShorthands(schema: Database, fields?: Filter) { - const types = new Set<string>() + const types = new Set<string>(); Object.keys(schema.tables).forEach(table => { - if (fields && !fields[table]) return - const { columns } = schema.tables[table] + if (fields && !fields[table]) return; + const { columns } = schema.tables[table]; Object.keys(columns).forEach(columnName => { - if (fields && !fields[table][columnName]) return - types.add(schema.tables[table].columns[columnName].type) - }) - }) - const shorthands: string[] = [] + if (fields && !fields[table][columnName]) return; + types.add(schema.tables[table].columns[columnName].type); + }); + }); + const shorthands: string[] = []; types.forEach(type => { switch (type) { - case 'str': shorthands.push('const str = Schema.str;'); break - case 'int': shorthands.push('const int = Schema.int;'); break - case 'float': shorthands.push('const float = Schema.float;'); break - case 'coord': shorthands.push('const coord = Schema.coord;'); break - case 'enum': shorthands.push('const Aliased = Schema.Aliased;'); break - case 'matrix': shorthands.push('const Matrix = Schema.Matrix;'); break - case 'vector': shorthands.push('const Vector = Schema.Vector;'); break - case 'list': shorthands.push('const List = Schema.List;'); break + case 'str': shorthands.push('const str = Schema.str;'); break; + case 'int': shorthands.push('const int = Schema.int;'); break; + case 'float': shorthands.push('const float = Schema.float;'); break; + case 'coord': shorthands.push('const coord = Schema.coord;'); break; + case 'enum': shorthands.push('const Aliased = Schema.Aliased;'); break; + case 'matrix': shorthands.push('const Matrix = Schema.Matrix;'); break; + case 'vector': shorthands.push('const Vector = Schema.Vector;'); break; + case 'list': shorthands.push('const List = Schema.List;'); break; } - }) - return shorthands.join('\n') + }); + return shorthands.join('\n'); } function getTypeDef(c: Column): string { switch (c.type) { - case 'str': return 'str' - case 'int': return 'int' - case 'float': return 'float' - case 'coord': return 'coord' + case 'str': return 'str'; + case 'int': return 'int'; + case 'float': return 'float'; + case 'coord': return 'coord'; case 'enum': - return `Aliased<'${c.values.map(v => v.replace(/'/g, '\\\'')).join(`' | '`)}'>(${c.subType})` + return `Aliased<'${c.values.map(v => v.replace(/'/g, '\\\'')).join(`' | '`)}'>(${c.subType})`; case 'matrix': - return `Matrix(${c.rows}, ${c.columns})` + return `Matrix(${c.rows}, ${c.columns})`; case 'vector': - return `Vector(${c.length})` + return `Vector(${c.length})`; case 'list': if (c.subType === 'int') { - return `List('${c.separator}', x => parseInt(x, 10))` + return `List('${c.separator}', x => parseInt(x, 10))`; } else if (c.subType === 'float' || c.subType === 'coord') { - return `List('${c.separator}', x => parseFloat(x))` + return `List('${c.separator}', x => parseFloat(x))`; } else { - return `List('${c.separator}', x => x)` + return `List('${c.separator}', x => x)`; } } } -const reSafePropertyName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/ -function safePropertyString(name: string) { return name.match(reSafePropertyName) ? name : `'${name}'` } +const reSafePropertyName = /^[a-zA-Z_$][0-9a-zA-Z_$]*$/; +function safePropertyString(name: string) { return name.match(reSafePropertyName) ? name : `'${name}'`; } function doc(description: string, spacesCount: number) { - const spaces = ' '.repeat(spacesCount) + const spaces = ' '.repeat(spacesCount); return [ `${spaces}/**`, `${indentString(description, 1, `${spaces} * `)}`.replace(/ +\n/g, '\n'), `${spaces} */` - ].join('\n') + ].join('\n'); } export function generate (name: string, info: string, schema: Database, fields: Filter | undefined, moldataImportPath: string, addAliases: boolean) { - const codeLines: string[] = [] + const codeLines: string[] = []; if (fields) { Object.keys(fields).forEach(table => { if (table in schema.tables) { - const schemaTable = schema.tables[table] + const schemaTable = schema.tables[table]; Object.keys(fields[table]).forEach(column => { if (!(column in schemaTable.columns)) { - console.log(`filter field '${table}.${column}' not found in schema`) + console.log(`filter field '${table}.${column}' not found in schema`); } - }) + }); } else { - console.log(`filter category '${table}' not found in schema`) + console.log(`filter category '${table}' not found in schema`); } - }) + }); } - codeLines.push(`export const ${name}_Schema = {`) + codeLines.push(`export const ${name}_Schema = {`); Object.keys(schema.tables).forEach(table => { - if (fields && !fields[table]) return - const { description, columns } = schema.tables[table] - if (description) codeLines.push(doc(description, 4)) - codeLines.push(` ${safePropertyString(table)}: {`) + if (fields && !fields[table]) return; + const { description, columns } = schema.tables[table]; + if (description) codeLines.push(doc(description, 4)); + codeLines.push(` ${safePropertyString(table)}: {`); Object.keys(columns).forEach(columnName => { - if (fields && !fields[table][columnName]) return - const c = columns[columnName] - const typeDef = getTypeDef(c) - if (c.description) codeLines.push(doc(c.description, 8)) - codeLines.push(` ${safePropertyString(columnName)}: ${typeDef},`) - }) - codeLines.push(' },') - }) - codeLines.push('}') + if (fields && !fields[table][columnName]) return; + const c = columns[columnName]; + const typeDef = getTypeDef(c); + if (c.description) codeLines.push(doc(c.description, 8)); + codeLines.push(` ${safePropertyString(columnName)}: ${typeDef},`); + }); + codeLines.push(' },'); + }); + codeLines.push('}'); if (addAliases) { - codeLines.push('') - codeLines.push(`export const ${name}_Aliases = {`) + codeLines.push(''); + codeLines.push(`export const ${name}_Aliases = {`); Object.keys(schema.aliases).forEach(path => { - const [ table, columnName ] = path.split('.') - if (fields && !fields[table]) return - if (fields && !fields[table][columnName]) return + const [ table, columnName ] = path.split('.'); + if (fields && !fields[table]) return; + if (fields && !fields[table][columnName]) return; - const filteredAliases = new Set<string>() + const filteredAliases = new Set<string>(); schema.aliases[path].forEach(p => { - if (!FieldPath.equal(p, path)) filteredAliases.add(FieldPath.canonical(p)) - }) + if (!FieldPath.equal(p, path)) filteredAliases.add(FieldPath.canonical(p)); + }); - if (filteredAliases.size === 0) return - codeLines.push(` ${safePropertyString(path)}: [`) + if (filteredAliases.size === 0) return; + codeLines.push(` ${safePropertyString(path)}: [`); filteredAliases.forEach(alias => { - codeLines.push(` '${alias}',`) - }) - codeLines.push(' ],') - }) - codeLines.push('}') + codeLines.push(` '${alias}',`); + }); + codeLines.push(' ],'); + }); + codeLines.push('}'); } - return `${header(name, info, moldataImportPath)}\n\n${getTypeShorthands(schema, fields)}\n\n${codeLines.join('\n')}\n${footer(name)}` + return `${header(name, info, moldataImportPath)}\n\n${getTypeShorthands(schema, fields)}\n\n${codeLines.join('\n')}\n${footer(name)}`; } \ No newline at end of file diff --git a/src/apps/cifschema/util/helper.ts b/src/apps/cifschema/util/helper.ts index b1bb36bb2b22b2f89dd032fe9c6872f3648b4d55..d7e9ab4d8408b31aa654c250b675da6cf4ff99e2 100644 --- a/src/apps/cifschema/util/helper.ts +++ b/src/apps/cifschema/util/helper.ts @@ -10,11 +10,11 @@ export function parseImportGet(s: string): Import[] { // [{'save':hi_ang_Fox_coeffs 'file':templ_attr.cif} {'save':hi_ang_Fox_c0 'file':templ_enum.cif}] // [{"file":'templ_enum.cif' "save":'H_M_ref'}] return s.trim().substring(2, s.length - 2).split(/}[ \n\t]*{/g).map(s => { - const save = s.match(/('save'|"save"):([^ \t\n]+)/) - const file = s.match(/('file'|"file"):([^ \t\n]+)/) + const save = s.match(/('save'|"save"):([^ \t\n]+)/); + const file = s.match(/('file'|"file"):([^ \t\n]+)/); return { save: save ? save[0].substr(7).replace(/['"]/g, '') : undefined, file: file ? file[0].substr(7).replace(/['"]/g, '') : undefined - } - }) + }; + }); } \ No newline at end of file diff --git a/src/apps/cifschema/util/schema.ts b/src/apps/cifschema/util/schema.ts index 0647c4f82d5d261c53de3846a88950db7b751a4f..579ba0a16f39f54d8454f11cc69a8cbb492d4863 100644 --- a/src/apps/cifschema/util/schema.ts +++ b/src/apps/cifschema/util/schema.ts @@ -18,60 +18,60 @@ export type Column = IntCol | StrCol | FloatCol | CoordCol | EnumCol | VectorCol type BaseCol = { description: string } export type IntCol = { type: 'int' } & BaseCol -export function IntCol(description: string): IntCol { return { type: 'int', description } } +export function IntCol(description: string): IntCol { return { type: 'int', description }; } export type StrCol = { type: 'str' } & BaseCol -export function StrCol(description: string): StrCol { return { type: 'str', description } } +export function StrCol(description: string): StrCol { return { type: 'str', description }; } export type FloatCol = { type: 'float' } & BaseCol -export function FloatCol(description: string): FloatCol { return { type: 'float', description } } +export function FloatCol(description: string): FloatCol { return { type: 'float', description }; } export type CoordCol = { type: 'coord' } & BaseCol -export function CoordCol(description: string): CoordCol { return { type: 'coord', description } } +export function CoordCol(description: string): CoordCol { return { type: 'coord', description }; } export type EnumCol = { type: 'enum', subType: 'int' | 'str', values: string[] } & BaseCol export function EnumCol(values: string[], subType: 'int' | 'str', description: string): EnumCol { - return { type: 'enum', description, values, subType } + return { type: 'enum', description, values, subType }; } export type VectorCol = { type: 'vector', length: number } & BaseCol export function VectorCol(length: number, description: string): VectorCol { - return { type: 'vector', description, length } + return { type: 'vector', description, length }; } export type MatrixCol = { type: 'matrix', rows: number, columns: number } & BaseCol export function MatrixCol(columns: number, rows: number, description: string): MatrixCol { - return { type: 'matrix', description, columns, rows } + return { type: 'matrix', description, columns, rows }; } export type ListCol = { type: 'list', subType: 'int' | 'str' | 'float' | 'coord', separator: string } & BaseCol export function ListCol(subType: 'int' | 'str' | 'float' | 'coord', separator: string, description: string): ListCol { - return { type: 'list', description, separator, subType } + return { type: 'list', description, separator, subType }; } export type Filter = { [ table: string ]: { [ column: string ]: true } } export function mergeFilters (...filters: Filter[]) { - const n = filters.length - const mergedFilter: Filter = {} - const fields: Map<string, number> = new Map() + const n = filters.length; + const mergedFilter: Filter = {}; + const fields: Map<string, number> = new Map(); filters.forEach(filter => { Object.keys(filter).forEach(category => { Object.keys(filter[ category ]).forEach(field => { - const key = `${category}.${field}` - const value = fields.get(key) || 0 - fields.set(key, value + 1) - }) - }) - }) + const key = `${category}.${field}`; + const value = fields.get(key) || 0; + fields.set(key, value + 1); + }); + }); + }); fields.forEach((v, k) => { - if (v !== n) return - const [categoryName, fieldName] = k.split('.') + if (v !== n) return; + const [categoryName, fieldName] = k.split('.'); if (categoryName in mergedFilter) { - mergedFilter[categoryName][fieldName] = true + mergedFilter[categoryName][fieldName] = true; } else { - mergedFilter[categoryName] = { fieldName: true } + mergedFilter[categoryName] = { fieldName: true }; } - }) - return mergedFilter + }); + return mergedFilter; } diff --git a/src/apps/state-docs/index.ts b/src/apps/state-docs/index.ts index 49289aab442ce4a5d301c419484f19ff6bf7057f..bdc50e6540969bcdad9f5dd18379d925ef295968 100644 --- a/src/apps/state-docs/index.ts +++ b/src/apps/state-docs/index.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as _ from '../../mol-plugin-state/transforms' +import * as _ from '../../mol-plugin-state/transforms'; import { StateTransformer, StateObject } from '../../mol-state'; import { StringBuilder } from '../../mol-util'; import * as fs from 'fs'; @@ -13,7 +13,7 @@ import { PluginContext } from '../../mol-plugin/context'; import { ParamDefinition } from '../../mol-util/param-definition'; // force the transform to be evaluated -_.StateTransforms.Data.Download.id +_.StateTransforms.Data.Download.id; // Empty plugin context const ctx = new PluginContext({ @@ -32,7 +32,7 @@ function writeTransformer(t: StateTransformer) { StringBuilder.write(builder, `## <a name="${t.id.replace('.', '-')}"></a>${t.id} :: ${typeToString(t.definition.from)} -> ${typeToString(t.definition.to)}`); StringBuilder.newline(builder); if (t.definition.display.description) { - StringBuilder.write(builder, `*${t.definition.display.description}*`) + StringBuilder.write(builder, `*${t.definition.display.description}*`); StringBuilder.newline(builder); } StringBuilder.newline(builder); @@ -48,7 +48,7 @@ function writeTransformer(t: StateTransformer) { StringBuilder.write(builder, `\`\`\`js\n${JSON.stringify(ParamDefinition.getDefaultValues(params), null, 2)}\n\`\`\``); StringBuilder.newline(builder); } - StringBuilder.write(builder, '----------------------------') + StringBuilder.write(builder, '----------------------------'); StringBuilder.newline(builder); } @@ -62,7 +62,7 @@ transformers.forEach(t => { StringBuilder.newline(builder); }); StringBuilder.newline(builder); -StringBuilder.write(builder, '----------------------------') +StringBuilder.write(builder, '----------------------------'); StringBuilder.newline(builder); transformers.forEach(t => writeTransformer(t)); diff --git a/src/apps/structure-info/helpers.ts b/src/apps/structure-info/helpers.ts index be1a7aac0c7a15a92744becd5b631fb4d13660f7..7cb437e5c9a902d4165de06d7d3850a49d7421c6 100644 --- a/src/apps/structure-info/helpers.ts +++ b/src/apps/structure-info/helpers.ts @@ -4,19 +4,19 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as util from 'util' -import * as fs from 'fs' -import fetch from 'node-fetch' +import * as util from 'util'; +import * as fs from 'fs'; +import fetch from 'node-fetch'; require('util.promisify').shim(); -import { CIF } from '../../mol-io/reader/cif' -import { Progress } from '../../mol-task' +import { CIF } from '../../mol-io/reader/cif'; +import { Progress } from '../../mol-task'; const readFileAsync = util.promisify(fs.readFile); async function readFile(path: string) { if (path.match(/\.bcif$/)) { - const input = await readFileAsync(path) + const input = await readFileAsync(path); const data = new Uint8Array(input.byteLength); for (let i = 0; i < input.byteLength; i++) data[i] = input[i]; return data; diff --git a/src/apps/structure-info/model.ts b/src/apps/structure-info/model.ts index d0498beff3601b1444116c301229b81fed5da37d..585a1e2e88256a335dfa3deb4b677cb7154cc934 100644 --- a/src/apps/structure-info/model.ts +++ b/src/apps/structure-info/model.ts @@ -5,11 +5,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as argparse from 'argparse' +import * as argparse from 'argparse'; require('util.promisify').shim(); -import { CifFrame } from '../../mol-io/reader/cif' -import { Model, Structure, StructureElement, Unit, StructureProperties, UnitRing } from '../../mol-model/structure' +import { CifFrame } from '../../mol-io/reader/cif'; +import { Model, Structure, StructureElement, Unit, StructureProperties, UnitRing } from '../../mol-model/structure'; // import { Run, Progress } from '../../mol-task' import { OrderedSet } from '../../mol-data/int'; import { openCif, downloadCif } from './helpers'; @@ -32,30 +32,30 @@ export async function readCifFile(path: string) { } export function atomLabel(model: Model, aI: number) { - const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy - const { label_atom_id } = atoms - const { label_comp_id, label_seq_id } = residues - const { label_asym_id } = chains - const rI = residueAtomSegments.index[aI] - const cI = chainAtomSegments.index[aI] - return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)} ${label_atom_id.value(aI)}` + const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy; + const { label_atom_id } = atoms; + const { label_comp_id, label_seq_id } = residues; + const { label_asym_id } = chains; + const rI = residueAtomSegments.index[aI]; + const cI = chainAtomSegments.index[aI]; + return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)} ${label_atom_id.value(aI)}`; } export function residueLabel(model: Model, rI: number) { - const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy - const { label_comp_id, label_seq_id } = residues - const { label_asym_id } = chains - const cI = chainAtomSegments.index[residueAtomSegments.offsets[rI]] - return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}` + const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy; + const { label_comp_id, label_seq_id } = residues; + const { label_asym_id } = chains; + const cI = chainAtomSegments.index[residueAtomSegments.offsets[rI]]; + return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}`; } export function printSecStructure(model: Model) { console.log('\nSecondary Structure\n============='); const { residues } = model.atomicHierarchy; const secondaryStructure = ModelSecondaryStructure.Provider.get(model); - if (!secondaryStructure) return + if (!secondaryStructure) return; - const { key, elements } = secondaryStructure + const { key, elements } = secondaryStructure; const count = residues._rowCount; let rI = 0; while (rI < count) { @@ -116,7 +116,7 @@ export function printSequence(model: Model) { const { byEntityKey } = model.sequence; for (const key of Object.keys(byEntityKey)) { const { sequence, entityId } = byEntityKey[+key]; - const { seqId, compId } = sequence + const { seqId, compId } = sequence; console.log(`${entityId} (${sequence.kind} ${seqId.value(0)} (offset ${sequence.offset}), ${seqId.value(seqId.rowCount - 1)}) (${compId.value(0)}, ${compId.value(compId.rowCount - 1)})`); console.log(`${Sequence.getSequenceString(sequence)}`); } @@ -132,7 +132,7 @@ export function printRings(structure: Structure) { for (let i = 0, _i = Math.min(5, all.length); i < _i; i++) { fps[fps.length] = UnitRing.fingerprint(unit, all[i]); } - if (all.length > 5) fps.push('...') + if (all.length > 5) fps.push('...'); console.log(`Unit ${unit.id}, ${all.length} ring(s), ${byFingerprint.size} different fingerprint(s).\n ${fps.join(', ')}`); } console.log(); @@ -171,8 +171,8 @@ export function printUnits(structure: Structure) { export function printSymmetryInfo(model: Model) { console.log('\nSymmetry Info\n============='); - const symmetry = ModelSymmetry.Provider.get(model) - if (!symmetry) return + const symmetry = ModelSymmetry.Provider.get(model); + if (!symmetry) return; const { size, anglesInRadians } = symmetry.spacegroup.cell; console.log(`Spacegroup: ${symmetry.spacegroup.name} size: ${Vec3.toString(size)} angles: ${Vec3.toString(anglesInRadians)}`); console.log(`Assembly names: ${symmetry.assemblies.map(a => a.id).join(', ')}`); @@ -213,7 +213,7 @@ async function run(frame: CifFrame, args: Args) { } async function runDL(pdb: string, args: Args) { - const mmcif = await downloadFromPdb(pdb) + const mmcif = await downloadFromPdb(pdb); run(mmcif, args); } @@ -255,5 +255,5 @@ interface Args { } const args: Args = parser.parseArgs(); -if (args.download) runDL(args.download, args) -else if (args.file) runFile(args.file, args) +if (args.download) runDL(args.download, args); +else if (args.file) runFile(args.file, args); diff --git a/src/apps/structure-info/volume.ts b/src/apps/structure-info/volume.ts index c3780e97c1b6701ad6b153e03e2d2e46f1151717..02e8e789fb024520b54ed3915e07c0e5da56e7a4 100644 --- a/src/apps/structure-info/volume.ts +++ b/src/apps/structure-info/volume.ts @@ -4,13 +4,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as fs from 'fs' -import * as argparse from 'argparse' -import * as util from 'util' +import * as fs from 'fs'; +import * as argparse from 'argparse'; +import * as util from 'util'; -import { VolumeData, VolumeIsoValue } from '../../mol-model/volume' -import { downloadCif } from './helpers' -import { CIF } from '../../mol-io/reader/cif' +import { VolumeData, VolumeIsoValue } from '../../mol-model/volume'; +import { downloadCif } from './helpers'; +import { CIF } from '../../mol-io/reader/cif'; import { DensityServer_Data_Database } from '../../mol-io/reader/cif/schema/density-server'; import { Table } from '../../mol-data/db'; import { StringBuilder } from '../../mol-util'; diff --git a/src/apps/viewer/extensions/cellpack/color.ts b/src/apps/viewer/extensions/cellpack/color.ts index d14de313246ea5b84d25911a8e3b7c07ea8e39f5..7491face8403910983893864d36f9ae5d69e8bdf 100644 --- a/src/apps/viewer/extensions/cellpack/color.ts +++ b/src/apps/viewer/extensions/cellpack/color.ts @@ -4,40 +4,40 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ThemeDataContext } from '../../../../mol-theme/theme' -import { ParamDefinition as PD } from '../../../../mol-util/param-definition' -import { Color } from '../../../../mol-util/color' -import { getPalette } from '../../../../mol-util/color/palette' -import { ColorTheme, LocationColor } from '../../../../mol-theme/color' -import { ScaleLegend, TableLegend } from '../../../../mol-util/legend' -import { StructureElement, Bond } from '../../../../mol-model/structure' +import { ThemeDataContext } from '../../../../mol-theme/theme'; +import { ParamDefinition as PD } from '../../../../mol-util/param-definition'; +import { Color } from '../../../../mol-util/color'; +import { getPalette } from '../../../../mol-util/color/palette'; +import { ColorTheme, LocationColor } from '../../../../mol-theme/color'; +import { ScaleLegend, TableLegend } from '../../../../mol-util/legend'; +import { StructureElement, Bond } from '../../../../mol-model/structure'; import { Location } from '../../../../mol-model/location'; -import { CellPackInfoProvider } from './property' -import { distinctColors } from '../../../../mol-util/color/distinct' -import { Hcl } from '../../../../mol-util/color/spaces/hcl' +import { CellPackInfoProvider } from './property'; +import { distinctColors } from '../../../../mol-util/color/distinct'; +import { Hcl } from '../../../../mol-util/color/spaces/hcl'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives every model in a CellPack packing a unique color similar to other models in the packing.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives every model in a CellPack packing a unique color similar to other models in the packing.'; -export const CellPackColorThemeParams = {} +export const CellPackColorThemeParams = {}; export type CellPackColorThemeParams = typeof CellPackColorThemeParams export function getCellPackColorThemeParams(ctx: ThemeDataContext) { - return CellPackColorThemeParams // TODO return copy + return CellPackColorThemeParams; // TODO return copy } export function CellPackColorTheme(ctx: ThemeDataContext, props: PD.Values<CellPackColorThemeParams>): ColorTheme<CellPackColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; - const info = ctx.structure && CellPackInfoProvider.get(ctx.structure).value + const info = ctx.structure && CellPackInfoProvider.get(ctx.structure).value; if (ctx.structure && info) { - const colors = distinctColors(info.packingsCount) - const hcl = Hcl.fromColor(Hcl(), colors[info.packingIndex]) - const hue = [Math.max(0, hcl[0] - 35), Math.min(360, hcl[0] + 35)] as [number, number] + const colors = distinctColors(info.packingsCount); + const hcl = Hcl.fromColor(Hcl(), colors[info.packingIndex]); + const hue = [Math.max(0, hcl[0] - 35), Math.min(360, hcl[0] + 35)] as [number, number]; - const { models } = ctx.structure.root + const { models } = ctx.structure.root; let size = 0; for (const m of models) size = Math.max(size, m.trajectoryInfo.size); @@ -49,24 +49,24 @@ export function CellPackColorTheme(ctx: ThemeDataContext, props: PD.Values<CellP clusteringStepCount: 50, minSampleCount: 800, maxCount: 75, minLabel: 'Min', maxLabel: 'Max', valueLabel: (i: number) => `${i + 1}`, } - }}) - legend = palette.legend - const modelColor = new Map<number, Color>() + }}); + legend = palette.legend; + const modelColor = new Map<number, Color>(); for (let i = 0, il = models.length; i < il; ++i) { const idx = models[i].trajectoryInfo.index; - modelColor.set(models[i].trajectoryInfo.index, palette.color(idx)) + modelColor.set(models[i].trajectoryInfo.index, palette.color(idx)); } color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - return modelColor.get(location.unit.model.trajectoryInfo.index)! + return modelColor.get(location.unit.model.trajectoryInfo.index)!; } else if (Bond.isLocation(location)) { - return modelColor.get(location.aUnit.model.trajectoryInfo.index)! + return modelColor.get(location.aUnit.model.trajectoryInfo.index)!; } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -76,7 +76,7 @@ export function CellPackColorTheme(ctx: ThemeDataContext, props: PD.Values<CellP props, description: Description, legend - } + }; } export const CellPackColorThemeProvider: ColorTheme.Provider<CellPackColorThemeParams, 'cellpack'> = { @@ -91,6 +91,6 @@ export const CellPackColorThemeProvider: ColorTheme.Provider<CellPackColorThemeP !!ctx.structure && ctx.structure.elementCount > 0 && ctx.structure.models[0].trajectoryInfo.size > 1 && !!CellPackInfoProvider.get(ctx.structure).value - ) + ); } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/apps/viewer/extensions/cellpack/curve.ts b/src/apps/viewer/extensions/cellpack/curve.ts index 6a31ac5a78a37700e2d995cba37f9a134407eba2..e939cbe12f851b2a7366490e95d66ec9ac268c59 100644 --- a/src/apps/viewer/extensions/cellpack/curve.ts +++ b/src/apps/viewer/extensions/cellpack/curve.ts @@ -14,210 +14,210 @@ interface Frame { s: Vec3, } -const a0Tmp = Vec3() -const a1Tmp = Vec3() -const a2Tmp = Vec3() -const a3Tmp = Vec3() +const a0Tmp = Vec3(); +const a1Tmp = Vec3(); +const a2Tmp = Vec3(); +const a3Tmp = Vec3(); function CubicInterpolate(out: Vec3, y0: Vec3, y1: Vec3, y2: Vec3, y3: Vec3, mu: number): Vec3 { const mu2 = mu * mu; - Vec3.sub(a0Tmp, y3, y2) - Vec3.sub(a0Tmp, a0Tmp, y0) - Vec3.add(a0Tmp, a0Tmp, y1) + Vec3.sub(a0Tmp, y3, y2); + Vec3.sub(a0Tmp, a0Tmp, y0); + Vec3.add(a0Tmp, a0Tmp, y1); - Vec3.sub(a1Tmp, y0, y1) - Vec3.sub(a1Tmp, a1Tmp, a0Tmp) + Vec3.sub(a1Tmp, y0, y1); + Vec3.sub(a1Tmp, a1Tmp, a0Tmp); - Vec3.sub(a2Tmp, y2, y0) + Vec3.sub(a2Tmp, y2, y0); - Vec3.copy(a3Tmp, y1) + Vec3.copy(a3Tmp, y1); - out[0] = a0Tmp[0] * mu * mu2 + a1Tmp[0] * mu2 + a2Tmp[0] * mu + a3Tmp[0] - out[1] = a0Tmp[1] * mu * mu2 + a1Tmp[1] * mu2 + a2Tmp[1] * mu + a3Tmp[1] - out[2] = a0Tmp[2] * mu * mu2 + a1Tmp[2] * mu2 + a2Tmp[2] * mu + a3Tmp[2] + out[0] = a0Tmp[0] * mu * mu2 + a1Tmp[0] * mu2 + a2Tmp[0] * mu + a3Tmp[0]; + out[1] = a0Tmp[1] * mu * mu2 + a1Tmp[1] * mu2 + a2Tmp[1] * mu + a3Tmp[1]; + out[2] = a0Tmp[2] * mu * mu2 + a1Tmp[2] * mu2 + a2Tmp[2] * mu + a3Tmp[2]; - return out + return out; } -const cp0 = Vec3() -const cp1 = Vec3() -const cp2 = Vec3() -const cp3 = Vec3() -const currentPosition = Vec3() +const cp0 = Vec3(); +const cp1 = Vec3(); +const cp2 = Vec3(); +const cp3 = Vec3(); +const currentPosition = Vec3(); function ResampleControlPoints(points: NumberArray, segmentLength: number) { - const nP = points.length / 3 + const nP = points.length / 3; // insert a point at the end and at the begining // controlPoints.Insert(0, controlPoints[0] + (controlPoints[0] - controlPoints[1]) / 2.0f); // controlPoints.Add(controlPoints[nP - 1] + (controlPoints[nP - 1] - controlPoints[nP - 2]) / 2.0f); - let resampledControlPoints: Vec3[] = [] + let resampledControlPoints: Vec3[] = []; // resampledControlPoints.Add(controlPoints[0]); // resampledControlPoints.Add(controlPoints[1]); - let idx = 1 + let idx = 1; // const currentPosition = Vec3.create(points[idx * 3], points[idx * 3 + 1], points[idx * 3 + 2]) - Vec3.fromArray(currentPosition, points, idx * 3) + Vec3.fromArray(currentPosition, points, idx * 3); - let lerpValue = 0.0 + let lerpValue = 0.0; // Normalize the distance between control points while (true) { - if (idx + 2 >= nP) break - Vec3.fromArray(cp0, points, (idx - 1) * 3) - Vec3.fromArray(cp1, points, idx * 3) - Vec3.fromArray(cp2, points, (idx + 1) * 3) - Vec3.fromArray(cp3, points, (idx + 2) * 3) + if (idx + 2 >= nP) break; + Vec3.fromArray(cp0, points, (idx - 1) * 3); + Vec3.fromArray(cp1, points, idx * 3); + Vec3.fromArray(cp2, points, (idx + 1) * 3); + Vec3.fromArray(cp3, points, (idx + 2) * 3); // const cp0 = Vec3.create(points[(idx-1)*3], points[(idx-1)*3+1], points[(idx-1)*3+2]) // controlPoints[currentPointId - 1]; // const cp1 = Vec3.create(points[idx*3], points[idx*3+1], points[idx*3+2]) // controlPoints[currentPointId]; // const cp2 = Vec3.create(points[(idx+1)*3], points[(idx+1)*3+1], points[(idx+1)*3+2]) // controlPoints[currentPointId + 1]; // const cp3 = Vec3.create(points[(idx+2)*3], points[(idx+2)*3+1], points[(idx+2)*3+2]); // controlPoints[currentPointId + 2]; - let found = false + let found = false; for (; lerpValue <= 1; lerpValue += 0.01) { // lerp?slerp // let candidate:Vec3 = Vec3.lerp(Vec3.zero(), cp0, cp1, lerpValue); // const candidate:Vec3 = Vec3.bezier(Vec3.zero(), cp0, cp1, cp2, cp3, lerpValue); - const candidate = CubicInterpolate(Vec3(), cp0, cp1, cp2, cp3, lerpValue) + const candidate = CubicInterpolate(Vec3(), cp0, cp1, cp2, cp3, lerpValue); const d = Vec3.distance(currentPosition, candidate); if (d > segmentLength) { - resampledControlPoints.push(candidate) - Vec3.copy(currentPosition, candidate) - found = true - break + resampledControlPoints.push(candidate); + Vec3.copy(currentPosition, candidate); + found = true; + break; } } if (!found) { - lerpValue = 0 - idx += 1 + lerpValue = 0; + idx += 1; } } - return resampledControlPoints + return resampledControlPoints; } -const prevV = Vec3() -const tmpV1 = Vec3() -const tmpV2 = Vec3() -const tmpV3 = Vec3() +const prevV = Vec3(); +const tmpV1 = Vec3(); +const tmpV2 = Vec3(); +const tmpV3 = Vec3(); // easier to align to theses normals function GetSmoothNormals(points: Vec3[]) { const nP: number = points.length; - const smoothNormals: Vec3[] = [] + const smoothNormals: Vec3[] = []; if (points.length < 3) { for (let i = 0; i < points.length; ++i) - smoothNormals.push(Vec3.normalize(Vec3(), points[i])) + smoothNormals.push(Vec3.normalize(Vec3(), points[i])); return smoothNormals; } - let p0 = points[0] - let p1 = points[1] - let p2 = points[2] - const p21 = Vec3.sub(tmpV1, p2, p1) - const p01 = Vec3.sub(tmpV2, p0, p1) - const p0121 = Vec3.cross(tmpV3, p01, p21) - Vec3.normalize(prevV, p0121) - smoothNormals.push(Vec3.clone(prevV)) + let p0 = points[0]; + let p1 = points[1]; + let p2 = points[2]; + const p21 = Vec3.sub(tmpV1, p2, p1); + const p01 = Vec3.sub(tmpV2, p0, p1); + const p0121 = Vec3.cross(tmpV3, p01, p21); + Vec3.normalize(prevV, p0121); + smoothNormals.push(Vec3.clone(prevV)); for (let i = 1; i < points.length - 1; ++i) { - p0 = points[i - 1] - p1 = points[i] - p2 = points[i + 1] - const t = Vec3.normalize(tmpV1, Vec3.sub(tmpV1, p2, p0)) - const b = Vec3.normalize(tmpV2, Vec3.cross(tmpV2, t, prevV)) - const n = Vec3.normalize(Vec3(), Vec3.cross(tmpV3, t, b)) - Vec3.negate(n, n) - Vec3.copy(prevV, n) - smoothNormals.push(n) + p0 = points[i - 1]; + p1 = points[i]; + p2 = points[i + 1]; + const t = Vec3.normalize(tmpV1, Vec3.sub(tmpV1, p2, p0)); + const b = Vec3.normalize(tmpV2, Vec3.cross(tmpV2, t, prevV)); + const n = Vec3.normalize(Vec3(), Vec3.cross(tmpV3, t, b)); + Vec3.negate(n, n); + Vec3.copy(prevV, n); + smoothNormals.push(n); } - const last = Vec3() + const last = Vec3(); Vec3.normalize(last, Vec3.cross(last, Vec3.sub(tmpV1, points[nP - 3], points[nP - 2]), Vec3.sub(tmpV2, points[nP - 2], points[nP - 1])) - ) - smoothNormals.push(last) + ); + smoothNormals.push(last); return smoothNormals; } -const frameTmpV1 = Vec3() -const frameTmpV2 = Vec3() -const frameTmpV3 = Vec3() +const frameTmpV1 = Vec3(); +const frameTmpV2 = Vec3(); +const frameTmpV3 = Vec3(); function getFrame(reference: Vec3, tangent: Vec3) { const t = Vec3.normalize(Vec3(), tangent); // make reference vector orthogonal to tangent const proj_r_to_t = Vec3.scale( frameTmpV1, tangent, Vec3.dot(reference, tangent) / Vec3.dot(tangent, tangent) - ) - const r = Vec3.normalize(Vec3(), Vec3.sub(frameTmpV2, reference, proj_r_to_t)) + ); + const r = Vec3.normalize(Vec3(), Vec3.sub(frameTmpV2, reference, proj_r_to_t)); // make bitangent vector orthogonal to the others - const s = Vec3.normalize(Vec3(), Vec3.cross(frameTmpV3, t, r)) - return { t, r, s } + const s = Vec3.normalize(Vec3(), Vec3.cross(frameTmpV3, t, r)); + return { t, r, s }; } -const mfTmpV1 = Vec3() -const mfTmpV2 = Vec3() -const mfTmpV3 = Vec3() -const mfTmpV4 = Vec3() -const mfTmpV5 = Vec3() -const mfTmpV6 = Vec3() -const mfTmpV7 = Vec3() -const mfTmpV8 = Vec3() -const mfTmpV9 = Vec3() +const mfTmpV1 = Vec3(); +const mfTmpV2 = Vec3(); +const mfTmpV3 = Vec3(); +const mfTmpV4 = Vec3(); +const mfTmpV5 = Vec3(); +const mfTmpV6 = Vec3(); +const mfTmpV7 = Vec3(); +const mfTmpV8 = Vec3(); +const mfTmpV9 = Vec3(); // easier to align to theses normals // https://github.com/bzamecnik/gpg/blob/master/rotation-minimizing-frame/rmf.py function GetMiniFrame(points: Vec3[], normals: Vec3[]) { const frames: Frame[] = []; - const t0 = Vec3.normalize(mfTmpV1, Vec3.sub(mfTmpV1, points[1], points[0])) - frames.push(getFrame(normals[0], t0)) + const t0 = Vec3.normalize(mfTmpV1, Vec3.sub(mfTmpV1, points[1], points[0])); + frames.push(getFrame(normals[0], t0)); for (let i = 0; i < points.length - 2; ++i) { - const t2 = Vec3.normalize(mfTmpV1, Vec3.sub(mfTmpV1, points[i + 2], points[i + 1])) - const v1 = Vec3.sub(mfTmpV2, points[i + 1], points[i]) // this is tangeant - const c1 = Vec3.dot(v1, v1) + const t2 = Vec3.normalize(mfTmpV1, Vec3.sub(mfTmpV1, points[i + 2], points[i + 1])); + const v1 = Vec3.sub(mfTmpV2, points[i + 1], points[i]); // this is tangeant + const c1 = Vec3.dot(v1, v1); // compute r_i^L = R_1 * r_i - const v1r = Vec3.scale(mfTmpV3, v1, (2.0 / c1) * Vec3.dot(v1, frames[i].r)) - const ref_L_i = Vec3.sub(mfTmpV4, frames[i].r, v1r) + const v1r = Vec3.scale(mfTmpV3, v1, (2.0 / c1) * Vec3.dot(v1, frames[i].r)); + const ref_L_i = Vec3.sub(mfTmpV4, frames[i].r, v1r); // compute t_i^L = R_1 * t_i - const v1t = Vec3.scale(mfTmpV5, v1, (2.0 / c1) * Vec3.dot(v1, frames[i].t)) - const tan_L_i = Vec3.sub(mfTmpV6, frames[i].t, v1t) + const v1t = Vec3.scale(mfTmpV5, v1, (2.0 / c1) * Vec3.dot(v1, frames[i].t)); + const tan_L_i = Vec3.sub(mfTmpV6, frames[i].t, v1t); // # compute reflection vector of R_2 - const v2 = Vec3.sub(mfTmpV7, t2, tan_L_i) - const c2 = Vec3.dot(v2, v2) + const v2 = Vec3.sub(mfTmpV7, t2, tan_L_i); + const c2 = Vec3.dot(v2, v2); // compute r_(i+1) = R_2 * r_i^L - const v2l = Vec3.scale(mfTmpV8, v1, (2.0 / c2) * Vec3.dot(v2, ref_L_i)) - const ref_next = Vec3.sub(mfTmpV9, ref_L_i, v2l) // ref_L_i - (2 / c2) * v2.dot(ref_L_i) * v2 - frames.push(getFrame(ref_next, t2)) // frames.append(Frame(ref_next, tangents[i+1])) + const v2l = Vec3.scale(mfTmpV8, v1, (2.0 / c2) * Vec3.dot(v2, ref_L_i)); + const ref_next = Vec3.sub(mfTmpV9, ref_L_i, v2l); // ref_L_i - (2 / c2) * v2.dot(ref_L_i) * v2 + frames.push(getFrame(ref_next, t2)); // frames.append(Frame(ref_next, tangents[i+1])) } return frames; } -const rpTmpVec1 = Vec3() +const rpTmpVec1 = Vec3(); export function getMatFromResamplePoints(points: NumberArray, segmentLength: number) { - const new_points = ResampleControlPoints(points, segmentLength) - const npoints = new_points.length - const new_normal = GetSmoothNormals(new_points) - const frames = GetMiniFrame(new_points, new_normal) - const limit = npoints - const transforms: Mat4[] = [] + const new_points = ResampleControlPoints(points, segmentLength); + const npoints = new_points.length; + const new_normal = GetSmoothNormals(new_points); + const frames = GetMiniFrame(new_points, new_normal); + const limit = npoints; + const transforms: Mat4[] = []; const pti = Vec3.copy(rpTmpVec1, new_points[0]); for (let i = 0; i < npoints - 2; ++i) { - const pti1: Vec3 = new_points[i + 1] // Vec3.create(points[(i+1)*3],points[(i+1)*3+1],points[(i+1)*3+2]); - const d = Vec3.distance(pti, pti1) + const pti1: Vec3 = new_points[i + 1]; // Vec3.create(points[(i+1)*3],points[(i+1)*3+1],points[(i+1)*3+2]); + const d = Vec3.distance(pti, pti1); if (d >= segmentLength) { // use twist or random? - const quat = Quat.rotationTo(Quat.zero(), Vec3.create(0, 0, 1), frames[i].t) // Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),new_normal[i]);//Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),direction);new_normal - const rq = Quat.setAxisAngle(Quat.zero(), frames[i].t, Math.random() * 3.60 ) // Quat.setAxisAngle(Quat.zero(),direction, Math.random()*3.60 );//Quat.identity();// - const m = Mat4.fromQuat(Mat4.zero(), Quat.multiply(Quat.zero(), rq, quat)) // Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),quat1,quat2));//Mat4.fromQuat(Mat4.zero(),quat);//Mat4.identity();//Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),rq,quat)); + const quat = Quat.rotationTo(Quat.zero(), Vec3.create(0, 0, 1), frames[i].t); // Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),new_normal[i]);//Quat.rotationTo(Quat.zero(), Vec3.create(0,0,1),direction);new_normal + const rq = Quat.setAxisAngle(Quat.zero(), frames[i].t, Math.random() * 3.60 ); // Quat.setAxisAngle(Quat.zero(),direction, Math.random()*3.60 );//Quat.identity();// + const m = Mat4.fromQuat(Mat4.zero(), Quat.multiply(Quat.zero(), rq, quat)); // Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),quat1,quat2));//Mat4.fromQuat(Mat4.zero(),quat);//Mat4.identity();//Mat4.fromQuat(Mat4.zero(),Quat.multiply(Quat.zero(),rq,quat)); // let pos:Vec3 = Vec3.add(Vec3.zero(),pti1,pti) // pos = Vec3.scale(pos,pos,1.0/2.0); // Vec3.makeRotation(Mat4.zero(),Vec3.create(0,0,1),frames[i].t);// - Mat4.setTranslation(m, pti1) + Mat4.setTranslation(m, pti1); // let m2:Mat4 = GetTubePropertiesMatrix(pti,pti1); // let q:Quat = Quat.rotationTo(Quat.zero(), Vec3.create(0,1,0),Vec3.create(0,0,1)) // m2=Mat4.mul(Mat4.identity(),Mat4.fromQuat(Mat4.zero(),q),m2); - transforms.push(m) - Vec3.copy(pti, pti1) + transforms.push(m); + Vec3.copy(pti, pti1); } - if (transforms.length >= limit) break + if (transforms.length >= limit) break; } - return transforms + return transforms; } \ No newline at end of file diff --git a/src/apps/viewer/extensions/cellpack/model.ts b/src/apps/viewer/extensions/cellpack/model.ts index bdc96b2a0b2c25972d8acbd2ed0d9676b873bc47..907bf7cdfd8d3734d4eb822d468f0298d715c12f 100644 --- a/src/apps/viewer/extensions/cellpack/model.ts +++ b/src/apps/viewer/extensions/cellpack/model.ts @@ -31,124 +31,124 @@ import { CellPackInfoProvider } from './property'; import { CellPackColorThemeProvider } from './color'; function getCellPackModelUrl(fileName: string, baseUrl: string) { - return `${baseUrl}/results/${fileName}` + return `${baseUrl}/results/${fileName}`; } async function getModel(id: string, model_id: number, baseUrl: string, file?: File) { let model: Model; if (file) { - const text = await file.text() + const text = await file.text(); if (file.name.endsWith('.cif')) { - const cif = (await parseCif(text)).blocks[0] - model = (await trajectoryFromMmCIF(cif).run())[model_id] + const cif = (await parseCif(text)).blocks[0]; + model = (await trajectoryFromMmCIF(cif).run())[model_id]; } else if (file.name.endsWith('.pdb')) { - const pdb = await parsePDBfile(text, id) + const pdb = await parsePDBfile(text, id); - model = (await trajectoryFromPDB(pdb).run())[model_id] + model = (await trajectoryFromPDB(pdb).run())[model_id]; } else { - throw new Error(`unsupported file type '${file.name}'`) + throw new Error(`unsupported file type '${file.name}'`); } } else if (id.match(/^[1-9][a-zA-Z0-9]{3,3}$/i)) { - const cif = await getFromPdb(id) - model = (await trajectoryFromMmCIF(cif).run())[model_id] + const cif = await getFromPdb(id); + model = (await trajectoryFromMmCIF(cif).run())[model_id]; } else { - const pdb = await getFromCellPackDB(id, baseUrl) - model = (await trajectoryFromPDB(pdb).run())[model_id] + const pdb = await getFromCellPackDB(id, baseUrl); + model = (await trajectoryFromPDB(pdb).run())[model_id]; } - return model + return model; } async function getStructure(model: Model, source: IngredientSource, props: { assembly?: string } = {}) { - let structure = Structure.ofModel(model) - const { assembly } = props + let structure = Structure.ofModel(model); + const { assembly } = props; if (assembly) { - structure = await StructureSymmetry.buildAssembly(structure, assembly).run() + structure = await StructureSymmetry.buildAssembly(structure, assembly).run(); } let query; if (source.selection){ - const asymIds: string[] = source.selection.replace(' :', '').split(' or') + const asymIds: string[] = source.selection.replace(' :', '').split(' or'); query = MS.struct.modifier.union([ MS.struct.generator.atomGroups({ 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer']), 'chain-test': MS.core.set.has([MS.set(...asymIds), MS.ammp('auth_asym_id')]) }) - ]) + ]); } else { query = MS.struct.modifier.union([ MS.struct.generator.atomGroups({ 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer']) }) - ]) + ]); } - const compiled = compile<StructureSelection>(query) - const result = compiled(new QueryContext(structure)) - structure = StructureSelection.unionStructure(result) + const compiled = compile<StructureSelection>(query); + const result = compiled(new QueryContext(structure)); + structure = StructureSelection.unionStructure(result); - return structure + return structure; } function getTransformLegacy(trans: Vec3, rot: Quat) { - const q: Quat = Quat.create(-rot[3], rot[0], rot[1], rot[2]) - const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q) - Mat4.transpose(m, m) - Mat4.scale(m, m, Vec3.create(-1.0, 1.0, -1.0)) - Mat4.setTranslation(m, trans) - return m + const q: Quat = Quat.create(-rot[3], rot[0], rot[1], rot[2]); + const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q); + Mat4.transpose(m, m); + Mat4.scale(m, m, Vec3.create(-1.0, 1.0, -1.0)); + Mat4.setTranslation(m, trans); + return m; } function getTransform(trans: Vec3, rot: Quat) { - const q: Quat = Quat.create(rot[0], rot[1], rot[2], rot[3]) - const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q) - const p: Vec3 = Vec3.create(trans[0], trans[1], trans[2]) - Mat4.setTranslation(m, p) - return m + const q: Quat = Quat.create(rot[0], rot[1], rot[2], rot[3]); + const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q); + const p: Vec3 = Vec3.create(trans[0], trans[1], trans[2]); + Mat4.setTranslation(m, p); + return m; } function getResultTransforms(results: Ingredient['results'], legacy: boolean) { - if (legacy) return results.map((r: Ingredient['results'][0]) => getTransformLegacy(r[0], r[1])) - else return results.map((r: Ingredient['results'][0]) => getTransform(r[0], r[1])) + if (legacy) return results.map((r: Ingredient['results'][0]) => getTransformLegacy(r[0], r[1])); + else return results.map((r: Ingredient['results'][0]) => getTransform(r[0], r[1])); } function getCurveTransforms(ingredient: Ingredient) { - const n = ingredient.nbCurve || 0 - const instances: Mat4[] = [] + const n = ingredient.nbCurve || 0; + const instances: Mat4[] = []; const segmentLength = ingredient.radii ? (ingredient.radii[0].radii ? ingredient.radii[0].radii[0] * 2.0 : 3.4) : 3.4; for (let i = 0; i < n; ++i) { - const cname = `curve${i}` + const cname = `curve${i}`; if (!(cname in ingredient)) { // console.warn(`Expected '${cname}' in ingredient`) - continue + continue; } - const _points = ingredient[cname] as Vec3[] + const _points = ingredient[cname] as Vec3[]; if (_points.length <= 2) { // TODO handle curve with 2 or less points - continue + continue; } - const points = new Float32Array(_points.length * 3) - for (let i = 0, il = _points.length; i < il; ++i) Vec3.toArray(_points[i], points, i * 3) - const newInstances = getMatFromResamplePoints(points, segmentLength) - instances.push(...newInstances) + const points = new Float32Array(_points.length * 3); + for (let i = 0, il = _points.length; i < il; ++i) Vec3.toArray(_points[i], points, i * 3); + const newInstances = getMatFromResamplePoints(points, segmentLength); + instances.push(...newInstances); } - return instances + return instances; } function getAssembly(transforms: Mat4[], structure: Structure) { - const builder = Structure.Builder() + const builder = Structure.Builder(); const { units } = structure; for (let i = 0, il = transforms.length; i < il; ++i) { - const id = `${i + 1}` - const op = SymmetryOperator.create(id, transforms[i], { assembly: { id, operId: i, operList: [ id ] } }) + const id = `${i + 1}`; + const op = SymmetryOperator.create(id, transforms[i], { assembly: { id, operId: i, operList: [ id ] } }); for (const unit of units) { - builder.addWithOperator(unit, op) + builder.addWithOperator(unit, op); } } @@ -156,51 +156,51 @@ function getAssembly(transforms: Mat4[], structure: Structure) { } function getCifCurve(name: string, transforms: Mat4[], model: Model) { - if (!MmcifFormat.is(model.sourceData)) throw new Error('mmcif source data needed') + if (!MmcifFormat.is(model.sourceData)) throw new Error('mmcif source data needed'); - const { db } = model.sourceData.data - const d = db.atom_site - const n = d._rowCount - const rowCount = n * transforms.length + const { db } = model.sourceData.data; + const d = db.atom_site; + const n = d._rowCount; + const rowCount = n * transforms.length; - const { offsets, count } = model.atomicHierarchy.chainAtomSegments + const { offsets, count } = model.atomicHierarchy.chainAtomSegments; - const x = d.Cartn_x.toArray() - const y = d.Cartn_y.toArray() - const z = d.Cartn_z.toArray() + const x = d.Cartn_x.toArray(); + const y = d.Cartn_y.toArray(); + const z = d.Cartn_z.toArray(); - const Cartn_x = new Float32Array(rowCount) - const Cartn_y = new Float32Array(rowCount) - const Cartn_z = new Float32Array(rowCount) - const map = new Uint32Array(rowCount) - const seq = new Int32Array(rowCount) - let offset = 0 + const Cartn_x = new Float32Array(rowCount); + const Cartn_y = new Float32Array(rowCount); + const Cartn_z = new Float32Array(rowCount); + const map = new Uint32Array(rowCount); + const seq = new Int32Array(rowCount); + let offset = 0; for (let c = 0; c < count; ++c) { - const cStart = offsets[c] - const cEnd = offsets[c + 1] - const cLength = cEnd - cStart + const cStart = offsets[c]; + const cEnd = offsets[c + 1]; + const cLength = cEnd - cStart; for (let t = 0, tl = transforms.length; t < tl; ++t) { - const m = transforms[t] + const m = transforms[t]; for (let j = cStart; j < cEnd; ++j) { - const i = offset + j - cStart - const xj = x[j], yj = y[j], zj = z[j] - Cartn_x[i] = m[0] * xj + m[4] * yj + m[8] * zj + m[12] - Cartn_y[i] = m[1] * xj + m[5] * yj + m[9] * zj + m[13] - Cartn_z[i] = m[2] * xj + m[6] * yj + m[10] * zj + m[14] - map[i] = j - seq[i] = t + 1 + const i = offset + j - cStart; + const xj = x[j], yj = y[j], zj = z[j]; + Cartn_x[i] = m[0] * xj + m[4] * yj + m[8] * zj + m[12]; + Cartn_y[i] = m[1] * xj + m[5] * yj + m[9] * zj + m[13]; + Cartn_z[i] = m[2] * xj + m[6] * yj + m[10] * zj + m[14]; + map[i] = j; + seq[i] = t + 1; } - offset += cLength + offset += cLength; } } function multColumn<T>(column: Column<T>) { - const array = column.toArray() + const array = column.toArray(); return Column.ofLambda({ value: row => array[map[row]], areValuesEqual: (rowA, rowB) => map[rowA] === map[rowB] || array[map[rowA]] === array[map[rowB]], rowCount, schema: column.schema - }) + }); } const _atom_site: CifCategory.SomeFields<mmCIF_Schema['atom_site']> = { @@ -233,13 +233,13 @@ function getCifCurve(name: string, transforms: Mat4[], model: Model) { pdbx_PDB_ins_code: CifField.ofColumn(Column.ofConst('', rowCount, Column.Schema.str)), pdbx_PDB_model_num: CifField.ofColumn(Column.ofConst(1, rowCount, Column.Schema.int)), - } + }; const categories = { entity: CifCategory.ofTable('entity', db.entity), chem_comp: CifCategory.ofTable('chem_comp', db.chem_comp), atom_site: CifCategory.ofFields('atom_site', _atom_site) - } + }; return { header: name, @@ -249,125 +249,125 @@ function getCifCurve(name: string, transforms: Mat4[], model: Model) { } async function getCurve(name: string, ingredient: Ingredient, transforms: Mat4[], model: Model) { - const cif = getCifCurve(name, transforms, model) + const cif = getCifCurve(name, transforms, model); const curveModelTask = Task.create('Curve Model', async ctx => { - const format = MmcifFormat.fromFrame(cif) - const models = await createModels(format.data.db, format, ctx) - return models[0] - }) + const format = MmcifFormat.fromFrame(cif); + const models = await createModels(format.data.db, format, ctx); + return models[0]; + }); - const curveModel = await curveModelTask.run() - return getStructure(curveModel, ingredient.source) + const curveModel = await curveModelTask.run(); + return getStructure(curveModel, ingredient.source); } async function getIngredientStructure(ingredient: Ingredient, baseUrl: string, ingredientFiles: IngredientFiles) { - const { name, source, results, nbCurve } = ingredient - if (source.pdb === 'None') return + const { name, source, results, nbCurve } = ingredient; + if (source.pdb === 'None') return; - const file = ingredientFiles[source.pdb] + const file = ingredientFiles[source.pdb]; if (!file) { // TODO can these be added to the library? - if (name === 'HIV1_CAhex_0_1_0') return - if (name === 'HIV1_CAhexCyclophilA_0_1_0') return - if (name === 'iLDL') return - if (name === 'peptides') return - if (name === 'lypoglycane') return + if (name === 'HIV1_CAhex_0_1_0') return; + if (name === 'HIV1_CAhexCyclophilA_0_1_0') return; + if (name === 'iLDL') return; + if (name === 'peptides') return; + if (name === 'lypoglycane') return; } // model id in case structure is NMR const model_id = (ingredient.source.model) ? parseInt(ingredient.source.model) : 0; - const model = await getModel(source.pdb || name, model_id, baseUrl, file) - if (!model) return + const model = await getModel(source.pdb || name, model_id, baseUrl, file); + if (!model) return; if (nbCurve) { - return getCurve(name, ingredient, getCurveTransforms(ingredient), model) + return getCurve(name, ingredient, getCurveTransforms(ingredient), model); } else { let bu: string|undefined = source.bu ? source.bu : undefined; if (bu){ if (bu === 'AU') { bu = undefined; } else { - bu = bu.slice(2) + bu = bu.slice(2); } } - let structure = await getStructure(model, source, { assembly: bu }) + let structure = await getStructure(model, source, { assembly: bu }); // transform with offset and pcp - let legacy: boolean = true + let legacy: boolean = true; if (ingredient.offset || ingredient.principalAxis){ // center the structure - legacy = false - const boundary = structure.boundary - let structureCenter: Vec3 = Vec3.zero() - Vec3.negate(structureCenter, boundary.sphere.center) - const m1: Mat4 = Mat4.identity() - Mat4.setTranslation(m1, structureCenter) - structure = Structure.transform(structure, m1) + legacy = false; + const boundary = structure.boundary; + let structureCenter: Vec3 = Vec3.zero(); + Vec3.negate(structureCenter, boundary.sphere.center); + const m1: Mat4 = Mat4.identity(); + Mat4.setTranslation(m1, structureCenter); + structure = Structure.transform(structure, m1); if (ingredient.offset){ if (!Vec3.exactEquals(ingredient.offset, Vec3.zero())){ const m: Mat4 = Mat4.identity(); - Mat4.setTranslation(m, ingredient.offset) + Mat4.setTranslation(m, ingredient.offset); structure = Structure.transform(structure, m); } } if (ingredient.principalAxis){ if (!Vec3.exactEquals(ingredient.principalAxis, Vec3.unitZ)){ const q: Quat = Quat.identity(); - Quat.rotationTo(q, ingredient.principalAxis, Vec3.unitZ) - const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q) + Quat.rotationTo(q, ingredient.principalAxis, Vec3.unitZ); + const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q); structure = Structure.transform(structure, m); } } } - return getAssembly(getResultTransforms(results, legacy), structure) + return getAssembly(getResultTransforms(results, legacy), structure); } } export function createStructureFromCellPack(packing: CellPacking, baseUrl: string, ingredientFiles: IngredientFiles) { return Task.create('Create Packing Structure', async ctx => { - const { ingredients, name } = packing - const structures: Structure[] = [] + const { ingredients, name } = packing; + const structures: Structure[] = []; for (const iName in ingredients) { - if (ctx.shouldUpdate) await ctx.update(iName) - const s = await getIngredientStructure(ingredients[iName], baseUrl, ingredientFiles) - if (s) structures.push(s) + if (ctx.shouldUpdate) await ctx.update(iName); + const s = await getIngredientStructure(ingredients[iName], baseUrl, ingredientFiles); + if (s) structures.push(s); } - if (ctx.shouldUpdate) await ctx.update(`${name} - units`) - const builder = Structure.Builder({ label: name }) - let offsetInvariantId = 0 + if (ctx.shouldUpdate) await ctx.update(`${name} - units`); + const builder = Structure.Builder({ label: name }); + let offsetInvariantId = 0; for (const s of structures) { - if (ctx.shouldUpdate) await ctx.update(`${s.label}`) - let maxInvariantId = 0 + if (ctx.shouldUpdate) await ctx.update(`${s.label}`); + let maxInvariantId = 0; for (const u of s.units) { - const invariantId = u.invariantId + offsetInvariantId - if (u.invariantId > maxInvariantId) maxInvariantId = u.invariantId - builder.addUnit(u.kind, u.model, u.conformation.operator, u.elements, Unit.Trait.None, invariantId) + const invariantId = u.invariantId + offsetInvariantId; + if (u.invariantId > maxInvariantId) maxInvariantId = u.invariantId; + builder.addUnit(u.kind, u.model, u.conformation.operator, u.elements, Unit.Trait.None, invariantId); } - offsetInvariantId += maxInvariantId + 1 + offsetInvariantId += maxInvariantId + 1; } - if (ctx.shouldUpdate) await ctx.update(`${name} - structure`) - const s = builder.getStructure() + if (ctx.shouldUpdate) await ctx.update(`${name} - structure`); + const s = builder.getStructure(); for( let i = 0, il = s.models.length; i < il; ++i) { - const { trajectoryInfo } = s.models[i] - trajectoryInfo.size = il - trajectoryInfo.index = i + const { trajectoryInfo } = s.models[i]; + trajectoryInfo.size = il; + trajectoryInfo.index = i; } - return s - }) + return s; + }); } async function handleHivRna(ctx: { runtime: RuntimeContext, fetch: AjaxTask }, packings: CellPacking[], baseUrl: string) { for (let i = 0, il = packings.length; i < il; ++i) { if (packings[i].name === 'HIV1_capsid_3j3q_PackInner_0_1_0') { - const url = `${baseUrl}/extras/rna_allpoints.json` + const url = `${baseUrl}/extras/rna_allpoints.json`; const data = await ctx.fetch({ url, type: 'string' }).runInContext(ctx.runtime); - const { points } = await (new Response(data)).json() as { points: number[] } + const { points } = await (new Response(data)).json() as { points: number[] }; - const curve0: Vec3[] = [] + const curve0: Vec3[] = []; for (let j = 0, jl = points.length; j < jl; j += 3) { - curve0.push(Vec3.fromArray(Vec3(), points, j)) + curve0.push(Vec3.fromArray(Vec3(), points, j)); } packings[i].ingredients['RNA'] = { source: { pdb: 'RNA_U_Base.pdb', transform: { center: false } }, @@ -375,106 +375,106 @@ async function handleHivRna(ctx: { runtime: RuntimeContext, fetch: AjaxTask }, p name: 'RNA', nbCurve: 1, curve0 - } + }; } } } async function loadMembrane(name: string, plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) { - const fname: string = `${name}.bcif` - let ingredientFiles: IngredientFiles = {} + const fname: string = `${name}.bcif`; + let ingredientFiles: IngredientFiles = {}; if (params.ingredients.files !== null) { for (let i = 0, il = params.ingredients.files.length; i < il; ++i) { - const file = params.ingredients.files.item(i) - if (file) ingredientFiles[file.name] = file + const file = params.ingredients.files.item(i); + if (file) ingredientFiles[file.name] = file; } } - let b = state.build().toRoot() + let b = state.build().toRoot(); if (fname in ingredientFiles) { const file = ingredientFiles[fname]; - b = b.apply(StateTransforms.Data.ReadFile, { file, isBinary: true, label: file.name }, { state: { isGhost: true } }) + b = b.apply(StateTransforms.Data.ReadFile, { file, isBinary: true, label: file.name }, { state: { isGhost: true } }); } else { - const url = `${params.baseUrl}/membranes/${name}.bcif` - b = b.apply(StateTransforms.Data.Download, { url, isBinary: true, label: name }, { state: { isGhost: true } }) + const url = `${params.baseUrl}/membranes/${name}.bcif`; + b = b.apply(StateTransforms.Data.Download, { url, isBinary: true, label: name }, { state: { isGhost: true } }); } const membrane = await b.apply(StateTransforms.Data.ParseCif, undefined, { state: { isGhost: true } }) .apply(StateTransforms.Model.TrajectoryFromMmCif, undefined, { state: { isGhost: true } }) .apply(StateTransforms.Model.ModelFromTrajectory, undefined, { state: { isGhost: true } }) .apply(StateTransforms.Model.StructureFromModel) - .commit() + .commit(); const membraneParams = { representation: params.preset.representation, - } - await CellpackMembranePreset.apply(membrane, membraneParams, plugin) + }; + await CellpackMembranePreset.apply(membrane, membraneParams, plugin); } async function loadHivMembrane(plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) { - const url = `${params.baseUrl}/membranes/hiv_lipids.bcif` + const url = `${params.baseUrl}/membranes/hiv_lipids.bcif`; const membrane = await state.build().toRoot() .apply(StateTransforms.Data.Download, { label: 'hiv_lipids', url, isBinary: true }, { state: { isGhost: true } }) .apply(StateTransforms.Data.ParseCif, undefined, { state: { isGhost: true } }) .apply(StateTransforms.Model.TrajectoryFromMmCif, undefined, { state: { isGhost: true } }) .apply(StateTransforms.Model.ModelFromTrajectory, undefined, { state: { isGhost: true } }) .apply(StateTransforms.Model.StructureFromModel) - .commit() + .commit(); const membraneParams = { representation: params.preset.representation, - } + }; - await CellpackMembranePreset.apply(membrane, membraneParams, plugin) + await CellpackMembranePreset.apply(membrane, membraneParams, plugin); } async function loadPackings(plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) { - let cellPackJson: StateBuilder.To<PSO.Format.Json, StateTransformer<PSO.Data.String, PSO.Format.Json>> + let cellPackJson: StateBuilder.To<PSO.Format.Json, StateTransformer<PSO.Data.String, PSO.Format.Json>>; if (params.source.name === 'id') { - const url = getCellPackModelUrl(params.source.params, params.baseUrl) + const url = getCellPackModelUrl(params.source.params, params.baseUrl); cellPackJson = state.build().toRoot() - .apply(StateTransforms.Data.Download, { url, isBinary: false, label: params.source.params }, { state: { isGhost: true } }) + .apply(StateTransforms.Data.Download, { url, isBinary: false, label: params.source.params }, { state: { isGhost: true } }); } else { - const file = params.source.params + const file = params.source.params; if (file === null) { - plugin.log.error('No file selected') - return + plugin.log.error('No file selected'); + return; } cellPackJson = state.build().toRoot() - .apply(StateTransforms.Data.ReadFile, { file, isBinary: false, label: file.name }, { state: { isGhost: true } }) + .apply(StateTransforms.Data.ReadFile, { file, isBinary: false, label: file.name }, { state: { isGhost: true } }); } const cellPackBuilder = cellPackJson .apply(StateTransforms.Data.ParseJson, undefined, { state: { isGhost: true } }) - .apply(ParseCellPack) + .apply(ParseCellPack); - const cellPackObject = await state.updateTree(cellPackBuilder).runInContext(runtime) - const { packings } = cellPackObject.obj!.data + const cellPackObject = await state.updateTree(cellPackBuilder).runInContext(runtime); + const { packings } = cellPackObject.obj!.data; - await handleHivRna({ runtime, fetch: plugin.fetch }, packings, params.baseUrl) + await handleHivRna({ runtime, fetch: plugin.fetch }, packings, params.baseUrl); for (let i = 0, il = packings.length; i < il; ++i) { - const p = { packing: i, baseUrl: params.baseUrl, ingredientFiles: params.ingredients.files } + const p = { packing: i, baseUrl: params.baseUrl, ingredientFiles: params.ingredients.files }; const packing = await state.build() .to(cellPackBuilder.ref) .apply(StructureFromCellpack, p) - .commit({ revertOnError: true }) + .commit({ revertOnError: true }); - const structure = packing.obj?.data + const structure = packing.obj?.data; if (structure) { await CellPackInfoProvider.attach({ fetch: plugin.fetch, runtime }, structure, { info: { packingsCount: packings.length, packingIndex: i } - }) + }); } const packingParams = { traceOnly: params.preset.traceOnly, representation: params.preset.representation, - } - await CellpackPackingPreset.apply(packing, packingParams, plugin) + }; + await CellpackPackingPreset.apply(packing, packingParams, plugin); if ( packings[i].location === 'surface' ){ - await loadMembrane(packings[i].name, plugin, runtime, state, params) + await loadMembrane(packings[i].name, plugin, runtime, state, params); } } } @@ -500,7 +500,7 @@ const LoadCellPackModelParams = { traceOnly: PD.Boolean(false), representation: PD.Select('gaussian-surface', PD.arrayToOptions(['spacefill', 'gaussian-surface', 'point', 'ellipsoid'])) }, { isExpanded: true }) -} +}; type LoadCellPackModelParams = PD.Values<typeof LoadCellPackModelParams> export const LoadCellPackModel = StateAction.build({ @@ -509,12 +509,12 @@ export const LoadCellPackModel = StateAction.build({ from: PSO.Root })(({ state, params }, ctx: PluginContext) => Task.create('CellPack Loader', async taskCtx => { if (!ctx.representation.structure.themes.colorThemeRegistry.has(CellPackColorThemeProvider)) { - ctx.representation.structure.themes.colorThemeRegistry.add(CellPackColorThemeProvider) + ctx.representation.structure.themes.colorThemeRegistry.add(CellPackColorThemeProvider); } if (params.source.name === 'id' && params.source.params === 'hiv_lipids.bcif') { - await loadHivMembrane(ctx, taskCtx, state, params) + await loadHivMembrane(ctx, taskCtx, state, params); } else { - await loadPackings(ctx, taskCtx, state, params) + await loadPackings(ctx, taskCtx, state, params); } })); \ No newline at end of file diff --git a/src/apps/viewer/extensions/cellpack/preset.ts b/src/apps/viewer/extensions/cellpack/preset.ts index fd6a2361da6931152d0ea1d692906d1a454e9f1e..3ce35d6253979c61da58fb364dd6120578534f43 100644 --- a/src/apps/viewer/extensions/cellpack/preset.ts +++ b/src/apps/viewer/extensions/cellpack/preset.ts @@ -13,7 +13,7 @@ import { CellPackColorThemeProvider } from './color'; export const CellpackPackingPresetParams = { traceOnly: PD.Boolean(true), representation: PD.Select('gaussian-surface', PD.arrayToOptions(['gaussian-surface', 'spacefill', 'point', 'orientation'])), -} +}; export type CellpackPackingPresetParams = PD.ValuesFor<typeof CellpackPackingPresetParams> export const CellpackPackingPreset = StructureRepresentationPresetProvider({ @@ -35,18 +35,18 @@ export const CellpackPackingPreset = StructureRepresentationPresetProvider({ if (params.representation === 'gaussian-surface') { Object.assign(reprProps, { quality: 'custom', resolution: 10, radiusOffset: 2, doubleSided: false - }) + }); } else if (params.representation === 'spacefill' && params.traceOnly) { - Object.assign(reprProps, { sizeFactor: 2 }) + Object.assign(reprProps, { sizeFactor: 2 }); } const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, {}); - const color = CellPackColorThemeProvider.name + const color = CellPackColorThemeProvider.name; const representations = { polymer: builder.buildRepresentation<any>(update, components.polymer, { type: params.representation, typeParams: { ...typeParams, ...reprProps }, color }, { tag: 'polymer' }) }; - await update.commit({ revertOnError: true }) + await update.commit({ revertOnError: true }); return { components, representations }; } }); @@ -55,7 +55,7 @@ export const CellpackPackingPreset = StructureRepresentationPresetProvider({ export const CellpackMembranePresetParams = { representation: PD.Select('gaussian-surface', PD.arrayToOptions(['gaussian-surface', 'spacefill', 'point', 'orientation'])), -} +}; export type CellpackMembranePresetParams = PD.ValuesFor<typeof CellpackMembranePresetParams> export const CellpackMembranePreset = StructureRepresentationPresetProvider({ @@ -76,7 +76,7 @@ export const CellpackMembranePreset = StructureRepresentationPresetProvider({ if (params.representation === 'gaussian-surface') { Object.assign(reprProps, { quality: 'custom', resolution: 10, radiusOffset: 2, doubleSided: false - }) + }); } const { update, builder, typeParams } = StructureRepresentationPresetProvider.reprBuilder(plugin, {}); @@ -84,7 +84,7 @@ export const CellpackMembranePreset = StructureRepresentationPresetProvider({ membrane: builder.buildRepresentation(update, components.membrane, { type: 'gaussian-surface', typeParams: { ...typeParams, ...reprProps }, color: 'uniform', colorParams: { value: ColorNames.lightgrey } }, { tag: 'all' }) }; - await update.commit({ revertOnError: true }) + await update.commit({ revertOnError: true }); return { components, representations }; } }); \ No newline at end of file diff --git a/src/apps/viewer/extensions/cellpack/property.ts b/src/apps/viewer/extensions/cellpack/property.ts index 2e670ffb97ed08211a683ad0ee6cf5cceb836a64..10a63ab4017adc3bdf5e633da68af42de7bd5ee4 100644 --- a/src/apps/viewer/extensions/cellpack/property.ts +++ b/src/apps/viewer/extensions/cellpack/property.ts @@ -4,10 +4,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { CustomStructureProperty } from '../../../../mol-model-props/common/custom-structure-property' -import { Structure, CustomPropertyDescriptor } from '../../../../mol-model/structure' -import { CustomProperty } from '../../../../mol-model-props/common/custom-property' -import { ParamDefinition as PD } from '../../../../mol-util/param-definition' +import { CustomStructureProperty } from '../../../../mol-model-props/common/custom-structure-property'; +import { Structure, CustomPropertyDescriptor } from '../../../../mol-model/structure'; +import { CustomProperty } from '../../../../mol-model-props/common/custom-property'; +import { ParamDefinition as PD } from '../../../../mol-util/param-definition'; export type CellPackInfoValue = { packingsCount: number @@ -16,7 +16,7 @@ export type CellPackInfoValue = { const CellPackInfoParams = { info: PD.Value<CellPackInfoValue>({ packingsCount: 1, packingIndex: 0 }, { isHidden: true }) -} +}; type CellPackInfoParams = PD.Values<typeof CellPackInfoParams> export const CellPackInfoProvider: CustomStructureProperty.Provider<typeof CellPackInfoParams, CellPackInfoValue> = CustomStructureProperty.createProvider({ @@ -27,6 +27,6 @@ export const CellPackInfoProvider: CustomStructureProperty.Provider<typeof CellP getParams: (data: Structure) => CellPackInfoParams, isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure, props: CellPackInfoParams) => { - return { ...CellPackInfoParams.info.defaultValue, ...props.info } + return { ...CellPackInfoParams.info.defaultValue, ...props.info }; } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/apps/viewer/extensions/cellpack/state.ts b/src/apps/viewer/extensions/cellpack/state.ts index 9908ede2657560f99f05847ea0f042e4453fc9bf..11be3241c9279e466fcd37302085bc43393e8b9b 100644 --- a/src/apps/viewer/extensions/cellpack/state.ts +++ b/src/apps/viewer/extensions/cellpack/state.ts @@ -11,11 +11,11 @@ import { CellPack as _CellPack, Cell, CellPacking } from './data'; import { createStructureFromCellPack } from './model'; import { IngredientFiles } from './util'; -export const DefaultCellPackBaseUrl = 'https://mesoscope.scripps.edu/data/cellPACK_data/cellPACK_database_1.1.0/' +export const DefaultCellPackBaseUrl = 'https://mesoscope.scripps.edu/data/cellPACK_data/cellPACK_database_1.1.0/'; export class CellPack extends PSO.Create<_CellPack>({ name: 'CellPack', typeClass: 'Object' }) { } -export { ParseCellPack } +export { ParseCellPack }; type ParseCellPack = typeof ParseCellPack const ParseCellPack = PluginStateTransform.BuiltIn({ name: 'parse-cellpack', @@ -25,25 +25,25 @@ const ParseCellPack = PluginStateTransform.BuiltIn({ })({ apply({ a }) { return Task.create('Parse CellPack', async ctx => { - const cell = a.data as Cell + const cell = a.data as Cell; - const packings: CellPacking[] = [] - const { compartments, cytoplasme } = cell + const packings: CellPacking[] = []; + const { compartments, cytoplasme } = cell; if (compartments) { for (const name in compartments) { - const { surface, interior } = compartments[name] - if (surface) packings.push({ name, location: 'surface', ingredients: surface.ingredients }) - if (interior) packings.push({ name, location: 'interior', ingredients: interior.ingredients }) + const { surface, interior } = compartments[name]; + if (surface) packings.push({ name, location: 'surface', ingredients: surface.ingredients }); + if (interior) packings.push({ name, location: 'interior', ingredients: interior.ingredients }); } } - if (cytoplasme) packings.push({ name: 'Cytoplasme', location: 'cytoplasme', ingredients: cytoplasme.ingredients }) + if (cytoplasme) packings.push({ name: 'Cytoplasme', location: 'cytoplasme', ingredients: cytoplasme.ingredients }); return new CellPack({ cell, packings }); }); } }); -export { StructureFromCellpack } +export { StructureFromCellpack }; type StructureFromCellpack = typeof ParseCellPack const StructureFromCellpack = PluginStateTransform.BuiltIn({ name: 'structure-from-cellpack', @@ -58,26 +58,26 @@ const StructureFromCellpack = PluginStateTransform.BuiltIn({ ingredientFiles: PD.FileList({ accept: '.cif,.pdb' }) }; } - const options = a.data.packings.map((d, i) => [i, d.name] as [number, string]) + const options = a.data.packings.map((d, i) => [i, d.name] as [number, string]); return { packing: PD.Select(0, options), baseUrl: PD.Text(DefaultCellPackBaseUrl), ingredientFiles: PD.FileList({ accept: '.cif,.pdb' }) - } + }; } })({ apply({ a, params }) { return Task.create('Structure from CellPack', async ctx => { - const packing = a.data.packings[params.packing] - const ingredientFiles: IngredientFiles = {} + const packing = a.data.packings[params.packing]; + const ingredientFiles: IngredientFiles = {}; if (params.ingredientFiles !== null) { for (let i = 0, il = params.ingredientFiles.length; i < il; ++i) { - const file = params.ingredientFiles.item(i) - if (file) ingredientFiles[file.name] = file + const file = params.ingredientFiles.item(i); + if (file) ingredientFiles[file.name] = file; } } - const structure = await createStructureFromCellPack(packing, params.baseUrl, ingredientFiles).runInContext(ctx) - return new PSO.Molecule.Structure(structure, { label: packing.name }) + const structure = await createStructureFromCellPack(packing, params.baseUrl, ingredientFiles).runInContext(ctx); + return new PSO.Molecule.Structure(structure, { label: packing.name }); }); } }); \ No newline at end of file diff --git a/src/apps/viewer/extensions/cellpack/util.ts b/src/apps/viewer/extensions/cellpack/util.ts index 4c36a142b6e00ee79cd384e447660a599ab1da61..127e80fcc59e57953e8f0f8cf426089e0924fafd 100644 --- a/src/apps/viewer/extensions/cellpack/util.ts +++ b/src/apps/viewer/extensions/cellpack/util.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { CIF } from '../../../../mol-io/reader/cif' +import { CIF } from '../../../../mol-io/reader/cif'; import { parsePDB } from '../../../../mol-io/reader/pdb/parser'; export async function parseCif(data: string|Uint8Array) { @@ -37,12 +37,12 @@ export async function getFromPdb(id: string) { } function getCellPackDataUrl(id: string, baseUrl: string) { - const url = `${baseUrl}/other/${id}` - return url.endsWith('.pdb') ? url : `${url}.pdb` + const url = `${baseUrl}/other/${id}`; + return url.endsWith('.pdb') ? url : `${url}.pdb`; } export async function getFromCellPackDB(id: string, baseUrl: string) { - const name = id.endsWith('.pdb') ? id.substring(0, id.length - 4) : id + const name = id.endsWith('.pdb') ? id.substring(0, id.length - 4) : id; const parsed = await downloadPDB(getCellPackDataUrl(id, baseUrl), name); return parsed; } diff --git a/src/apps/viewer/index.ts b/src/apps/viewer/index.ts index 329610b2b7903f1b5335b3796334fe3a11bf3461..5dd4449c6ae56796b1071bac104b03dd66ad7c1c 100644 --- a/src/apps/viewer/index.ts +++ b/src/apps/viewer/index.ts @@ -7,8 +7,8 @@ import '../../mol-util/polyfill'; import { createPlugin, DefaultPluginSpec } from '../../mol-plugin'; -import './index.html' -import './favicon.ico' +import './index.html'; +import './favicon.ico'; import { PluginContext } from '../../mol-plugin/context'; import { PluginCommands } from '../../mol-plugin/commands'; import { PluginSpec } from '../../mol-plugin/spec'; @@ -16,7 +16,7 @@ import { LoadCellPackModel } from './extensions/cellpack/model'; import { StructureFromCellpack } from './extensions/cellpack/state'; import { DownloadStructure } from '../../mol-plugin-state/actions/structure'; import { PluginConfig } from '../../mol-plugin/config'; -require('mol-plugin-ui/skin/light.scss') +require('mol-plugin-ui/skin/light.scss'); function getParam(name: string, regex: string): string { let r = new RegExp(`${name}=(${regex})[&]?`, 'i'); @@ -62,7 +62,7 @@ async function trySetSnapshot(ctx: PluginContext) { const url = snapshotId ? `https://webchem.ncbr.muni.cz/molstar-state/get/${snapshotId}` : snapshotUrl; - await PluginCommands.State.Snapshots.Fetch(ctx, { url }) + await PluginCommands.State.Snapshots.Fetch(ctx, { url }); } catch (e) { ctx.log.error('Failed to load snapshot.'); console.warn('Failed to load snapshot', e); diff --git a/src/examples/basic-wrapper/coloring.ts b/src/examples/basic-wrapper/coloring.ts index d3348197ccf1058c339688506a3b831ea550f3e1..0b5fe352b1bcd605b54e7e9ca23ef7a5d0ddf110 100644 --- a/src/examples/basic-wrapper/coloring.ts +++ b/src/examples/basic-wrapper/coloring.ts @@ -21,10 +21,10 @@ export const StripedResidues = CustomElementProperty.create<number>({ return map; }, coloring: { - getColor(e) { return e === 0 ? Color(0xff0000) : Color(0x0000ff) }, + getColor(e) { return e === 0 ? Color(0xff0000) : Color(0x0000ff); }, defaultColor: Color(0x777777) }, getLabel(e) { - return e === 0 ? 'Odd stripe' : 'Even stripe' + return e === 0 ? 'Odd stripe' : 'Even stripe'; } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/examples/basic-wrapper/index.ts b/src/examples/basic-wrapper/index.ts index 4fed9b455644763a68fd4bb11837dafcb85cb3c9..9abaae674faf0a0acc23ec4afc1c7f285f891d10 100644 --- a/src/examples/basic-wrapper/index.ts +++ b/src/examples/basic-wrapper/index.ts @@ -19,7 +19,7 @@ import { StripedResidues } from './coloring'; import { CustomToastMessage } from './controls'; import './index.html'; import { buildStaticSuperposition, dynamicSuperpositionTest, StaticSuperpositionTestData } from './superposition'; -require('mol-plugin-ui/skin/light.scss') +require('mol-plugin-ui/skin/light.scss'); type LoadParams = { url: string, format?: BuiltInTrajectoryFormat, isBinary?: boolean, assemblyId?: string } @@ -62,7 +62,7 @@ class BasicWrapper { } setBackground(color: number) { - PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: props => { props.renderer.backgroundColor = Color(color) } }); + PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: props => { props.renderer.backgroundColor = Color(color); } }); } toggleSpin() { @@ -79,10 +79,10 @@ class BasicWrapper { animate = { modelIndex: { maxFPS: 8, - onceForward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }) }, - onceBackward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }) }, - palindrome: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }) }, - loop: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }) }, + onceForward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); }, + onceBackward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); }, + palindrome: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); }, + loop: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); }, stop: () => this.plugin.state.animation.stop() } } @@ -91,14 +91,14 @@ class BasicWrapper { applyStripes: async () => { this.plugin.dataTransaction(async () => { for (const s of this.plugin.managers.structure.hierarchy.current.structures) { - await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: StripedResidues.propertyProvider.descriptor.name as any }) + await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: StripedResidues.propertyProvider.descriptor.name as any }); } }); }, applyDefault: async () => { this.plugin.dataTransaction(async () => { for (const s of this.plugin.managers.structure.hierarchy.current.structures) { - await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: 'default' }) + await this.plugin.managers.structure.component.updateRepresentationsTheme(s.components, { color: 'default' }); } }); } @@ -130,7 +130,7 @@ class BasicWrapper { return dynamicSuperpositionTest(this.plugin, ['1tqn', '2hhb', '4hhb'], 'HEM'); }, toggleValidationTooltip: () => { - return this.plugin.state.updateBehavior(PDBeStructureQualityReport, params => { params.showTooltip = !params.showTooltip }); + return this.plugin.state.updateBehavior(PDBeStructureQualityReport, params => { params.showTooltip = !params.showTooltip; }); }, showToasts: () => { PluginCommands.Toast.Show(this.plugin, { diff --git a/src/examples/basic-wrapper/superposition.ts b/src/examples/basic-wrapper/superposition.ts index 9c45bc0391b5bae28bc76d93db28636114c3f5ba..7eac5b49e72edb5eadc4cd92a0d8245c2be9af62 100644 --- a/src/examples/basic-wrapper/superposition.ts +++ b/src/examples/basic-wrapper/superposition.ts @@ -30,7 +30,7 @@ export function buildStaticSuperposition(plugin: PluginContext, src: Superpositi const chain = await plugin.builders.structure.tryCreateComponentFromExpression(structure, chainSelection(s.auth_asym_id), `Chain ${s.auth_asym_id}`); if (chain) await plugin.builders.structure.representation.addRepresentation(chain, { type: 'cartoon' }); } - }) + }); } export const StaticSuperpositionTestData: SuperpositionTestInput = [ diff --git a/src/examples/domain-annotation-server/mapping.ts b/src/examples/domain-annotation-server/mapping.ts index 094ccf7d29e6c8174c51ebb5c827a5f48b9fd48c..468fb14ebaa84c07c0280e262ff90d129ef4f459 100644 --- a/src/examples/domain-annotation-server/mapping.ts +++ b/src/examples/domain-annotation-server/mapping.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Table } from '../../mol-data/db' -import { CifWriter } from '../../mol-io/writer/cif' -import * as S from './schemas' +import { Table } from '../../mol-data/db'; +import { CifWriter } from '../../mol-io/writer/cif'; +import * as S from './schemas'; // import { getCategoryInstanceProvider } from './utils' export default function create(allData: any) { diff --git a/src/examples/domain-annotation-server/schemas.ts b/src/examples/domain-annotation-server/schemas.ts index 3384e77795f11ce41c624a9100032a44a1f76021..34e1489a256c702789b6b3ce01c5cc7e45fd98f4 100644 --- a/src/examples/domain-annotation-server/schemas.ts +++ b/src/examples/domain-annotation-server/schemas.ts @@ -4,21 +4,21 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column } from '../../mol-data/db' +import { Column } from '../../mol-data/db'; import Type = Column.Schema export const Sources = { id: Type.str, count: Type.int -} +}; export type Sources = typeof Sources export const Base = { id: Type.str, identifier: Type.str, mapping_group_id: Type.int -} +}; export type Base = typeof Base export const mapping = { @@ -36,17 +36,17 @@ export const mapping = { end_label_seq_id: Type.int, end_auth_seq_id: Type.int, pdbx_end_PDB_ins_code: Type.str -} +}; export type mapping = typeof mapping export const Pfam = { description: Type.str -} +}; export type Pfam = typeof Pfam export const InterPro = { name: Type.str -} +}; export type InterPro = typeof InterPro export const CATH = { @@ -56,32 +56,32 @@ export const CATH = { identifier: Type.str, class: Type.str, topology: Type.str, -} +}; export type CATH = typeof CATH export const EC = { accepted_name: Type.str, reaction: Type.str, systematic_name: Type.str -} +}; export type EC = typeof EC export const UniProt = { name: Type.str -} +}; export type UniProt = typeof UniProt export const SCOP = { sccs: Type.str, description: Type.str -} +}; export type SCOP = typeof SCOP export const GO = { category: Type.str, definition: Type.str, name: Type.str -} +}; export type GO = typeof GO export const categories = { @@ -92,4 +92,4 @@ export const categories = { UniProt, SCOP, GO -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/examples/domain-annotation-server/server.ts b/src/examples/domain-annotation-server/server.ts index 4758a4d07e01da4598117900530aff40722334e8..bda931c690bd415017ecaf694f46895340be2b09 100644 --- a/src/examples/domain-annotation-server/server.ts +++ b/src/examples/domain-annotation-server/server.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import express from 'express' -import fetch from 'node-fetch' -import createMapping from './mapping' +import express from 'express'; +import fetch from 'node-fetch'; +import createMapping from './mapping'; async function getMappings(id: string) { const data = await fetch(`https://www.ebi.ac.uk/pdbe/api/mappings/${id}`); @@ -19,7 +19,7 @@ let PORT = process.env.port || 1338; const app = express(); -const PREFIX = '/' +const PREFIX = '/'; app.get(`${PREFIX}/:id`, async (req, res) => { try { @@ -41,7 +41,7 @@ app.get(`${PREFIX}/:id`, async (req, res) => { app.get(`${PREFIX}`, (req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end('Usage: /pdb_id, e.g. /1tqn'); -}) +}); app.listen(PORT); diff --git a/src/examples/domain-annotation-server/test.ts b/src/examples/domain-annotation-server/test.ts index 66911dec6ce7484f2bd24bc3784b126cbe974259..09d007b180d5cdedece03d4e90a95212abf4af04 100644 --- a/src/examples/domain-annotation-server/test.ts +++ b/src/examples/domain-annotation-server/test.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import fetch from 'node-fetch' -import createMapping from './mapping' +import fetch from 'node-fetch'; +import createMapping from './mapping'; (async function () { const data = await fetch('https://www.ebi.ac.uk/pdbe/api/mappings/1tqn?pretty=true'); diff --git a/src/examples/lighting/index.ts b/src/examples/lighting/index.ts index 3c52b3e5d855907624990ab0f96a990f73e8179a..941c843a05e2fa15132d1a35e58b0101afb4e6eb 100644 --- a/src/examples/lighting/index.ts +++ b/src/examples/lighting/index.ts @@ -10,7 +10,7 @@ import { BuiltInTrajectoryFormat } from '../../mol-plugin-state/formats/trajecto import { PluginCommands } from '../../mol-plugin/commands'; import { PluginContext } from '../../mol-plugin/context'; import './index.html'; -require('mol-plugin-ui/skin/light.scss') +require('mol-plugin-ui/skin/light.scss'); type LoadParams = { url: string, format?: BuiltInTrajectoryFormat, isBinary?: boolean, assemblyId?: string } @@ -57,7 +57,7 @@ const Canvas3DPresets = { lightIntensity: 0.6, } } -} +}; type Canvas3DPreset = keyof typeof Canvas3DPresets @@ -80,7 +80,7 @@ class LightingDemo { } setPreset(preset: Canvas3DPreset) { - const props = Canvas3DPresets[preset] + const props = Canvas3DPresets[preset]; PluginCommands.Canvas3D.SetSettings(this.plugin, { settings: { ...props, multiSample: { diff --git a/src/examples/proteopedia-wrapper/annotation.ts b/src/examples/proteopedia-wrapper/annotation.ts index 055b15cf7d25b2523b603f673b91fdd23aa8100a..647d0f6032858d7f31adc55e2b8a58f64b56efec 100644 --- a/src/examples/proteopedia-wrapper/annotation.ts +++ b/src/examples/proteopedia-wrapper/annotation.ts @@ -30,8 +30,8 @@ export const EvolutionaryConservation = CustomElementProperty.create<number>({ type: 'static', async getData(model: Model, ctx: CustomProperty.Context) { const id = model.entryId.toLowerCase(); - const url = `https://proteopedia.org/cgi-bin/cnsrf?${id}` - const json = await ctx.fetch({ url, type: 'json' }).runInContext(ctx.runtime) + const url = `https://proteopedia.org/cgi-bin/cnsrf?${id}`; + const json = await ctx.fetch({ url, type: 'json' }).runInContext(ctx.runtime); const annotations = (json && json.residueAnnotations) || []; const conservationMap = new Map<string, number>(); diff --git a/src/examples/proteopedia-wrapper/coloring.ts b/src/examples/proteopedia-wrapper/coloring.ts index 2eb6d9e80cc9d175f53269e2133c2d343010afd6..9274ffd05e249747cc912cd3cac17376a9f5507a 100644 --- a/src/examples/proteopedia-wrapper/coloring.ts +++ b/src/examples/proteopedia-wrapper/coloring.ts @@ -11,58 +11,58 @@ import { Unit, StructureProperties, StructureElement, Bond } from '../../mol-mod import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../../mol-theme/color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { Column } from '../../mol-data/db'; -const Description = 'Gives every chain a color from a list based on its `asym_id` value.' +const Description = 'Gives every chain a color from a list based on its `asym_id` value.'; export function createProteopediaCustomTheme(colors: number[]) { const ProteopediaCustomColorThemeParams = { colors: PD.ObjectList({ color: PD.Color(Color(0xffffff)) }, ({ color }) => Color.toHexString(color), { defaultValue: colors.map(c => ({ color: Color(c) })) }) - } + }; type ProteopediaCustomColorThemeParams = typeof ProteopediaCustomColorThemeParams function getChainIdColorThemeParams(ctx: ThemeDataContext) { - return ProteopediaCustomColorThemeParams // TODO return copy + return ProteopediaCustomColorThemeParams; // TODO return copy } function getAsymId(unit: Unit): StructureElement.Property<string> { switch (unit.kind) { case Unit.Kind.Atomic: - return StructureProperties.chain.label_asym_id + return StructureProperties.chain.label_asym_id; case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return StructureProperties.coarse.asym_id + return StructureProperties.coarse.asym_id; } } function addAsymIds(map: Map<string, number>, data: Column<string>) { - let j = map.size + let j = map.size; for (let o = 0, ol = data.rowCount; o < ol; ++o) { - const k = data.value(o) + const k = data.value(o); if (!map.has(k)) { - map.set(k, j) - j += 1 + map.set(k, j); + j += 1; } } } function ProteopediaCustomColorTheme(ctx: ThemeDataContext, props: PD.Values<ProteopediaCustomColorThemeParams>): ColorTheme<ProteopediaCustomColorThemeParams> { - let color: LocationColor + let color: LocationColor; const colors = props.colors, colorCount = colors.length, defaultColor = colors[0].color; if (ctx.structure) { - const l = StructureElement.Location.create(ctx.structure) - const { models } = ctx.structure - const asymIdSerialMap = new Map<string, number>() + const l = StructureElement.Location.create(ctx.structure); + const { models } = ctx.structure; + const asymIdSerialMap = new Map<string, number>(); for (let i = 0, il = models.length; i < il; ++i) { - const m = models[i] - addAsymIds(asymIdSerialMap, m.atomicHierarchy.chains.label_asym_id) + const m = models[i]; + addAsymIds(asymIdSerialMap, m.atomicHierarchy.chains.label_asym_id); if (m.coarseHierarchy.isDefined) { - addAsymIds(asymIdSerialMap, m.coarseHierarchy.spheres.asym_id) - addAsymIds(asymIdSerialMap, m.coarseHierarchy.gaussians.asym_id) + addAsymIds(asymIdSerialMap, m.coarseHierarchy.spheres.asym_id); + addAsymIds(asymIdSerialMap, m.coarseHierarchy.gaussians.asym_id); } } @@ -72,16 +72,16 @@ export function createProteopediaCustomTheme(colors: number[]) { const o = asymIdSerialMap.get(asym_id(location)) || 0; return colors[o % colorCount].color; } else if (Bond.isLocation(location)) { - const asym_id = getAsymId(location.aUnit) - l.unit = location.aUnit - l.element = location.aUnit.elements[location.aIndex] + const asym_id = getAsymId(location.aUnit); + l.unit = location.aUnit; + l.element = location.aUnit.elements[location.aIndex]; const o = asymIdSerialMap.get(asym_id(l)) || 0; return colors[o % colorCount].color; } - return defaultColor - } + return defaultColor; + }; } else { - color = () => defaultColor + color = () => defaultColor; } return { @@ -91,7 +91,7 @@ export function createProteopediaCustomTheme(colors: number[]) { props, description: Description, legend: undefined - } + }; } return { @@ -102,5 +102,5 @@ export function createProteopediaCustomTheme(colors: number[]) { getParams: getChainIdColorThemeParams, defaultValues: PD.getDefaultValues(ProteopediaCustomColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure - } + }; } \ No newline at end of file diff --git a/src/examples/proteopedia-wrapper/helpers.ts b/src/examples/proteopedia-wrapper/helpers.ts index ca20703c2390805233983f81b494314b524fcb58..8f736506035984a4a4ecc437b65f19b3ed4cfede 100644 --- a/src/examples/proteopedia-wrapper/helpers.ts +++ b/src/examples/proteopedia-wrapper/helpers.ts @@ -70,7 +70,7 @@ export namespace ModelInfo { } const preferredAssemblyId = await pref; - const symmetry = ModelSymmetry.Provider.get(model) + const symmetry = ModelSymmetry.Provider.get(model); return { hetResidues: hetResidues, diff --git a/src/examples/proteopedia-wrapper/index.ts b/src/examples/proteopedia-wrapper/index.ts index 81bc45633da991964f2c8cbb9bacdf19ecc99696..66d298d241e663388d2045c79a6ff25b21737a67 100644 --- a/src/examples/proteopedia-wrapper/index.ts +++ b/src/examples/proteopedia-wrapper/index.ts @@ -6,7 +6,7 @@ import * as ReactDOM from 'react-dom'; import { createPlugin, DefaultPluginSpec } from '../../mol-plugin'; -import './index.html' +import './index.html'; import { PluginContext } from '../../mol-plugin/context'; import { PluginCommands } from '../../mol-plugin/commands'; import { StateTransforms } from '../../mol-plugin-state/transforms'; @@ -28,7 +28,7 @@ import { DefaultCanvas3DParams, Canvas3DProps } from '../../mol-canvas3d/canvas3 import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params'; import { download } from '../../mol-util/download'; import { getFormattedTime } from '../../mol-util/date'; -require('../../mol-plugin-ui/skin/light.scss') +require('../../mol-plugin-ui/skin/light.scss'); class MolStarProteopediaWrapper { static VERSION_MAJOR = 5; @@ -74,7 +74,7 @@ class MolStarProteopediaWrapper { } private download(b: StateBuilder.To<PSO.Root>, url: string) { - return b.apply(StateTransforms.Data.Download, { url, isBinary: false }) + return b.apply(StateTransforms.Data.Download, { url, isBinary: false }); } private model(b: StateBuilder.To<PSO.Data.Binary | PSO.Data.String>, format: SupportedFormats) { @@ -93,7 +93,7 @@ class MolStarProteopediaWrapper { name: 'assembly' as const, params: { id: assemblyId || 'deposited' } } - } + }; const s = model .apply(StateTransforms.Model.StructureFromModel, props, { ref: StateElements.Assembly }); @@ -185,7 +185,7 @@ class MolStarProteopediaWrapper { const model = this.getObj<PluginStateObject.Molecule.Model>('model'); if (!model) return; - const info = await ModelInfo.get(this.plugin, model, checkPreferredAssembly) + const info = await ModelInfo.get(this.plugin, model, checkPreferredAssembly); this.events.modelInfo.next(info); return info; } @@ -223,7 +223,7 @@ class MolStarProteopediaWrapper { name: 'assembly' as const, params: { id: asmId || 'deposited' } } - } + }; tree.to(StateElements.Assembly).update(StateTransforms.Model.StructureFromModel, p => ({ ...p, ...props })); await this.applyState(tree); } @@ -289,10 +289,10 @@ class MolStarProteopediaWrapper { animate = { modelIndex: { maxFPS: 8, - onceForward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }) }, - onceBackward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }) }, - palindrome: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }) }, - loop: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }) }, + onceForward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'forward' } } }); }, + onceBackward: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'once', params: { direction: 'backward' } } }); }, + palindrome: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'palindrome', params: {} } }); }, + loop: () => { this.plugin.state.animation.play(AnimateModelIndex, { maxFPS: Math.max(0.5, this.animate.modelIndex.maxFPS | 0), mode: { name: 'loop', params: {} } }); }, stop: () => this.plugin.state.animation.stop() } } @@ -371,12 +371,35 @@ class MolStarProteopediaWrapper { ]); const surroundings = MS.struct.modifier.includeSurroundings({ 0: core, radius: 5, 'as-whole-residues': true }); + const onlySurroundings = MS.struct.modifier.exceptBy({ 0: surroundings, by: core }); + const group = update.to(StateElements.Assembly).group(StateTransforms.Misc.CreateGroup, { label: compId }, { ref: StateElements.HetGroupFocusGroup }); - group.apply(StateTransforms.Model.StructureSelectionFromExpression, { label: 'Core', expression: core }, { ref: StateElements.HetGroupFocus }) - .apply(StateTransforms.Representation.StructureRepresentation3D, this.createCoreVisualParams()); + const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure; + + const coreSel = group.apply(StateTransforms.Model.StructureSelectionFromExpression, { label: 'Core', expression: core }, { ref: StateElements.HetGroupFocus }); + + coreSel.apply(StateTransforms.Representation.StructureRepresentation3D, createStructureRepresentationParams(this.plugin, asm.data, { + type: 'ball-and-stick' + })); + coreSel.apply(StateTransforms.Representation.StructureRepresentation3D, createStructureRepresentationParams(this.plugin, asm.data, { + type: 'label', + typeParams: { level: 'element' } + }), { tags: ['proteopedia-labels'] }); + group.apply(StateTransforms.Model.StructureSelectionFromExpression, { label: 'Surroundings', expression: surroundings }) - .apply(StateTransforms.Representation.StructureRepresentation3D, this.createSurVisualParams()); + .apply(StateTransforms.Representation.StructureRepresentation3D, createStructureRepresentationParams(this.plugin, asm.data, { + type: 'ball-and-stick', + color: 'uniform', colorParams: { value: ColorNames.gray }, + size: 'uniform', sizeParams: { value: 0.33 } + })); + + group.apply(StateTransforms.Model.StructureSelectionFromExpression, { label: 'Surroundings (only)', expression: onlySurroundings }) + .apply(StateTransforms.Representation.StructureRepresentation3D, createStructureRepresentationParams(this.plugin, asm.data, { + type: 'label', + typeParams: { level: 'residue' } + }), { tags: ['proteopedia-labels'] }); // the tag can later be used to toggle the labels + // sel.apply(StateTransforms.Representation.StructureLabels3D, { // target: { name: 'residues', params: { } }, // options: { @@ -396,27 +419,27 @@ class MolStarProteopediaWrapper { // const position = Vec3.sub(Vec3.zero(), sphere.center, asmCenter); // Vec3.normalize(position, position); // Vec3.scaleAndAdd(position, sphere.center, position, sphere.radius); - const radius = Math.max(sphere.radius, 5) + const radius = Math.max(sphere.radius, 5); const snapshot = this.plugin.canvas3d!.camera.getFocus(sphere.center, radius); PluginCommands.Camera.SetSnapshot(this.plugin, { snapshot, durationMs: 250 }); } } - private createSurVisualParams() { - const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure; - return createStructureRepresentationParams(this.plugin, asm.data, { - type: 'ball-and-stick', - color: 'uniform', colorParams: { value: ColorNames.gray }, - size: 'uniform', sizeParams: { value: 0.33 } - }); - } - - private createCoreVisualParams() { - const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure; - return createStructureRepresentationParams(this.plugin, asm.data, { - type: 'ball-and-stick' - }); - } + // private createSurVisualParams() { + // const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure; + // return createStructureRepresentationParams(this.plugin, asm.data, { + // type: 'ball-and-stick', + // color: 'uniform', colorParams: { value: ColorNames.gray }, + // size: 'uniform', sizeParams: { value: 0.33 } + // }); + // } + + // private createCoreVisualParams() { + // const asm = this.state.select(StateElements.Assembly)[0].obj as PluginStateObject.Molecule.Structure; + // return createStructureRepresentationParams(this.plugin, asm.data, { + // type: 'ball-and-stick' + // }); + // } snapshot = { get: () => { @@ -428,7 +451,7 @@ class MolStarProteopediaWrapper { download: () => { const json = JSON.stringify(this.plugin.state.getSnapshot(), null, 2); const blob = new Blob([json], {type : 'application/json;charset=utf-8'}); - download(blob, `mol-star_state_${(name || getFormattedTime())}.json`) + download(blob, `mol-star_state_${(name || getFormattedTime())}.json`); }, fetch: async (url: string) => { try { diff --git a/src/examples/task.ts b/src/examples/task.ts index 1378785ce863bc7488761cce480b3bcde80364d9..388b93ea9541c9faee08ea1e7e43b864c2e1c181 100644 --- a/src/examples/task.ts +++ b/src/examples/task.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Task, Progress, Scheduler, MultistepTask, chunkedSubtask } from '../mol-task' +import { Task, Progress, Scheduler, MultistepTask, chunkedSubtask } from '../mol-task'; import { now } from '../mol-util/now'; export async function test1() { @@ -85,19 +85,19 @@ export const ms = MultistepTask('ms-task', ['step 1', 'step 2', 'step 3'], async await step(0); const child = Task.create('chunked', async ctx => { - const s = await chunkedSubtask(ctx, 25, { i: 0, current: 0, total: 125 }, processChunk, (ctx, s, p) => ctx.update('chunk test ' + p)) + const s = await chunkedSubtask(ctx, 25, { i: 0, current: 0, total: 125 }, processChunk, (ctx, s, p) => ctx.update('chunk test ' + p)); return s.i; }); await child.runAsChild(ctx); await Scheduler.delay(250); await step(1); - await chunkedSubtask(ctx, 25, { i: 0, current: 0, total: 80 }, processChunk, (ctx, s, p) => ctx.update('chunk test ' + p)) + await chunkedSubtask(ctx, 25, { i: 0, current: 0, total: 80 }, processChunk, (ctx, s, p) => ctx.update('chunk test ' + p)); await Scheduler.delay(250); await step(2); await Scheduler.delay(250); return p.i + 3; -}) +}); export function abortingObserver(p: Progress) { diff --git a/src/mol-canvas3d/camera.ts b/src/mol-canvas3d/camera.ts index a38882f130ab2b209773f3e4892fd924e4639065..94eef75267cabead1ad52e4d42849b3bb6d2c24a 100644 --- a/src/mol-canvas3d/camera.ts +++ b/src/mol-canvas3d/camera.ts @@ -5,12 +5,12 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Mat4, Vec3, Vec4, EPSILON } from '../mol-math/linear-algebra' +import { Mat4, Vec3, Vec4, EPSILON } from '../mol-math/linear-algebra'; import { Viewport, cameraProject, cameraUnproject } from './camera/util'; import { CameraTransitionManager } from './camera/transition'; import { BehaviorSubject } from 'rxjs'; -export { Camera } +export { Camera }; class Camera { readonly view: Mat4 = Mat4.identity(); @@ -66,8 +66,8 @@ class Camera { const changed = !Mat4.areEqual(this.projection, this.prevProjection, EPSILON) || !Mat4.areEqual(this.view, this.prevView, EPSILON); if (changed) { - Mat4.mul(this.projectionView, this.projection, this.view) - Mat4.invert(this.inverseProjectionView, this.projectionView) + Mat4.mul(this.projectionView, this.projection, this.view); + Mat4.invert(this.inverseProjectionView, this.projectionView); Mat4.copy(this.prevView, this.view); Mat4.copy(this.prevProjection, this.projection); @@ -86,30 +86,30 @@ class Camera { } getTargetDistance(radius: number) { - const r = Math.max(radius, 0.01) - const { fov } = this.state - const { width, height } = this.viewport - const aspect = width / height - const aspectFactor = (height < width ? 1 : aspect) - return Math.abs((r / aspectFactor) / Math.sin(fov / 2)) + const r = Math.max(radius, 0.01); + const { fov } = this.state; + const { width, height } = this.viewport; + const aspect = width / height; + const aspectFactor = (height < width ? 1 : aspect); + return Math.abs((r / aspectFactor) / Math.sin(fov / 2)); } getFocus(target: Vec3, radius: number, up?: Vec3, dir?: Vec3): Partial<Camera.Snapshot> { - const r = Math.max(radius, 0.01) - const targetDistance = this.getTargetDistance(r) + const r = Math.max(radius, 0.01); + const targetDistance = this.getTargetDistance(r); - Vec3.sub(this.deltaDirection, this.target, this.position) - if (dir) Vec3.matchDirection(this.deltaDirection, dir, this.deltaDirection) - Vec3.setMagnitude(this.deltaDirection, this.deltaDirection, targetDistance) - Vec3.sub(this.newPosition, target, this.deltaDirection) + Vec3.sub(this.deltaDirection, this.target, this.position); + if (dir) Vec3.matchDirection(this.deltaDirection, dir, this.deltaDirection); + Vec3.setMagnitude(this.deltaDirection, this.deltaDirection, targetDistance); + Vec3.sub(this.newPosition, target, this.deltaDirection); - const state = Camera.copySnapshot(Camera.createDefaultSnapshot(), this.state) - state.target = Vec3.clone(target) - state.radius = r - state.position = Vec3.clone(this.newPosition) - if (up) Vec3.matchDirection(state.up, up, state.up) + const state = Camera.copySnapshot(Camera.createDefaultSnapshot(), this.state); + state.target = Vec3.clone(target); + state.radius = r; + state.position = Vec3.clone(this.newPosition); + if (up) Vec3.matchDirection(state.up, up, state.up); - return state + return state; } focus(target: Vec3, radius: number, durationMs?: number, up?: Vec3, dir?: Vec3) { @@ -119,11 +119,11 @@ class Camera { } project(out: Vec4, point: Vec3) { - return cameraProject(out, point, this.viewport, this.projectionView) + return cameraProject(out, point, this.viewport, this.projectionView); } unproject(out: Vec3, point: Vec3) { - return cameraUnproject(out, point, this.viewport, this.inverseProjectionView) + return cameraUnproject(out, point, this.viewport, this.inverseProjectionView); } constructor(state?: Partial<Camera.Snapshot>, viewport = Viewport.create(-1, -1, 1, 1)) { @@ -151,12 +151,12 @@ namespace Camera { } export function setViewOffset(out: ViewOffset, fullWidth: number, fullHeight: number, offsetX: number, offsetY: number, width: number, height: number) { - out.fullWidth = fullWidth - out.fullHeight = fullHeight - out.offsetX = offsetX - out.offsetY = offsetY - out.width = width - out.height = height + out.fullWidth = fullWidth; + out.fullHeight = fullHeight; + out.offsetX = offsetX; + out.offsetY = offsetY; + out.width = width; + out.height = height; } export function createDefaultSnapshot(): Snapshot { @@ -209,90 +209,90 @@ namespace Camera { } function updateOrtho(camera: Camera) { - const { viewport, zoom, near, far, viewOffset } = camera + const { viewport, zoom, near, far, viewOffset } = camera; - const fullLeft = -(viewport.width - viewport.x) / 2 - const fullRight = (viewport.width - viewport.x) / 2 - const fullTop = (viewport.height - viewport.y) / 2 - const fullBottom = -(viewport.height - viewport.y) / 2 + const fullLeft = -(viewport.width - viewport.x) / 2; + const fullRight = (viewport.width - viewport.x) / 2; + const fullTop = (viewport.height - viewport.y) / 2; + const fullBottom = -(viewport.height - viewport.y) / 2; - const dx = (fullRight - fullLeft) / (2 * zoom) - const dy = (fullTop - fullBottom) / (2 * zoom) - const cx = (fullRight + fullLeft) / 2 - const cy = (fullTop + fullBottom) / 2 + const dx = (fullRight - fullLeft) / (2 * zoom); + const dy = (fullTop - fullBottom) / (2 * zoom); + const cx = (fullRight + fullLeft) / 2; + const cy = (fullTop + fullBottom) / 2; - let left = cx - dx - let right = cx + dx - let top = cy + dy - let bottom = cy - dy + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; if (viewOffset.enabled) { - const zoomW = zoom / (viewOffset.width / viewOffset.fullWidth) - const zoomH = zoom / (viewOffset.height / viewOffset.fullHeight) - const scaleW = (fullRight - fullLeft) / viewOffset.width - const scaleH = (fullTop - fullBottom) / viewOffset.height - left += scaleW * (viewOffset.offsetX / zoomW) - right = left + scaleW * (viewOffset.width / zoomW) - top -= scaleH * (viewOffset.offsetY / zoomH) - bottom = top - scaleH * (viewOffset.height / zoomH) + const zoomW = zoom / (viewOffset.width / viewOffset.fullWidth); + const zoomH = zoom / (viewOffset.height / viewOffset.fullHeight); + const scaleW = (fullRight - fullLeft) / viewOffset.width; + const scaleH = (fullTop - fullBottom) / viewOffset.height; + left += scaleW * (viewOffset.offsetX / zoomW); + right = left + scaleW * (viewOffset.width / zoomW); + top -= scaleH * (viewOffset.offsetY / zoomH); + bottom = top - scaleH * (viewOffset.height / zoomH); } // build projection matrix - Mat4.ortho(camera.projection, left, right, top, bottom, near, far) + Mat4.ortho(camera.projection, left, right, top, bottom, near, far); // build view matrix - Mat4.lookAt(camera.view, camera.position, camera.target, camera.up) + Mat4.lookAt(camera.view, camera.position, camera.target, camera.up); } function updatePers(camera: Camera) { - const aspect = camera.viewport.width / camera.viewport.height + const aspect = camera.viewport.width / camera.viewport.height; - const { near, far, viewOffset } = camera + const { near, far, viewOffset } = camera; - let top = near * Math.tan(0.5 * camera.state.fov) - let height = 2 * top - let width = aspect * height - let left = -0.5 * width + let top = near * Math.tan(0.5 * camera.state.fov); + let height = 2 * top; + let width = aspect * height; + let left = -0.5 * width; if (viewOffset.enabled) { - left += viewOffset.offsetX * width / viewOffset.fullWidth - top -= viewOffset.offsetY * height / viewOffset.fullHeight - width *= viewOffset.width / viewOffset.fullWidth - height *= viewOffset.height / viewOffset.fullHeight + left += viewOffset.offsetX * width / viewOffset.fullWidth; + top -= viewOffset.offsetY * height / viewOffset.fullHeight; + width *= viewOffset.width / viewOffset.fullWidth; + height *= viewOffset.height / viewOffset.fullHeight; } // build projection matrix - Mat4.perspective(camera.projection, left, left + width, top, top - height, near, far) + Mat4.perspective(camera.projection, left, left + width, top, top - height, near, far); // build view matrix - Mat4.lookAt(camera.view, camera.position, camera.target, camera.up) + Mat4.lookAt(camera.view, camera.position, camera.target, camera.up); } function updateClip(camera: Camera) { - let { radius, radiusMax, mode, fog, clipFar } = camera.state - if (radius < 0.01) radius = 0.01 + let { radius, radiusMax, mode, fog, clipFar } = camera.state; + if (radius < 0.01) radius = 0.01; - const normalizedFar = clipFar ? radius : radiusMax - const cameraDistance = Vec3.distance(camera.position, camera.target) - let near = cameraDistance - radius - let far = cameraDistance + normalizedFar + const normalizedFar = clipFar ? radius : radiusMax; + const cameraDistance = Vec3.distance(camera.position, camera.target); + let near = cameraDistance - radius; + let far = cameraDistance + normalizedFar; - const fogNearFactor = -(50 - fog) / 50 - let fogNear = cameraDistance - (normalizedFar * fogNearFactor) - let fogFar = far + const fogNearFactor = -(50 - fog) / 50; + let fogNear = cameraDistance - (normalizedFar * fogNearFactor); + let fogFar = far; if (mode === 'perspective') { // set at least to 5 to avoid slow sphere impostor rendering - near = Math.max(5, near) - far = Math.max(5, far) + near = Math.max(5, near); + far = Math.max(5, far); } else { - near = Math.max(0, near) - far = Math.max(0, far) + near = Math.max(0, near); + far = Math.max(0, far); } if (near === far) { // make sure near and far are not identical to avoid Infinity in the projection matrix - far = near + 0.01 + far = near + 0.01; } camera.near = near; diff --git a/src/mol-canvas3d/camera/transition.ts b/src/mol-canvas3d/camera/transition.ts index a9daac3510797a6fe095fc8aa4d951c8c6820f4f..62f3f50c5c030947329fbb637221e42d7b12893c 100644 --- a/src/mol-canvas3d/camera/transition.ts +++ b/src/mol-canvas3d/camera/transition.ts @@ -8,7 +8,7 @@ import { Camera } from '../camera'; import { Quat, Vec3 } from '../../mol-math/linear-algebra'; import { lerp } from '../../mol-math/interpolate'; -export { CameraTransitionManager } +export { CameraTransitionManager }; class CameraTransitionManager { private t = 0; @@ -21,8 +21,8 @@ class CameraTransitionManager { private _target: Camera.Snapshot = Camera.createDefaultSnapshot(); private _current = Camera.createDefaultSnapshot(); - get source(): Readonly<Camera.Snapshot> { return this._source } - get target(): Readonly<Camera.Snapshot> { return this._target } + get source(): Readonly<Camera.Snapshot> { return this._source; } + get target(): Readonly<Camera.Snapshot> { return this._target; } apply(to: Partial<Camera.Snapshot>, durationMs: number = 0, transition?: CameraTransitionManager.TransitionFunc) { if (!this.inTransition || durationMs > 0) { @@ -36,7 +36,7 @@ class CameraTransitionManager { Camera.copySnapshot(this._target, to); if (this._target.radius > this._target.radiusMax) { - this._target.radius = this._target.radiusMax + this._target.radius = this._target.radiusMax; } if (!this.inTransition && durationMs <= 0 || (typeof to.mode !== 'undefined' && to.mode !== this.camera.state.mode)) { diff --git a/src/mol-canvas3d/camera/util.ts b/src/mol-canvas3d/camera/util.ts index 2dc02fcce6f0704dffae3b41e57171cb7ee68213..0e3b31766debbb99e731c9dfd7b31cee4403825d 100644 --- a/src/mol-canvas3d/camera/util.ts +++ b/src/mol-canvas3d/camera/util.ts @@ -4,9 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Mat4, Vec3, Vec4 } from '../../mol-math/linear-algebra' +import { Mat4, Vec3, Vec4 } from '../../mol-math/linear-algebra'; -export { Viewport } +export { Viewport }; type Viewport = { x: number @@ -16,74 +16,74 @@ type Viewport = { } function Viewport() { - return Viewport.zero() + return Viewport.zero(); } namespace Viewport { export function zero(): Viewport { - return { x: 0, y: 0, width: 0, height: 0 } + return { x: 0, y: 0, width: 0, height: 0 }; } export function create(x: number, y: number, width: number, height: number): Viewport { - return { x, y, width, height } + return { x, y, width, height }; } export function clone(viewport: Viewport): Viewport { - return { ...viewport } + return { ...viewport }; } export function copy(target: Viewport, source: Viewport): Viewport { - return Object.assign(target, source) + return Object.assign(target, source); } export function set(viewport: Viewport, x: number, y: number, width: number, height: number): Viewport { - viewport.x = x - viewport.y = y - viewport.width = width - viewport.height = height - return viewport + viewport.x = x; + viewport.y = y; + viewport.width = width; + viewport.height = height; + return viewport; } export function toVec4(v4: Vec4, viewport: Viewport): Vec4 { - v4[0] = viewport.x - v4[1] = viewport.y - v4[2] = viewport.width - v4[3] = viewport.height - return v4 + v4[0] = viewport.x; + v4[1] = viewport.y; + v4[2] = viewport.width; + v4[3] = viewport.height; + return v4; } export function equals(a: Viewport, b: Viewport) { - return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height + return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; } } // -const NEAR_RANGE = 0 -const FAR_RANGE = 1 +const NEAR_RANGE = 0; +const FAR_RANGE = 1; -const tmpVec4 = Vec4() +const tmpVec4 = Vec4(); /** Transform point into 2D window coordinates. */ export function cameraProject (out: Vec4, point: Vec3, viewport: Viewport, projectionView: Mat4) { - const { x: vX, y: vY, width: vWidth, height: vHeight } = viewport + const { x: vX, y: vY, width: vWidth, height: vHeight } = viewport; // clip space -> NDC -> window coordinates, implicit 1.0 for w component - Vec4.set(tmpVec4, point[0], point[1], point[2], 1.0) + Vec4.set(tmpVec4, point[0], point[1], point[2], 1.0); // transform into clip space - Vec4.transformMat4(tmpVec4, tmpVec4, projectionView) + Vec4.transformMat4(tmpVec4, tmpVec4, projectionView); // transform into NDC - const w = tmpVec4[3] + const w = tmpVec4[3]; if (w !== 0) { - tmpVec4[0] /= w - tmpVec4[1] /= w - tmpVec4[2] /= w + tmpVec4[0] /= w; + tmpVec4[1] /= w; + tmpVec4[2] /= w; } // transform into window coordinates, set fourth component is (1/clip.w) as in gl_FragCoord.w - out[0] = vX + vWidth / 2 * tmpVec4[0] + (0 + vWidth / 2) - out[1] = vY + vHeight / 2 * tmpVec4[1] + (0 + vHeight / 2) - out[2] = (FAR_RANGE - NEAR_RANGE) / 2 * tmpVec4[2] + (FAR_RANGE + NEAR_RANGE) / 2 - out[3] = w === 0 ? 0 : 1 / w - return out + out[0] = vX + vWidth / 2 * tmpVec4[0] + (0 + vWidth / 2); + out[1] = vY + vHeight / 2 * tmpVec4[1] + (0 + vHeight / 2); + out[2] = (FAR_RANGE - NEAR_RANGE) / 2 * tmpVec4[2] + (FAR_RANGE + NEAR_RANGE) / 2; + out[3] = w === 0 ? 0 : 1 / w; + return out; } /** @@ -91,14 +91,14 @@ export function cameraProject (out: Vec4, point: Vec3, viewport: Viewport, proje * The point must have x and y set to 2D window coordinates and z between 0 (near) and 1 (far). */ export function cameraUnproject (out: Vec3, point: Vec3, viewport: Viewport, inverseProjectionView: Mat4) { - const { x: vX, y: vY, width: vWidth, height: vHeight } = viewport + const { x: vX, y: vY, width: vWidth, height: vHeight } = viewport; - const x = point[0] - vX - const y = (vHeight - point[1] - 1) - vY - const z = point[2] + const x = point[0] - vX; + const y = (vHeight - point[1] - 1) - vY; + const z = point[2]; - out[0] = (2 * x) / vWidth - 1 - out[1] = (2 * y) / vHeight - 1 - out[2] = 2 * z - 1 - return Vec3.transformMat4(out, out, inverseProjectionView) + out[0] = (2 * x) / vWidth - 1; + out[1] = (2 * y) / vHeight - 1; + out[2] = 2 * z - 1; + return Vec3.transformMat4(out, out, inverseProjectionView); } \ No newline at end of file diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts index 5046ebb83f7392949e0a9c6368e1fd53fd0b84c6..68d9f581f74a9b161ab070d5ae0942ecebfffa29 100644 --- a/src/mol-canvas3d/canvas3d.ts +++ b/src/mol-canvas3d/canvas3d.ts @@ -7,12 +7,12 @@ import { BehaviorSubject, Subscription } from 'rxjs'; import { now } from '../mol-util/now'; -import { Vec3 } from '../mol-math/linear-algebra' -import InputObserver, { ModifiersKeys, ButtonsType } from '../mol-util/input/input-observer' -import Renderer, { RendererStats, RendererParams } from '../mol-gl/renderer' -import { GraphicsRenderObject } from '../mol-gl/render-object' -import { TrackballControls, TrackballControlsParams } from './controls/trackball' -import { Viewport } from './camera/util' +import { Vec3 } from '../mol-math/linear-algebra'; +import InputObserver, { ModifiersKeys, ButtonsType } from '../mol-util/input/input-observer'; +import Renderer, { RendererStats, RendererParams } from '../mol-gl/renderer'; +import { GraphicsRenderObject } from '../mol-gl/render-object'; +import { TrackballControls, TrackballControlsParams } from './controls/trackball'; +import { Viewport } from './camera/util'; import { createContext, WebGLContext, getGLContext } from '../mol-gl/webgl/context'; import { Representation } from '../mol-repr/representation'; import Scene from '../mol-gl/scene'; @@ -61,11 +61,11 @@ export const Canvas3DParams = { renderer: PD.Group(RendererParams), trackball: PD.Group(TrackballControlsParams), debug: PD.Group(DebugHelperParams) -} +}; export const DefaultCanvas3DParams = PD.getDefaultValues(Canvas3DParams); export type Canvas3DProps = PD.Values<typeof Canvas3DParams> -export { Canvas3D } +export { Canvas3D }; interface Canvas3D { readonly webgl: WebGLContext, @@ -107,7 +107,7 @@ interface Canvas3D { dispose(): void } -const requestAnimationFrame = typeof window !== 'undefined' ? window.requestAnimationFrame : (f: (time: number) => void) => setImmediate(()=>f(Date.now())) +const requestAnimationFrame = typeof window !== 'undefined' ? window.requestAnimationFrame : (f: (time: number) => void) => setImmediate(()=>f(Date.now())); namespace Canvas3D { export interface HoverEvent { current: Representation.Loci, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys } @@ -120,139 +120,139 @@ namespace Canvas3D { depth: true, preserveDrawingBuffer: true, premultipliedAlpha: false, - }) - if (gl === null) throw new Error('Could not create a WebGL rendering context') - const input = InputObserver.fromElement(canvas) - const webgl = createContext(gl) + }); + if (gl === null) throw new Error('Could not create a WebGL rendering context'); + const input = InputObserver.fromElement(canvas); + const webgl = createContext(gl); if (isDebugMode) { - const loseContextExt = gl.getExtension('WEBGL_lose_context') + const loseContextExt = gl.getExtension('WEBGL_lose_context'); if (loseContextExt) { canvas.addEventListener('mousedown', e => { - if (webgl.isContextLost) return - if (!e.shiftKey || !e.ctrlKey || !e.altKey) return + if (webgl.isContextLost) return; + if (!e.shiftKey || !e.ctrlKey || !e.altKey) return; - console.log('lose context') - loseContextExt.loseContext() + console.log('lose context'); + loseContextExt.loseContext(); setTimeout(() => { - if (!webgl.isContextLost) return - console.log('restore context') - loseContextExt.restoreContext() - }, 1000) - }, false) + if (!webgl.isContextLost) return; + console.log('restore context'); + loseContextExt.restoreContext(); + }, 1000); + }, false); } } // https://www.khronos.org/webgl/wiki/HandlingContextLost canvas.addEventListener('webglcontextlost', e => { - webgl.setContextLost() - e.preventDefault() - if (isDebugMode) console.log('context lost') - }, false) + webgl.setContextLost(); + e.preventDefault(); + if (isDebugMode) console.log('context lost'); + }, false); canvas.addEventListener('webglcontextrestored', () => { - if (!webgl.isContextLost) return - webgl.handleContextRestored() - if (isDebugMode) console.log('context restored') - }, false) + if (!webgl.isContextLost) return; + webgl.handleContextRestored(); + if (isDebugMode) console.log('context restored'); + }, false); - return Canvas3D.create(webgl, input, props) + return Canvas3D.create(webgl, input, props); } export function create(webgl: WebGLContext, input: InputObserver, props: Partial<Canvas3DProps> = {}): Canvas3D { - const p = { ...DefaultCanvas3DParams, ...props } + const p = { ...DefaultCanvas3DParams, ...props }; - const reprRenderObjects = new Map<Representation.Any, Set<GraphicsRenderObject>>() - const reprUpdatedSubscriptions = new Map<Representation.Any, Subscription>() - const reprCount = new BehaviorSubject(0) + const reprRenderObjects = new Map<Representation.Any, Set<GraphicsRenderObject>>(); + const reprUpdatedSubscriptions = new Map<Representation.Any, Subscription>(); + const reprCount = new BehaviorSubject(0); - const startTime = now() - const didDraw = new BehaviorSubject<now.Timestamp>(0 as now.Timestamp) + const startTime = now(); + const didDraw = new BehaviorSubject<now.Timestamp>(0 as now.Timestamp); - const { gl, contextRestored } = webgl + const { gl, contextRestored } = webgl; - let width = gl.drawingBufferWidth - let height = gl.drawingBufferHeight + let width = gl.drawingBufferWidth; + let height = gl.drawingBufferHeight; - const scene = Scene.create(webgl) + const scene = Scene.create(webgl); const camera = new Camera({ position: Vec3.create(0, 0, 100), mode: p.camera.mode, fog: p.cameraFog.name === 'on' ? p.cameraFog.params.intensity : 0, clipFar: p.cameraClipping.far - }) + }); - const controls = TrackballControls.create(input, camera, p.trackball) - const renderer = Renderer.create(webgl, p.renderer) + const controls = TrackballControls.create(input, camera, p.trackball); + const renderer = Renderer.create(webgl, p.renderer); const debugHelper = new BoundingSphereHelper(webgl, scene, p.debug); const interactionHelper = new Canvas3dInteractionHelper(identify, getLoci, input); const drawPass = new DrawPass(webgl, renderer, scene, camera, debugHelper, { cameraHelper: p.camera.helper - }) - const pickPass = new PickPass(webgl, renderer, scene, camera, 0.5) - const postprocessing = new PostprocessingPass(webgl, camera, drawPass, p.postprocessing) - const multiSample = new MultiSamplePass(webgl, camera, drawPass, postprocessing, p.multiSample) + }); + const pickPass = new PickPass(webgl, renderer, scene, camera, 0.5); + const postprocessing = new PostprocessingPass(webgl, camera, drawPass, p.postprocessing); + const multiSample = new MultiSamplePass(webgl, camera, drawPass, postprocessing, p.multiSample); - let drawPending = false - let cameraResetRequested = false - let nextCameraResetDuration: number | undefined = void 0 - let nextCameraResetSnapshot: Partial<Camera.Snapshot> | undefined = void 0 + let drawPending = false; + let cameraResetRequested = false; + let nextCameraResetDuration: number | undefined = void 0; + let nextCameraResetSnapshot: Partial<Camera.Snapshot> | undefined = void 0; function getLoci(pickingId: PickingId) { - let loci: Loci = EmptyLoci - let repr: Representation.Any = Representation.Empty + let loci: Loci = EmptyLoci; + let repr: Representation.Any = Representation.Empty; reprRenderObjects.forEach((_, _repr) => { - const _loci = _repr.getLoci(pickingId) + const _loci = _repr.getLoci(pickingId); if (!isEmptyLoci(_loci)) { if (!isEmptyLoci(loci)) { - console.warn('found another loci, this should not happen') + console.warn('found another loci, this should not happen'); } - loci = _loci - repr = _repr + loci = _loci; + repr = _repr; } - }) - return { loci, repr } + }); + return { loci, repr }; } function mark(reprLoci: Representation.Loci, action: MarkerAction) { - const { repr, loci } = reprLoci - let changed = false + const { repr, loci } = reprLoci; + let changed = false; if (repr) { - changed = repr.mark(loci, action) + changed = repr.mark(loci, action); } else { - reprRenderObjects.forEach((_, _repr) => { changed = _repr.mark(loci, action) || changed }) + reprRenderObjects.forEach((_, _repr) => { changed = _repr.mark(loci, action) || changed; }); } if (changed) { - scene.update(void 0, true) - const prevPickDirty = pickPass.pickDirty - draw(true) - pickPass.pickDirty = prevPickDirty // marking does not change picking buffers + scene.update(void 0, true); + const prevPickDirty = pickPass.pickDirty; + draw(true); + pickPass.pickDirty = prevPickDirty; // marking does not change picking buffers } } function render(force: boolean) { - if (webgl.isContextLost) return false + if (webgl.isContextLost) return false; - let didRender = false - controls.update(currentTime) - Viewport.set(camera.viewport, 0, 0, width, height) - const cameraChanged = camera.update() - multiSample.update(force || cameraChanged, currentTime) + let didRender = false; + controls.update(currentTime); + Viewport.set(camera.viewport, 0, 0, width, height); + const cameraChanged = camera.update(); + multiSample.update(force || cameraChanged, currentTime); if (force || cameraChanged || multiSample.enabled) { - renderer.setViewport(0, 0, width, height) + renderer.setViewport(0, 0, width, height); if (multiSample.enabled) { - multiSample.render(true, p.transparentBackground) + multiSample.render(true, p.transparentBackground); } else { - drawPass.render(!postprocessing.enabled, p.transparentBackground) - if (postprocessing.enabled) postprocessing.render(true) + drawPass.render(!postprocessing.enabled, p.transparentBackground); + if (postprocessing.enabled) postprocessing.render(true); } - pickPass.pickDirty = true - didRender = true + pickPass.pickDirty = true; + didRender = true; } return didRender; @@ -263,15 +263,15 @@ namespace Canvas3D { function draw(force?: boolean) { if (render(!!force || forceNextDraw)) { - didDraw.next(now() - startTime as now.Timestamp) + didDraw.next(now() - startTime as now.Timestamp); } forceNextDraw = false; - drawPending = false + drawPending = false; } function requestDraw(force?: boolean) { - if (drawPending) return - drawPending = true + if (drawPending) return; + drawPending = true; forceNextDraw = !!force; } @@ -284,11 +284,11 @@ namespace Canvas3D { if (!camera.transition.inTransition && !webgl.isContextLost) { interactionHelper.tick(currentTime); } - requestAnimationFrame(animate) + requestAnimationFrame(animate); } function identify(x: number, y: number): PickingId | undefined { - return webgl.isContextLost ? undefined : pickPass.identify(x, y) + return webgl.isContextLost ? undefined : pickPass.identify(x, y); } function commit(isSynchronous: boolean = false) { @@ -302,7 +302,7 @@ namespace Canvas3D { const { center, radius } = scene.boundingSphereVisible; if (radius > 0) { - const duration = nextCameraResetDuration === undefined ? p.cameraResetDurationMs : nextCameraResetDuration + const duration = nextCameraResetDuration === undefined ? p.cameraResetDurationMs : nextCameraResetDuration; const focus = camera.getFocus(center, radius); const snapshot = nextCameraResetSnapshot ? { ...focus, ...nextCameraResetSnapshot } : focus; camera.setState(snapshot, duration); @@ -321,8 +321,8 @@ namespace Canvas3D { if (camera.transition.inTransition || nextCameraResetSnapshot) return false; - let cameraSphereOverlapsNone = true - Sphere3D.set(cameraSphere, camera.state.target, camera.state.radius) + let cameraSphereOverlapsNone = true; + Sphere3D.set(cameraSphere, camera.state.target, camera.state.radius); // check if any renderable has moved outside of the old bounding sphere // and if no renderable is overlapping with the camera sphere @@ -354,7 +354,7 @@ namespace Canvas3D { } if (oldBoundingSphereVisible.radius === 0) nextCameraResetDuration = 0; - camera.setState({ radiusMax: scene.boundingSphere.radius }, 0) + camera.setState({ radiusMax: scene.boundingSphere.radius }, 0); reprCount.next(reprRenderObjects.size); return true; @@ -363,31 +363,31 @@ namespace Canvas3D { function add(repr: Representation.Any) { registerAutoUpdate(repr); - const oldRO = reprRenderObjects.get(repr) - const newRO = new Set<GraphicsRenderObject>() - repr.renderObjects.forEach(o => newRO.add(o)) + const oldRO = reprRenderObjects.get(repr); + const newRO = new Set<GraphicsRenderObject>(); + repr.renderObjects.forEach(o => newRO.add(o)); if (oldRO) { if (!SetUtils.areEqual(newRO, oldRO)) { - newRO.forEach(o => { if (!oldRO.has(o)) scene.add(o) }) - oldRO.forEach(o => { if (!newRO.has(o)) scene.remove(o) }) + newRO.forEach(o => { if (!oldRO.has(o)) scene.add(o); }); + oldRO.forEach(o => { if (!newRO.has(o)) scene.remove(o); }); } } else { - repr.renderObjects.forEach(o => scene.add(o)) + repr.renderObjects.forEach(o => scene.add(o)); } - reprRenderObjects.set(repr, newRO) + reprRenderObjects.set(repr, newRO); - scene.update(repr.renderObjects, false) + scene.update(repr.renderObjects, false); } function remove(repr: Representation.Any) { unregisterAutoUpdate(repr); - const renderObjects = reprRenderObjects.get(repr) + const renderObjects = reprRenderObjects.get(repr); if (renderObjects) { - renderObjects.forEach(o => scene.remove(o)) - reprRenderObjects.delete(repr) - scene.update(repr.renderObjects, false, true) + renderObjects.forEach(o => scene.remove(o)); + reprRenderObjects.delete(repr); + scene.update(repr.renderObjects, false, true); } } @@ -396,7 +396,7 @@ namespace Canvas3D { reprUpdatedSubscriptions.set(repr, repr.updated.subscribe(_ => { if (!repr.state.syncManually) add(repr); - })) + })); } function unregisterAutoUpdate(repr: Representation.Any) { @@ -410,7 +410,7 @@ namespace Canvas3D { function getProps(): Canvas3DProps { const radius = scene.boundingSphere.radius > 0 ? 100 - Math.round((camera.transition.target.radius / scene.boundingSphere.radius) * 100) - : 0 + : 0; return { camera: { @@ -429,15 +429,15 @@ namespace Canvas3D { renderer: { ...renderer.props }, trackball: { ...controls.props }, debug: { ...debugHelper.props } - } + }; } - handleResize() + handleResize(); const contextRestoredSub = contextRestored.subscribe(() => { - pickPass.pickDirty = true - draw(true) - }) + pickPass.pickDirty = true; + draw(true); + }); return { webgl, @@ -450,26 +450,26 @@ namespace Canvas3D { if (!reprRenderObjects.has(repr)) return; scene.update(repr.renderObjects, !!keepSphere); } else { - scene.update(void 0, !!keepSphere) + scene.update(void 0, !!keepSphere); } }, clear: () => { - reprUpdatedSubscriptions.forEach(v => v.unsubscribe()) - reprUpdatedSubscriptions.clear() - reprRenderObjects.clear() - scene.clear() - debugHelper.clear() - requestDraw(true) - reprCount.next(reprRenderObjects.size) + reprUpdatedSubscriptions.forEach(v => v.unsubscribe()); + reprUpdatedSubscriptions.clear(); + reprRenderObjects.clear(); + scene.clear(); + debugHelper.clear(); + requestDraw(true); + reprCount.next(reprRenderObjects.size); }, syncVisibility: () => { if (camera.state.radiusMax === 0) { - cameraResetRequested = true - nextCameraResetDuration = 0 + cameraResetRequested = true; + nextCameraResetDuration = 0; } if (scene.syncVisibility()) { - if (debugHelper.isEnabled) debugHelper.update() + if (debugHelper.isEnabled) debugHelper.update(); } }, @@ -490,11 +490,11 @@ namespace Canvas3D { boundingSphere: scene.boundingSphere, getPixelData: (variant: GraphicsRenderVariant) => { switch (variant) { - case 'color': return webgl.getDrawingBufferPixelData() - case 'pickObject': return pickPass.objectPickTarget.getPixelData() - case 'pickInstance': return pickPass.instancePickTarget.getPixelData() - case 'pickGroup': return pickPass.groupPickTarget.getPixelData() - case 'depth': return readTexture(webgl, drawPass.depthTexture) as PixelData + case 'color': return webgl.getDrawingBufferPixelData(); + case 'pickObject': return pickPass.objectPickTarget.getPixelData(); + case 'pickInstance': return pickPass.instancePickTarget.getPixelData(); + case 'pickGroup': return pickPass.groupPickTarget.getPixelData(); + case 'depth': return readTexture(webgl, drawPass.depthTexture) as PixelData; } }, didDraw, @@ -504,48 +504,48 @@ namespace Canvas3D { ? produce(getProps(), properties) : properties; - const cameraState: Partial<Camera.Snapshot> = Object.create(null) + const cameraState: Partial<Camera.Snapshot> = Object.create(null); if (props.camera && props.camera.mode !== undefined && props.camera.mode !== camera.state.mode) { - cameraState.mode = props.camera.mode + cameraState.mode = props.camera.mode; } if (props.cameraFog !== undefined) { - const newFog = props.cameraFog.name === 'on' ? props.cameraFog.params.intensity : 0 - if (newFog !== camera.state.fog) cameraState.fog = newFog + const newFog = props.cameraFog.name === 'on' ? props.cameraFog.params.intensity : 0; + if (newFog !== camera.state.fog) cameraState.fog = newFog; } if (props.cameraClipping !== undefined) { if (props.cameraClipping.far !== undefined && props.cameraClipping.far !== camera.state.clipFar) { - cameraState.clipFar = props.cameraClipping.far + cameraState.clipFar = props.cameraClipping.far; } if (props.cameraClipping.radius !== undefined) { - const radius = (scene.boundingSphere.radius / 100) * (100 - props.cameraClipping.radius) + const radius = (scene.boundingSphere.radius / 100) * (100 - props.cameraClipping.radius); if (radius > 0 && radius !== cameraState.radius) { // if radius = 0, NaNs happen - cameraState.radius = Math.max(radius, 0.01) + cameraState.radius = Math.max(radius, 0.01); } } } - if (Object.keys(cameraState).length > 0) camera.setState(cameraState) + if (Object.keys(cameraState).length > 0) camera.setState(cameraState); - if (props.camera?.helper) drawPass.setProps({ cameraHelper: props.camera.helper }) - if (props.cameraResetDurationMs !== undefined) p.cameraResetDurationMs = props.cameraResetDurationMs - if (props.transparentBackground !== undefined) p.transparentBackground = props.transparentBackground + if (props.camera?.helper) drawPass.setProps({ cameraHelper: props.camera.helper }); + if (props.cameraResetDurationMs !== undefined) p.cameraResetDurationMs = props.cameraResetDurationMs; + if (props.transparentBackground !== undefined) p.transparentBackground = props.transparentBackground; - if (props.postprocessing) postprocessing.setProps(props.postprocessing) - if (props.multiSample) multiSample.setProps(props.multiSample) - if (props.renderer) renderer.setProps(props.renderer) - if (props.trackball) controls.setProps(props.trackball) - if (props.debug) debugHelper.setProps(props.debug) + if (props.postprocessing) postprocessing.setProps(props.postprocessing); + if (props.multiSample) multiSample.setProps(props.multiSample); + if (props.renderer) renderer.setProps(props.renderer); + if (props.trackball) controls.setProps(props.trackball); + if (props.debug) debugHelper.setProps(props.debug); - requestDraw(true) + requestDraw(true); }, getImagePass: (props: Partial<ImageProps> = {}) => { - return new ImagePass(webgl, renderer, scene, camera, debugHelper, props) + return new ImagePass(webgl, renderer, scene, camera, debugHelper, props); }, get props() { const radius = scene.boundingSphere.radius > 0 ? 100 - Math.round((camera.transition.target.radius / scene.boundingSphere.radius) * 100) - : 0 + : 0; return { camera: { @@ -564,43 +564,43 @@ namespace Canvas3D { renderer: { ...renderer.props }, trackball: { ...controls.props }, debug: { ...debugHelper.props } - } + }; }, get input() { - return input + return input; }, get stats() { - return renderer.stats + return renderer.stats; }, get interaction() { - return interactionHelper.events + return interactionHelper.events; }, dispose: () => { - contextRestoredSub.unsubscribe() - - scene.clear() - debugHelper.clear() - input.dispose() - controls.dispose() - renderer.dispose() - interactionHelper.dispose() + contextRestoredSub.unsubscribe(); + + scene.clear(); + debugHelper.clear(); + input.dispose(); + controls.dispose(); + renderer.dispose(); + interactionHelper.dispose(); } - } + }; function handleResize() { - width = gl.drawingBufferWidth - height = gl.drawingBufferHeight + width = gl.drawingBufferWidth; + height = gl.drawingBufferHeight; - renderer.setViewport(0, 0, width, height) - Viewport.set(camera.viewport, 0, 0, width, height) - Viewport.set(controls.viewport, 0, 0, width, height) + renderer.setViewport(0, 0, width, height); + Viewport.set(camera.viewport, 0, 0, width, height); + Viewport.set(controls.viewport, 0, 0, width, height); - drawPass.setSize(width, height) - pickPass.setSize(width, height) - postprocessing.setSize(width, height) - multiSample.setSize(width, height) + drawPass.setSize(width, height); + pickPass.setSize(width, height); + postprocessing.setSize(width, height); + multiSample.setSize(width, height); - requestDraw(true) + requestDraw(true); } } } \ No newline at end of file diff --git a/src/mol-canvas3d/controls/trackball.ts b/src/mol-canvas3d/controls/trackball.ts index c768750eee58b419ea820697755a65da1e1bf1d1..356f27bf2097e6ff5340b8e5d05c2c7839cf36ff 100644 --- a/src/mol-canvas3d/controls/trackball.ts +++ b/src/mol-canvas3d/controls/trackball.ts @@ -16,9 +16,9 @@ import { Camera } from '../camera'; import { absMax } from '../../mol-math/misc'; import { Binding } from '../../mol-util/binding'; -const B = ButtonsType -const M = ModifiersKeys -const Trigger = Binding.Trigger +const B = ButtonsType; +const M = ModifiersKeys; +const Trigger = Binding.Trigger; export const DefaultTrackballBindings = { dragRotate: Binding([Trigger(B.Flag.Primary, M.create())], 'Rotate', 'Drag using ${triggers}'), @@ -31,7 +31,7 @@ export const DefaultTrackballBindings = { scrollZoom: Binding([Trigger(B.Flag.Auxilary, M.create())], 'Zoom', 'Scroll using ${triggers}'), scrollFocus: Binding([Trigger(B.Flag.Auxilary, M.create({ shift: true }))], 'Clip', 'Scroll using ${triggers}'), scrollFocusZoom: Binding.Empty, -} +}; export const TrackballControlsParams = { noScroll: PD.Boolean(true, { isHidden: true }), @@ -50,10 +50,10 @@ export const TrackballControlsParams = { maxDistance: PD.Numeric(1e150, {}, { isHidden: true }), bindings: PD.Value(DefaultTrackballBindings, { isHidden: true }) -} +}; export type TrackballControlsProps = PD.Values<typeof TrackballControlsParams> -export { TrackballControls } +export { TrackballControls }; interface TrackballControls { viewport: Viewport @@ -66,48 +66,48 @@ interface TrackballControls { } namespace TrackballControls { export function create(input: InputObserver, camera: Camera, props: Partial<TrackballControlsProps> = {}): TrackballControls { - const p = { ...PD.getDefaultValues(TrackballControlsParams), ...props } + const p = { ...PD.getDefaultValues(TrackballControlsParams), ...props }; - const viewport = Viewport() + const viewport = Viewport(); - let disposed = false + let disposed = false; - const dragSub = input.drag.subscribe(onDrag) - const interactionEndSub = input.interactionEnd.subscribe(onInteractionEnd) - const wheelSub = input.wheel.subscribe(onWheel) - const pinchSub = input.pinch.subscribe(onPinch) + const dragSub = input.drag.subscribe(onDrag); + const interactionEndSub = input.interactionEnd.subscribe(onInteractionEnd); + const wheelSub = input.wheel.subscribe(onWheel); + const pinchSub = input.pinch.subscribe(onPinch); let _isInteracting = false; // For internal use - const lastPosition = Vec3() + const lastPosition = Vec3(); - const _eye = Vec3() + const _eye = Vec3(); - const _rotPrev = Vec2() - const _rotCurr = Vec2() - const _rotLastAxis = Vec3() - let _rotLastAngle = 0 + const _rotPrev = Vec2(); + const _rotCurr = Vec2(); + const _rotLastAxis = Vec3(); + let _rotLastAngle = 0; - const _zRotPrev = Vec2() - const _zRotCurr = Vec2() - let _zRotLastAngle = 0 + const _zRotPrev = Vec2(); + const _zRotCurr = Vec2(); + let _zRotLastAngle = 0; - const _zoomStart = Vec2() - const _zoomEnd = Vec2() + const _zoomStart = Vec2(); + const _zoomEnd = Vec2(); - const _focusStart = Vec2() - const _focusEnd = Vec2() + const _focusStart = Vec2(); + const _focusEnd = Vec2(); - const _panStart = Vec2() - const _panEnd = Vec2() + const _panStart = Vec2(); + const _panEnd = Vec2(); // Initial values for reseting - const target0 = Vec3.clone(camera.target) - const position0 = Vec3.clone(camera.position) - const up0 = Vec3.clone(camera.up) + const target0 = Vec3.clone(camera.target); + const position0 = Vec3.clone(camera.position); + const up0 = Vec3.clone(camera.up); - const mouseOnScreenVec2 = Vec2() + const mouseOnScreenVec2 = Vec2(); function getMouseOnScreen(pageX: number, pageY: number) { return Vec2.set( mouseOnScreenVec2, @@ -116,7 +116,7 @@ namespace TrackballControls { ); } - const mouseOnCircleVec2 = Vec2() + const mouseOnCircleVec2 = Vec2(); function getMouseOnCircle(pageX: number, pageY: number) { return Vec2.set( mouseOnCircleVec2, @@ -125,125 +125,125 @@ namespace TrackballControls { ); } - const rotAxis = Vec3() - const rotQuat = Quat() - const rotEyeDir = Vec3() - const rotObjUpDir = Vec3() - const rotObjSideDir = Vec3() - const rotMoveDir = Vec3() + const rotAxis = Vec3(); + const rotQuat = Quat(); + const rotEyeDir = Vec3(); + const rotObjUpDir = Vec3(); + const rotObjSideDir = Vec3(); + const rotMoveDir = Vec3(); function rotateCamera() { - const dx = _rotCurr[0] - _rotPrev[0] - const dy = _rotCurr[1] - _rotPrev[1] + const dx = _rotCurr[0] - _rotPrev[0]; + const dy = _rotCurr[1] - _rotPrev[1]; Vec3.set(rotMoveDir, dx, dy, 0); const angle = Vec3.magnitude(rotMoveDir) * p.rotateSpeed; if (angle) { - Vec3.sub(_eye, camera.position, camera.target) + Vec3.sub(_eye, camera.position, camera.target); - Vec3.normalize(rotEyeDir, _eye) - Vec3.normalize(rotObjUpDir, camera.up) - Vec3.normalize(rotObjSideDir, Vec3.cross(rotObjSideDir, rotObjUpDir, rotEyeDir)) + Vec3.normalize(rotEyeDir, _eye); + Vec3.normalize(rotObjUpDir, camera.up); + Vec3.normalize(rotObjSideDir, Vec3.cross(rotObjSideDir, rotObjUpDir, rotEyeDir)); - Vec3.setMagnitude(rotObjUpDir, rotObjUpDir, dy) - Vec3.setMagnitude(rotObjSideDir, rotObjSideDir, dx) + Vec3.setMagnitude(rotObjUpDir, rotObjUpDir, dy); + Vec3.setMagnitude(rotObjSideDir, rotObjSideDir, dx); - Vec3.add(rotMoveDir, rotObjUpDir, rotObjSideDir) - Vec3.normalize(rotAxis, Vec3.cross(rotAxis, rotMoveDir, _eye)) - Quat.setAxisAngle(rotQuat, rotAxis, angle) + Vec3.add(rotMoveDir, rotObjUpDir, rotObjSideDir); + Vec3.normalize(rotAxis, Vec3.cross(rotAxis, rotMoveDir, _eye)); + Quat.setAxisAngle(rotQuat, rotAxis, angle); - Vec3.transformQuat(_eye, _eye, rotQuat) - Vec3.transformQuat(camera.up, camera.up, rotQuat) + Vec3.transformQuat(_eye, _eye, rotQuat); + Vec3.transformQuat(camera.up, camera.up, rotQuat); - Vec3.copy(_rotLastAxis, rotAxis) + Vec3.copy(_rotLastAxis, rotAxis); _rotLastAngle = angle; } else if (!p.staticMoving && _rotLastAngle) { _rotLastAngle *= Math.sqrt(1.0 - p.dynamicDampingFactor); - Vec3.sub(_eye, camera.position, camera.target) - Quat.setAxisAngle(rotQuat, _rotLastAxis, _rotLastAngle) + Vec3.sub(_eye, camera.position, camera.target); + Quat.setAxisAngle(rotQuat, _rotLastAxis, _rotLastAngle); - Vec3.transformQuat(_eye, _eye, rotQuat) - Vec3.transformQuat(camera.up, camera.up, rotQuat) + Vec3.transformQuat(_eye, _eye, rotQuat); + Vec3.transformQuat(camera.up, camera.up, rotQuat); } - Vec2.copy(_rotPrev, _rotCurr) + Vec2.copy(_rotPrev, _rotCurr); } - const zRotQuat = Quat() + const zRotQuat = Quat(); function zRotateCamera() { - const dx = _zRotCurr[0] - _zRotPrev[0] - const dy = _zRotCurr[1] - _zRotPrev[1] - const angle = p.rotateSpeed * (-dx + dy) * -0.05 + const dx = _zRotCurr[0] - _zRotPrev[0]; + const dy = _zRotCurr[1] - _zRotPrev[1]; + const angle = p.rotateSpeed * (-dx + dy) * -0.05; if (angle) { - Vec3.sub(_eye, camera.position, camera.target) - Quat.setAxisAngle(zRotQuat, _eye, angle) - Vec3.transformQuat(camera.up, camera.up, zRotQuat) + Vec3.sub(_eye, camera.position, camera.target); + Quat.setAxisAngle(zRotQuat, _eye, angle); + Vec3.transformQuat(camera.up, camera.up, zRotQuat); _zRotLastAngle = angle; } else if (!p.staticMoving && _zRotLastAngle) { _zRotLastAngle *= Math.sqrt(1.0 - p.dynamicDampingFactor); - Vec3.sub(_eye, camera.position, camera.target) - Quat.setAxisAngle(zRotQuat, _eye, _zRotLastAngle) - Vec3.transformQuat(camera.up, camera.up, zRotQuat) + Vec3.sub(_eye, camera.position, camera.target); + Quat.setAxisAngle(zRotQuat, _eye, _zRotLastAngle); + Vec3.transformQuat(camera.up, camera.up, zRotQuat); } - Vec2.copy(_zRotPrev, _zRotCurr) + Vec2.copy(_zRotPrev, _zRotCurr); } function zoomCamera() { - const factor = 1.0 + (_zoomEnd[1] - _zoomStart[1]) * p.zoomSpeed + const factor = 1.0 + (_zoomEnd[1] - _zoomStart[1]) * p.zoomSpeed; if (factor !== 1.0 && factor > 0.0) { - Vec3.scale(_eye, _eye, factor) + Vec3.scale(_eye, _eye, factor); } if (p.staticMoving) { - Vec2.copy(_zoomStart, _zoomEnd) + Vec2.copy(_zoomStart, _zoomEnd); } else { - _zoomStart[1] += (_zoomEnd[1] - _zoomStart[1]) * p.dynamicDampingFactor + _zoomStart[1] += (_zoomEnd[1] - _zoomStart[1]) * p.dynamicDampingFactor; } } function focusCamera() { - const factor = (_focusEnd[1] - _focusStart[1]) * p.zoomSpeed + const factor = (_focusEnd[1] - _focusStart[1]) * p.zoomSpeed; if (factor !== 0.0) { - const radius = Math.max(1, camera.state.radius + camera.state.radius * factor) - camera.setState({ radius }) + const radius = Math.max(1, camera.state.radius + camera.state.radius * factor); + camera.setState({ radius }); } if (p.staticMoving) { - Vec2.copy(_focusStart, _focusEnd) + Vec2.copy(_focusStart, _focusEnd); } else { - _focusStart[1] += (_focusEnd[1] - _focusStart[1]) * p.dynamicDampingFactor + _focusStart[1] += (_focusEnd[1] - _focusStart[1]) * p.dynamicDampingFactor; } } - const panMouseChange = Vec2() - const panObjUp = Vec3() - const panOffset = Vec3() + const panMouseChange = Vec2(); + const panObjUp = Vec3(); + const panOffset = Vec3(); function panCamera() { - Vec2.sub(panMouseChange, Vec2.copy(panMouseChange, _panEnd), _panStart) + Vec2.sub(panMouseChange, Vec2.copy(panMouseChange, _panEnd), _panStart); if (Vec2.squaredMagnitude(panMouseChange)) { - Vec2.scale(panMouseChange, panMouseChange, Vec3.magnitude(_eye) * p.panSpeed) + Vec2.scale(panMouseChange, panMouseChange, Vec3.magnitude(_eye) * p.panSpeed); - Vec3.cross(panOffset, Vec3.copy(panOffset, _eye), camera.up) - Vec3.setMagnitude(panOffset, panOffset, panMouseChange[0]) + Vec3.cross(panOffset, Vec3.copy(panOffset, _eye), camera.up); + Vec3.setMagnitude(panOffset, panOffset, panMouseChange[0]); - Vec3.setMagnitude(panObjUp, camera.up, panMouseChange[1]) - Vec3.add(panOffset, panOffset, panObjUp) + Vec3.setMagnitude(panObjUp, camera.up, panMouseChange[1]); + Vec3.add(panOffset, panOffset, panObjUp); - Vec3.add(camera.position, camera.position, panOffset) - Vec3.add(camera.target, camera.target, panOffset) + Vec3.add(camera.position, camera.position, panOffset); + Vec3.add(camera.target, camera.target, panOffset); if (p.staticMoving) { - Vec2.copy(_panStart, _panEnd) + Vec2.copy(_panStart, _panEnd); } else { - Vec2.sub(panMouseChange, _panEnd, _panStart) - Vec2.scale(panMouseChange, panMouseChange, p.dynamicDampingFactor) - Vec2.add(_panStart, _panStart, panMouseChange) + Vec2.sub(panMouseChange, _panEnd, _panStart); + Vec2.scale(panMouseChange, panMouseChange, p.dynamicDampingFactor); + Vec2.add(_panStart, _panStart, panMouseChange); } } } @@ -253,19 +253,19 @@ namespace TrackballControls { * and not too large compared to `camera.state.radiusMax` */ function checkDistances() { - const maxDistance = Math.min(Math.max(camera.state.radiusMax * 1000, 0.01), p.maxDistance) + const maxDistance = Math.min(Math.max(camera.state.radiusMax * 1000, 0.01), p.maxDistance); if (Vec3.squaredMagnitude(_eye) > maxDistance * maxDistance) { - Vec3.setMagnitude(_eye, _eye, maxDistance) - Vec3.add(camera.position, camera.target, _eye) - Vec2.copy(_zoomStart, _zoomEnd) - Vec2.copy(_focusStart, _focusEnd) + Vec3.setMagnitude(_eye, _eye, maxDistance); + Vec3.add(camera.position, camera.target, _eye); + Vec2.copy(_zoomStart, _zoomEnd); + Vec2.copy(_focusStart, _focusEnd); } if (Vec3.squaredMagnitude(_eye) < p.minDistance * p.minDistance) { - Vec3.setMagnitude(_eye, _eye, p.minDistance) - Vec3.add(camera.position, camera.target, _eye) - Vec2.copy(_zoomStart, _zoomEnd) - Vec2.copy(_focusStart, _focusEnd) + Vec3.setMagnitude(_eye, _eye, p.minDistance); + Vec3.add(camera.position, camera.target, _eye); + Vec2.copy(_zoomStart, _zoomEnd); + Vec2.copy(_focusStart, _focusEnd); } } @@ -275,19 +275,19 @@ namespace TrackballControls { if (lastUpdated === t) return; if (p.spin) spin(t - lastUpdated); - Vec3.sub(_eye, camera.position, camera.target) + Vec3.sub(_eye, camera.position, camera.target); - rotateCamera() - zRotateCamera() - zoomCamera() - focusCamera() - panCamera() + rotateCamera(); + zRotateCamera(); + zoomCamera(); + focusCamera(); + panCamera(); - Vec3.add(camera.position, camera.target, _eye) - checkDistances() + Vec3.add(camera.position, camera.target, _eye); + checkDistances(); if (Vec3.squaredDistance(lastPosition, camera.position) > EPSILON) { - Vec3.copy(lastPosition, camera.position) + Vec3.copy(lastPosition, camera.position); } lastUpdated = t; @@ -295,12 +295,12 @@ namespace TrackballControls { /** Reset object's vectors and the target vector to their initial values */ function reset() { - Vec3.copy(camera.target, target0) - Vec3.copy(camera.position, position0) - Vec3.copy(camera.up, up0) + Vec3.copy(camera.target, target0); + Vec3.copy(camera.position, position0); + Vec3.copy(camera.up, up0); - Vec3.sub(_eye, camera.position, camera.target) - Vec3.copy(lastPosition, camera.position) + Vec3.sub(_eye, camera.position, camera.target); + Vec3.copy(lastPosition, camera.position); } // listeners @@ -308,48 +308,48 @@ namespace TrackballControls { function onDrag({ pageX, pageY, buttons, modifiers, isStart }: DragInput) { _isInteracting = true; - const dragRotate = Binding.match(p.bindings.dragRotate, buttons, modifiers) - const dragRotateZ = Binding.match(p.bindings.dragRotateZ, buttons, modifiers) - const dragPan = Binding.match(p.bindings.dragPan, buttons, modifiers) - const dragZoom = Binding.match(p.bindings.dragZoom, buttons, modifiers) - const dragFocus = Binding.match(p.bindings.dragFocus, buttons, modifiers) - const dragFocusZoom = Binding.match(p.bindings.dragFocusZoom, buttons, modifiers) + const dragRotate = Binding.match(p.bindings.dragRotate, buttons, modifiers); + const dragRotateZ = Binding.match(p.bindings.dragRotateZ, buttons, modifiers); + const dragPan = Binding.match(p.bindings.dragPan, buttons, modifiers); + const dragZoom = Binding.match(p.bindings.dragZoom, buttons, modifiers); + const dragFocus = Binding.match(p.bindings.dragFocus, buttons, modifiers); + const dragFocusZoom = Binding.match(p.bindings.dragFocusZoom, buttons, modifiers); - getMouseOnCircle(pageX, pageY) - getMouseOnScreen(pageX, pageY) + getMouseOnCircle(pageX, pageY); + getMouseOnScreen(pageX, pageY); if (isStart) { if (dragRotate) { - Vec2.copy(_rotCurr, mouseOnCircleVec2) - Vec2.copy(_rotPrev, _rotCurr) + Vec2.copy(_rotCurr, mouseOnCircleVec2); + Vec2.copy(_rotPrev, _rotCurr); } if (dragRotateZ) { - Vec2.copy(_zRotCurr, mouseOnCircleVec2) - Vec2.copy(_zRotPrev, _zRotCurr) + Vec2.copy(_zRotCurr, mouseOnCircleVec2); + Vec2.copy(_zRotPrev, _zRotCurr); } if (dragZoom || dragFocusZoom) { - Vec2.copy(_zoomStart, mouseOnScreenVec2) - Vec2.copy(_zoomEnd, _zoomStart) + Vec2.copy(_zoomStart, mouseOnScreenVec2); + Vec2.copy(_zoomEnd, _zoomStart); } if (dragFocus) { - Vec2.copy(_focusStart, mouseOnScreenVec2) - Vec2.copy(_focusEnd, _focusStart) + Vec2.copy(_focusStart, mouseOnScreenVec2); + Vec2.copy(_focusEnd, _focusStart); } if (dragPan) { - Vec2.copy(_panStart, mouseOnScreenVec2) - Vec2.copy(_panEnd, _panStart) + Vec2.copy(_panStart, mouseOnScreenVec2); + Vec2.copy(_panEnd, _panStart); } } - if (dragRotate) Vec2.copy(_rotCurr, mouseOnCircleVec2) - if (dragRotateZ) Vec2.copy(_zRotCurr, mouseOnCircleVec2) - if (dragZoom || dragFocusZoom) Vec2.copy(_zoomEnd, mouseOnScreenVec2) - if (dragFocus) Vec2.copy(_focusEnd, mouseOnScreenVec2) + if (dragRotate) Vec2.copy(_rotCurr, mouseOnCircleVec2); + if (dragRotateZ) Vec2.copy(_zRotCurr, mouseOnCircleVec2); + if (dragZoom || dragFocusZoom) Vec2.copy(_zoomEnd, mouseOnScreenVec2); + if (dragFocus) Vec2.copy(_focusEnd, mouseOnScreenVec2); if (dragFocusZoom) { const dist = Vec3.distance(camera.state.position, camera.state.target); - camera.setState({ radius: dist / 5 }) + camera.setState({ radius: dist / 5 }); } - if (dragPan) Vec2.copy(_panEnd, mouseOnScreenVec2) + if (dragPan) Vec2.copy(_panEnd, mouseOnScreenVec2); } function onInteractionEnd() { @@ -357,30 +357,30 @@ namespace TrackballControls { } function onWheel({ dx, dy, dz, buttons, modifiers }: WheelInput) { - const delta = absMax(dx, dy, dz) + const delta = absMax(dx, dy, dz); if (Binding.match(p.bindings.scrollZoom, buttons, modifiers)) { - _zoomEnd[1] += delta * 0.0001 + _zoomEnd[1] += delta * 0.0001; } if (Binding.match(p.bindings.scrollFocus, buttons, modifiers)) { - _focusEnd[1] += delta * 0.0001 + _focusEnd[1] += delta * 0.0001; } } function onPinch({ fraction, buttons, modifiers }: PinchInput) { if (Binding.match(p.bindings.scrollZoom, buttons, modifiers)) { _isInteracting = true; - _zoomEnd[1] += (fraction - 1) * 0.1 + _zoomEnd[1] += (fraction - 1) * 0.1; } } function dispose() { - if (disposed) return - disposed = true + if (disposed) return; + disposed = true; - dragSub.unsubscribe() - wheelSub.unsubscribe() - pinchSub.unsubscribe() - interactionEndSub.unsubscribe() + dragSub.unsubscribe(); + wheelSub.unsubscribe(); + pinchSub.unsubscribe(); + interactionEndSub.unsubscribe(); } const _spinSpeed = Vec2.create(0.005, 0); @@ -396,14 +396,14 @@ namespace TrackballControls { return { viewport, - get props() { return p as Readonly<TrackballControlsProps> }, + get props() { return p as Readonly<TrackballControlsProps>; }, setProps: (props: Partial<TrackballControlsProps>) => { - Object.assign(p, props) + Object.assign(p, props); }, update, reset, dispose - } + }; } } \ No newline at end of file diff --git a/src/mol-canvas3d/helper/bounding-sphere-helper.ts b/src/mol-canvas3d/helper/bounding-sphere-helper.ts index 62cb5ad937b48e31898f4e4edb34673c700ab73a..57540217aac5624d43d261f4ae15bb0d2916ef29 100644 --- a/src/mol-canvas3d/helper/bounding-sphere-helper.ts +++ b/src/mol-canvas3d/helper/bounding-sphere-helper.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { createRenderObject, GraphicsRenderObject, getNextMaterialId } from '../../mol-gl/render-object' +import { createRenderObject, GraphicsRenderObject, getNextMaterialId } from '../../mol-gl/render-object'; import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder'; import { addSphere } from '../../mol-geo/geometry/mesh/builder/sphere'; import { Mesh } from '../../mol-geo/geometry/mesh/mesh'; @@ -24,7 +24,7 @@ export const DebugHelperParams = { visibleSceneBoundingSpheres: PD.Boolean(false, { description: 'Show visible scene bounding spheres.' }), objectBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of visible render objects.' }), instanceBoundingSpheres: PD.Boolean(false, { description: 'Show bounding spheres of visible instances.' }), -} +}; export type DebugHelperParams = typeof DebugHelperParams export type DebugHelperProps = PD.Values<DebugHelperParams> @@ -41,24 +41,24 @@ export class BoundingSphereHelper { private visibleSceneData: BoundingSphereData | undefined constructor(ctx: WebGLContext, parent: Scene, props: Partial<DebugHelperProps>) { - this.scene = Scene.create(ctx) - this.parent = parent - this._props = { ...PD.getDefaultValues(DebugHelperParams), ...props } + this.scene = Scene.create(ctx); + this.parent = parent; + this._props = { ...PD.getDefaultValues(DebugHelperParams), ...props }; } update() { - const newSceneData = updateBoundingSphereData(this.scene, this.parent.boundingSphere, this.sceneData, ColorNames.lightgrey, sceneMaterialId) - if (newSceneData) this.sceneData = newSceneData + const newSceneData = updateBoundingSphereData(this.scene, this.parent.boundingSphere, this.sceneData, ColorNames.lightgrey, sceneMaterialId); + if (newSceneData) this.sceneData = newSceneData; - const newVisibleSceneData = updateBoundingSphereData(this.scene, this.parent.boundingSphereVisible, this.visibleSceneData, ColorNames.black, visibleSceneMaterialId) - if (newVisibleSceneData) this.visibleSceneData = newVisibleSceneData + const newVisibleSceneData = updateBoundingSphereData(this.scene, this.parent.boundingSphereVisible, this.visibleSceneData, ColorNames.black, visibleSceneMaterialId); + if (newVisibleSceneData) this.visibleSceneData = newVisibleSceneData; this.parent.forEach((r, ro) => { - const objectData = this.objectsData.get(ro) - const newObjectData = updateBoundingSphereData(this.scene, r.values.boundingSphere.ref.value, objectData, ColorNames.tomato, objectMaterialId) - if (newObjectData) this.objectsData.set(ro, newObjectData) + const objectData = this.objectsData.get(ro); + const newObjectData = updateBoundingSphereData(this.scene, r.values.boundingSphere.ref.value, objectData, ColorNames.tomato, objectMaterialId); + if (newObjectData) this.objectsData.set(ro, newObjectData); - const instanceData = this.instancesData.get(ro) + const instanceData = this.instancesData.get(ro); const newInstanceData = updateBoundingSphereData(this.scene, r.values.invariantBoundingSphere.ref.value, instanceData, ColorNames.skyblue, instanceMaterialId, { aTransform: ro.values.aTransform, matrix: ro.values.matrix, @@ -67,97 +67,97 @@ export class BoundingSphereHelper { uInstanceCount: ro.values.uInstanceCount, instanceCount: ro.values.instanceCount, aInstance: ro.values.aInstance, - }) - if (newInstanceData) this.instancesData.set(ro, newInstanceData) - }) + }); + if (newInstanceData) this.instancesData.set(ro, newInstanceData); + }); this.objectsData.forEach((objectData, ro) => { if (!this.parent.has(ro)) { - this.scene.remove(objectData.renderObject) - this.objectsData.delete(ro) + this.scene.remove(objectData.renderObject); + this.objectsData.delete(ro); } - }) + }); this.instancesData.forEach((instanceData, ro) => { if (!this.parent.has(ro)) { - this.scene.remove(instanceData.renderObject) - this.instancesData.delete(ro) + this.scene.remove(instanceData.renderObject); + this.instancesData.delete(ro); } - }) + }); - this.scene.update(void 0, false) - this.scene.commit() + this.scene.update(void 0, false); + this.scene.commit(); } syncVisibility() { if (this.sceneData) { - this.sceneData.renderObject.state.visible = this._props.sceneBoundingSpheres + this.sceneData.renderObject.state.visible = this._props.sceneBoundingSpheres; } if (this.visibleSceneData) { - this.visibleSceneData.renderObject.state.visible = this._props.visibleSceneBoundingSpheres + this.visibleSceneData.renderObject.state.visible = this._props.visibleSceneBoundingSpheres; } this.parent.forEach((_, ro) => { - const objectData = this.objectsData.get(ro) - if (objectData) objectData.renderObject.state.visible = ro.state.visible && this._props.objectBoundingSpheres + const objectData = this.objectsData.get(ro); + if (objectData) objectData.renderObject.state.visible = ro.state.visible && this._props.objectBoundingSpheres; - const instanceData = this.instancesData.get(ro) - if (instanceData) instanceData.renderObject.state.visible = ro.state.visible && this._props.instanceBoundingSpheres - }) + const instanceData = this.instancesData.get(ro); + if (instanceData) instanceData.renderObject.state.visible = ro.state.visible && this._props.instanceBoundingSpheres; + }); } clear() { - this.sceneData = undefined - this.objectsData.clear() - this.scene.clear() + this.sceneData = undefined; + this.objectsData.clear(); + this.scene.clear(); } get isEnabled() { return ( this._props.sceneBoundingSpheres || this._props.visibleSceneBoundingSpheres || this._props.objectBoundingSpheres || this._props.instanceBoundingSpheres - ) + ); } - get props() { return this._props as Readonly<DebugHelperProps> } + get props() { return this._props as Readonly<DebugHelperProps>; } setProps (props: Partial<DebugHelperProps>) { - Object.assign(this._props, props) - if (this.isEnabled) this.update() + Object.assign(this._props, props); + if (this.isEnabled) this.update(); } } function updateBoundingSphereData(scene: Scene, boundingSphere: Sphere3D, data: BoundingSphereData | undefined, color: Color, materialId: number, transform?: TransformData) { if (!data || !Sphere3D.equals(data.boundingSphere, boundingSphere)) { - const mesh = createBoundingSphereMesh(boundingSphere, data && data.mesh) - const renderObject = data ? data.renderObject : createBoundingSphereRenderObject(mesh, color, materialId, transform) + const mesh = createBoundingSphereMesh(boundingSphere, data && data.mesh); + const renderObject = data ? data.renderObject : createBoundingSphereRenderObject(mesh, color, materialId, transform); if (data) { - ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(mesh)) + ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(mesh)); } else { - scene.add(renderObject) + scene.add(renderObject); } - return { boundingSphere: Sphere3D.clone(boundingSphere), renderObject, mesh } + return { boundingSphere: Sphere3D.clone(boundingSphere), renderObject, mesh }; } } function createBoundingSphereMesh(boundingSphere: Sphere3D, mesh?: Mesh) { - const detail = 2 - const vertexCount = sphereVertexCount(detail) - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh) + const detail = 2; + const vertexCount = sphereVertexCount(detail); + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh); if (boundingSphere.radius) { - addSphere(builderState, boundingSphere.center, boundingSphere.radius, detail) + addSphere(builderState, boundingSphere.center, boundingSphere.radius, detail); if (Sphere3D.hasExtrema(boundingSphere)) { - for (const e of boundingSphere.extrema) addSphere(builderState, e, 1.0, 0) + for (const e of boundingSphere.extrema) addSphere(builderState, e, 1.0, 0); } } - return MeshBuilder.getMesh(builderState) + return MeshBuilder.getMesh(builderState); } -const sceneMaterialId = getNextMaterialId() -const visibleSceneMaterialId = getNextMaterialId() -const objectMaterialId = getNextMaterialId() -const instanceMaterialId = getNextMaterialId() +const sceneMaterialId = getNextMaterialId(); +const visibleSceneMaterialId = getNextMaterialId(); +const objectMaterialId = getNextMaterialId(); +const instanceMaterialId = getNextMaterialId(); function createBoundingSphereRenderObject(mesh: Mesh, color: Color, materialId: number, transform?: TransformData) { - const values = Mesh.Utils.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, 1, transform) - return createRenderObject('mesh', values, { visible: true, alphaFactor: 1, pickable: false, opaque: false }, materialId) + const values = Mesh.Utils.createValuesSimple(mesh, { alpha: 0.1, doubleSided: false }, color, 1, transform); + return createRenderObject('mesh', values, { visible: true, alphaFactor: 1, pickable: false, opaque: false }, materialId); } \ No newline at end of file diff --git a/src/mol-canvas3d/helper/camera-helper.ts b/src/mol-canvas3d/helper/camera-helper.ts index 6cde389cbaf259d0ba7948170a02edd9c1f753bb..586d2a09b01c70bf7a824556df71a1668d22e107 100644 --- a/src/mol-canvas3d/helper/camera-helper.ts +++ b/src/mol-canvas3d/helper/camera-helper.ts @@ -31,7 +31,7 @@ const AxesParams = { colorY: PD.Color(ColorNames.green, { isEssential: true }), colorZ: PD.Color(ColorNames.blue, { isEssential: true }), scale: PD.Numeric(0.33, { min: 0.1, max: 2, step: 0.1 }, { isEssential: true }), -} +}; type AxesParams = typeof AxesParams type AxesProps = PD.Values<AxesParams> @@ -40,7 +40,7 @@ export const CameraHelperParams = { on: PD.Group(AxesParams), off: PD.Group({}) }, { cycle: true, description: 'Show camera orientation axes' }), -} +}; export type CameraHelperParams = typeof CameraHelperParams export type CameraHelperProps = PD.Values<CameraHelperParams> @@ -54,122 +54,122 @@ export class CameraHelper { private renderObject: GraphicsRenderObject | undefined constructor(private webgl: WebGLContext, props: Partial<CameraHelperProps> = {}) { - this.scene = Scene.create(webgl) + this.scene = Scene.create(webgl); - this.camera = new Camera() - Vec3.set(this.camera.up, 0, 1, 0) - Vec3.set(this.camera.target, 0, 0, 0) + this.camera = new Camera(); + Vec3.set(this.camera.up, 0, 1, 0); + Vec3.set(this.camera.target, 0, 0, 0); - this.setProps(props) + this.setProps(props); } setProps(props: Partial<CameraHelperProps>) { this.props = produce(this.props, p => { if (props.axes !== undefined) { - p.axes.name = props.axes.name + p.axes.name = props.axes.name; if (props.axes.name === 'on') { - this.scene.clear() - const params = { ...props.axes.params, scale: props.axes.params.scale * this.webgl.pixelRatio } - this.renderObject = createAxesRenderObject(params) - this.scene.add(this.renderObject) - this.scene.commit() + this.scene.clear(); + const params = { ...props.axes.params, scale: props.axes.params.scale * this.webgl.pixelRatio }; + this.renderObject = createAxesRenderObject(params); + this.scene.add(this.renderObject); + this.scene.commit(); - Vec3.set(this.camera.position, 0, 0, params.scale * 200) - Mat4.lookAt(this.camera.view, this.camera.position, this.camera.target, this.camera.up) + Vec3.set(this.camera.position, 0, 0, params.scale * 200); + Mat4.lookAt(this.camera.view, this.camera.position, this.camera.target, this.camera.up); - p.axes.params = { ...props.axes.params } + p.axes.params = { ...props.axes.params }; } } - }) + }); } get isEnabled() { - return this.props.axes.name === 'on' + return this.props.axes.name === 'on'; } update(camera: Camera) { - if (!this.renderObject) return + if (!this.renderObject) return; - updateCamera(this.camera, camera.viewport) + updateCamera(this.camera, camera.viewport); - const m = this.renderObject.values.aTransform.ref.value as unknown as Mat4 - Mat4.extractRotation(m, camera.view) + const m = this.renderObject.values.aTransform.ref.value as unknown as Mat4; + Mat4.extractRotation(m, camera.view); - const r = this.renderObject.values.boundingSphere.ref.value.radius + const r = this.renderObject.values.boundingSphere.ref.value.radius; Mat4.setTranslation(m, Vec3.create( -camera.viewport.width / 2 + r, -camera.viewport.height / 2 + r, 0 - )) + )); - ValueCell.update(this.renderObject.values.aTransform, this.renderObject.values.aTransform.ref.value) - this.scene.update([this.renderObject], true) + ValueCell.update(this.renderObject.values.aTransform, this.renderObject.values.aTransform.ref.value); + this.scene.update([this.renderObject], true); } } function updateCamera(camera: Camera, viewport: Viewport) { - const { near, far } = camera + const { near, far } = camera; - const fullLeft = -(viewport.width - viewport.x) / 2 - const fullRight = (viewport.width - viewport.x) / 2 - const fullTop = (viewport.height - viewport.y) / 2 - const fullBottom = -(viewport.height - viewport.y) / 2 + const fullLeft = -(viewport.width - viewport.x) / 2; + const fullRight = (viewport.width - viewport.x) / 2; + const fullTop = (viewport.height - viewport.y) / 2; + const fullBottom = -(viewport.height - viewport.y) / 2; - const dx = (fullRight - fullLeft) / 2 - const dy = (fullTop - fullBottom) / 2 - const cx = (fullRight + fullLeft) / 2 - const cy = (fullTop + fullBottom) / 2 + const dx = (fullRight - fullLeft) / 2; + const dy = (fullTop - fullBottom) / 2; + const cx = (fullRight + fullLeft) / 2; + const cy = (fullTop + fullBottom) / 2; - const left = cx - dx - const right = cx + dx - const top = cy + dy - const bottom = cy - dy + const left = cx - dx; + const right = cx + dx; + const top = cy + dy; + const bottom = cy - dy; - Mat4.ortho(camera.projection, left, right, top, bottom, near, far) + Mat4.ortho(camera.projection, left, right, top, bottom, near, far); } function createAxesMesh(scale: number, mesh?: Mesh) { - const state = MeshBuilder.createState(512, 256, mesh) - const radius = 0.05 * scale - const x = Vec3.scale(Vec3(), Vec3.unitX, scale) - const y = Vec3.scale(Vec3(), Vec3.unitY, scale) - const z = Vec3.scale(Vec3(), Vec3.unitZ, scale) - const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments: 32 } + const state = MeshBuilder.createState(512, 256, mesh); + const radius = 0.05 * scale; + const x = Vec3.scale(Vec3(), Vec3.unitX, scale); + const y = Vec3.scale(Vec3(), Vec3.unitY, scale); + const z = Vec3.scale(Vec3(), Vec3.unitZ, scale); + const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments: 32 }; - state.currentGroup = 0 - addSphere(state, Vec3.origin, radius, 2) + state.currentGroup = 0; + addSphere(state, Vec3.origin, radius, 2); - state.currentGroup = 1 - addSphere(state, x, radius, 2) - addCylinder(state, Vec3.origin, x, 1, cylinderProps) + state.currentGroup = 1; + addSphere(state, x, radius, 2); + addCylinder(state, Vec3.origin, x, 1, cylinderProps); - state.currentGroup = 2 - addSphere(state, y, radius, 2) - addCylinder(state, Vec3.origin, y, 1, cylinderProps) + state.currentGroup = 2; + addSphere(state, y, radius, 2); + addCylinder(state, Vec3.origin, y, 1, cylinderProps); - state.currentGroup = 3 - addSphere(state, z, radius, 2) - addCylinder(state, Vec3.origin, z, 1, cylinderProps) + state.currentGroup = 3; + addSphere(state, z, radius, 2); + addCylinder(state, Vec3.origin, z, 1, cylinderProps); - return MeshBuilder.getMesh(state) + return MeshBuilder.getMesh(state); } function getAxesShape(props: AxesProps, shape?: Shape<Mesh>) { - const scale = 100 * props.scale - const mesh = createAxesMesh(scale, shape?.geometry) - mesh.setBoundingSphere(Sphere3D.create(Vec3.create(scale / 2, scale / 2, scale / 2), scale + scale / 4)) + const scale = 100 * props.scale; + const mesh = createAxesMesh(scale, shape?.geometry); + mesh.setBoundingSphere(Sphere3D.create(Vec3.create(scale / 2, scale / 2, scale / 2), scale + scale / 4)); const getColor = (groupId: number) => { switch (groupId) { - case 1: return props.colorX - case 2: return props.colorY - case 3: return props.colorZ - default: return ColorNames.grey + case 1: return props.colorX; + case 2: return props.colorY; + case 3: return props.colorZ; + default: return ColorNames.grey; } - } - return Shape.create('axes', {}, mesh, getColor, () => 1, () => '') + }; + return Shape.create('axes', {}, mesh, getColor, () => 1, () => ''); } function createAxesRenderObject(props: AxesProps) { - const shape = getAxesShape(props) - return Shape.createRenderObject(shape, props) + const shape = getAxesShape(props); + return Shape.createRenderObject(shape, props); } \ No newline at end of file diff --git a/src/mol-canvas3d/passes/draw.ts b/src/mol-canvas3d/passes/draw.ts index a86d5a357e4a4772634f71ba26bb06669702caa4..090579166ff9193611fe21db1fa0d194f938fd7b 100644 --- a/src/mol-canvas3d/passes/draw.ts +++ b/src/mol-canvas3d/passes/draw.ts @@ -16,7 +16,7 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition'; export const DrawPassParams = { cameraHelper: PD.Group(CameraHelperParams) -} +}; export const DefaultDrawPassProps = PD.getDefaultValues(DrawPassParams); export type DrawPassProps = PD.Values<typeof DrawPassParams> @@ -30,74 +30,74 @@ export class DrawPass { private depthTarget: RenderTarget | null constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private camera: Camera, private debugHelper: BoundingSphereHelper, props: Partial<DrawPassProps> = {}) { - const { gl, extensions, resources } = webgl - const width = gl.drawingBufferWidth - const height = gl.drawingBufferHeight - this.colorTarget = webgl.createRenderTarget(width, height) - this.packedDepth = !extensions.depthTexture - this.depthTarget = this.packedDepth ? webgl.createRenderTarget(width, height) : null - this.depthTexture = this.depthTarget ? this.depthTarget.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest') + const { gl, extensions, resources } = webgl; + const width = gl.drawingBufferWidth; + const height = gl.drawingBufferHeight; + this.colorTarget = webgl.createRenderTarget(width, height); + this.packedDepth = !extensions.depthTexture; + this.depthTarget = this.packedDepth ? webgl.createRenderTarget(width, height) : null; + this.depthTexture = this.depthTarget ? this.depthTarget.texture : resources.texture('image-depth', 'depth', 'ushort', 'nearest'); if (!this.packedDepth) { - this.depthTexture.define(width, height) - this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth') + this.depthTexture.define(width, height); + this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); } - const p = { ...DefaultDrawPassProps, ...props } + const p = { ...DefaultDrawPassProps, ...props }; this.cameraHelper = new CameraHelper(webgl, p.cameraHelper); } setSize(width: number, height: number) { - this.colorTarget.setSize(width, height) + this.colorTarget.setSize(width, height); if (this.depthTarget) { - this.depthTarget.setSize(width, height) + this.depthTarget.setSize(width, height); } else { - this.depthTexture.define(width, height) + this.depthTexture.define(width, height); } } setProps(props: Partial<DrawPassProps>) { - if (props.cameraHelper) this.cameraHelper.setProps(props.cameraHelper) + if (props.cameraHelper) this.cameraHelper.setProps(props.cameraHelper); } get props(): DrawPassProps { return { cameraHelper: { ...this.cameraHelper.props } - } + }; } render(toDrawingBuffer: boolean, transparentBackground: boolean) { - const { webgl, renderer, colorTarget, depthTarget } = this + const { webgl, renderer, colorTarget, depthTarget } = this; if (toDrawingBuffer) { - webgl.unbindFramebuffer() + webgl.unbindFramebuffer(); } else { - colorTarget.bind() + colorTarget.bind(); if (!this.packedDepth) { // TODO unlcear why it is not enough to call `attachFramebuffer` in `Texture.reset` - this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth') + this.depthTexture.attachFramebuffer(this.colorTarget.framebuffer, 'depth'); } } - renderer.setViewport(0, 0, colorTarget.getWidth(), colorTarget.getHeight()) - this.renderInternal('color', transparentBackground) + renderer.setViewport(0, 0, colorTarget.getWidth(), colorTarget.getHeight()); + this.renderInternal('color', transparentBackground); // do a depth pass if not rendering to drawing buffer and // extensions.depthTexture is unsupported (i.e. depthTarget is set) if (!toDrawingBuffer && depthTarget) { - depthTarget.bind() - this.renderInternal('depth', transparentBackground) + depthTarget.bind(); + this.renderInternal('depth', transparentBackground); } } private renderInternal(variant: 'color' | 'depth', transparentBackground: boolean) { - const { renderer, scene, camera, debugHelper, cameraHelper } = this - renderer.render(scene, camera, variant, true, transparentBackground) + const { renderer, scene, camera, debugHelper, cameraHelper } = this; + renderer.render(scene, camera, variant, true, transparentBackground); if (debugHelper.isEnabled) { - debugHelper.syncVisibility() - renderer.render(debugHelper.scene, camera, variant, false, transparentBackground) + debugHelper.syncVisibility(); + renderer.render(debugHelper.scene, camera, variant, false, transparentBackground); } if (cameraHelper.isEnabled) { - cameraHelper.update(camera) - renderer.render(cameraHelper.scene, cameraHelper.camera, variant, false, transparentBackground) + cameraHelper.update(camera); + renderer.render(cameraHelper.scene, cameraHelper.camera, variant, false, transparentBackground); } } } \ No newline at end of file diff --git a/src/mol-canvas3d/passes/image.ts b/src/mol-canvas3d/passes/image.ts index 6867a17002a52e9106d1f0407b6ebc00094b6e59..41147edefb87005b0c678525fbcce6ce640f4096 100644 --- a/src/mol-canvas3d/passes/image.ts +++ b/src/mol-canvas3d/passes/image.ts @@ -10,9 +10,9 @@ import Renderer from '../../mol-gl/renderer'; import Scene from '../../mol-gl/scene'; import { BoundingSphereHelper } from '../helper/bounding-sphere-helper'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; -import { DrawPass, DrawPassParams } from './draw' -import { PostprocessingPass, PostprocessingParams } from './postprocessing' -import { MultiSamplePass, MultiSampleParams } from './multi-sample' +import { DrawPass, DrawPassParams } from './draw'; +import { PostprocessingPass, PostprocessingParams } from './postprocessing'; +import { MultiSamplePass, MultiSampleParams } from './multi-sample'; import { Camera } from '../camera'; import { Viewport } from '../camera/util'; @@ -21,7 +21,7 @@ export const ImageParams = { multiSample: PD.Group(MultiSampleParams), postprocessing: PD.Group(PostprocessingParams), drawPass: PD.Group(DrawPassParams), -} +}; export type ImageProps = PD.Values<typeof ImageParams> export class ImagePass { @@ -31,43 +31,43 @@ export class ImagePass { private _transparentBackground = false private _colorTarget: RenderTarget - get colorTarget() { return this._colorTarget } + get colorTarget() { return this._colorTarget; } readonly drawPass: DrawPass private readonly postprocessing: PostprocessingPass private readonly multiSample: MultiSamplePass - get width() { return this._width } - get height() { return this._height } + get width() { return this._width; } + get height() { return this._height; } constructor(webgl: WebGLContext, private renderer: Renderer, scene: Scene, private camera: Camera, debugHelper: BoundingSphereHelper, props: Partial<ImageProps>) { - const p = { ...PD.getDefaultValues(ImageParams), ...props } + const p = { ...PD.getDefaultValues(ImageParams), ...props }; - this._transparentBackground = p.transparentBackground + this._transparentBackground = p.transparentBackground; - this.drawPass = new DrawPass(webgl, renderer, scene, this._camera, debugHelper, p.drawPass) - this.postprocessing = new PostprocessingPass(webgl, this._camera, this.drawPass, p.postprocessing) - this.multiSample = new MultiSamplePass(webgl, this._camera, this.drawPass, this.postprocessing, p.multiSample) + this.drawPass = new DrawPass(webgl, renderer, scene, this._camera, debugHelper, p.drawPass); + this.postprocessing = new PostprocessingPass(webgl, this._camera, this.drawPass, p.postprocessing); + this.multiSample = new MultiSamplePass(webgl, this._camera, this.drawPass, this.postprocessing, p.multiSample); - this.setSize(this._width, this._height) + this.setSize(this._width, this._height); } setSize(width: number, height: number) { - if (width === this._width && height === this._height) return + if (width === this._width && height === this._height) return; - this._width = width - this._height = height + this._width = width; + this._height = height; - this.drawPass.setSize(width, height) - this.postprocessing.setSize(width, height) - this.multiSample.setSize(width, height) + this.drawPass.setSize(width, height); + this.postprocessing.setSize(width, height); + this.multiSample.setSize(width, height); } setProps(props: Partial<ImageProps> = {}) { - if (props.transparentBackground !== undefined) this._transparentBackground = props.transparentBackground - if (props.postprocessing) this.postprocessing.setProps(props.postprocessing) - if (props.multiSample) this.multiSample.setProps(props.multiSample) - if (props.drawPass) this.drawPass.setProps(props.drawPass) + if (props.transparentBackground !== undefined) this._transparentBackground = props.transparentBackground; + if (props.postprocessing) this.postprocessing.setProps(props.postprocessing); + if (props.multiSample) this.multiSample.setProps(props.multiSample); + if (props.drawPass) this.drawPass.setProps(props.drawPass); } get props(): ImageProps { @@ -76,34 +76,34 @@ export class ImagePass { postprocessing: this.postprocessing.props, multiSample: this.multiSample.props, drawPass: this.drawPass.props - } + }; } render() { - Camera.copySnapshot(this._camera.state, this.camera.state) - Viewport.set(this._camera.viewport, 0, 0, this._width, this._height) - this._camera.update() + Camera.copySnapshot(this._camera.state, this.camera.state); + Viewport.set(this._camera.viewport, 0, 0, this._width, this._height); + this._camera.update(); this.renderer.setViewport(0, 0, this._width, this._height); if (this.multiSample.enabled) { - this.multiSample.render(false, this._transparentBackground) - this._colorTarget = this.multiSample.colorTarget + this.multiSample.render(false, this._transparentBackground); + this._colorTarget = this.multiSample.colorTarget; } else { - this.drawPass.render(false, this._transparentBackground) + this.drawPass.render(false, this._transparentBackground); if (this.postprocessing.enabled) { - this.postprocessing.render(false) - this._colorTarget = this.postprocessing.target + this.postprocessing.render(false); + this._colorTarget = this.postprocessing.target; } else { - this._colorTarget = this.drawPass.colorTarget + this._colorTarget = this.drawPass.colorTarget; } } } getImageData(width: number, height: number) { - this.setSize(width, height) - this.render() - const pd = this.colorTarget.getPixelData() - return new ImageData(new Uint8ClampedArray(pd.array), pd.width, pd.height) + this.setSize(width, height); + this.render(); + const pd = this.colorTarget.getPixelData(); + return new ImageData(new Uint8ClampedArray(pd.array), pd.width, pd.height); } } \ No newline at end of file diff --git a/src/mol-canvas3d/passes/multi-sample.ts b/src/mol-canvas3d/passes/multi-sample.ts index 661054c3971f1af6e4ecdcbb3d23442ce018e648..35e9874d6a6fe165d856a3c35be88c044a0781d2 100644 --- a/src/mol-canvas3d/passes/multi-sample.ts +++ b/src/mol-canvas3d/passes/multi-sample.ts @@ -19,15 +19,15 @@ import { Camera } from '../../mol-canvas3d/camera'; import { PostprocessingPass } from './postprocessing'; import { DrawPass } from './draw'; -import quad_vert from '../../mol-gl/shader/quad.vert' -import compose_frag from '../../mol-gl/shader/compose.frag' +import quad_vert from '../../mol-gl/shader/quad.vert'; +import compose_frag from '../../mol-gl/shader/compose.frag'; const ComposeSchema = { ...QuadSchema, tColor: TextureSpec('texture', 'rgba', 'ubyte', 'nearest'), uTexSize: UniformSpec('v2'), uWeight: UniformSpec('f'), -} +}; type ComposeRenderable = ComputeRenderable<Values<typeof ComposeSchema>> @@ -37,19 +37,19 @@ function getComposeRenderable(ctx: WebGLContext, colorTexture: Texture): Compose tColor: ValueCell.create(colorTexture), uTexSize: ValueCell.create(Vec2.create(colorTexture.getWidth(), colorTexture.getHeight())), uWeight: ValueCell.create(1.0), - } + }; - const schema = { ...ComposeSchema } - const shaderCode = ShaderCode('compose', quad_vert, compose_frag) - const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values) + const schema = { ...ComposeSchema }; + const shaderCode = ShaderCode('compose', quad_vert, compose_frag); + const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values); - return createComputeRenderable(renderItem, values) + return createComputeRenderable(renderItem, values); } export const MultiSampleParams = { mode: PD.Select('off', [['off', 'Off'], ['on', 'On'], ['temporal', 'Temporal']]), sampleLevel: PD.Numeric(2, { min: 0, max: 5, step: 1 }), -} +}; export type MultiSampleProps = PD.Values<typeof MultiSampleParams> export class MultiSamplePass { @@ -65,229 +65,229 @@ export class MultiSamplePass { private lastRenderTime = 0 constructor(private webgl: WebGLContext, private camera: Camera, private drawPass: DrawPass, private postprocessing: PostprocessingPass, props: Partial<MultiSampleProps>) { - const { gl } = webgl - this.colorTarget = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight) - this.composeTarget = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight) - this.holdTarget = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight) - this.compose = getComposeRenderable(webgl, drawPass.colorTarget.texture) - this.props = { ...PD.getDefaultValues(MultiSampleParams), ...props } + const { gl } = webgl; + this.colorTarget = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight); + this.composeTarget = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight); + this.holdTarget = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight); + this.compose = getComposeRenderable(webgl, drawPass.colorTarget.texture); + this.props = { ...PD.getDefaultValues(MultiSampleParams), ...props }; } get enabled() { if (this.props.mode === 'temporal') { if (this.currentTime - this.lastRenderTime > 200) { - return this.sampleIndex !== -1 + return this.sampleIndex !== -1; } else { - this.sampleIndex = 0 - return false + this.sampleIndex = 0; + return false; } } else if (this.props.mode === 'on') { - return true + return true; } else { - return false + return false; } } update(changed: boolean, currentTime: number) { - if (changed) this.lastRenderTime = currentTime - this.currentTime = currentTime + if (changed) this.lastRenderTime = currentTime; + this.currentTime = currentTime; } setSize(width: number, height: number) { - this.colorTarget.setSize(width, height) - this.composeTarget.setSize(width, height) - this.holdTarget.setSize(width, height) - ValueCell.update(this.compose.values.uTexSize, Vec2.set(this.compose.values.uTexSize.ref.value, width, height)) + this.colorTarget.setSize(width, height); + this.composeTarget.setSize(width, height); + this.holdTarget.setSize(width, height); + ValueCell.update(this.compose.values.uTexSize, Vec2.set(this.compose.values.uTexSize.ref.value, width, height)); } setProps(props: Partial<MultiSampleProps>) { - if (props.mode !== undefined) this.props.mode = props.mode - if (props.sampleLevel !== undefined) this.props.sampleLevel = props.sampleLevel + if (props.mode !== undefined) this.props.mode = props.mode; + if (props.sampleLevel !== undefined) this.props.sampleLevel = props.sampleLevel; } render(toDrawingBuffer: boolean, transparentBackground: boolean) { if (this.props.mode === 'temporal') { - this.renderTemporalMultiSample(toDrawingBuffer, transparentBackground) + this.renderTemporalMultiSample(toDrawingBuffer, transparentBackground); } else { - this.renderMultiSample(toDrawingBuffer, transparentBackground) + this.renderMultiSample(toDrawingBuffer, transparentBackground); } } private renderMultiSample(toDrawingBuffer: boolean, transparentBackground: boolean) { - const { camera, compose, composeTarget, drawPass, postprocessing, webgl } = this - const { gl, state } = webgl + const { camera, compose, composeTarget, drawPass, postprocessing, webgl } = this; + const { gl, state } = webgl; // based on the Multisample Anti-Aliasing Render Pass // contributed to three.js by bhouston / http://clara.io/ // // This manual approach to MSAA re-renders the scene once for // each sample with camera jitter and accumulates the results. - const offsetList = JitterVectors[ Math.max(0, Math.min(this.props.sampleLevel, 5)) ] + const offsetList = JitterVectors[ Math.max(0, Math.min(this.props.sampleLevel, 5)) ]; - const baseSampleWeight = 1.0 / offsetList.length - const roundingRange = 1 / 32 + const baseSampleWeight = 1.0 / offsetList.length; + const roundingRange = 1 / 32; - camera.viewOffset.enabled = true - ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture) - compose.update() + camera.viewOffset.enabled = true; + ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture); + compose.update(); - const width = drawPass.colorTarget.getWidth() - const height = drawPass.colorTarget.getHeight() + const width = drawPass.colorTarget.getWidth(); + const height = drawPass.colorTarget.getHeight(); // render the scene multiple times, each slightly jitter offset // from the last and accumulate the results. for (let i = 0; i < offsetList.length; ++i) { - const offset = offsetList[i] - Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height) - camera.update() + const offset = offsetList[i]; + Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height); + camera.update(); // the theory is that equal weights for each sample lead to an accumulation of rounding // errors. The following equation varies the sampleWeight per sample so that it is uniformly // distributed across a range of values whose rounding errors cancel each other out. - const uniformCenteredDistribution = -0.5 + (i + 0.5) / offsetList.length - const sampleWeight = baseSampleWeight + roundingRange * uniformCenteredDistribution - ValueCell.update(compose.values.uWeight, sampleWeight) + const uniformCenteredDistribution = -0.5 + (i + 0.5) / offsetList.length; + const sampleWeight = baseSampleWeight + roundingRange * uniformCenteredDistribution; + ValueCell.update(compose.values.uWeight, sampleWeight); // render scene and optionally postprocess - drawPass.render(false, transparentBackground) - if (postprocessing.enabled) postprocessing.render(false) + drawPass.render(false, transparentBackground); + if (postprocessing.enabled) postprocessing.render(false); // compose rendered scene with compose target - composeTarget.bind() - gl.viewport(0, 0, width, height) - state.enable(gl.BLEND) - state.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD) - state.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) + composeTarget.bind(); + gl.viewport(0, 0, width, height); + state.enable(gl.BLEND); + state.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD); + state.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); if (i === 0) { - state.clearColor(0, 0, 0, 0) - gl.clear(gl.COLOR_BUFFER_BIT) + state.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); } - compose.render() + compose.render(); } - ValueCell.update(compose.values.uWeight, 1.0) - ValueCell.update(compose.values.tColor, composeTarget.texture) - compose.update() + ValueCell.update(compose.values.uWeight, 1.0); + ValueCell.update(compose.values.tColor, composeTarget.texture); + compose.update(); if (toDrawingBuffer) { - webgl.unbindFramebuffer() + webgl.unbindFramebuffer(); } else { - this.colorTarget.bind() + this.colorTarget.bind(); } - gl.viewport(0, 0, width, height) - state.disable(gl.BLEND) - compose.render() + gl.viewport(0, 0, width, height); + state.disable(gl.BLEND); + compose.render(); - camera.viewOffset.enabled = false - camera.update() + camera.viewOffset.enabled = false; + camera.update(); } private renderTemporalMultiSample(toDrawingBuffer: boolean, transparentBackground: boolean) { - const { camera, compose, composeTarget, holdTarget, postprocessing, drawPass, webgl } = this - const { gl, state } = webgl + const { camera, compose, composeTarget, holdTarget, postprocessing, drawPass, webgl } = this; + const { gl, state } = webgl; // based on the Multisample Anti-Aliasing Render Pass // contributed to three.js by bhouston / http://clara.io/ // // This manual approach to MSAA re-renders the scene once for // each sample with camera jitter and accumulates the results. - const offsetList = JitterVectors[ Math.max(0, Math.min(this.props.sampleLevel, 5)) ] + const offsetList = JitterVectors[ Math.max(0, Math.min(this.props.sampleLevel, 5)) ]; - if (this.sampleIndex === -1) return + if (this.sampleIndex === -1) return; if (this.sampleIndex >= offsetList.length) { - this.sampleIndex = -1 - return + this.sampleIndex = -1; + return; } - const i = this.sampleIndex + const i = this.sampleIndex; if (i === 0) { - drawPass.render(false, transparentBackground) - if (postprocessing.enabled) postprocessing.render(false) - ValueCell.update(compose.values.uWeight, 1.0) - ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture) - compose.update() - - holdTarget.bind() - state.disable(gl.BLEND) - compose.render() + drawPass.render(false, transparentBackground); + if (postprocessing.enabled) postprocessing.render(false); + ValueCell.update(compose.values.uWeight, 1.0); + ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture); + compose.update(); + + holdTarget.bind(); + state.disable(gl.BLEND); + compose.render(); } - const sampleWeight = 1.0 / offsetList.length + const sampleWeight = 1.0 / offsetList.length; - camera.viewOffset.enabled = true - ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture) - ValueCell.update(compose.values.uWeight, sampleWeight) - compose.update() + camera.viewOffset.enabled = true; + ValueCell.update(compose.values.tColor, postprocessing.enabled ? postprocessing.target.texture : drawPass.colorTarget.texture); + ValueCell.update(compose.values.uWeight, sampleWeight); + compose.update(); - const width = drawPass.colorTarget.getWidth() - const height = drawPass.colorTarget.getHeight() + const width = drawPass.colorTarget.getWidth(); + const height = drawPass.colorTarget.getHeight(); // render the scene multiple times, each slightly jitter offset // from the last and accumulate the results. - const numSamplesPerFrame = Math.pow(2, this.props.sampleLevel) + const numSamplesPerFrame = Math.pow(2, this.props.sampleLevel); for (let i = 0; i < numSamplesPerFrame; ++i) { - const offset = offsetList[this.sampleIndex] - Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height) - camera.update() + const offset = offsetList[this.sampleIndex]; + Camera.setViewOffset(camera.viewOffset, width, height, offset[0], offset[1], width, height); + camera.update(); // render scene and optionally postprocess - drawPass.render(false, transparentBackground) - if (postprocessing.enabled) postprocessing.render(false) + drawPass.render(false, transparentBackground); + if (postprocessing.enabled) postprocessing.render(false); // compose rendered scene with compose target - composeTarget.bind() - state.enable(gl.BLEND) - state.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD) - state.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) + composeTarget.bind(); + state.enable(gl.BLEND); + state.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD); + state.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); if (this.sampleIndex === 0) { - state.clearColor(0, 0, 0, 0) - gl.clear(gl.COLOR_BUFFER_BIT) + state.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); } - compose.render() + compose.render(); - this.sampleIndex += 1 - if (this.sampleIndex >= offsetList.length ) break + this.sampleIndex += 1; + if (this.sampleIndex >= offsetList.length ) break; } - const accumulationWeight = this.sampleIndex * sampleWeight + const accumulationWeight = this.sampleIndex * sampleWeight; if (accumulationWeight > 0) { - ValueCell.update(compose.values.uWeight, 1.0) - ValueCell.update(compose.values.tColor, composeTarget.texture) - compose.update() + ValueCell.update(compose.values.uWeight, 1.0); + ValueCell.update(compose.values.tColor, composeTarget.texture); + compose.update(); if (toDrawingBuffer) { - webgl.unbindFramebuffer() + webgl.unbindFramebuffer(); } else { - this.colorTarget.bind() + this.colorTarget.bind(); } - gl.viewport(0, 0, width, height) - state.disable(gl.BLEND) - compose.render() + gl.viewport(0, 0, width, height); + state.disable(gl.BLEND); + compose.render(); } if (accumulationWeight < 1.0) { - ValueCell.update(compose.values.uWeight, 1.0 - accumulationWeight) - ValueCell.update(compose.values.tColor, holdTarget.texture) - compose.update() + ValueCell.update(compose.values.uWeight, 1.0 - accumulationWeight); + ValueCell.update(compose.values.tColor, holdTarget.texture); + compose.update(); if (toDrawingBuffer) { - webgl.unbindFramebuffer() + webgl.unbindFramebuffer(); } else { - this.colorTarget.bind() + this.colorTarget.bind(); } - gl.viewport(0, 0, width, height) - if (accumulationWeight === 0) state.disable(gl.BLEND) - else state.enable(gl.BLEND) - compose.render() + gl.viewport(0, 0, width, height); + if (accumulationWeight === 0) state.disable(gl.BLEND); + else state.enable(gl.BLEND); + compose.render(); } - camera.viewOffset.enabled = false - camera.update() - if (this.sampleIndex >= offsetList.length) this.sampleIndex = -1 + camera.viewOffset.enabled = false; + camera.update(); + if (this.sampleIndex >= offsetList.length) this.sampleIndex = -1; } } @@ -321,12 +321,12 @@ const JitterVectors = [ [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ] ] -] +]; JitterVectors.forEach(offsetList => { offsetList.forEach(offset => { // 0.0625 = 1 / 16 - offset[0] *= 0.0625 - offset[1] *= 0.0625 - }) -}) \ No newline at end of file + offset[0] *= 0.0625; + offset[1] *= 0.0625; + }); +}); \ No newline at end of file diff --git a/src/mol-canvas3d/passes/pick.ts b/src/mol-canvas3d/passes/pick.ts index a2cf1a8affe7ca66d44ee97ca9b80a9595cfb823..8b13397654d19732355b99c69ac6dbbb2978fc7b 100644 --- a/src/mol-canvas3d/passes/pick.ts +++ b/src/mol-canvas3d/passes/pick.ts @@ -28,44 +28,44 @@ export class PickPass { private pickHeight: number constructor(private webgl: WebGLContext, private renderer: Renderer, private scene: Scene, private camera: Camera, private pickBaseScale: number) { - const { gl } = webgl - const width = gl.drawingBufferWidth - const height = gl.drawingBufferHeight + const { gl } = webgl; + const width = gl.drawingBufferWidth; + const height = gl.drawingBufferHeight; - this.pickScale = pickBaseScale / webgl.pixelRatio - this.pickWidth = Math.round(width * this.pickScale) - this.pickHeight = Math.round(height * this.pickScale) + this.pickScale = pickBaseScale / webgl.pixelRatio; + this.pickWidth = Math.round(width * this.pickScale); + this.pickHeight = Math.round(height * this.pickScale); - this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight) - this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight) - this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight) + this.objectPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); + this.instancePickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); + this.groupPickTarget = webgl.createRenderTarget(this.pickWidth, this.pickHeight); - this.setupBuffers() + this.setupBuffers(); } private setupBuffers() { - const bufferSize = this.pickWidth * this.pickHeight * 4 + const bufferSize = this.pickWidth * this.pickHeight * 4; if (!this.objectBuffer || this.objectBuffer.length !== bufferSize) { - this.objectBuffer = new Uint8Array(bufferSize) - this.instanceBuffer = new Uint8Array(bufferSize) - this.groupBuffer = new Uint8Array(bufferSize) + this.objectBuffer = new Uint8Array(bufferSize); + this.instanceBuffer = new Uint8Array(bufferSize); + this.groupBuffer = new Uint8Array(bufferSize); } } setSize(width: number, height: number) { - this.pickScale = this.pickBaseScale / this.webgl.pixelRatio - this.pickWidth = Math.round(width * this.pickScale) - this.pickHeight = Math.round(height * this.pickScale) + this.pickScale = this.pickBaseScale / this.webgl.pixelRatio; + this.pickWidth = Math.round(width * this.pickScale); + this.pickHeight = Math.round(height * this.pickScale); - this.objectPickTarget.setSize(this.pickWidth, this.pickHeight) - this.instancePickTarget.setSize(this.pickWidth, this.pickHeight) - this.groupPickTarget.setSize(this.pickWidth, this.pickHeight) + this.objectPickTarget.setSize(this.pickWidth, this.pickHeight); + this.instancePickTarget.setSize(this.pickWidth, this.pickHeight); + this.groupPickTarget.setSize(this.pickWidth, this.pickHeight); - this.setupBuffers() + this.setupBuffers(); } render() { - const { renderer, scene, camera } = this + const { renderer, scene, camera } = this; renderer.setViewport(0, 0, this.pickWidth, this.pickHeight); this.objectPickTarget.bind(); renderer.render(scene, camera, 'pickObject', true, false); @@ -74,53 +74,53 @@ export class PickPass { this.groupPickTarget.bind(); renderer.render(scene, camera, 'pickGroup', true, false); - this.pickDirty = false + this.pickDirty = false; } private syncBuffers() { - const { webgl } = this + const { webgl } = this; - this.objectPickTarget.bind() - webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.objectBuffer) + this.objectPickTarget.bind(); + webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.objectBuffer); - this.instancePickTarget.bind() - webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.instanceBuffer) + this.instancePickTarget.bind(); + webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.instanceBuffer); - this.groupPickTarget.bind() - webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.groupBuffer) + this.groupPickTarget.bind(); + webgl.readPixels(0, 0, this.pickWidth, this.pickHeight, this.groupBuffer); } private getId(x: number, y: number, buffer: Uint8Array) { - const idx = (y * this.pickWidth + x) * 4 - return decodeFloatRGB(buffer[idx], buffer[idx + 1], buffer[idx + 2]) + const idx = (y * this.pickWidth + x) * 4; + return decodeFloatRGB(buffer[idx], buffer[idx + 1], buffer[idx + 2]); } identify(x: number, y: number): PickingId | undefined { - const { webgl, pickScale } = this - if (webgl.isContextLost) return + const { webgl, pickScale } = this; + if (webgl.isContextLost) return; - const { gl } = webgl + const { gl } = webgl; if (this.pickDirty) { - this.render() - this.syncBuffers() + this.render(); + this.syncBuffers(); } - x *= webgl.pixelRatio - y *= webgl.pixelRatio - y = gl.drawingBufferHeight - y // flip y + x *= webgl.pixelRatio; + y *= webgl.pixelRatio; + y = gl.drawingBufferHeight - y; // flip y - const xp = Math.round(x * pickScale) - const yp = Math.round(y * pickScale) + const xp = Math.round(x * pickScale); + const yp = Math.round(y * pickScale); - const objectId = this.getId(xp, yp, this.objectBuffer) - if (objectId === -1) return + const objectId = this.getId(xp, yp, this.objectBuffer); + if (objectId === -1) return; - const instanceId = this.getId(xp, yp, this.instanceBuffer) - if (instanceId === -1) return + const instanceId = this.getId(xp, yp, this.instanceBuffer); + if (instanceId === -1) return; - const groupId = this.getId(xp, yp, this.groupBuffer) - if (groupId === -1) return + const groupId = this.getId(xp, yp, this.groupBuffer); + if (groupId === -1) return; - return { objectId, instanceId, groupId } + return { objectId, instanceId, groupId }; } } \ No newline at end of file diff --git a/src/mol-canvas3d/passes/postprocessing.ts b/src/mol-canvas3d/passes/postprocessing.ts index a1e0a33220b9e35244db515476aba5a73e26256f..bbf5f61858ec58211ce122fa5916a58846914256 100644 --- a/src/mol-canvas3d/passes/postprocessing.ts +++ b/src/mol-canvas3d/passes/postprocessing.ts @@ -19,8 +19,8 @@ import { DrawPass } from './draw'; import { Camera } from '../../mol-canvas3d/camera'; import { produce } from 'immer'; -import quad_vert from '../../mol-gl/shader/quad.vert' -import postprocessing_frag from '../../mol-gl/shader/postprocessing.frag' +import quad_vert from '../../mol-gl/shader/quad.vert'; +import postprocessing_frag from '../../mol-gl/shader/postprocessing.frag'; const PostprocessingSchema = { ...QuadSchema, @@ -45,7 +45,7 @@ const PostprocessingSchema = { uOutlineThreshold: UniformSpec('f'), dPackedDepth: DefineSpec('boolean'), -} +}; export const PostprocessingParams = { occlusion: PD.MappedStatic('off', { @@ -63,13 +63,13 @@ export const PostprocessingParams = { }), off: PD.Group({}) }, { cycle: true, description: 'Draw outline around 3D objects' }) -} +}; export type PostprocessingProps = PD.Values<typeof PostprocessingParams> type PostprocessingRenderable = ComputeRenderable<Values<typeof PostprocessingSchema>> function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, depthTexture: Texture, packedDepth: boolean, props: Partial<PostprocessingProps>): PostprocessingRenderable { - const p = { ...PD.getDefaultValues(PostprocessingParams), ...props } + const p = { ...PD.getDefaultValues(PostprocessingParams), ...props }; const values: Values<typeof PostprocessingSchema> = { ...QuadValues, tColor: ValueCell.create(colorTexture), @@ -93,13 +93,13 @@ function getPostprocessingRenderable(ctx: WebGLContext, colorTexture: Texture, d uOutlineThreshold: ValueCell.create(p.outline.name === 'on' ? p.outline.params.threshold : 0.8), dPackedDepth: ValueCell.create(packedDepth), - } + }; - const schema = { ...PostprocessingSchema } - const shaderCode = ShaderCode('postprocessing', quad_vert, postprocessing_frag) - const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values) + const schema = { ...PostprocessingSchema }; + const shaderCode = ShaderCode('postprocessing', quad_vert, postprocessing_frag); + const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values); - return createComputeRenderable(renderItem, values) + return createComputeRenderable(renderItem, values); } export class PostprocessingPass { @@ -108,67 +108,67 @@ export class PostprocessingPass { renderable: PostprocessingRenderable constructor(private webgl: WebGLContext, private camera: Camera, drawPass: DrawPass, props: Partial<PostprocessingProps>) { - const { gl } = webgl - this.target = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight) - this.props = { ...PD.getDefaultValues(PostprocessingParams), ...props } - const { colorTarget, depthTexture, packedDepth } = drawPass - this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTexture, packedDepth, this.props) + const { gl } = webgl; + this.target = webgl.createRenderTarget(gl.drawingBufferWidth, gl.drawingBufferHeight); + this.props = { ...PD.getDefaultValues(PostprocessingParams), ...props }; + const { colorTarget, depthTexture, packedDepth } = drawPass; + this.renderable = getPostprocessingRenderable(webgl, colorTarget.texture, depthTexture, packedDepth, this.props); } get enabled() { - return this.props.occlusion.name === 'on' || this.props.outline.name === 'on' + return this.props.occlusion.name === 'on' || this.props.outline.name === 'on'; } setSize(width: number, height: number) { - this.target.setSize(width, height) - ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height)) + this.target.setSize(width, height); + ValueCell.update(this.renderable.values.uTexSize, Vec2.set(this.renderable.values.uTexSize.ref.value, width, height)); } setProps(props: Partial<PostprocessingProps>) { this.props = produce(this.props, p => { if (props.occlusion !== undefined) { - p.occlusion.name = props.occlusion.name - ValueCell.updateIfChanged(this.renderable.values.dOcclusionEnable, props.occlusion.name === 'on') + p.occlusion.name = props.occlusion.name; + ValueCell.updateIfChanged(this.renderable.values.dOcclusionEnable, props.occlusion.name === 'on'); if (props.occlusion.name === 'on') { - p.occlusion.params = { ...props.occlusion.params } - ValueCell.updateIfChanged(this.renderable.values.dOcclusionKernelSize, props.occlusion.params.kernelSize) - ValueCell.updateIfChanged(this.renderable.values.uOcclusionBias, props.occlusion.params.bias) - ValueCell.updateIfChanged(this.renderable.values.uOcclusionRadius, props.occlusion.params.radius) + p.occlusion.params = { ...props.occlusion.params }; + ValueCell.updateIfChanged(this.renderable.values.dOcclusionKernelSize, props.occlusion.params.kernelSize); + ValueCell.updateIfChanged(this.renderable.values.uOcclusionBias, props.occlusion.params.bias); + ValueCell.updateIfChanged(this.renderable.values.uOcclusionRadius, props.occlusion.params.radius); } } if (props.outline !== undefined) { - p.outline.name = props.outline.name - ValueCell.updateIfChanged(this.renderable.values.dOutlineEnable, props.outline.name === 'on') + p.outline.name = props.outline.name; + ValueCell.updateIfChanged(this.renderable.values.dOutlineEnable, props.outline.name === 'on'); if (props.outline.name === 'on') { - p.outline.params = { ...props.outline.params } - ValueCell.updateIfChanged(this.renderable.values.uOutlineScale, props.outline.params.scale) - ValueCell.updateIfChanged(this.renderable.values.uOutlineThreshold, props.outline.params.threshold) + p.outline.params = { ...props.outline.params }; + ValueCell.updateIfChanged(this.renderable.values.uOutlineScale, props.outline.params.scale); + ValueCell.updateIfChanged(this.renderable.values.uOutlineThreshold, props.outline.params.threshold); } } - }) + }); - this.renderable.update() + this.renderable.update(); } render(toDrawingBuffer: boolean) { - ValueCell.update(this.renderable.values.uFar, this.camera.far) - ValueCell.update(this.renderable.values.uNear, this.camera.near) - ValueCell.update(this.renderable.values.uFogFar, this.camera.fogFar) - ValueCell.update(this.renderable.values.uFogNear, this.camera.fogNear) - ValueCell.update(this.renderable.values.dOrthographic, this.camera.state.mode === 'orthographic' ? 1 : 0) + ValueCell.update(this.renderable.values.uFar, this.camera.far); + ValueCell.update(this.renderable.values.uNear, this.camera.near); + ValueCell.update(this.renderable.values.uFogFar, this.camera.fogFar); + ValueCell.update(this.renderable.values.uFogNear, this.camera.fogNear); + ValueCell.update(this.renderable.values.dOrthographic, this.camera.state.mode === 'orthographic' ? 1 : 0); - const { gl, state } = this.webgl + const { gl, state } = this.webgl; if (toDrawingBuffer) { - this.webgl.unbindFramebuffer() - gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight) + this.webgl.unbindFramebuffer(); + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); } else { - this.target.bind() + this.target.bind(); } - state.disable(gl.SCISSOR_TEST) - state.disable(gl.BLEND) - state.disable(gl.DEPTH_TEST) - state.depthMask(false) - this.renderable.render() + state.disable(gl.SCISSOR_TEST); + state.disable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.depthMask(false); + this.renderable.render(); } } \ No newline at end of file diff --git a/src/mol-canvas3d/util.ts b/src/mol-canvas3d/util.ts index ae1d7270a221bd135b7d5e17b43c2f6c8c10ba17..01d12b00028ee3037cc059e86485efe378aae216 100644 --- a/src/mol-canvas3d/util.ts +++ b/src/mol-canvas3d/util.ts @@ -6,40 +6,40 @@ /** Set canvas size taking `devicePixelRatio` into account */ export function setCanvasSize(canvas: HTMLCanvasElement, width: number, height: number) { - canvas.width = Math.round(window.devicePixelRatio * width) - canvas.height = Math.round(window.devicePixelRatio * height) - Object.assign(canvas.style, { width: `${width}px`, height: `${height}px` }) + canvas.width = Math.round(window.devicePixelRatio * width); + canvas.height = Math.round(window.devicePixelRatio * height); + Object.assign(canvas.style, { width: `${width}px`, height: `${height}px` }); } /** Resize canvas to container element taking `devicePixelRatio` into account */ export function resizeCanvas (canvas: HTMLCanvasElement, container: Element) { - let width = window.innerWidth - let height = window.innerHeight + let width = window.innerWidth; + let height = window.innerHeight; if (container !== document.body) { - let bounds = container.getBoundingClientRect() - width = bounds.right - bounds.left - height = bounds.bottom - bounds.top + let bounds = container.getBoundingClientRect(); + width = bounds.right - bounds.left; + height = bounds.bottom - bounds.top; } - setCanvasSize(canvas, width, height) + setCanvasSize(canvas, width, height); } function _canvasToBlob(canvas: HTMLCanvasElement, callback: BlobCallback, type?: string, quality?: any) { - const bin = atob(canvas.toDataURL(type, quality).split(',')[1]) - const len = bin.length - const len32 = len >> 2 - const a8 = new Uint8Array(len) - const a32 = new Uint32Array(a8.buffer, 0, len32) + const bin = atob(canvas.toDataURL(type, quality).split(',')[1]); + const len = bin.length; + const len32 = len >> 2; + const a8 = new Uint8Array(len); + const a32 = new Uint32Array(a8.buffer, 0, len32); - let j = 0 + let j = 0; for (let i = 0; i < len32; ++i) { a32[i] = bin.charCodeAt(j++) | bin.charCodeAt(j++) << 8 | bin.charCodeAt(j++) << 16 | - bin.charCodeAt(j++) << 24 + bin.charCodeAt(j++) << 24; } let tailLength = len & 3; - while (tailLength--) a8[j] = bin.charCodeAt(j++) + while (tailLength--) a8[j] = bin.charCodeAt(j++); callback(new Blob([a8], { type: type || 'image/png' })); } @@ -47,14 +47,14 @@ function _canvasToBlob(canvas: HTMLCanvasElement, callback: BlobCallback, type?: export async function canvasToBlob(canvas: HTMLCanvasElement, type?: string, quality?: any): Promise<Blob> { return new Promise((resolve, reject) => { const callback = (blob: Blob | null) => { - if (blob) resolve(blob) - else reject('no blob returned') - } + if (blob) resolve(blob); + else reject('no blob returned'); + }; if (!HTMLCanvasElement.prototype.toBlob) { - _canvasToBlob(canvas, callback, type, quality) + _canvasToBlob(canvas, callback, type, quality); } else { - canvas.toBlob(callback, type, quality) + canvas.toBlob(callback, type, quality); } - }) + }); } \ No newline at end of file diff --git a/src/mol-data/_spec/equiv-index.spec.ts b/src/mol-data/_spec/equiv-index.spec.ts index 339022a969f1e072aeaa0199be98926106332623..9dd4f7f674257d8faebb239de1283928a5ec7678 100644 --- a/src/mol-data/_spec/equiv-index.spec.ts +++ b/src/mol-data/_spec/equiv-index.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { EquivalenceClasses } from '../util' +import { EquivalenceClasses } from '../util'; describe('equiv-classes', () => { it('integer mod classes', () => { diff --git a/src/mol-data/_spec/iterators.spec.ts b/src/mol-data/_spec/iterators.spec.ts index a2e9a353650010c377c64699c9e47ab19fcc7556..f7b4d163a0ace2882d30c7f72dc76a5bf00f272b 100644 --- a/src/mol-data/_spec/iterators.spec.ts +++ b/src/mol-data/_spec/iterators.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Iterator from '../iterator' +import Iterator from '../iterator'; function iteratorToArray<T>(it: Iterator<T>): T[] { const ret = []; diff --git a/src/mol-data/_spec/sort.spec.ts b/src/mol-data/_spec/sort.spec.ts index 9d2a122ccfead9d33a783df1a05c7c21e3cc8d06..dfa24e6b1d3cfff6b9329bb291178457de0c9c7c 100644 --- a/src/mol-data/_spec/sort.spec.ts +++ b/src/mol-data/_spec/sort.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Sort from '../util/sort' +import * as Sort from '../util/sort'; function shuffle<T>(data: T, len: number, clone: (s: T) => T, swap: Sort.Swapper = Sort.arraySwap) { const a = clone(data); @@ -40,7 +40,7 @@ describe('qsort-array asc', () => { test('uniq shuffle', data0, true); test('rep', data1, false); test('rep shuffle', data1, true); -}) +}); describe('qsort-array generic', () => { const data0 = new Array(50); @@ -63,15 +63,15 @@ describe('qsort-array generic', () => { test('uniq shuffle', data0, true); test('rep', data1, false); test('rep shuffle', data1, true); -}) +}); describe('qsort-dual array', () => { const len = 3; const data = { xs: [0, 1, 2], ys: ['x', 'y', 'z'] }; const cmp: Sort.Comparer<typeof data> = (data, i, j) => data.xs[i] - data.xs[j]; - const swap: Sort.Swapper<typeof data> = (data, i, j) => { Sort.arraySwap(data.xs, i, j); Sort.arraySwap(data.ys, i, j); } - const clone = (d: typeof data) => ({ xs: [...d.xs], ys: [...d.ys] }) + const swap: Sort.Swapper<typeof data> = (data, i, j) => { Sort.arraySwap(data.xs, i, j); Sort.arraySwap(data.ys, i, j); }; + const clone = (d: typeof data) => ({ xs: [...d.xs], ys: [...d.ys] }); function test(name: string, src: typeof data, randomize: boolean) { it(name, () => { @@ -87,4 +87,4 @@ describe('qsort-dual array', () => { } test('sorted', data, false); test('shuffled', data, true); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-data/db.ts b/src/mol-data/db.ts index e783dac4f7eb88954cd4955805efcbf1047b113a..5958737825a062df45ca77e12241fa0074736a93 100644 --- a/src/mol-data/db.ts +++ b/src/mol-data/db.ts @@ -5,11 +5,11 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import Database from './db/database' -import Table from './db/table' -import Column from './db/column' -import * as ColumnHelpers from './db/column-helpers' +import Database from './db/database'; +import Table from './db/table'; +import Column from './db/column'; +import * as ColumnHelpers from './db/column-helpers'; type DatabaseCollection<T extends Database.Schema> = { [name: string]: Database<T> } -export { DatabaseCollection, Database, Table, Column, ColumnHelpers } \ No newline at end of file +export { DatabaseCollection, Database, Table, Column, ColumnHelpers }; \ No newline at end of file diff --git a/src/mol-data/db/_spec/table.spec.ts b/src/mol-data/db/_spec/table.spec.ts index 0691665197e6d4132d9e7e89ff9dab8dc73cafd1..17fa9202980b4c8fecbf3692f206677da197c55f 100644 --- a/src/mol-data/db/_spec/table.spec.ts +++ b/src/mol-data/db/_spec/table.spec.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as ColumnHelpers from '../column-helpers' -import Column from '../column' -import Table from '../table' +import * as ColumnHelpers from '../column-helpers'; +import Column from '../column'; +import Table from '../table'; describe('column', () => { const cc = Column.ofConst(10, 2, Column.Schema.int); @@ -59,7 +59,7 @@ describe('column', () => { it('map to array', () => { expect(Column.mapToArray(arrWindow, x => x + 1)).toEqual([3, 4]); }); -}) +}); describe('table', () => { const schema = { @@ -125,7 +125,7 @@ describe('table', () => { n: Column.ofArray({ array: ['row1', 'row2'], schema: Column.Schema.str }), }); const { x } = t; - const sorted = Table.sort(t, (i, j) => x.value(i) - x.value(j)) + const sorted = Table.sort(t, (i, j) => x.value(i) - x.value(j)); expect(sorted.x.toArray()).toEqual([-1, 10]); expect(sorted.n.toArray()).toEqual(['row2', 'row1']); }); diff --git a/src/mol-data/db/column-helpers.ts b/src/mol-data/db/column-helpers.ts index b1645fb061f9346e4ebfd8f3bb45c1e27397e435..c4c54d951edeae3403d74384108f09b94aea85fe 100644 --- a/src/mol-data/db/column-helpers.ts +++ b/src/mol-data/db/column-helpers.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Column from './column' +import Column from './column'; export function getArrayBounds(rowCount: number, params?: Column.ToArrayParams<any>) { const start = params && typeof params.start !== 'undefined' ? Math.max(Math.min(params.start, rowCount - 1), 0) : 0; diff --git a/src/mol-data/db/column.ts b/src/mol-data/db/column.ts index 8f242202ca93a747e465b0587c6fa6d8d7f1fee8..7b127113aa20df3595a183b4c4e9c35243c460ab 100644 --- a/src/mol-data/db/column.ts +++ b/src/mol-data/db/column.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as ColumnHelpers from './column-helpers' -import { Tensor as Tensors } from '../../mol-math/linear-algebra' +import * as ColumnHelpers from './column-helpers'; +import { Tensor as Tensors } from '../../mol-math/linear-algebra'; import { Tokens } from '../../mol-io/reader/common/text/tokenizer'; import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../mol-io/reader/common/text/number-parser'; @@ -45,9 +45,9 @@ namespace Column { export const coord: Coordinate = { '@type': 'coord', T: 0, valueType: 'float' }; export const float: Float = { '@type': 'float', T: 0, valueType: 'float' }; - export function Str(defaultValue = ''): Str { return { '@type': 'str', T: defaultValue, valueType: 'str' } }; - export function Int(defaultValue = 0): Int { return { '@type': 'int', T: defaultValue, valueType: 'int' } }; - export function Float(defaultValue = 0): Float { return { '@type': 'float', T: defaultValue, valueType: 'float' } }; + export function Str(defaultValue = ''): Str { return { '@type': 'str', T: defaultValue, valueType: 'str' }; }; + export function Int(defaultValue = 0): Int { return { '@type': 'int', T: defaultValue, valueType: 'int' }; }; + export function Float(defaultValue = 0): Float { return { '@type': 'float', T: defaultValue, valueType: 'float' }; }; export function Tensor(space: Tensors.Space, baseType: Int | Float = float): Tensor { return { '@type': 'tensor', T: space.create(), space, valueType: 'tensor', baseType }; } export function Vector(dim: number, baseType: Int | Float = float): Tensor { return Tensor(Tensors.Vector(dim, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); } export function Matrix(rows: number, cols: number, baseType: Int | Float = float): Tensor { return Tensor(Tensors.ColumnMajorMatrix(rows, cols, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); } @@ -57,7 +57,7 @@ namespace Column { return t as any as Aliased<T>; } export function List<T extends number|string>(separator: string, itemParse: (x: string) => T, defaultValue: T[] = []): List<T> { - return { '@type': 'list', T: defaultValue, separator, itemParse, valueType: 'list' } + return { '@type': 'list', T: defaultValue, separator, itemParse, valueType: 'list' }; } } @@ -146,7 +146,7 @@ namespace Column { } export function ofIntTokens(tokens: Tokens) { - const { count, data, indices } = tokens + const { count, data, indices } = tokens; return lambdaColumn({ value: (row: number) => fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0, rowCount: count, @@ -155,7 +155,7 @@ namespace Column { } export function ofFloatTokens(tokens: Tokens) { - const { count, data, indices } = tokens + const { count, data, indices } = tokens; return lambdaColumn({ value: (row: number) => fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0, rowCount: count, @@ -164,7 +164,7 @@ namespace Column { } export function ofStringTokens(tokens: Tokens) { - const { count, data, indices } = tokens + const { count, data, indices } = tokens; return lambdaColumn({ value: (row: number) => { const ret = data.substring(indices[2 * row], indices[2 * row + 1]); @@ -214,7 +214,7 @@ namespace Column { export function copyToArray<T extends number>(c: Column<T>, array: { [k: number]: T, length: number }, offset = 0) { if (!c.isDefined) return; - const cArray = c.__array + const cArray = c.__array; if (cArray) { for (let i = 0, _i = cArray.length; i < _i; i++) array[offset + i] = cArray[i]; } else { @@ -259,7 +259,7 @@ function constColumn<T extends Column.Schema>(v: T['T'], rowCount: number, schem return array; }, areValuesEqual: (rowA, rowB) => true - } + }; } function lambdaColumn<T extends Column.Schema>({ value, valueKind, areValuesEqual, rowCount, schema }: Column.LambdaSpec<T>): Column<T['T']> { @@ -276,7 +276,7 @@ function lambdaColumn<T extends Column.Schema>({ value, valueKind, areValuesEqua return array; }, areValuesEqual: areValuesEqual ? areValuesEqual : (rowA, rowB) => value(rowA) === value(rowB) - } + }; } function arrayColumn<T extends Column.Schema>({ array, schema, valueKind }: Column.ArraySpec<T>): Column<T['T']> { @@ -313,7 +313,7 @@ function arrayColumn<T extends Column.Schema>({ array, schema, valueKind }: Colu return ret; }, areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB] - } + }; } function windowColumn<T>(column: Column<T>, start: number, end: number): Column<T> { diff --git a/src/mol-data/db/database.ts b/src/mol-data/db/database.ts index 5aa2f2700dd732f6d2981a1232e2a099109b2da0..49405a4139d66294bc96a133c38f62c411e21ae4 100644 --- a/src/mol-data/db/database.ts +++ b/src/mol-data/db/database.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Table from './table' +import Table from './table'; /** A collection of tables */ type Database<Schema extends Database.Schema> = { @@ -41,4 +41,4 @@ namespace Database { } } -export default Database \ No newline at end of file +export default Database; \ No newline at end of file diff --git a/src/mol-data/db/table.ts b/src/mol-data/db/table.ts index b202468232b649e0591a39a496fc178bdf5d2f5a..4c6b34cf7ed485111f83c5457cd63414f0baa0db 100644 --- a/src/mol-data/db/table.ts +++ b/src/mol-data/db/table.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Column from './column' -import { sortArray } from '../util/sort' +import Column from './column'; +import { sortArray } from '../util/sort'; import { StringBuilder } from '../../mol-util'; /** A collection of columns */ @@ -55,8 +55,8 @@ namespace Table { ret._columns = columns; ret._schema = schema; for (const k of columns) { - if (k in partialColumns) ret[k] = partialColumns[k] - else ret[k] = Column.Undefined(rowCount, schema[k]) + if (k in partialColumns) ret[k] = partialColumns[k]; + else ret[k] = Column.Undefined(rowCount, schema[k]); } return ret; } @@ -68,7 +68,7 @@ namespace Table { ret._columns = columns; ret._schema = schema; for (const k of columns) { - ret[k] = Column.Undefined(rowCount, schema[k]) + ret[k] = Column.Undefined(rowCount, schema[k]); } return ret; } @@ -86,7 +86,7 @@ namespace Table { schema: schema[k], value: r => rows[r][k], valueKind: r => typeof rows[r][k] === 'undefined' ? Column.ValueKind.NotPresent : Column.ValueKind.Present - }) + }); } return ret as R; } @@ -121,11 +121,11 @@ namespace Table { } export function pick<S extends R, R extends Schema>(table: Table<S>, schema: R, test: (i: number) => boolean) { - const _view: number[] = [] + const _view: number[] = []; for (let i = 0, il = table._rowCount; i < il; ++i) { - if (test(i)) _view.push(i) + if (test(i)) _view.push(i); } - return view(table, schema, _view) + return view(table, schema, _view); } export function window<S extends R, R extends Schema>(table: Table<S>, schema: R, start: number, end: number) { @@ -144,25 +144,25 @@ namespace Table { export function concat<S extends R, R extends Schema>(tables: Table<S>[], schema: R) { const ret = Object.create(null); const columns = Object.keys(schema); - ret._rowCount = 0 + ret._rowCount = 0; for (const table of tables) { - ret._rowCount += table._rowCount + ret._rowCount += table._rowCount; } - const arrays: any = {} + const arrays: any = {}; for (const column of columns) { - arrays[column] = new Array(ret._rowCount) + arrays[column] = new Array(ret._rowCount); } ret._columns = columns; ret._schema = schema; - let offset = 0 + let offset = 0; for (const table of tables) { for (const k of columns) { - Column.copyToArray(table[k], arrays[k], offset) + Column.copyToArray(table[k], arrays[k], offset); } - offset += table._rowCount + offset += table._rowCount; } for (const k of columns) { - ret[k] = Column.ofArray({ array: arrays[k], schema: schema[k] }) + ret[k] = Column.ofArray({ array: arrays[k], schema: schema[k] }); } return ret as Table<R>; } @@ -224,7 +224,7 @@ namespace Table { /** Pick the first row for which `test` evaluates to true */ export function pickRow<S extends Schema>(table: Table<S>, test: (i: number) => boolean) { for (let i = 0, il = table._rowCount; i < il; ++i) { - if (test(i)) return getRow(table, i) + if (test(i)) return getRow(table, i); } } @@ -238,13 +238,13 @@ namespace Table { } export function toArrays<S extends Schema>(table: Table<S>) { - const arrays: { [k: string]: ArrayLike<any> } = {} + const arrays: { [k: string]: ArrayLike<any> } = {}; const { _columns } = table; for (let i = 0; i < _columns.length; i++) { - const c = _columns[i] + const c = _columns[i]; arrays[c] = table[c].toArray(); } - return arrays as { [k in keyof S]: ArrayLike<S[k]['T']> } + return arrays as { [k in keyof S]: ArrayLike<S[k]['T']> }; } export function formatToString<S extends Schema>(table: Table<S>) { @@ -280,4 +280,4 @@ namespace Table { } } -export default Table \ No newline at end of file +export default Table; \ No newline at end of file diff --git a/src/mol-data/generic.ts b/src/mol-data/generic.ts index d837d1060ef77cafd9a0cf7c493a05f90b2a03b2..f74a1446dc377c46e1b92c0636355048bd88f2e4 100644 --- a/src/mol-data/generic.ts +++ b/src/mol-data/generic.ts @@ -4,6 +4,6 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './generic/hash-set' -export * from './generic/linked-list' -export * from './generic/unique-array' \ No newline at end of file +export * from './generic/hash-set'; +export * from './generic/linked-list'; +export * from './generic/unique-array'; \ No newline at end of file diff --git a/src/mol-data/generic/_spec/linked-list.spec.ts b/src/mol-data/generic/_spec/linked-list.spec.ts index cb439b3da78117e85734fa39ffd040f86cc260a5..871f36639719dc560997d27187b1df7c267521bf 100644 --- a/src/mol-data/generic/_spec/linked-list.spec.ts +++ b/src/mol-data/generic/_spec/linked-list.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { LinkedList } from '../linked-list' +import { LinkedList } from '../linked-list'; describe('linked list', () => { @@ -59,5 +59,5 @@ describe('linked list', () => { expect(list.last).toBe(null); expect(list.count).toBe(0); expect(toArray(list)).toEqual([]); - }) + }); }); \ No newline at end of file diff --git a/src/mol-data/generic/linked-list.ts b/src/mol-data/generic/linked-list.ts index efd64e347c07ed662cf70248ebb73619c60c19fc..436fe11ac2d982d541cc782614c265a1bda90056 100644 --- a/src/mol-data/generic/linked-list.ts +++ b/src/mol-data/generic/linked-list.ts @@ -114,4 +114,4 @@ class LinkedListImpl<T> implements LinkedList<T> { } } -export { LinkedList } \ No newline at end of file +export { LinkedList }; \ No newline at end of file diff --git a/src/mol-data/generic/unique-array.ts b/src/mol-data/generic/unique-array.ts index 8e02d5abe4ce37432f1b8ea5ce686aab496ab19d..f29e2b1443fe0009f464c6f6a04399b01582af48 100644 --- a/src/mol-data/generic/unique-array.ts +++ b/src/mol-data/generic/unique-array.ts @@ -26,4 +26,4 @@ namespace UniqueArray { } } -export { UniqueArray } \ No newline at end of file +export { UniqueArray }; \ No newline at end of file diff --git a/src/mol-data/index.ts b/src/mol-data/index.ts index b1d2500848e1069a962d90d252e76406d47a9441..cfd7b323132e576b4c2683c406d67a1a36f4fa3e 100644 --- a/src/mol-data/index.ts +++ b/src/mol-data/index.ts @@ -4,10 +4,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as DB from './db' -import * as Int from './int' -import Iterator from './iterator' -import * as Util from './util' -import * as Generic from './generic' +import * as DB from './db'; +import * as Int from './int'; +import Iterator from './iterator'; +import * as Util from './util'; +import * as Generic from './generic'; -export { DB, Int, Iterator, Util, Generic } \ No newline at end of file +export { DB, Int, Iterator, Util, Generic }; \ No newline at end of file diff --git a/src/mol-data/int.ts b/src/mol-data/int.ts index 24b005bd24adbc9949770670c2c6fb2a4535485b..9ecda41a04b047f1246af2a670c2540fe6434add 100644 --- a/src/mol-data/int.ts +++ b/src/mol-data/int.ts @@ -4,13 +4,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Interval from './int/interval' -import OrderedSet from './int/ordered-set' -import Segmentation from './int/segmentation' -import SortedArray from './int/sorted-array' -import Tuple from './int/tuple' -import LinkedIndex from './int/linked-index' -import IntMap from './int/map' -import Iterator from './iterator' +import Interval from './int/interval'; +import OrderedSet from './int/ordered-set'; +import Segmentation from './int/segmentation'; +import SortedArray from './int/sorted-array'; +import Tuple from './int/tuple'; +import LinkedIndex from './int/linked-index'; +import IntMap from './int/map'; +import Iterator from './iterator'; -export { Interval, OrderedSet, Segmentation, SortedArray, Tuple, LinkedIndex, IntMap, Iterator } \ No newline at end of file +export { Interval, OrderedSet, Segmentation, SortedArray, Tuple, LinkedIndex, IntMap, Iterator }; \ No newline at end of file diff --git a/src/mol-data/int/_spec/interval.spec.ts b/src/mol-data/int/_spec/interval.spec.ts index 0b981d35b7fe0364b825965618c76ebb26edf5fb..f2ddf0e8a26a42774fd02aef2d2c8b2007938f0c 100644 --- a/src/mol-data/int/_spec/interval.spec.ts +++ b/src/mol-data/int/_spec/interval.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Interval from '../interval' +import Interval from '../interval'; describe('interval', () => { function testI(name: string, a: Interval, b: Interval) { diff --git a/src/mol-data/int/_spec/linked-index.spec.ts b/src/mol-data/int/_spec/linked-index.spec.ts index 743c39a3e0b3170e988c1fcb012981db5141a9f2..d1895a0efc7d135176ad4ec619abf3582e0e92df 100644 --- a/src/mol-data/int/_spec/linked-index.spec.ts +++ b/src/mol-data/int/_spec/linked-index.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import LinkedIndex from '../linked-index' +import LinkedIndex from '../linked-index'; describe('linked-index', () => { it('initial state', () => { diff --git a/src/mol-data/int/_spec/ordered-set.spec.ts b/src/mol-data/int/_spec/ordered-set.spec.ts index 341e7d14b5c68a2c54ef064b3e879fd13381f843..a699dbe32c009970c8b314f045cadcce9ade40ec 100644 --- a/src/mol-data/int/_spec/ordered-set.spec.ts +++ b/src/mol-data/int/_spec/ordered-set.spec.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import OrderedSet from '../ordered-set' -import Interval from '../interval' +import OrderedSet from '../ordered-set'; +import Interval from '../interval'; import SortedArray from '../sorted-array'; describe('ordered set', () => { @@ -122,14 +122,14 @@ describe('ordered set', () => { expect(OrderedSet.findRange(arr136, 0, 4)).toEqual(iB(0, 2)); expect(OrderedSet.findRange(arr136, 2, 4)).toEqual(iB(1, 2)); expect(OrderedSet.findRange(arr136, 2, 7)).toEqual(iB(1, 3)); - }) + }); it('intersectionSize', () => { expect(OrderedSet.intersectionSize(arr136, range1_4)).toEqual(2); expect(OrderedSet.intersectionSize(arr12369, range1_4)).toEqual(3); expect(OrderedSet.intersectionSize(OrderedSet.ofSortedArray([12, 13, 16]), range1_4)).toEqual(0); expect(OrderedSet.intersectionSize(OrderedSet.ofSortedArray([1, 2, 4]), range1_4)).toEqual(3); - }) + }); testEq('union ES', OrderedSet.union(empty, singleton10), [10]); testEq('union ER', OrderedSet.union(empty, range1_4), [1, 2, 3, 4]); @@ -201,5 +201,5 @@ describe('ordered set', () => { const int = OrderedSet.ofBounds(1, 3), set = OrderedSet.ofSortedArray([2, 3, 4]); expect(OrderedSet.forEach(int, (v, i, ctx) => ctx[i] = v, [] as number[])).toEqual([1, 2]); expect(OrderedSet.forEach(set, (v, i, ctx) => ctx[i] = v, [] as number[])).toEqual([2, 3, 4]); - }) + }); }); \ No newline at end of file diff --git a/src/mol-data/int/_spec/segmentation.spec.ts b/src/mol-data/int/_spec/segmentation.spec.ts index ef253062a74e3205f9a472fc0163ecea97384118..95248bbfbe45bff3efcd0d5f67df41abc23cdb5a 100644 --- a/src/mol-data/int/_spec/segmentation.spec.ts +++ b/src/mol-data/int/_spec/segmentation.spec.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import OrderedSet from '../ordered-set' -import Interval from '../interval' -import Segmentation from '../segmentation' +import OrderedSet from '../ordered-set'; +import Interval from '../interval'; +import Segmentation from '../segmentation'; describe('segments', () => { const data = OrderedSet.ofSortedArray([4, 9, 10, 11, 14, 15, 16]); @@ -16,12 +16,12 @@ describe('segments', () => { it('project', () => { const p = Segmentation.projectValue(segs, data, 4); - expect(p).toBe(Interval.ofBounds(0, 2)) + expect(p).toBe(Interval.ofBounds(0, 2)); }); it('ofOffsetts', () => { const p = Segmentation.ofOffsets([10, 12], Interval.ofBounds(10, 14)); - expect(p.offsets).toEqual(new Int32Array([0, 2, 4])) + expect(p.offsets).toEqual(new Int32Array([0, 2, 4])); }); it('map', () => { diff --git a/src/mol-data/int/_spec/sorted-array.spec.ts b/src/mol-data/int/_spec/sorted-array.spec.ts index e63692d1ab60e95697677ec52276c1c9a8e100aa..cfa94e87cfbdde103c6068349ed6af071395ede4 100644 --- a/src/mol-data/int/_spec/sorted-array.spec.ts +++ b/src/mol-data/int/_spec/sorted-array.spec.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Interval from '../interval' -import SortedArray from '../sorted-array' +import Interval from '../interval'; +import SortedArray from '../sorted-array'; describe('sortedArray', () => { function testI(name: string, a: Interval, b: Interval) { @@ -61,7 +61,7 @@ describe('sortedArray', () => { it('indicesOf', () => { compareArrays(SortedArray.indicesOf(SortedArray.ofSortedArray([10, 11, 12]), SortedArray.ofSortedArray([10, 12, 14])), [0, 2]); - }) + }); it('indicesOf 2', () => { compareArrays( @@ -71,7 +71,7 @@ describe('sortedArray', () => { ), [1, 3, 4, 6, 7] ); - }) + }); test('intersectionSize', SortedArray.intersectionSize(a1234, a2468), 2); @@ -82,8 +82,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([835]) ), SortedArray.ofSortedArray([830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843]) - ) - }) + ); + }); it('union2', () => { compareArrays( @@ -92,8 +92,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([831]) ), SortedArray.ofSortedArray([830, 831, 832, 833]) - ) - }) + ); + }); it('union3ab', () => { compareArrays( @@ -102,8 +102,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([836, 837, 838, 839, 840, 841, 842, 843]) ), SortedArray.ofSortedArray([830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843]) - ) - }) + ); + }); it('union3ba', () => { compareArrays( @@ -112,8 +112,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([830, 831, 832, 833, 834, 835]) ), SortedArray.ofSortedArray([830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843]) - ) - }) + ); + }); it('union4', () => { compareArrays( @@ -122,8 +122,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([2, 4, 6, 8]) ), SortedArray.ofSortedArray([1, 2, 3, 4, 5, 6, 7, 8, 9]) - ) - }) + ); + }); it('union5', () => { compareArrays( @@ -132,8 +132,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([10, 11, 12]) ), SortedArray.ofSortedArray([2, 3, 4, 10, 11, 12, 20, 21, 22]) - ) - }) + ); + }); it('union6', () => { compareArrays( @@ -142,8 +142,8 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758]) ), SortedArray.ofSortedArray([768, 769, 770, 771, 772, 773, 774, 775, 776, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819]) - ) - }) + ); + }); it('union7', () => { compareArrays( @@ -152,13 +152,13 @@ describe('sortedArray', () => { SortedArray.ofSortedArray([3769, 3790, 3794]) ), SortedArray.ofSortedArray([3766, 3767, 3768, 3769, 3770, 3773, 3780, 3783, 3787, 3790, 3794, 3797]) - ) - }) + ); + }); it('isSubset', () => { expect(SortedArray.isSubset( SortedArray.ofSortedArray([1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295]), SortedArray.ofSortedArray([1271, 1272, 1274, 1275, 1276, 1278, 1280, 1282, 1284, 1286, 1288, 1290, 1292, 1294]) )).toBe(true); - }) + }); }); \ No newline at end of file diff --git a/src/mol-data/int/_spec/sorted-ranges.spec.ts b/src/mol-data/int/_spec/sorted-ranges.spec.ts index 84075305edfe65c901c316a2b287bbc94f0f7314..942eaad88c52e2c39aed90f1097f505a50f7e78a 100644 --- a/src/mol-data/int/_spec/sorted-ranges.spec.ts +++ b/src/mol-data/int/_spec/sorted-ranges.spec.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import SortedRanges from '../sorted-ranges' +import SortedRanges from '../sorted-ranges'; import OrderedSet from '../ordered-set'; import SortedArray from '../sorted-array'; @@ -15,19 +15,19 @@ describe('rangesArray', () => { function testIterator(name: string, ranges: SortedRanges, set: OrderedSet, expectedValues: { index: number[], start: number[], end: number[]}) { it(`iterator, ${name}`, () => { - const rangesIt = SortedRanges.transientSegments(ranges, set) - const { index, start, end } = expectedValues + const rangesIt = SortedRanges.transientSegments(ranges, set); + const { index, start, end } = expectedValues; - let i = 0 + let i = 0; while (rangesIt.hasNext) { - const segment = rangesIt.move() - expect(segment.index).toBe(index[i]) - expect(segment.start).toBe(start[i]) - expect(segment.end).toBe(end[i]) - ++i + const segment = rangesIt.move(); + expect(segment.index).toBe(index[i]); + expect(segment.start).toBe(start[i]); + expect(segment.end).toBe(end[i]); + ++i; } - expect(i).toBe(index.length) - }) + expect(i).toBe(index.length); + }); } const a1234 = SortedRanges.ofSortedRanges([1, 2, 3, 4]); @@ -43,30 +43,30 @@ describe('rangesArray', () => { SortedRanges.ofSortedRanges([1, 2, 3, 4]), OrderedSet.ofBounds(1, 5), { index: [0, 1], start: [0, 2], end: [2, 4] } - ) + ); testIterator('first range', SortedRanges.ofSortedRanges([1, 2, 3, 4]), SortedArray.ofSortedArray([2]), { index: [0], start: [0], end: [1] } - ) + ); testIterator('second range', SortedRanges.ofSortedRanges([1, 2, 3, 4]), SortedArray.ofSortedArray([4]), { index: [1], start: [0], end: [1] } - ) + ); testIterator('set not in ranges', SortedRanges.ofSortedRanges([1, 2, 3, 4]), SortedArray.ofSortedArray([10]), { index: [], start: [], end: [] } - ) + ); testIterator('set in second range and beyond', SortedRanges.ofSortedRanges([1, 2, 3, 4]), SortedArray.ofSortedArray([3, 10]), { index: [1], start: [0], end: [1] } - ) + ); testIterator('length 1 range', SortedRanges.ofSortedRanges([1, 1, 3, 4]), SortedArray.ofSortedArray([0, 1, 10]), { index: [0], start: [1], end: [2] } - ) + ); }); \ No newline at end of file diff --git a/src/mol-data/int/_spec/tuple.spec.ts b/src/mol-data/int/_spec/tuple.spec.ts index 37610b8393b40f1305d460dfab128d99d8954887..0ea8e5eab1b37216271ea30b548acf89a2b56150 100644 --- a/src/mol-data/int/_spec/tuple.spec.ts +++ b/src/mol-data/int/_spec/tuple.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import IntTuple from '../tuple' +import IntTuple from '../tuple'; describe('int pair', () => { it('works', () => { @@ -15,5 +15,5 @@ describe('int pair', () => { expect(IntTuple.snd(t)).toBe(j); } } - }) -}) \ No newline at end of file + }); +}); \ No newline at end of file diff --git a/src/mol-data/int/impl/interval.ts b/src/mol-data/int/impl/interval.ts index 29307c74bb81a065ef6a8e23054de577325cd891..127c1860db7f4ca634d92f0390df8252b888f39c 100644 --- a/src/mol-data/int/impl/interval.ts +++ b/src/mol-data/int/impl/interval.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Tuple from '../tuple' +import Tuple from '../tuple'; export const Empty = Tuple.Zero; export function ofRange(min: number, max: number) { return max < min ? Tuple.create(min, min) : Tuple.create(min, max + 1); } @@ -64,5 +64,5 @@ export function intersect(a: Tuple, b: Tuple) { } export function intersectionSize(a: Tuple, b: Tuple) { - return size(findRange(a, min(b), max(b))) + return size(findRange(a, min(b), max(b))); } \ No newline at end of file diff --git a/src/mol-data/int/impl/ordered-set.ts b/src/mol-data/int/impl/ordered-set.ts index 47a91eed2de4d0f8e2ffd07a6f7e29cab24e25a7..ce80702f3429c442e00049d3ea54b18de3fa5a1a 100644 --- a/src/mol-data/int/impl/ordered-set.ts +++ b/src/mol-data/int/impl/ordered-set.ts @@ -4,17 +4,17 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import S from '../sorted-array' -import I from '../interval' +import S from '../sorted-array'; +import I from '../interval'; type OrderedSetImpl = I | S type Nums = ArrayLike<number> export const Empty: OrderedSetImpl = I.Empty; -export const ofSingleton = I.ofSingleton -export const ofRange = I.ofRange -export const ofBounds = I.ofBounds +export const ofSingleton = I.ofSingleton; +export const ofRange = I.ofRange; +export const ofBounds = I.ofBounds; export function ofSortedArray(xs: Nums): OrderedSetImpl { if (!xs.length) return Empty; diff --git a/src/mol-data/int/impl/segmentation.ts b/src/mol-data/int/impl/segmentation.ts index 6ffb90b133053bb62c5e80021cc35b8aded7e49d..4704df14b1f3fb45c88019f77c88ed03c8e9dd53 100644 --- a/src/mol-data/int/impl/segmentation.ts +++ b/src/mol-data/int/impl/segmentation.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Iterator from '../../iterator' -import OrderedSet from '../ordered-set' -import Interval from '../interval' -import SortedArray from '../sorted-array' -import Segs from '../segmentation' +import Iterator from '../../iterator'; +import OrderedSet from '../ordered-set'; +import Interval from '../interval'; +import SortedArray from '../sorted-array'; +import Segs from '../segmentation'; interface Segmentation { /** Segments stored as a sorted array */ diff --git a/src/mol-data/int/impl/sorted-array.ts b/src/mol-data/int/impl/sorted-array.ts index 87eacf6b0b8c91243f00447a118b3b69cb801e67..d8bcbab630a230f0d5f159673fa8fd37bd8c174a 100644 --- a/src/mol-data/int/impl/sorted-array.ts +++ b/src/mol-data/int/impl/sorted-array.ts @@ -4,13 +4,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { sortArray, hash3, hash4, createRangeArray } from '../../util' -import Interval from '../interval' +import { sortArray, hash3, hash4, createRangeArray } from '../../util'; +import Interval from '../interval'; type Nums = ArrayLike<number> -export const Empty: Nums = [] +export const Empty: Nums = []; export function ofSingleton(v: number) { return [v]; } export function ofSortedArray(xs: Nums) { return xs; } @@ -47,7 +47,7 @@ export function indexOf(xs: Nums, v: number) { return l === 0 ? -1 : xs[0] <= v && v <= xs[l - 1] ? binarySearchRange(xs, v, 0, l) : -1; } export function indexOfInInterval(xs: Nums, v: number, bounds: Interval) { - return indexOfInRange(xs, v, Interval.start(bounds), Interval.end(bounds)) + return indexOfInRange(xs, v, Interval.start(bounds), Interval.end(bounds)); } export function indexOfInRange(xs: Nums, v: number, s: number, e: number) { const l = xs.length; diff --git a/src/mol-data/int/interval.ts b/src/mol-data/int/interval.ts index ea8e9c18e766a2a8872a70ded1f8d95b80f1e8bc..8d0f6df436bd2cef60ab0b6ee24363a9d13b18f5 100644 --- a/src/mol-data/int/interval.ts +++ b/src/mol-data/int/interval.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Impl from './impl/interval' +import * as Impl from './impl/interval'; namespace Interval { export const Empty: Interval = Impl.Empty as any; @@ -60,4 +60,4 @@ namespace Interval { /** Interval describing a range [min, max] of values */ interface Interval<T extends number = number> { '@type': 'int-interval' } -export default Interval \ No newline at end of file +export default Interval; \ No newline at end of file diff --git a/src/mol-data/int/map.ts b/src/mol-data/int/map.ts index 30725a89c49238468e858c85cb88c65f3b3062e4..0f99314ae0f1040843cdd5cc4ac38a6ca8867426 100644 --- a/src/mol-data/int/map.ts +++ b/src/mol-data/int/map.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { iterableToArray } from '../util' +import { iterableToArray } from '../util'; // TODO: rename to "linear map" and just do key value mapping from index? diff --git a/src/mol-data/int/ordered-set.ts b/src/mol-data/int/ordered-set.ts index 1cca12b4f17d25aeefd08f8221f5cb8030b27d5a..9e652a3b257ca3bb700c80fd714332ed1beb693a 100644 --- a/src/mol-data/int/ordered-set.ts +++ b/src/mol-data/int/ordered-set.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Base from './impl/ordered-set' -import Interval from './interval' +import * as Base from './impl/ordered-set'; +import Interval from './interval'; import SortedArray from './sorted-array'; namespace OrderedSet { @@ -70,16 +70,16 @@ namespace OrderedSet { } export function toArray<T extends number = number>(set: OrderedSet<T>): T[] { - const array: T[] = [] - OrderedSet.forEach(set, v => array.push(v)) - return array + const array: T[] = []; + OrderedSet.forEach(set, v => array.push(v)); + return array; } export function toString<T extends number = number>(set: OrderedSet<T>): string { - return Base.toString(set) + return Base.toString(set); } } type OrderedSet<T extends number = number> = SortedArray<T> | Interval<T> -export default OrderedSet \ No newline at end of file +export default OrderedSet; \ No newline at end of file diff --git a/src/mol-data/int/segmentation.ts b/src/mol-data/int/segmentation.ts index 8d26c5f1f67e023fbd225e9fe2e9084e741e0d50..a9e4d5d0a99774b0c5758ffa8819a0600358d8e1 100644 --- a/src/mol-data/int/segmentation.ts +++ b/src/mol-data/int/segmentation.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Interval from './interval' -import OrderedSet from './ordered-set' -import * as Impl from './impl/segmentation' +import Interval from './interval'; +import OrderedSet from './ordered-set'; +import * as Impl from './impl/segmentation'; namespace Segmentation { export interface Segment<I extends number = number> { index: I, start: number, end: number } @@ -33,4 +33,4 @@ interface Segmentation<T extends number = number, I extends number = number> { readonly count: number } -export default Segmentation \ No newline at end of file +export default Segmentation; \ No newline at end of file diff --git a/src/mol-data/int/sorted-array.ts b/src/mol-data/int/sorted-array.ts index 1f33a78370419fa6978d2485a48a6f6d7fc4bbde..330bd1d9f2c353f362461db22c9021293f3cf149 100644 --- a/src/mol-data/int/sorted-array.ts +++ b/src/mol-data/int/sorted-array.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Impl from './impl/sorted-array' -import Interval from './interval' +import * as Impl from './impl/sorted-array'; +import Interval from './interval'; namespace SortedArray { export const Empty: SortedArray = Impl.Empty as any; @@ -54,4 +54,4 @@ namespace SortedArray { interface SortedArray<T extends number = number> extends ArrayLike<T> { '@type': 'int-sorted-array' } -export default SortedArray \ No newline at end of file +export default SortedArray; \ No newline at end of file diff --git a/src/mol-data/int/sorted-ranges.ts b/src/mol-data/int/sorted-ranges.ts index 03f33012c4ca2af5fc80fe4d746a39f574492b3f..d7639812a8bc72acd866b4213cfd97673fde9692 100644 --- a/src/mol-data/int/sorted-ranges.ts +++ b/src/mol-data/int/sorted-ranges.ts @@ -11,79 +11,79 @@ import _Iterator from '../iterator'; type SortedRanges<T extends number = number> = SortedArray<T> namespace SortedRanges { - export function ofSortedRanges<T extends number = number>(array: ArrayLike<T>) { return SortedArray.ofSortedArray<T>(array) } - export function start<T extends number = number>(ranges: SortedRanges<T>) { return ranges[0] } - export function end<T extends number = number>(ranges: SortedRanges<T>) { return ranges[ranges.length - 1] + 1 } - export function min<T extends number = number>(ranges: SortedRanges<T>) { return ranges[0] } - export function max<T extends number = number>(ranges: SortedRanges<T>) { return ranges[ranges.length - 1] } + export function ofSortedRanges<T extends number = number>(array: ArrayLike<T>) { return SortedArray.ofSortedArray<T>(array); } + export function start<T extends number = number>(ranges: SortedRanges<T>) { return ranges[0]; } + export function end<T extends number = number>(ranges: SortedRanges<T>) { return ranges[ranges.length - 1] + 1; } + export function min<T extends number = number>(ranges: SortedRanges<T>) { return ranges[0]; } + export function max<T extends number = number>(ranges: SortedRanges<T>) { return ranges[ranges.length - 1]; } export function size<T extends number = number>(ranges: SortedRanges<T>) { - let size = 0 + let size = 0; for (let i = 0, il = ranges.length; i < il; i += 2) { - size += ranges[i + 1] - ranges[i] + 1 + size += ranges[i + 1] - ranges[i] + 1; } - return size + return size; } - export function count<T extends number = number>(ranges: SortedRanges<T>) { return ranges.length / 2 } + export function count<T extends number = number>(ranges: SortedRanges<T>) { return ranges.length / 2; } export function startAt<T extends number = number>(ranges: SortedRanges<T>, index: number) { - return ranges[index * 2] + return ranges[index * 2]; } export function endAt<T extends number = number>(ranges: SortedRanges<T>, index: number) { - return ranges[index * 2 + 1] + 1 + return ranges[index * 2 + 1] + 1; } export function minAt<T extends number = number>(ranges: SortedRanges<T>, index: number) { - return ranges[index * 2] + return ranges[index * 2]; } export function maxAt<T extends number = number>(ranges: SortedRanges<T>, index: number) { - return ranges[index * 2 + 1] + return ranges[index * 2 + 1]; } export function areEqual<T extends number = number>(a: SortedRanges<T>, b: SortedRanges<T>) { - if (a.length !== b.length) return false + if (a.length !== b.length) return false; for (let i = 0, il = a.length; i < il; ++i) { - if (a[i] !== b[i]) return false + if (a[i] !== b[i]) return false; } - return true + return true; } export function forEach<T extends number = number>(ranges: SortedRanges<T>, f: (value: T, i: number) => void) { - let k = 0 + let k = 0; for (let i = 0, il = ranges.length; i < il; i += 2) { for (let j = ranges[i], jl = ranges[i + 1]; j <= jl; ++j) { f(j, k); - ++k + ++k; } } } /** Returns if a value of `set` is included in `ranges` */ export function has<T extends number = number>(ranges: SortedRanges<T>, set: OrderedSet<T>) { - return firstIntersectionIndex(ranges, set) !== -1 + return firstIntersectionIndex(ranges, set) !== -1; } /** Returns if a value of `set` is included in `ranges` from given index */ export function hasFrom<T extends number = number>(ranges: SortedRanges<T>, set: OrderedSet<T>, from: number) { - return firstIntersectionIndexFrom(ranges, set, from) !== -1 + return firstIntersectionIndexFrom(ranges, set, from) !== -1; } export function firstIntersectionIndex<T extends number = number>(ranges: SortedRanges<T>, set: OrderedSet<T>): number { - return firstIntersectionIndexFrom(ranges, set, 0) + return firstIntersectionIndexFrom(ranges, set, 0); } export function firstIntersectionIndexFrom<T extends number = number>(ranges: SortedRanges<T>, set: OrderedSet<T>, from: number): number { - if (minAt(ranges, from) > OrderedSet.max(set) || max(ranges) < OrderedSet.min(set)) return -1 + if (minAt(ranges, from) > OrderedSet.max(set) || max(ranges) < OrderedSet.min(set)) return -1; for (let i = from, il = count(ranges); i < il; ++i) { - const interval = Interval.ofRange(minAt(ranges, i), maxAt(ranges, i)) - if (OrderedSet.areIntersecting(interval, set)) return i + const interval = Interval.ofRange(minAt(ranges, i), maxAt(ranges, i)); + if (OrderedSet.areIntersecting(interval, set)) return i; } - return -1 + return -1; } export function transientSegments<T extends number = number, I extends number = number>(ranges: SortedRanges<T>, set: OrderedSet<T>) { - return new Iterator<T, I>(ranges, set) + return new Iterator<T, I>(ranges, set); } export class Iterator<T extends number = number, I extends number = number> implements _Iterator<Segmentation.Segment<I>> { @@ -94,25 +94,25 @@ namespace SortedRanges { hasNext: boolean = false; private updateValue() { - this.value.index = this.curIndex as I - this.value.start = OrderedSet.findPredecessorIndex(this.set, startAt(this.ranges, this.curIndex)) - this.value.end = OrderedSet.findPredecessorIndex(this.set, endAt(this.ranges, this.curIndex)) + this.value.index = this.curIndex as I; + this.value.start = OrderedSet.findPredecessorIndex(this.set, startAt(this.ranges, this.curIndex)); + this.value.end = OrderedSet.findPredecessorIndex(this.set, endAt(this.ranges, this.curIndex)); } move() { if (this.hasNext) { - this.updateValue() - this.curIndex = firstIntersectionIndexFrom(this.ranges, this.set, this.curIndex + 1) - this.hasNext = this.curIndex !== -1 + this.updateValue(); + this.curIndex = firstIntersectionIndexFrom(this.ranges, this.set, this.curIndex + 1); + this.hasNext = this.curIndex !== -1; } return this.value; } constructor(private ranges: SortedRanges<T>, private set: OrderedSet<T>) { - this.curIndex = firstIntersectionIndex(ranges, set) - this.hasNext = this.curIndex !== -1 + this.curIndex = firstIntersectionIndex(ranges, set); + this.hasNext = this.curIndex !== -1; } } } -export default SortedRanges \ No newline at end of file +export default SortedRanges; \ No newline at end of file diff --git a/src/mol-data/int/tuple.ts b/src/mol-data/int/tuple.ts index 215ed92c905281a653430ac22b6eccbd0acb9052..4a9076f5d8b7a1e4103ecc7543e13cfdc1d25b54 100644 --- a/src/mol-data/int/tuple.ts +++ b/src/mol-data/int/tuple.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { hash2 } from '../util' +import { hash2 } from '../util'; /** * Represents a pair of two integers as a double, @@ -80,4 +80,4 @@ namespace IntTuple { } } -export default IntTuple \ No newline at end of file +export default IntTuple; \ No newline at end of file diff --git a/src/mol-data/iterator.ts b/src/mol-data/iterator.ts index 8d5713f1fd56e138d61a6a1aba77010b746ae2bc..0ae20d1768f796afa2d782b0119e1537f2a9ddde 100644 --- a/src/mol-data/iterator.ts +++ b/src/mol-data/iterator.ts @@ -117,4 +117,4 @@ namespace Iterator { } } -export default Iterator \ No newline at end of file +export default Iterator; \ No newline at end of file diff --git a/src/mol-data/util.ts b/src/mol-data/util.ts index e92041312001c8f55e84f79b3f49dd5d9c16e109..3d2f8028e0a25735bb009fb46fdbd68fa631182f 100644 --- a/src/mol-data/util.ts +++ b/src/mol-data/util.ts @@ -4,10 +4,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './util/chunked-array' -export * from './util/buckets' -export * from './util/equivalence-classes' -export * from './util/hash-functions' -export * from './util/sort' -export * from './util/grouping' -export * from './util/array' \ No newline at end of file +export * from './util/chunked-array'; +export * from './util/buckets'; +export * from './util/equivalence-classes'; +export * from './util/hash-functions'; +export * from './util/sort'; +export * from './util/grouping'; +export * from './util/array'; \ No newline at end of file diff --git a/src/mol-data/util/_spec/buckets.spec.ts b/src/mol-data/util/_spec/buckets.spec.ts index e4e3d1857761950d7ad3ded5646a8befac515f95..680f4283c0ad41883cae9ea7237832dbb1dbcc93 100644 --- a/src/mol-data/util/_spec/buckets.spec.ts +++ b/src/mol-data/util/_spec/buckets.spec.ts @@ -39,5 +39,5 @@ describe('buckets', () => { expect(reorder(range, xs)).toEqual([2, 1, 1, 2, 2, 3, 1]); expect(Array.from(bs)).toEqual([1, 3, 5]); - }) -}) \ No newline at end of file + }); +}); \ No newline at end of file diff --git a/src/mol-data/util/_spec/chunked-array.spec.ts b/src/mol-data/util/_spec/chunked-array.spec.ts index 297777c7ad0602fa07ce54c5dc1f3fc0239e0a18..d3c065271484f8bf087b8fdf63b4fbf2f9e03931 100644 --- a/src/mol-data/util/_spec/chunked-array.spec.ts +++ b/src/mol-data/util/_spec/chunked-array.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { ChunkedArray } from '../chunked-array' +import { ChunkedArray } from '../chunked-array'; describe('Chunked Array', () => { it('creation', () => { @@ -45,7 +45,7 @@ describe('Chunked Array', () => { ChunkedArray.add2(arr, 5, 6); ChunkedArray.add2(arr, 7, 8); ChunkedArray.add2(arr, 9, 10); - expect(arr.elementCount).toBe(5) + expect(arr.elementCount).toBe(5); expect(ChunkedArray.compact(arr)).toEqual(new Int32Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); }); }); \ No newline at end of file diff --git a/src/mol-data/util/_spec/combination.spec.ts b/src/mol-data/util/_spec/combination.spec.ts index a11c12f84964ddece9d1641467c9efd0b373dc27..dde95af43eb5041d4707099805aa18958c9fb5f5 100644 --- a/src/mol-data/util/_spec/combination.spec.ts +++ b/src/mol-data/util/_spec/combination.spec.ts @@ -4,26 +4,26 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { combinations } from '../combination' +import { combinations } from '../combination'; describe('Combination', () => { it('test123-2', () => { - const c = combinations([1, 2, 3], 2) + const c = combinations([1, 2, 3], 2); expect(c).toEqual([[1, 2], [1, 3], [2, 3]]); }); it('test1234-2', () => { - const c = combinations([1, 2, 3, 4], 2) + const c = combinations([1, 2, 3, 4], 2); expect(c).toEqual([[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4]]); }); it('test1234-1', () => { - const c = combinations([1, 2, 3, 4], 1) + const c = combinations([1, 2, 3, 4], 1); expect(c).toEqual([[1], [2], [3], [4]]); }); it('test1234-4', () => { - const c = combinations([1, 2, 3, 4], 4) + const c = combinations([1, 2, 3, 4], 4); expect(c).toEqual([[1, 2, 3, 4]]); }); }); \ No newline at end of file diff --git a/src/mol-data/util/_spec/interval-iterator.spec.ts b/src/mol-data/util/_spec/interval-iterator.spec.ts index c2dabf8853dcc00aa069d5018071ba1524318ec4..ae20d6ae0eccf26a48f790ed8eb3c44338bad24a 100644 --- a/src/mol-data/util/_spec/interval-iterator.spec.ts +++ b/src/mol-data/util/_spec/interval-iterator.spec.ts @@ -10,24 +10,24 @@ import { IntervalIterator } from '../interval-iterator'; describe('interval', () => { function testIterator(name: string, interval: Interval, set: OrderedSet, expectedValues: { index: number[], start: number[], end: number[]}) { it(`iterator, ${name}`, () => { - const intervalIt = new IntervalIterator(interval, set) - const { index, start, end } = expectedValues + const intervalIt = new IntervalIterator(interval, set); + const { index, start, end } = expectedValues; - let i = 0 + let i = 0; while (intervalIt.hasNext) { - const segment = intervalIt.move() - expect(segment.index).toBe(index[i]) - expect(segment.start).toBe(start[i]) - expect(segment.end).toBe(end[i]) - ++i + const segment = intervalIt.move(); + expect(segment.index).toBe(index[i]); + expect(segment.start).toBe(start[i]); + expect(segment.end).toBe(end[i]); + ++i; } - expect(i).toBe(index.length) - }) + expect(i).toBe(index.length); + }); } testIterator('basic', Interval.ofRange(0, 5), SortedArray.ofSortedArray([1, 3, 7, 8]), { index: [1, 3], start: [0, 1], end: [1, 2] } - ) + ); }); \ No newline at end of file diff --git a/src/mol-data/util/chunked-array.ts b/src/mol-data/util/chunked-array.ts index f7fa1ed91f7de64fa62ab173c1590d5b0de0ffd9..a2652ac71318acc98dd28b16729feabd39451923 100644 --- a/src/mol-data/util/chunked-array.ts +++ b/src/mol-data/util/chunked-array.ts @@ -185,4 +185,4 @@ namespace ChunkedArray { } } -export { ChunkedArray } \ No newline at end of file +export { ChunkedArray }; \ No newline at end of file diff --git a/src/mol-data/util/combination.ts b/src/mol-data/util/combination.ts index d749c2a1c7cbc1955e12de10dc1e9921951a0736..7135f35472e9570d72af3286e1e0af67aae0485f 100644 --- a/src/mol-data/util/combination.ts +++ b/src/mol-data/util/combination.ts @@ -6,25 +6,25 @@ // adpated from https://github.com/dankogai/js-combinatorics, MIT 2013-2016 Dan Kogai -import Iterator from '../iterator' +import Iterator from '../iterator'; function P(m: number, n: number) { - let p = 1 - while (n--) p *= m-- - return p + let p = 1; + while (n--) p *= m--; + return p; } function C(m: number, n: number) { - if (n > m) return 0 - return P(m, n) / P(n, n) + if (n > m) return 0; + return P(m, n) / P(n, n); } function nextIndex(n: number) { - const smallest = n & -n - const ripple = n + smallest - const newSmallest = ripple & -ripple - const ones = ((newSmallest / smallest) >> 1) - 1 - return ripple | ones + const smallest = n & -n; + const ripple = n + smallest; + const newSmallest = ripple & -ripple; + const ones = ((newSmallest / smallest) >> 1) - 1; + return ripple | ones; }; export class CombinationIterator<T> implements Iterator<ReadonlyArray<T>> { @@ -37,29 +37,29 @@ export class CombinationIterator<T> implements Iterator<ReadonlyArray<T>> { move() { if (this.hasNext) { - let i = 0, j = 0, n = this.index + let i = 0, j = 0, n = this.index; for (; n; n >>>= 1, i++) { - if (n & 1) this.value[j++] = this.array[i] + if (n & 1) this.value[j++] = this.array[i]; } - this.index = nextIndex(this.index) - this.hasNext = this.index < this.maxIndex + this.index = nextIndex(this.index); + this.hasNext = this.index < this.maxIndex; } return this.value; } constructor(private array: T[], count: number) { - this.index = (1 << count) - 1 - this.size = C(array.length, count) + this.index = (1 << count) - 1; + this.size = C(array.length, count); this.maxIndex = 1 << array.length, - this.value = new Array(count) - this.hasNext = count > 0 && count <= array.length + this.value = new Array(count); + this.hasNext = count > 0 && count <= array.length; } } export function combinations<T>(array: T[], count: number): T[][] { - const out: T[][] = [] - const combinationIt = new CombinationIterator(array, count) - while (combinationIt.hasNext) out.push(combinationIt.move().slice()) - return out + const out: T[][] = []; + const combinationIt = new CombinationIterator(array, count); + while (combinationIt.hasNext) out.push(combinationIt.move().slice()); + return out; } \ No newline at end of file diff --git a/src/mol-data/util/grouping.ts b/src/mol-data/util/grouping.ts index 71e9ce5a045ce14238ae3a1ffece9e08114a196b..5b8275cacdc28a937deb4e85a8aee3061123418f 100644 --- a/src/mol-data/util/grouping.ts +++ b/src/mol-data/util/grouping.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column } from '../db' +import { Column } from '../db'; export interface Grouping<V, K> { map: Map<K, V[]>, diff --git a/src/mol-data/util/hash-functions.ts b/src/mol-data/util/hash-functions.ts index c554ab9756992e90d40eb3e65330e823a691af53..c515d5df2630cdbd2f884183d114ae1c965ea13b 100644 --- a/src/mol-data/util/hash-functions.ts +++ b/src/mol-data/util/hash-functions.ts @@ -17,7 +17,7 @@ export function hash2(i: number, j: number) { let a = 23; a = (31 * a + i) | 0; a = (31 * a + j) | 0; - a = a ^ (a >> 4) + a = a ^ (a >> 4); a = (a ^ 0xdeadbeef) + (a << 5); a = a ^ (a >> 11); return a; @@ -28,7 +28,7 @@ export function hash3(i: number, j: number, k: number) { a = (31 * a + i) | 0; a = (31 * a + j) | 0; a = (31 * a + k) | 0; - a = a ^ (a >> 4) + a = a ^ (a >> 4); a = (a ^ 0xdeadbeef) + (a << 5); a = a ^ (a >> 11); return a; @@ -40,7 +40,7 @@ export function hash4(i: number, j: number, k: number, l: number) { a = (31 * a + j) | 0; a = (31 * a + k) | 0; a = (31 * a + l) | 0; - a = a ^ (a >> 4) + a = a ^ (a >> 4); a = (a ^ 0xdeadbeef) + (a << 5); a = a ^ (a >> 11); return a; diff --git a/src/mol-data/util/interval-iterator.ts b/src/mol-data/util/interval-iterator.ts index 7f134d0c3f0f494ab90bff728f87aa1d65aff457..d02c28dfda5b2e13f5dfeeb913dacb37e4e758c6 100644 --- a/src/mol-data/util/interval-iterator.ts +++ b/src/mol-data/util/interval-iterator.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import Iterator from '../iterator' +import Iterator from '../iterator'; import { OrderedSet, Interval, Segmentation } from '../int'; /** Emits a segment of length one for each element in the interval that is also in the set */ @@ -17,29 +17,29 @@ export class IntervalIterator<I extends number = number> implements Iterator<Seg hasNext: boolean = false; updateValue() { - this.value.index = this.curIndex as I - this.value.start = OrderedSet.findPredecessorIndex(this.set, Interval.getAt(this.interval, this.curIndex)) - this.value.end = this.value.start + 1 + this.value.index = this.curIndex as I; + this.value.start = OrderedSet.findPredecessorIndex(this.set, Interval.getAt(this.interval, this.curIndex)); + this.value.end = this.value.start + 1; } move() { if (this.hasNext) { - this.updateValue() + this.updateValue(); while (this.curIndex <= this.maxIndex) { - ++this.curIndex - if (OrderedSet.has(this.set, this.curIndex)) break + ++this.curIndex; + if (OrderedSet.has(this.set, this.curIndex)) break; } - this.hasNext = this.curIndex <= this.maxIndex + this.hasNext = this.curIndex <= this.maxIndex; } return this.value; } constructor(private interval: Interval<I>, private set: OrderedSet<I>) { if (Interval.size(interval)) { - this.curIndex = Interval.findPredecessorIndex(interval, OrderedSet.min(set)) - this.maxIndex = Interval.findPredecessorIndex(interval, OrderedSet.max(set)) + this.curIndex = Interval.findPredecessorIndex(interval, OrderedSet.min(set)); + this.maxIndex = Interval.findPredecessorIndex(interval, OrderedSet.max(set)); } - this.hasNext = OrderedSet.areIntersecting(this.interval, this.set) + this.hasNext = OrderedSet.areIntersecting(this.interval, this.set); } } \ No newline at end of file diff --git a/src/mol-geo/geometry/base.ts b/src/mol-geo/geometry/base.ts index 52bdd34589063236806ac7972d40b6fff1517d41..6433278a92015384697084d328dfc7e9144457d7 100644 --- a/src/mol-geo/geometry/base.ts +++ b/src/mol-geo/geometry/base.ts @@ -8,7 +8,7 @@ import { RenderableState } from '../../mol-gl/renderable'; import { ValueCell } from '../../mol-util'; import { BaseValues } from '../../mol-gl/renderable/schema'; import { LocationIterator } from '../util/location-iterator'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { TransformData, createIdentityTransform } from './transform-data'; import { Theme } from '../../mol-theme/theme'; import { ColorNames } from '../../mol-util/color/names'; @@ -26,10 +26,10 @@ export const VisualQualityInfo = { 'low': {}, 'lower': {}, 'lowest': {}, -} +}; export type VisualQuality = keyof typeof VisualQualityInfo -export const VisualQualityNames = Object.keys(VisualQualityInfo) as VisualQuality[] -export const VisualQualityOptions = PD.arrayToOptions(VisualQualityNames) +export const VisualQualityNames = Object.keys(VisualQualityInfo) as VisualQuality[]; +export const VisualQualityOptions = PD.arrayToOptions(VisualQualityNames); // @@ -37,7 +37,7 @@ export namespace BaseGeometry { export const Params = { alpha: PD.Numeric(1, { min: 0, max: 1, step: 0.01 }, { label: 'Opacity', isEssential: true, description: 'How opaque/transparent the representation is rendered.' }), quality: PD.Select<VisualQuality>('auto', VisualQualityOptions, { isEssential: true, description: 'Visual/rendering quality of the representation.' }), - } + }; export type Params = typeof Params export const ShadingCategory: PD.Info = { category: 'Shading' }; @@ -49,13 +49,13 @@ export namespace BaseGeometry { export type Counts = { drawCount: number, groupCount: number, instanceCount: number } export function createSimple(colorValue = ColorNames.grey, sizeValue = 1, transform?: TransformData) { - if (!transform) transform = createIdentityTransform() - const locationIterator = LocationIterator(1, transform.instanceCount.ref.value, () => NullLocation, false, () => false) + if (!transform) transform = createIdentityTransform(); + const locationIterator = LocationIterator(1, transform.instanceCount.ref.value, () => NullLocation, false, () => false); const theme: Theme = { color: UniformColorTheme({}, { value: colorValue}), size: UniformSizeTheme({}, { value: sizeValue}) - } - return { transform, locationIterator, theme } + }; + return { transform, locationIterator, theme }; } export function createValues(props: PD.Values<Params>, counts: Counts) { @@ -64,11 +64,11 @@ export namespace BaseGeometry { uAlpha: ValueCell.create(props.alpha), uGroupCount: ValueCell.create(counts.groupCount), drawCount: ValueCell.create(counts.drawCount), - } + }; } export function updateValues(values: BaseValues, props: PD.Values<Params>) { - ValueCell.updateIfChanged(values.alpha, props.alpha) // `uAlpha` is set in renderable.render + ValueCell.updateIfChanged(values.alpha, props.alpha); // `uAlpha` is set in renderable.render } export function createRenderableState(props: Partial<PD.Values<Params>> = {}): RenderableState { @@ -77,10 +77,10 @@ export namespace BaseGeometry { alphaFactor: 1, pickable: true, opaque: props.alpha === undefined ? true : props.alpha === 1 - } + }; } export function updateRenderableState(state: RenderableState, props: PD.Values<Params>) { - state.opaque = props.alpha * state.alphaFactor >= 1 + state.opaque = props.alpha * state.alphaFactor >= 1; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/color-data.ts b/src/mol-geo/geometry/color-data.ts index 423e2ba64e61f73455b9d81464922215c994fb30..19361ffdcd96bb59f2baecd1c568f0bd5840b2f9 100644 --- a/src/mol-geo/geometry/color-data.ts +++ b/src/mol-geo/geometry/color-data.ts @@ -24,87 +24,87 @@ export type ColorData = { export function createColors(locationIt: LocationIterator, colorTheme: ColorTheme<any>, colorData?: ColorData): ColorData { switch (Geometry.getGranularity(locationIt, colorTheme.granularity)) { - case 'uniform': return createUniformColor(locationIt, colorTheme.color, colorData) - case 'group': return createGroupColor(locationIt, colorTheme.color, colorData) - case 'groupInstance': return createGroupInstanceColor(locationIt, colorTheme.color, colorData) - case 'instance': return createInstanceColor(locationIt, colorTheme.color, colorData) + case 'uniform': return createUniformColor(locationIt, colorTheme.color, colorData); + case 'group': return createGroupColor(locationIt, colorTheme.color, colorData); + case 'groupInstance': return createGroupInstanceColor(locationIt, colorTheme.color, colorData); + case 'instance': return createInstanceColor(locationIt, colorTheme.color, colorData); } } export function createValueColor(value: Color, colorData?: ColorData): ColorData { if (colorData) { - ValueCell.update(colorData.uColor, Color.toVec3Normalized(colorData.uColor.ref.value, value)) + ValueCell.update(colorData.uColor, Color.toVec3Normalized(colorData.uColor.ref.value, value)); if (colorData.dColorType.ref.value !== 'uniform') { - ValueCell.update(colorData.dColorType, 'uniform') + ValueCell.update(colorData.dColorType, 'uniform'); } - return colorData + return colorData; } else { return { uColor: ValueCell.create(Color.toVec3Normalized(Vec3(), value)), tColor: ValueCell.create({ array: new Uint8Array(3), width: 1, height: 1 }), uColorTexDim: ValueCell.create(Vec2.create(1, 1)), dColorType: ValueCell.create('uniform'), - } + }; } } /** Creates color uniform */ export function createUniformColor(locationIt: LocationIterator, color: LocationColor, colorData?: ColorData): ColorData { - return createValueColor(color(NullLocation, false), colorData) + return createValueColor(color(NullLocation, false), colorData); } export function createTextureColor(colors: TextureImage<Uint8Array>, type: ColorType, colorData?: ColorData): ColorData { if (colorData) { - ValueCell.update(colorData.tColor, colors) - ValueCell.update(colorData.uColorTexDim, Vec2.create(colors.width, colors.height)) + ValueCell.update(colorData.tColor, colors); + ValueCell.update(colorData.uColorTexDim, Vec2.create(colors.width, colors.height)); if (colorData.dColorType.ref.value !== type) { - ValueCell.update(colorData.dColorType, type) + ValueCell.update(colorData.dColorType, type); } - return colorData + return colorData; } else { return { uColor: ValueCell.create(Vec3.zero()), tColor: ValueCell.create(colors), uColorTexDim: ValueCell.create(Vec2.create(colors.width, colors.height)), dColorType: ValueCell.create(type), - } + }; } } /** Creates color texture with color for each instance/unit */ export function createInstanceColor(locationIt: LocationIterator, color: LocationColor, colorData?: ColorData): ColorData { - const { instanceCount } = locationIt - const colors = createTextureImage(Math.max(1, instanceCount), 3, Uint8Array, colorData && colorData.tColor.ref.value.array) - locationIt.reset() + const { instanceCount } = locationIt; + const colors = createTextureImage(Math.max(1, instanceCount), 3, Uint8Array, colorData && colorData.tColor.ref.value.array); + locationIt.reset(); while (locationIt.hasNext) { - const { location, isSecondary, instanceIndex } = locationIt.move() - Color.toArray(color(location, isSecondary), colors.array, instanceIndex * 3) - locationIt.skipInstance() + const { location, isSecondary, instanceIndex } = locationIt.move(); + Color.toArray(color(location, isSecondary), colors.array, instanceIndex * 3); + locationIt.skipInstance(); } - return createTextureColor(colors, 'instance', colorData) + return createTextureColor(colors, 'instance', colorData); } /** Creates color texture with color for each group (i.e. shared across instances/units) */ export function createGroupColor(locationIt: LocationIterator, color: LocationColor, colorData?: ColorData): ColorData { - const { groupCount } = locationIt - const colors = createTextureImage(Math.max(1, groupCount), 3, Uint8Array, colorData && colorData.tColor.ref.value.array) - locationIt.reset() + const { groupCount } = locationIt; + const colors = createTextureImage(Math.max(1, groupCount), 3, Uint8Array, colorData && colorData.tColor.ref.value.array); + locationIt.reset(); while (locationIt.hasNext && !locationIt.isNextNewInstance) { - const { location, isSecondary, groupIndex } = locationIt.move() - Color.toArray(color(location, isSecondary), colors.array, groupIndex * 3) + const { location, isSecondary, groupIndex } = locationIt.move(); + Color.toArray(color(location, isSecondary), colors.array, groupIndex * 3); } - return createTextureColor(colors, 'group', colorData) + return createTextureColor(colors, 'group', colorData); } /** Creates color texture with color for each group in each instance (i.e. for each unit) */ export function createGroupInstanceColor(locationIt: LocationIterator, color: LocationColor, colorData?: ColorData): ColorData { - const { groupCount, instanceCount } = locationIt - const count = instanceCount * groupCount - const colors = createTextureImage(Math.max(1, count), 3, Uint8Array, colorData && colorData.tColor.ref.value.array) - locationIt.reset() + const { groupCount, instanceCount } = locationIt; + const count = instanceCount * groupCount; + const colors = createTextureImage(Math.max(1, count), 3, Uint8Array, colorData && colorData.tColor.ref.value.array); + locationIt.reset(); while (locationIt.hasNext) { - const { location, isSecondary, index } = locationIt.move() - Color.toArray(color(location, isSecondary), colors.array, index * 3) + const { location, isSecondary, index } = locationIt.move(); + Color.toArray(color(location, isSecondary), colors.array, index * 3); } - return createTextureColor(colors, 'groupInstance', colorData) + return createTextureColor(colors, 'groupInstance', colorData); } \ No newline at end of file diff --git a/src/mol-geo/geometry/direct-volume/direct-volume.ts b/src/mol-geo/geometry/direct-volume/direct-volume.ts index ababeceb0d030c80b7b7c12104a5bc3f4e687d33..75257f19da6f1ec541391560e2b04e8b29f3c467 100644 --- a/src/mol-geo/geometry/direct-volume/direct-volume.ts +++ b/src/mol-geo/geometry/direct-volume/direct-volume.ts @@ -27,8 +27,8 @@ import { TransformData } from '../transform-data'; import { createEmptyTransparency } from '../transparency-data'; import { createTransferFunctionTexture, getControlPointsFromVec2Array } from './transfer-function'; -const VolumeBox = Box() -const RenderModeOptions = [['isosurface', 'Isosurface'], ['volume', 'Volume']] as [string, string][] +const VolumeBox = Box(); +const RenderModeOptions = [['isosurface', 'Isosurface'], ['volume', 'Volume']] as [string, string][]; export interface DirectVolume { readonly kind: 'direct-volume', @@ -49,23 +49,23 @@ export namespace DirectVolume { export function create(bbox: Box3D, gridDimension: Vec3, transform: Mat4, texture: Texture, directVolume?: DirectVolume): DirectVolume { return directVolume ? update(bbox, gridDimension, transform, texture, directVolume) : - fromData(bbox, gridDimension, transform, texture) + fromData(bbox, gridDimension, transform, texture); } function hashCode(directVolume: DirectVolume) { return hashFnv32a([ directVolume.bboxSize.ref.version, directVolume.gridDimension.ref.version, directVolume.gridTexture.ref.version, directVolume.transform.ref.version, - ]) + ]); } function fromData(bbox: Box3D, gridDimension: Vec3, transform: Mat4, texture: Texture): DirectVolume { - const boundingSphere = Sphere3D() - let currentHash = -1 + const boundingSphere = Sphere3D(); + let currentHash = -1; - const width = texture.getWidth() - const height = texture.getHeight() - const depth = texture.getDepth() + const width = texture.getWidth(); + const height = texture.getHeight(); + const depth = texture.getDepth(); const directVolume = { kind: 'direct-volume' as const, @@ -77,35 +77,35 @@ export namespace DirectVolume { bboxSize: ValueCell.create(Vec3.sub(Vec3.zero(), bbox.max, bbox.min)), transform: ValueCell.create(transform), get boundingSphere() { - const newHash = hashCode(directVolume) + const newHash = hashCode(directVolume); if (newHash !== currentHash) { - const b = getBoundingSphere(directVolume.gridDimension.ref.value, directVolume.transform.ref.value) - Sphere3D.copy(boundingSphere, b) - currentHash = newHash + const b = getBoundingSphere(directVolume.gridDimension.ref.value, directVolume.transform.ref.value); + Sphere3D.copy(boundingSphere, b); + currentHash = newHash; } - return boundingSphere + return boundingSphere; }, - } - return directVolume + }; + return directVolume; } function update(bbox: Box3D, gridDimension: Vec3, transform: Mat4, texture: Texture, directVolume: DirectVolume): DirectVolume { - const width = texture.getWidth() - const height = texture.getHeight() - const depth = texture.getDepth() - - ValueCell.update(directVolume.gridDimension, gridDimension) - ValueCell.update(directVolume.gridTexture, texture) - ValueCell.update(directVolume.gridTextureDim, Vec3.set(directVolume.gridTextureDim.ref.value, width, height, depth)) - ValueCell.update(directVolume.bboxMin, bbox.min) - ValueCell.update(directVolume.bboxMax, bbox.max) - ValueCell.update(directVolume.bboxSize, Vec3.sub(directVolume.bboxSize.ref.value, bbox.max, bbox.min)) - ValueCell.update(directVolume.transform, transform) - return directVolume + const width = texture.getWidth(); + const height = texture.getHeight(); + const depth = texture.getDepth(); + + ValueCell.update(directVolume.gridDimension, gridDimension); + ValueCell.update(directVolume.gridTexture, texture); + ValueCell.update(directVolume.gridTextureDim, Vec3.set(directVolume.gridTextureDim.ref.value, width, height, depth)); + ValueCell.update(directVolume.bboxMin, bbox.min); + ValueCell.update(directVolume.bboxMax, bbox.max); + ValueCell.update(directVolume.bboxSize, Vec3.sub(directVolume.bboxSize.ref.value, bbox.max, bbox.min)); + ValueCell.update(directVolume.transform, transform); + return directVolume; } export function createEmpty(directVolume?: DirectVolume): DirectVolume { - return {} as DirectVolume // TODO + return {} as DirectVolume; // TODO } export const Params = { @@ -117,7 +117,7 @@ export namespace DirectVolume { Vec2.create(0.79, 0.0), Vec2.create(0.8, 0.05), Vec2.create(0.85, 0.05), Vec2.create(0.86, 0.0), ]), list: PD.ColorList('red-yellow-blue'), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<DirectVolume, Params> = { @@ -129,27 +129,27 @@ export namespace DirectVolume { updateBoundingSphere, createRenderableState, updateRenderableState - } + }; function createValues(directVolume: DirectVolume, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): DirectVolumeValues { - const { gridTexture, gridTextureDim } = directVolume - const { bboxSize, bboxMin, bboxMax, gridDimension, transform: gridTransform } = directVolume + const { gridTexture, gridTextureDim } = directVolume; + const { bboxSize, bboxMin, bboxMax, gridDimension, transform: gridTransform } = directVolume; - const { instanceCount, groupCount } = locationIt - const color = createColors(locationIt, theme.color) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const { instanceCount, groupCount } = locationIt; + const color = createColors(locationIt, theme.color); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: VolumeBox.indices.length, groupCount, instanceCount } + const counts = { drawCount: VolumeBox.indices.length, groupCount, instanceCount }; - const invariantBoundingSphere = Sphere3D.clone(directVolume.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount) + const invariantBoundingSphere = Sphere3D.clone(directVolume.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount); - const controlPoints = getControlPointsFromVec2Array(props.controlPoints) - const transferTex = createTransferFunctionTexture(controlPoints, props.list.colors) + const controlPoints = getControlPointsFromVec2Array(props.controlPoints); + const transferTex = createTransferFunctionTexture(controlPoints, props.list.colors); - const maxSteps = Math.ceil(Vec3.magnitude(gridDimension.ref.value)) * 2 * 5 + const maxSteps = Math.ceil(Vec3.magnitude(gridDimension.ref.value)) * 2 * 5; return { ...color, @@ -177,60 +177,60 @@ export namespace DirectVolume { dGridTexType: ValueCell.create(gridTexture.ref.value.getDepth() > 0 ? '3d' : '2d'), uGridTexDim: gridTextureDim, tGridTex: gridTexture, - } + }; } function createValuesSimple(directVolume: DirectVolume, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(directVolume, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(directVolume, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: DirectVolumeValues, props: PD.Values<Params>) { - ValueCell.updateIfChanged(values.uIsoValue, props.isoValueNorm) - ValueCell.updateIfChanged(values.uAlpha, props.alpha) - ValueCell.updateIfChanged(values.dRenderMode, props.renderMode) + ValueCell.updateIfChanged(values.uIsoValue, props.isoValueNorm); + ValueCell.updateIfChanged(values.uAlpha, props.alpha); + ValueCell.updateIfChanged(values.dRenderMode, props.renderMode); - const controlPoints = getControlPointsFromVec2Array(props.controlPoints) - createTransferFunctionTexture(controlPoints, props.list.colors, values.tTransferTex) + const controlPoints = getControlPointsFromVec2Array(props.controlPoints); + createTransferFunctionTexture(controlPoints, props.list.colors, values.tTransferTex); } function updateBoundingSphere(values: DirectVolumeValues, directVolume: DirectVolume) { - const invariantBoundingSphere = Sphere3D.clone(directVolume.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const invariantBoundingSphere = Sphere3D.clone(directVolume.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } } function createRenderableState(props: PD.Values<Params>): RenderableState { - const state = BaseGeometry.createRenderableState(props) - state.opaque = false - return state + const state = BaseGeometry.createRenderableState(props); + state.opaque = false; + return state; } function updateRenderableState(state: RenderableState, props: PD.Values<Params>) { - BaseGeometry.updateRenderableState(state, props) - state.opaque = false + BaseGeometry.updateRenderableState(state, props); + state.opaque = false; } } // -const mTmp = Mat4.identity() -const mTmp2 = Mat4.identity() -const vHalfUnit = Vec3.create(0.5, 0.5, 0.5) -const tmpVertices = new Float32Array(VolumeBox.vertices.length) +const mTmp = Mat4.identity(); +const mTmp2 = Mat4.identity(); +const vHalfUnit = Vec3.create(0.5, 0.5, 0.5); +const tmpVertices = new Float32Array(VolumeBox.vertices.length); function getBoundingSphere(gridDimension: Vec3, gridTransform: Mat4) { - tmpVertices.set(VolumeBox.vertices) - Mat4.fromTranslation(mTmp, vHalfUnit) - Mat4.mul(mTmp, Mat4.fromScaling(mTmp2, gridDimension), mTmp) - Mat4.mul(mTmp, gridTransform, mTmp) - transformPositionArray(mTmp, tmpVertices, 0, tmpVertices.length / 3) - return calculateInvariantBoundingSphere(tmpVertices, tmpVertices.length / 3, 1) + tmpVertices.set(VolumeBox.vertices); + Mat4.fromTranslation(mTmp, vHalfUnit); + Mat4.mul(mTmp, Mat4.fromScaling(mTmp2, gridDimension), mTmp); + Mat4.mul(mTmp, gridTransform, mTmp); + transformPositionArray(mTmp, tmpVertices, 0, tmpVertices.length / 3); + return calculateInvariantBoundingSphere(tmpVertices, tmpVertices.length / 3, 1); // return calculateBoundingSphere(tmpVertices, tmpVertices.length / 3, transform, transformCount) } \ No newline at end of file diff --git a/src/mol-geo/geometry/direct-volume/transfer-function.ts b/src/mol-geo/geometry/direct-volume/transfer-function.ts index 2fd3ec13f907ab30f6845b05c5ee6937e4a0d5b7..c65e1067be63c80344ac5b6864b4c526b33f34d3 100644 --- a/src/mol-geo/geometry/direct-volume/transfer-function.ts +++ b/src/mol-geo/geometry/direct-volume/transfer-function.ts @@ -15,13 +15,13 @@ export interface ControlPoint { x: number, alpha: number } export function getControlPointsFromString(s: string): ControlPoint[] { return s.split(/\s*,\s*/).map(p => { - const ps = p.split(/\s*:\s*/) - return { x: parseFloat(ps[0]), alpha: parseFloat(ps[1]) } - }) + const ps = p.split(/\s*:\s*/); + return { x: parseFloat(ps[0]), alpha: parseFloat(ps[1]) }; + }); } export function getControlPointsFromVec2Array(array: Vec2[]): ControlPoint[] { - return array.map(v => ({ x: v[0], alpha: v[1] })) + return array.map(v => ({ x: v[0], alpha: v[1] })); } export function createTransferFunctionTexture(controlPoints: ControlPoint[], listOrName: Color[] | ColorListName, texture?: ValueCell<TextureImage<Uint8Array>>): ValueCell<TextureImage<Uint8Array>> { @@ -31,40 +31,40 @@ export function createTransferFunctionTexture(controlPoints: ControlPoint[], lis ...controlPoints, { x: 1, alpha: 0 }, { x: 1, alpha: 0 }, - ] - const scale = ColorScale.create({ domain: [0, 1], listOrName }) + ]; + const scale = ColorScale.create({ domain: [0, 1], listOrName }); - const n = 256 - const array = texture ? texture.ref.value.array : new Uint8Array(n * 4) + const n = 256; + const array = texture ? texture.ref.value.array : new Uint8Array(n * 4); - let k = 0 - let x1: number, x2: number - let a0: number, a1: number, a2: number, a3: number + let k = 0; + let x1: number, x2: number; + let a0: number, a1: number, a2: number, a3: number; - const il = controlPoints.length + 1 + const il = controlPoints.length + 1; for (let i = 0; i < il; ++i) { - x1 = cp[i + 1].x - x2 = cp[i + 2].x + x1 = cp[i + 1].x; + x2 = cp[i + 2].x; - a0 = cp[i].alpha - a1 = cp[i + 1].alpha - a2 = cp[i + 2].alpha - a3 = cp[i + 3].alpha + a0 = cp[i].alpha; + a1 = cp[i + 1].alpha; + a2 = cp[i + 2].alpha; + a3 = cp[i + 3].alpha; - const jl = Math.round((x2 - x1) * n) + const jl = Math.round((x2 - x1) * n); for (let j = 0; j < jl; ++j) { - const t = j / jl - array[k * 4 + 3] = Math.max(0, spline(a0, a1, a2, a3, t, 0.5) * 255) - scale.colorToArray(k / 255, array, k * 4) - ++k + const t = j / jl; + array[k * 4 + 3] = Math.max(0, spline(a0, a1, a2, a3, t, 0.5) * 255); + scale.colorToArray(k / 255, array, k * 4); + ++k; } } - const textureImage = { array, width: 256, height: 1 } + const textureImage = { array, width: 256, height: 1 }; if (texture) { - ValueCell.update(texture, textureImage) - return texture + ValueCell.update(texture, textureImage); + return texture; } else { - return ValueCell.create(textureImage) + return ValueCell.create(textureImage); } } \ No newline at end of file diff --git a/src/mol-geo/geometry/geometry.ts b/src/mol-geo/geometry/geometry.ts index 71c29ed937aaf844b5998b9512830fa9fd67e855..d2687f1039c8552fa1fa2a145f3be91658b4b808 100644 --- a/src/mol-geo/geometry/geometry.ts +++ b/src/mol-geo/geometry/geometry.ts @@ -12,7 +12,7 @@ import { LocationIterator } from '../util/location-iterator'; import { ColorType } from './color-data'; import { SizeType } from './size-data'; import { Lines } from './lines/lines'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { DirectVolume } from './direct-volume/direct-volume'; import { Color } from '../../mol-util/color'; import { Spheres } from './spheres/spheres'; @@ -58,13 +58,13 @@ export namespace Geometry { export function getDrawCount(geometry: Geometry): number { switch (geometry.kind) { - case 'mesh': return geometry.triangleCount * 3 - case 'points': return geometry.pointCount - case 'spheres': return geometry.sphereCount * 2 * 3 - case 'text': return geometry.charCount * 2 * 3 - case 'lines': return geometry.lineCount * 2 * 3 - case 'direct-volume': return 12 * 3 - case 'texture-mesh': return geometry.vertexCount + case 'mesh': return geometry.triangleCount * 3; + case 'points': return geometry.pointCount; + case 'spheres': return geometry.sphereCount * 2 * 3; + case 'text': return geometry.charCount * 2 * 3; + case 'lines': return geometry.lineCount * 2 * 3; + case 'direct-volume': return 12 * 3; + case 'texture-mesh': return geometry.vertexCount; } } @@ -75,30 +75,30 @@ export namespace Geometry { case 'spheres': case 'text': case 'lines': - return getDrawCount(geometry) === 0 ? 0 : (arrayMax(geometry.groupBuffer.ref.value) + 1) + return getDrawCount(geometry) === 0 ? 0 : (arrayMax(geometry.groupBuffer.ref.value) + 1); case 'direct-volume': - return 1 + return 1; case 'texture-mesh': - return geometry.groupCount + return geometry.groupCount; } } export function getUtils<G extends Geometry>(geometry: G): GeometryUtils<G> { // TODO avoid casting switch (geometry.kind) { - case 'mesh': return Mesh.Utils as any - case 'points': return Points.Utils as any - case 'spheres': return Spheres.Utils as any - case 'text': return Text.Utils as any - case 'lines': return Lines.Utils as any - case 'direct-volume': return DirectVolume.Utils as any - case 'texture-mesh': return TextureMesh.Utils as any + case 'mesh': return Mesh.Utils as any; + case 'points': return Points.Utils as any; + case 'spheres': return Spheres.Utils as any; + case 'text': return Text.Utils as any; + case 'lines': return Lines.Utils as any; + case 'direct-volume': return DirectVolume.Utils as any; + case 'texture-mesh': return TextureMesh.Utils as any; } } export function getGranularity(locationIt: LocationIterator, granularity: ColorType | SizeType) { // Always use 'group' granularity for 'complex' location iterators, // i.e. for which an instance may include multiple units - return granularity === 'instance' && locationIt.isComplex ? 'group' : granularity + return granularity === 'instance' && locationIt.isComplex ? 'group' : granularity; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/lines/lines-builder.ts b/src/mol-geo/geometry/lines/lines-builder.ts index 3b512c7e5fd431b3fbd8db5d32e0fd35d28fd919..6ed66d766bea505039db48e620dfa64f0a8a70aa 100644 --- a/src/mol-geo/geometry/lines/lines-builder.ts +++ b/src/mol-geo/geometry/lines/lines-builder.ts @@ -17,9 +17,9 @@ export interface LinesBuilder { getLines(): Lines } -const tmpVecA = Vec3() -const tmpVecB = Vec3() -const tmpDir = Vec3() +const tmpVecA = Vec3(); +const tmpVecB = Vec3(); +const tmpDir = Vec3(); export namespace LinesBuilder { export function create(initialCount = 2048, chunkSize = 1024, lines?: Lines): LinesBuilder { @@ -30,7 +30,7 @@ export namespace LinesBuilder { const ends = ChunkedArray.create(Float32Array, 3, chunkSize, lines ? lines.endBuffer.ref.value : initialCount); const add = (startX: number, startY: number, startZ: number, endX: number, endY: number, endZ: number, group: number) => { - const offset = mappings.elementCount + const offset = mappings.elementCount; for (let i = 0; i < 4; ++i) { ChunkedArray.add3(starts, startX, startY, startZ); ChunkedArray.add3(ends, endX, endY, endZ); @@ -42,49 +42,49 @@ export namespace LinesBuilder { ChunkedArray.add2(mappings, 1, -1); ChunkedArray.add3(indices, offset, offset + 1, offset + 2); ChunkedArray.add3(indices, offset + 1, offset + 3, offset + 2); - } + }; const addFixedCountDashes = (start: Vec3, end: Vec3, segmentCount: number, group: number) => { - const d = Vec3.distance(start, end) - const s = Math.floor(segmentCount / 2) - const step = 1 / segmentCount + const d = Vec3.distance(start, end); + const s = Math.floor(segmentCount / 2); + const step = 1 / segmentCount; - Vec3.sub(tmpDir, end, start) + Vec3.sub(tmpDir, end, start); for (let j = 0; j < s; ++j) { - const f = step * (j * 2 + 1) - Vec3.setMagnitude(tmpDir, tmpDir, d * f) - Vec3.add(tmpVecA, start, tmpDir) - Vec3.setMagnitude(tmpDir, tmpDir, d * step * ((j + 1) * 2)) - Vec3.add(tmpVecB, start, tmpDir) - add(tmpVecA[0], tmpVecA[1], tmpVecA[2], tmpVecB[0], tmpVecB[1], tmpVecB[2], group) + const f = step * (j * 2 + 1); + Vec3.setMagnitude(tmpDir, tmpDir, d * f); + Vec3.add(tmpVecA, start, tmpDir); + Vec3.setMagnitude(tmpDir, tmpDir, d * step * ((j + 1) * 2)); + Vec3.add(tmpVecB, start, tmpDir); + add(tmpVecA[0], tmpVecA[1], tmpVecA[2], tmpVecB[0], tmpVecB[1], tmpVecB[2], group); } - } + }; return { add, addFixedCountDashes, addFixedLengthDashes: (start: Vec3, end: Vec3, segmentLength: number, group: number) => { - const d = Vec3.distance(start, end) - addFixedCountDashes(start, end, d / segmentLength, group) + const d = Vec3.distance(start, end); + addFixedCountDashes(start, end, d / segmentLength, group); }, addCage: (t: Mat4, cage: Cage, group: number) => { - const { vertices, edges } = cage + const { vertices, edges } = cage; for (let i = 0, il = edges.length; i < il; i += 2) { - Vec3.fromArray(tmpVecA, vertices, edges[i] * 3) - Vec3.fromArray(tmpVecB, vertices, edges[i + 1] * 3) - Vec3.transformMat4(tmpVecA, tmpVecA, t) - Vec3.transformMat4(tmpVecB, tmpVecB, t) - add(tmpVecA[0], tmpVecA[1], tmpVecA[2], tmpVecB[0], tmpVecB[1], tmpVecB[2], group) + Vec3.fromArray(tmpVecA, vertices, edges[i] * 3); + Vec3.fromArray(tmpVecB, vertices, edges[i + 1] * 3); + Vec3.transformMat4(tmpVecA, tmpVecA, t); + Vec3.transformMat4(tmpVecB, tmpVecB, t); + add(tmpVecA[0], tmpVecA[1], tmpVecA[2], tmpVecB[0], tmpVecB[1], tmpVecB[2], group); } }, getLines: () => { - const mb = ChunkedArray.compact(mappings, true) as Float32Array - const ib = ChunkedArray.compact(indices, true) as Uint32Array - const gb = ChunkedArray.compact(groups, true) as Float32Array - const sb = ChunkedArray.compact(starts, true) as Float32Array - const eb = ChunkedArray.compact(ends, true) as Float32Array - return Lines.create(mb, ib, gb, sb, eb, indices.elementCount / 2) + const mb = ChunkedArray.compact(mappings, true) as Float32Array; + const ib = ChunkedArray.compact(indices, true) as Uint32Array; + const gb = ChunkedArray.compact(groups, true) as Float32Array; + const sb = ChunkedArray.compact(starts, true) as Float32Array; + const eb = ChunkedArray.compact(ends, true) as Float32Array; + return Lines.create(mb, ib, gb, sb, eb, indices.elementCount / 2); } - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/lines/lines.ts b/src/mol-geo/geometry/lines/lines.ts index cb85e175d762995ac3c9899e92663247293140e8..80f32670f32a025fd40ad39851b6d93825e087b9 100644 --- a/src/mol-geo/geometry/lines/lines.ts +++ b/src/mol-geo/geometry/lines/lines.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from '../../../mol-util' -import { Mat4 } from '../../../mol-math/linear-algebra' +import { ValueCell } from '../../../mol-util'; +import { Mat4 } from '../../../mol-math/linear-algebra'; import { transformPositionArray, GroupMapping, createGroupMapping} from '../../util'; import { GeometryUtils } from '../geometry'; import { createColors } from '../color-data'; @@ -56,24 +56,24 @@ export namespace Lines { export function create(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number, lines?: Lines): Lines { return lines ? update(mappings, indices, groups, starts, ends, lineCount, lines) : - fromArrays(mappings, indices, groups, starts, ends, lineCount) + fromArrays(mappings, indices, groups, starts, ends, lineCount); } export function createEmpty(lines?: Lines): Lines { - const mb = lines ? lines.mappingBuffer.ref.value : new Float32Array(0) - const ib = lines ? lines.indexBuffer.ref.value : new Uint32Array(0) - const gb = lines ? lines.groupBuffer.ref.value : new Float32Array(0) - const sb = lines ? lines.startBuffer.ref.value : new Float32Array(0) - const eb = lines ? lines.endBuffer.ref.value : new Float32Array(0) - return create(mb, ib, gb, sb, eb, 0, lines) + const mb = lines ? lines.mappingBuffer.ref.value : new Float32Array(0); + const ib = lines ? lines.indexBuffer.ref.value : new Uint32Array(0); + const gb = lines ? lines.groupBuffer.ref.value : new Float32Array(0); + const sb = lines ? lines.startBuffer.ref.value : new Float32Array(0); + const eb = lines ? lines.endBuffer.ref.value : new Float32Array(0); + return create(mb, ib, gb, sb, eb, 0, lines); } export function fromMesh(mesh: Mesh, lines?: Lines) { - const vb = mesh.vertexBuffer.ref.value - const ib = mesh.indexBuffer.ref.value - const gb = mesh.groupBuffer.ref.value + const vb = mesh.vertexBuffer.ref.value; + const ib = mesh.indexBuffer.ref.value; + const gb = mesh.groupBuffer.ref.value; - const builder = LinesBuilder.create(mesh.triangleCount * 3, mesh.triangleCount / 10, lines) + const builder = LinesBuilder.create(mesh.triangleCount * 3, mesh.triangleCount / 10, lines); // TODO avoid duplicate lines for (let i = 0, il = mesh.triangleCount * 3; i < il; i += 3) { @@ -81,9 +81,9 @@ export namespace Lines { const x0 = vb[i0 * 3], y0 = vb[i0 * 3 + 1], z0 = vb[i0 * 3 + 2]; const x1 = vb[i1 * 3], y1 = vb[i1 * 3 + 1], z1 = vb[i1 * 3 + 2]; const x2 = vb[i2 * 3], y2 = vb[i2 * 3 + 1], z2 = vb[i2 * 3 + 2]; - builder.add(x0, y0, z0, x1, y1, z1, gb[i0]) - builder.add(x0, y0, z0, x2, y2, z2, gb[i0]) - builder.add(x1, y1, z1, x2, y2, z2, gb[i1]) + builder.add(x0, y0, z0, x1, y1, z1, gb[i0]); + builder.add(x0, y0, z0, x2, y2, z2, gb[i0]); + builder.add(x1, y1, z1, x2, y2, z2, gb[i1]); } return builder.getLines(); @@ -93,16 +93,16 @@ export namespace Lines { return hashFnv32a([ lines.lineCount, lines.mappingBuffer.ref.version, lines.indexBuffer.ref.version, lines.groupBuffer.ref.version, lines.startBuffer.ref.version, lines.startBuffer.ref.version - ]) + ]); } function fromArrays(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number): Lines { - const boundingSphere = Sphere3D() - let groupMapping: GroupMapping + const boundingSphere = Sphere3D(); + let groupMapping: GroupMapping; - let currentHash = -1 - let currentGroup = -1 + let currentHash = -1; + let currentGroup = -1; const lines = { kind: 'lines' as const, @@ -113,47 +113,47 @@ export namespace Lines { startBuffer: ValueCell.create(starts), endBuffer: ValueCell.create(ends), get boundingSphere() { - const newHash = hashCode(lines) + const newHash = hashCode(lines); if (newHash !== currentHash) { - const s = calculateInvariantBoundingSphere(lines.startBuffer.ref.value, lines.lineCount * 4, 4) - const e = calculateInvariantBoundingSphere(lines.endBuffer.ref.value, lines.lineCount * 4, 4) + const s = calculateInvariantBoundingSphere(lines.startBuffer.ref.value, lines.lineCount * 4, 4); + const e = calculateInvariantBoundingSphere(lines.endBuffer.ref.value, lines.lineCount * 4, 4); - Sphere3D.expandBySphere(boundingSphere, s, e) - currentHash = newHash + Sphere3D.expandBySphere(boundingSphere, s, e); + currentHash = newHash; } - return boundingSphere + return boundingSphere; }, get groupMapping() { if (lines.groupBuffer.ref.version !== currentGroup) { - groupMapping = createGroupMapping(lines.groupBuffer.ref.value, lines.lineCount, 4) - currentGroup = lines.groupBuffer.ref.version + groupMapping = createGroupMapping(lines.groupBuffer.ref.value, lines.lineCount, 4); + currentGroup = lines.groupBuffer.ref.version; } - return groupMapping + return groupMapping; }, setBoundingSphere(sphere: Sphere3D) { - Sphere3D.copy(boundingSphere, sphere) - currentHash = hashCode(lines) + Sphere3D.copy(boundingSphere, sphere); + currentHash = hashCode(lines); } - } - return lines + }; + return lines; } function update(mappings: Float32Array, indices: Uint32Array, groups: Float32Array, starts: Float32Array, ends: Float32Array, lineCount: number, lines: Lines) { - lines.lineCount = lineCount - ValueCell.update(lines.mappingBuffer, mappings) - ValueCell.update(lines.indexBuffer, indices) - ValueCell.update(lines.groupBuffer, groups) - ValueCell.update(lines.startBuffer, starts) - ValueCell.update(lines.endBuffer, ends) - return lines + lines.lineCount = lineCount; + ValueCell.update(lines.mappingBuffer, mappings); + ValueCell.update(lines.indexBuffer, indices); + ValueCell.update(lines.groupBuffer, groups); + ValueCell.update(lines.startBuffer, starts); + ValueCell.update(lines.endBuffer, ends); + return lines; } export function transform(lines: Lines, t: Mat4) { - const start = lines.startBuffer.ref.value - transformPositionArray(t, start, 0, lines.lineCount * 4) + const start = lines.startBuffer.ref.value; + transformPositionArray(t, start, 0, lines.lineCount * 4); ValueCell.update(lines.startBuffer, start); - const end = lines.endBuffer.ref.value - transformPositionArray(t, end, 0, lines.lineCount * 4) + const end = lines.endBuffer.ref.value; + transformPositionArray(t, end, 0, lines.lineCount * 4); ValueCell.update(lines.endBuffer, end); } @@ -163,7 +163,7 @@ export namespace Lines { ...BaseGeometry.Params, sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }), lineSizeAttenuation: PD.Boolean(false), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<Lines, Params> = { @@ -175,20 +175,20 @@ export namespace Lines { updateBoundingSphere, createRenderableState: BaseGeometry.createRenderableState, updateRenderableState: BaseGeometry.updateRenderableState - } + }; function createValues(lines: Lines, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): LinesValues { - const { instanceCount, groupCount } = locationIt - const color = createColors(locationIt, theme.color) - const size = createSizes(locationIt, theme.size) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const { instanceCount, groupCount } = locationIt; + const color = createColors(locationIt, theme.color); + const size = createSizes(locationIt, theme.size); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: lines.lineCount * 2 * 3, groupCount, instanceCount } + const counts = { drawCount: lines.lineCount * 2 * 3, groupCount, instanceCount }; - const invariantBoundingSphere = Sphere3D.clone(lines.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount) + const invariantBoundingSphere = Sphere3D.clone(lines.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount); return { aMapping: lines.mappingBuffer, @@ -210,30 +210,30 @@ export namespace Lines { dLineSizeAttenuation: ValueCell.create(props.lineSizeAttenuation), dDoubleSided: ValueCell.create(true), dFlipSided: ValueCell.create(false), - } + }; } function createValuesSimple(lines: Lines, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(lines, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(lines, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: LinesValues, props: PD.Values<Params>) { - BaseGeometry.updateValues(values, props) - ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor) - ValueCell.updateIfChanged(values.dLineSizeAttenuation, props.lineSizeAttenuation) + BaseGeometry.updateValues(values, props); + ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor); + ValueCell.updateIfChanged(values.dLineSizeAttenuation, props.lineSizeAttenuation); } function updateBoundingSphere(values: LinesValues, lines: Lines) { - const invariantBoundingSphere = Sphere3D.clone(lines.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const invariantBoundingSphere = Sphere3D.clone(lines.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } } } \ No newline at end of file diff --git a/src/mol-geo/geometry/marker-data.ts b/src/mol-geo/geometry/marker-data.ts index 508786dbf0625aee411bb596e84b8b7592ecefce..b22e0ce9deab5bf7cf102f98014246f3f62f114a 100644 --- a/src/mol-geo/geometry/marker-data.ts +++ b/src/mol-geo/geometry/marker-data.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from '../../mol-util/value-cell' -import { Vec2 } from '../../mol-math/linear-algebra' +import { ValueCell } from '../../mol-util/value-cell'; +import { Vec2 } from '../../mol-math/linear-algebra'; import { TextureImage, createTextureImage } from '../../mol-gl/renderable/util'; export type MarkerData = { @@ -14,29 +14,29 @@ export type MarkerData = { } export function createMarkers(count: number, markerData?: MarkerData): MarkerData { - const markers = createTextureImage(Math.max(1, count), 1, Uint8Array, markerData && markerData.tMarker.ref.value.array) + const markers = createTextureImage(Math.max(1, count), 1, Uint8Array, markerData && markerData.tMarker.ref.value.array); if (markerData) { - ValueCell.update(markerData.tMarker, markers) - ValueCell.update(markerData.uMarkerTexDim, Vec2.create(markers.width, markers.height)) - return markerData + ValueCell.update(markerData.tMarker, markers); + ValueCell.update(markerData.uMarkerTexDim, Vec2.create(markers.width, markers.height)); + return markerData; } else { return { tMarker: ValueCell.create(markers), uMarkerTexDim: ValueCell.create(Vec2.create(markers.width, markers.height)), - } + }; } } -const emptyMarkerTexture = { array: new Uint8Array(1), width: 1, height: 1 } +const emptyMarkerTexture = { array: new Uint8Array(1), width: 1, height: 1 }; export function createEmptyMarkers(markerData?: MarkerData): MarkerData { if (markerData) { - ValueCell.update(markerData.tMarker, emptyMarkerTexture) - ValueCell.update(markerData.uMarkerTexDim, Vec2.create(1, 1)) - return markerData + ValueCell.update(markerData.tMarker, emptyMarkerTexture); + ValueCell.update(markerData.uMarkerTexDim, Vec2.create(1, 1)); + return markerData; } else { return { tMarker: ValueCell.create(emptyMarkerTexture), uMarkerTexDim: ValueCell.create(Vec2.create(1, 1)), - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/axes.ts b/src/mol-geo/geometry/mesh/builder/axes.ts index 010bf091e0107a4a7c706b8713cd5c68576a5367..c11adfd09ed3a6ae3164876fc750bc174bac7de3 100644 --- a/src/mol-geo/geometry/mesh/builder/axes.ts +++ b/src/mol-geo/geometry/mesh/builder/axes.ts @@ -9,26 +9,26 @@ import { MeshBuilder } from '../mesh-builder'; import { Axes3D } from '../../../../mol-math/geometry'; import { createCage } from '../../../primitive/cage'; -const tmpVec = Vec3() -const tmpMatrix = Mat4.identity() +const tmpVec = Vec3(); +const tmpMatrix = Mat4.identity(); -const tmpVertices = new Float32Array(6 * 3) -const tmpEdges = new Uint8Array([0, 1, 2, 3, 4, 5]) +const tmpVertices = new Float32Array(6 * 3); +const tmpEdges = new Uint8Array([0, 1, 2, 3, 4, 5]); export function addAxes(state: MeshBuilder.State, axes: Axes3D, radiusScale: number, detail: number, radialSegments: number) { - const { origin, dirA, dirB, dirC } = axes + const { origin, dirA, dirB, dirC } = axes; - Vec3.add(tmpVec, origin, dirA) - Vec3.toArray(Vec3.add(tmpVec, origin, dirA), tmpVertices, 0) - Vec3.toArray(Vec3.sub(tmpVec, origin, dirA), tmpVertices, 3) - Vec3.toArray(Vec3.add(tmpVec, origin, dirB), tmpVertices, 6) - Vec3.toArray(Vec3.sub(tmpVec, origin, dirB), tmpVertices, 9) - Vec3.toArray(Vec3.add(tmpVec, origin, dirC), tmpVertices, 12) - Vec3.toArray(Vec3.sub(tmpVec, origin, dirC), tmpVertices, 15) + Vec3.add(tmpVec, origin, dirA); + Vec3.toArray(Vec3.add(tmpVec, origin, dirA), tmpVertices, 0); + Vec3.toArray(Vec3.sub(tmpVec, origin, dirA), tmpVertices, 3); + Vec3.toArray(Vec3.add(tmpVec, origin, dirB), tmpVertices, 6); + Vec3.toArray(Vec3.sub(tmpVec, origin, dirB), tmpVertices, 9); + Vec3.toArray(Vec3.add(tmpVec, origin, dirC), tmpVertices, 12); + Vec3.toArray(Vec3.sub(tmpVec, origin, dirC), tmpVertices, 15); - const cage = createCage(tmpVertices, tmpEdges) - const volume = Axes3D.volume(axes) - const radius = (Math.cbrt(volume) / 300) * radiusScale + const cage = createCage(tmpVertices, tmpEdges); + const volume = Axes3D.volume(axes); + const radius = (Math.cbrt(volume) / 300) * radiusScale; - MeshBuilder.addCage(state, tmpMatrix, cage, radius, detail, radialSegments) + MeshBuilder.addCage(state, tmpMatrix, cage, radius, detail, radialSegments); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/box.ts b/src/mol-geo/geometry/mesh/builder/box.ts index 552525eb294388a82fce3e28cb8b2a79fd29eba6..1006515ccd8ffaad70217653ce956f1d3e94d492 100644 --- a/src/mol-geo/geometry/mesh/builder/box.ts +++ b/src/mol-geo/geometry/mesh/builder/box.ts @@ -12,100 +12,100 @@ import { addCylinder } from './cylinder'; import { addSphere } from './sphere'; import { createCage } from '../../../primitive/cage'; -const tmpStart = Vec3.zero() -const tmpEnd = Vec3.zero() -const cylinderProps: CylinderProps = {} +const tmpStart = Vec3.zero(); +const tmpEnd = Vec3.zero(); +const cylinderProps: CylinderProps = {}; export function addBoundingBox(state: MeshBuilder.State, box: Box3D, radius: number, detail: number, radialSegments: number) { - const { min, max } = box - - cylinderProps.radiusTop = radius - cylinderProps.radiusBottom = radius - cylinderProps.radialSegments = radialSegments - - Vec3.set(tmpStart, max[0], max[1], max[2]) - addSphere(state, tmpStart, radius, detail) - Vec3.set(tmpEnd, max[0], max[1], min[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, max[0], min[1], max[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, min[0], max[1], max[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - - Vec3.set(tmpStart, min[0], min[1], min[2]) - addSphere(state, tmpStart, radius, detail) - Vec3.set(tmpEnd, min[0], min[1], max[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, min[0], max[1], min[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, max[0], min[1], min[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - - Vec3.set(tmpStart, max[0], min[1], min[2]) - addSphere(state, tmpStart, radius, detail) - Vec3.set(tmpEnd, max[0], min[1], max[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, max[0], max[1], min[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - - Vec3.set(tmpStart, min[0], min[1], max[2]) - addSphere(state, tmpStart, radius, detail) - Vec3.set(tmpEnd, min[0], max[1], max[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, max[0], min[1], max[2]) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - - Vec3.set(tmpStart, min[0], max[1], min[2]) - addSphere(state, tmpStart, radius, detail) - Vec3.set(tmpEnd, max[0], max[1], min[2]) - addSphere(state, tmpEnd, radius, detail) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) - Vec3.set(tmpEnd, min[0], max[1], max[2]) - addSphere(state, tmpEnd, radius, detail) - addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps) + const { min, max } = box; + + cylinderProps.radiusTop = radius; + cylinderProps.radiusBottom = radius; + cylinderProps.radialSegments = radialSegments; + + Vec3.set(tmpStart, max[0], max[1], max[2]); + addSphere(state, tmpStart, radius, detail); + Vec3.set(tmpEnd, max[0], max[1], min[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, max[0], min[1], max[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, min[0], max[1], max[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + + Vec3.set(tmpStart, min[0], min[1], min[2]); + addSphere(state, tmpStart, radius, detail); + Vec3.set(tmpEnd, min[0], min[1], max[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, min[0], max[1], min[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, max[0], min[1], min[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + + Vec3.set(tmpStart, max[0], min[1], min[2]); + addSphere(state, tmpStart, radius, detail); + Vec3.set(tmpEnd, max[0], min[1], max[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, max[0], max[1], min[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + + Vec3.set(tmpStart, min[0], min[1], max[2]); + addSphere(state, tmpStart, radius, detail); + Vec3.set(tmpEnd, min[0], max[1], max[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, max[0], min[1], max[2]); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + + Vec3.set(tmpStart, min[0], max[1], min[2]); + addSphere(state, tmpStart, radius, detail); + Vec3.set(tmpEnd, max[0], max[1], min[2]); + addSphere(state, tmpEnd, radius, detail); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); + Vec3.set(tmpEnd, min[0], max[1], max[2]); + addSphere(state, tmpEnd, radius, detail); + addCylinder(state, tmpStart, tmpEnd, 1, cylinderProps); } // -const tmpBoxVecCorner = Vec3() -const tmpBoxVecA = Vec3() -const tmpBoxVecB = Vec3() -const tmpBoxVecC = Vec3() -const tmpMatrix = Mat4.identity() +const tmpBoxVecCorner = Vec3(); +const tmpBoxVecA = Vec3(); +const tmpBoxVecB = Vec3(); +const tmpBoxVecC = Vec3(); +const tmpMatrix = Mat4.identity(); -const tmpVertices = new Float32Array(8 * 3) +const tmpVertices = new Float32Array(8 * 3); const tmpEdges = new Uint8Array([ 0, 1, 0, 3, 0, 6, 1, 2, 1, 7, 2, 3, 2, 4, 3, 5, 4, 5, 4, 7, 5, 6, 6, 7 -]) +]); export function addOrientedBox(state: MeshBuilder.State, axes: Axes3D, radiusScale: number, detail: number, radialSegments: number) { - const { origin, dirA, dirB, dirC } = axes - const negDirA = Vec3.negate(tmpBoxVecA, dirA) - const negDirB = Vec3.negate(tmpBoxVecB, dirB) - const negDirC = Vec3.negate(tmpBoxVecC, dirC) + const { origin, dirA, dirB, dirC } = axes; + const negDirA = Vec3.negate(tmpBoxVecA, dirA); + const negDirB = Vec3.negate(tmpBoxVecB, dirB); + const negDirC = Vec3.negate(tmpBoxVecC, dirC); - let offset = 0 + let offset = 0; const addCornerHelper = function (v1: Vec3, v2: Vec3, v3: Vec3) { - Vec3.copy(tmpBoxVecCorner, origin) - Vec3.add(tmpBoxVecCorner, tmpBoxVecCorner, v1) - Vec3.add(tmpBoxVecCorner, tmpBoxVecCorner, v2) - Vec3.add(tmpBoxVecCorner, tmpBoxVecCorner, v3) - Vec3.toArray(tmpBoxVecCorner, tmpVertices, offset) - offset += 3 - } - addCornerHelper(dirA, dirB, dirC) - addCornerHelper(dirA, dirB, negDirC) - addCornerHelper(dirA, negDirB, negDirC) - addCornerHelper(dirA, negDirB, dirC) - addCornerHelper(negDirA, negDirB, negDirC) - addCornerHelper(negDirA, negDirB, dirC) - addCornerHelper(negDirA, dirB, dirC) - addCornerHelper(negDirA, dirB, negDirC) - - const cage = createCage(tmpVertices, tmpEdges) - const volume = Axes3D.volume(axes) - const radius = (Math.cbrt(volume) / 300) * radiusScale - - MeshBuilder.addCage(state, tmpMatrix, cage, radius, detail, radialSegments) + Vec3.copy(tmpBoxVecCorner, origin); + Vec3.add(tmpBoxVecCorner, tmpBoxVecCorner, v1); + Vec3.add(tmpBoxVecCorner, tmpBoxVecCorner, v2); + Vec3.add(tmpBoxVecCorner, tmpBoxVecCorner, v3); + Vec3.toArray(tmpBoxVecCorner, tmpVertices, offset); + offset += 3; + }; + addCornerHelper(dirA, dirB, dirC); + addCornerHelper(dirA, dirB, negDirC); + addCornerHelper(dirA, negDirB, negDirC); + addCornerHelper(dirA, negDirB, dirC); + addCornerHelper(negDirA, negDirB, negDirC); + addCornerHelper(negDirA, negDirB, dirC); + addCornerHelper(negDirA, dirB, dirC); + addCornerHelper(negDirA, dirB, negDirC); + + const cage = createCage(tmpVertices, tmpEdges); + const volume = Axes3D.volume(axes); + const radius = (Math.cbrt(volume) / 300) * radiusScale; + + MeshBuilder.addCage(state, tmpMatrix, cage, radius, detail, radialSegments); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/cylinder.ts b/src/mol-geo/geometry/mesh/builder/cylinder.ts index ed58e2b0af1dd184f3325c1f4b0295269541df13..d2108a17aa1b63c068b01fd55c836fcca8f680d7 100644 --- a/src/mol-geo/geometry/mesh/builder/cylinder.ts +++ b/src/mol-geo/geometry/mesh/builder/cylinder.ts @@ -11,85 +11,85 @@ import { Cylinder, CylinderProps } from '../../../primitive/cylinder'; import { Prism } from '../../../primitive/prism'; import { polygon } from '../../../primitive/polygon'; -const cylinderMap = new Map<string, Primitive>() -const up = Vec3.create(0, 1, 0) +const cylinderMap = new Map<string, Primitive>(); +const up = Vec3.create(0, 1, 0); -const tmpCylinderDir = Vec3.zero() -const tmpCylinderMatDir = Vec3.zero() -const tmpCylinderCenter = Vec3.zero() -const tmpCylinderMat = Mat4.zero() -const tmpCylinderStart = Vec3.zero() -const tmpUp = Vec3.zero() +const tmpCylinderDir = Vec3.zero(); +const tmpCylinderMatDir = Vec3.zero(); +const tmpCylinderCenter = Vec3.zero(); +const tmpCylinderMat = Mat4.zero(); +const tmpCylinderStart = Vec3.zero(); +const tmpUp = Vec3.zero(); function setCylinderMat(m: Mat4, start: Vec3, dir: Vec3, length: number) { - Vec3.setMagnitude(tmpCylinderMatDir, dir, length / 2) - Vec3.add(tmpCylinderCenter, start, tmpCylinderMatDir) + Vec3.setMagnitude(tmpCylinderMatDir, dir, length / 2); + Vec3.add(tmpCylinderCenter, start, tmpCylinderMatDir); // ensure the direction used to create the rotation is always pointing in the same // direction so the triangles of adjacent cylinder will line up - Vec3.matchDirection(tmpUp, up, tmpCylinderMatDir) - Vec3.makeRotation(m, tmpUp, tmpCylinderMatDir) - return Mat4.setTranslation(m, tmpCylinderCenter) + Vec3.matchDirection(tmpUp, up, tmpCylinderMatDir); + Vec3.makeRotation(m, tmpUp, tmpCylinderMatDir); + return Mat4.setTranslation(m, tmpCylinderCenter); } function getCylinder(props: CylinderProps) { - const key = JSON.stringify(props) - let cylinder = cylinderMap.get(key) + const key = JSON.stringify(props); + let cylinder = cylinderMap.get(key); if (cylinder === undefined) { if (props.radialSegments && props.radialSegments <= 4) { - const box = Prism(polygon(4, true, props.radiusTop), props) - cylinder = transformPrimitive(box, Mat4.rotX90) + const box = Prism(polygon(4, true, props.radiusTop), props); + cylinder = transformPrimitive(box, Mat4.rotX90); } else { - cylinder = Cylinder(props) + cylinder = Cylinder(props); } - cylinderMap.set(key, cylinder) + cylinderMap.set(key, cylinder); } - return cylinder + return cylinder; } export function addCylinder(state: MeshBuilder.State, start: Vec3, end: Vec3, lengthScale: number, props: CylinderProps) { - const d = Vec3.distance(start, end) * lengthScale - props.height = d - Vec3.sub(tmpCylinderDir, end, start) - setCylinderMat(tmpCylinderMat, start, tmpCylinderDir, d) - MeshBuilder.addPrimitive(state, tmpCylinderMat, getCylinder(props)) + const d = Vec3.distance(start, end) * lengthScale; + props.height = d; + Vec3.sub(tmpCylinderDir, end, start); + setCylinderMat(tmpCylinderMat, start, tmpCylinderDir, d); + MeshBuilder.addPrimitive(state, tmpCylinderMat, getCylinder(props)); } export function addDoubleCylinder(state: MeshBuilder.State, start: Vec3, end: Vec3, lengthScale: number, shift: Vec3, props: CylinderProps) { - const d = Vec3.distance(start, end) * lengthScale - props.height = d - const cylinder = getCylinder(props) - Vec3.sub(tmpCylinderDir, end, start) + const d = Vec3.distance(start, end) * lengthScale; + props.height = d; + const cylinder = getCylinder(props); + Vec3.sub(tmpCylinderDir, end, start); // positivly shifted cylinder - Vec3.add(tmpCylinderStart, start, shift) - setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d) - MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder) + Vec3.add(tmpCylinderStart, start, shift); + setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d); + MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder); // negativly shifted cylinder - Vec3.sub(tmpCylinderStart, start, shift) - setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d) - MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder) + Vec3.sub(tmpCylinderStart, start, shift); + setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d); + MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder); } export function addFixedCountDashedCylinder(state: MeshBuilder.State, start: Vec3, end: Vec3, lengthScale: number, segmentCount: number, props: CylinderProps) { - const s = Math.floor(segmentCount / 2) - const step = 1 / segmentCount + const s = Math.floor(segmentCount / 2); + const step = 1 / segmentCount; // automatically adjust length so links/bonds that are rendered as two half cylinders // have evenly spaced dashed cylinders if (lengthScale < 1) { - const bias = lengthScale / 2 / segmentCount - lengthScale += segmentCount % 2 === 1 ? bias : -bias + const bias = lengthScale / 2 / segmentCount; + lengthScale += segmentCount % 2 === 1 ? bias : -bias; } - const d = Vec3.distance(start, end) * lengthScale - props.height = d * step - const cylinder = getCylinder(props) - Vec3.sub(tmpCylinderDir, end, start) + const d = Vec3.distance(start, end) * lengthScale; + props.height = d * step; + const cylinder = getCylinder(props); + Vec3.sub(tmpCylinderDir, end, start); for (let j = 0; j < s; ++j) { - const f = step * (j * 2 + 1) - Vec3.setMagnitude(tmpCylinderDir, tmpCylinderDir, d * f) - Vec3.add(tmpCylinderStart, start, tmpCylinderDir) - setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d * step) - MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder) + const f = step * (j * 2 + 1); + Vec3.setMagnitude(tmpCylinderDir, tmpCylinderDir, d * f); + Vec3.add(tmpCylinderStart, start, tmpCylinderDir); + setCylinderMat(tmpCylinderMat, tmpCylinderStart, tmpCylinderDir, d * step); + MeshBuilder.addPrimitive(state, tmpCylinderMat, cylinder); } } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/ellipsoid.ts b/src/mol-geo/geometry/mesh/builder/ellipsoid.ts index 453c9025c6430e2d6514cf1bc2e91ea8a64f7bda..4b04f9366a510fb9c091cdc3917bd5f3cb5d4686 100644 --- a/src/mol-geo/geometry/mesh/builder/ellipsoid.ts +++ b/src/mol-geo/geometry/mesh/builder/ellipsoid.ts @@ -8,16 +8,16 @@ import { Vec3, Mat4 } from '../../../../mol-math/linear-algebra'; import { MeshBuilder } from '../mesh-builder'; import { getSphere } from './sphere'; -const tmpEllipsoidMat = Mat4.identity() -const tmpVec = Vec3() +const tmpEllipsoidMat = Mat4.identity(); +const tmpVec = Vec3(); function setEllipsoidMat(m: Mat4, center: Vec3, dirMajor: Vec3, dirMinor: Vec3, radiusScale: Vec3) { - Vec3.add(tmpVec, center, dirMajor) - Mat4.targetTo(m, center, tmpVec, dirMinor) - Mat4.setTranslation(m, center) - return Mat4.scale(m, m, radiusScale) + Vec3.add(tmpVec, center, dirMajor); + Mat4.targetTo(m, center, tmpVec, dirMinor); + Mat4.setTranslation(m, center); + return Mat4.scale(m, m, radiusScale); } export function addEllipsoid(state: MeshBuilder.State, center: Vec3, dirMajor: Vec3, dirMinor: Vec3, radiusScale: Vec3, detail: number) { - MeshBuilder.addPrimitive(state, setEllipsoidMat(tmpEllipsoidMat, center, dirMajor, dirMinor, radiusScale), getSphere(detail)) + MeshBuilder.addPrimitive(state, setEllipsoidMat(tmpEllipsoidMat, center, dirMajor, dirMinor, radiusScale), getSphere(detail)); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/ribbon.ts b/src/mol-geo/geometry/mesh/builder/ribbon.ts index c227b68fd55233a539dac47c6476e9fb0532685c..f3e7990f11497c26f99bcc2f3051792cb5eb42e8 100644 --- a/src/mol-geo/geometry/mesh/builder/ribbon.ts +++ b/src/mol-geo/geometry/mesh/builder/ribbon.ts @@ -9,70 +9,70 @@ import { Vec3 } from '../../../../mol-math/linear-algebra'; import { ChunkedArray } from '../../../../mol-data/util'; import { MeshBuilder } from '../mesh-builder'; -const tA = Vec3.zero() -const tB = Vec3.zero() -const tV = Vec3.zero() +const tA = Vec3.zero(); +const tB = Vec3.zero(); +const tV = Vec3.zero(); -const horizontalVector = Vec3.zero() -const verticalVector = Vec3.zero() -const normalOffset = Vec3.zero() -const positionVector = Vec3.zero() -const normalVector = Vec3.zero() -const torsionVector = Vec3.zero() +const horizontalVector = Vec3.zero(); +const verticalVector = Vec3.zero(); +const normalOffset = Vec3.zero(); +const positionVector = Vec3.zero(); +const normalVector = Vec3.zero(); +const torsionVector = Vec3.zero(); /** set arrowHeight = 0 for no arrow */ export function addRibbon(state: MeshBuilder.State, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, widthValues: ArrayLike<number>, heightValues: ArrayLike<number>, arrowHeight: number) { - const { currentGroup, vertices, normals, indices, groups } = state + const { currentGroup, vertices, normals, indices, groups } = state; - let vertexCount = vertices.elementCount - let offsetLength = 0 + let vertexCount = vertices.elementCount; + let offsetLength = 0; if (arrowHeight > 0) { - Vec3.fromArray(tA, controlPoints, 0) - Vec3.fromArray(tB, controlPoints, linearSegments * 3) - offsetLength = arrowHeight / Vec3.magnitude(Vec3.sub(tV, tB, tA)) + Vec3.fromArray(tA, controlPoints, 0); + Vec3.fromArray(tB, controlPoints, linearSegments * 3); + offsetLength = arrowHeight / Vec3.magnitude(Vec3.sub(tV, tB, tA)); } for (let i = 0; i <= linearSegments; ++i) { - const width = widthValues[i] - const height = heightValues[i] + const width = widthValues[i]; + const height = heightValues[i]; const actualHeight = arrowHeight === 0 ? height : arrowHeight * (1 - i / linearSegments); - const i3 = i * 3 + const i3 = i * 3; - Vec3.fromArray(verticalVector, normalVectors, i3) + Vec3.fromArray(verticalVector, normalVectors, i3); Vec3.scale(verticalVector, verticalVector, actualHeight); - Vec3.fromArray(horizontalVector, binormalVectors, i3) + Vec3.fromArray(horizontalVector, binormalVectors, i3); Vec3.scale(horizontalVector, horizontalVector, width); if (arrowHeight > 0) { - Vec3.fromArray(tA, normalVectors, i3) - Vec3.fromArray(tB, binormalVectors, i3) - Vec3.scale(normalOffset, Vec3.cross(normalOffset, tA, tB), offsetLength) + Vec3.fromArray(tA, normalVectors, i3); + Vec3.fromArray(tB, binormalVectors, i3); + Vec3.scale(normalOffset, Vec3.cross(normalOffset, tA, tB), offsetLength); } - Vec3.fromArray(positionVector, controlPoints, i3) - Vec3.fromArray(normalVector, normalVectors, i3) - Vec3.fromArray(torsionVector, binormalVectors, i3) + Vec3.fromArray(positionVector, controlPoints, i3); + Vec3.fromArray(normalVector, normalVectors, i3); + Vec3.fromArray(torsionVector, binormalVectors, i3); - Vec3.add(tA, positionVector, verticalVector) - Vec3.negate(tB, torsionVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tA, positionVector, verticalVector); + Vec3.negate(tB, torsionVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.sub(tA, positionVector, verticalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.sub(tA, positionVector, verticalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.add(tA, positionVector, verticalVector) - Vec3.copy(tB, torsionVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tA, positionVector, verticalVector); + Vec3.copy(tB, torsionVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.sub(tA, positionVector, verticalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.sub(tA, positionVector, verticalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); } for (let i = 0; i < linearSegments; ++i) { @@ -103,6 +103,6 @@ export function addRibbon(state: MeshBuilder.State, controlPoints: ArrayLike<num ); } - const addedVertexCount = (linearSegments + 1) * 4 - for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup) + const addedVertexCount = (linearSegments + 1) * 4; + for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/sheet.ts b/src/mol-geo/geometry/mesh/builder/sheet.ts index 89fde7afb160baf8976ee8d880e93e0b25c11133..4b8fbd9671c378635314a8d69c8f037c3b0d36dc 100644 --- a/src/mol-geo/geometry/mesh/builder/sheet.ts +++ b/src/mol-geo/geometry/mesh/builder/sheet.ts @@ -9,138 +9,138 @@ import { Vec3 } from '../../../../mol-math/linear-algebra'; import { ChunkedArray } from '../../../../mol-data/util'; import { MeshBuilder } from '../mesh-builder'; -const tA = Vec3.zero() -const tB = Vec3.zero() -const tV = Vec3.zero() - -const horizontalVector = Vec3.zero() -const verticalVector = Vec3.zero() -const verticalRightVector = Vec3.zero() -const verticalLeftVector = Vec3.zero() -const normalOffset = Vec3.zero() -const positionVector = Vec3.zero() -const normalVector = Vec3.zero() -const torsionVector = Vec3.zero() - -const p1 = Vec3.zero() -const p2 = Vec3.zero() -const p3 = Vec3.zero() -const p4 = Vec3.zero() +const tA = Vec3.zero(); +const tB = Vec3.zero(); +const tV = Vec3.zero(); + +const horizontalVector = Vec3.zero(); +const verticalVector = Vec3.zero(); +const verticalRightVector = Vec3.zero(); +const verticalLeftVector = Vec3.zero(); +const normalOffset = Vec3.zero(); +const positionVector = Vec3.zero(); +const normalVector = Vec3.zero(); +const torsionVector = Vec3.zero(); + +const p1 = Vec3.zero(); +const p2 = Vec3.zero(); +const p3 = Vec3.zero(); +const p4 = Vec3.zero(); function addCap(offset: number, state: MeshBuilder.State, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, width: number, leftHeight: number, rightHeight: number) { - const { vertices, normals, indices } = state - const vertexCount = vertices.elementCount + const { vertices, normals, indices } = state; + const vertexCount = vertices.elementCount; - Vec3.fromArray(verticalLeftVector, normalVectors, offset) - Vec3.scale(verticalLeftVector, verticalLeftVector, leftHeight) + Vec3.fromArray(verticalLeftVector, normalVectors, offset); + Vec3.scale(verticalLeftVector, verticalLeftVector, leftHeight); - Vec3.fromArray(verticalRightVector, normalVectors, offset) - Vec3.scale(verticalRightVector, verticalRightVector, rightHeight) + Vec3.fromArray(verticalRightVector, normalVectors, offset); + Vec3.scale(verticalRightVector, verticalRightVector, rightHeight); - Vec3.fromArray(horizontalVector, binormalVectors, offset) - Vec3.scale(horizontalVector, horizontalVector, width) + Vec3.fromArray(horizontalVector, binormalVectors, offset); + Vec3.scale(horizontalVector, horizontalVector, width); - Vec3.fromArray(positionVector, controlPoints, offset) + Vec3.fromArray(positionVector, controlPoints, offset); - Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalRightVector) - Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalLeftVector) - Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalLeftVector) - Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalRightVector) + Vec3.add(p1, Vec3.add(p1, positionVector, horizontalVector), verticalRightVector); + Vec3.sub(p2, Vec3.add(p2, positionVector, horizontalVector), verticalLeftVector); + Vec3.sub(p3, Vec3.sub(p3, positionVector, horizontalVector), verticalLeftVector); + Vec3.add(p4, Vec3.sub(p4, positionVector, horizontalVector), verticalRightVector); if (leftHeight < rightHeight) { - ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]) - ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]) - ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]) - ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]) - Vec3.copy(verticalVector, verticalRightVector) + ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]); + ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]); + ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]); + ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]); + Vec3.copy(verticalVector, verticalRightVector); } else { - ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]) - ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]) - ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]) - ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]) - Vec3.copy(verticalVector, verticalLeftVector) + ChunkedArray.add3(vertices, p1[0], p1[1], p1[2]); + ChunkedArray.add3(vertices, p2[0], p2[1], p2[2]); + ChunkedArray.add3(vertices, p3[0], p3[1], p3[2]); + ChunkedArray.add3(vertices, p4[0], p4[1], p4[2]); + Vec3.copy(verticalVector, verticalLeftVector); } - Vec3.cross(normalVector, horizontalVector, verticalVector) + Vec3.cross(normalVector, horizontalVector, verticalVector); for (let i = 0; i < 4; ++i) { - ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]) + ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]); } - ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount) - ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2) + ChunkedArray.add3(indices, vertexCount + 2, vertexCount + 1, vertexCount); + ChunkedArray.add3(indices, vertexCount, vertexCount + 3, vertexCount + 2); } /** set arrowHeight = 0 for no arrow */ export function addSheet(state: MeshBuilder.State, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, widthValues: ArrayLike<number>, heightValues: ArrayLike<number>, arrowHeight: number, startCap: boolean, endCap: boolean) { - const { currentGroup, vertices, normals, indices, groups } = state + const { currentGroup, vertices, normals, indices, groups } = state; - let vertexCount = vertices.elementCount - let offsetLength = 0 + let vertexCount = vertices.elementCount; + let offsetLength = 0; if (arrowHeight > 0) { - Vec3.fromArray(tA, controlPoints, 0) - Vec3.fromArray(tB, controlPoints, linearSegments * 3) - offsetLength = arrowHeight / Vec3.magnitude(Vec3.sub(tV, tB, tA)) + Vec3.fromArray(tA, controlPoints, 0); + Vec3.fromArray(tB, controlPoints, linearSegments * 3); + offsetLength = arrowHeight / Vec3.magnitude(Vec3.sub(tV, tB, tA)); } for (let i = 0; i <= linearSegments; ++i) { - const width = widthValues[i] - const height = heightValues[i] + const width = widthValues[i]; + const height = heightValues[i]; const actualHeight = arrowHeight === 0 ? height : arrowHeight * (1 - i / linearSegments); - const i3 = i * 3 + const i3 = i * 3; - Vec3.fromArray(verticalVector, normalVectors, i3) + Vec3.fromArray(verticalVector, normalVectors, i3); Vec3.scale(verticalVector, verticalVector, actualHeight); - Vec3.fromArray(horizontalVector, binormalVectors, i3) + Vec3.fromArray(horizontalVector, binormalVectors, i3); Vec3.scale(horizontalVector, horizontalVector, width); if (arrowHeight > 0) { - Vec3.fromArray(tA, normalVectors, i3) - Vec3.fromArray(tB, binormalVectors, i3) - Vec3.scale(normalOffset, Vec3.cross(normalOffset, tA, tB), offsetLength) + Vec3.fromArray(tA, normalVectors, i3); + Vec3.fromArray(tB, binormalVectors, i3); + Vec3.scale(normalOffset, Vec3.cross(normalOffset, tA, tB), offsetLength); } - Vec3.fromArray(positionVector, controlPoints, i3) - Vec3.fromArray(normalVector, normalVectors, i3) - Vec3.fromArray(torsionVector, binormalVectors, i3) + Vec3.fromArray(positionVector, controlPoints, i3); + Vec3.fromArray(normalVector, normalVectors, i3); + Vec3.fromArray(torsionVector, binormalVectors, i3); - Vec3.add(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector) - Vec3.copy(tB, normalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector); + Vec3.copy(tB, normalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.add(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); // Vec3.add(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector) // reuse tA - Vec3.add(tB, Vec3.negate(tB, torsionVector), normalOffset) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tB, Vec3.negate(tB, torsionVector), normalOffset); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.sub(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.sub(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); // Vec3.sub(tA, Vec3.sub(tA, positionVector, horizontalVector), verticalVector) // reuse tA - Vec3.negate(tB, normalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.negate(tB, normalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.sub(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.sub(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); // Vec3.sub(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector) // reuse tA - Vec3.add(tB, torsionVector, normalOffset) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tB, torsionVector, normalOffset); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); - Vec3.add(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector) - ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]) - ChunkedArray.add3(normals, tB[0], tB[1], tB[2]) + Vec3.add(tA, Vec3.add(tA, positionVector, horizontalVector), verticalVector); + ChunkedArray.add3(vertices, tA[0], tA[1], tA[2]); + ChunkedArray.add3(normals, tB[0], tB[1], tB[2]); } for (let i = 0; i < linearSegments; ++i) { @@ -177,26 +177,26 @@ export function addSheet(state: MeshBuilder.State, controlPoints: ArrayLike<numb } if (startCap) { - const width = widthValues[0] - const height = heightValues[0] - const h = arrowHeight === 0 ? height : arrowHeight - addCap(0, state, controlPoints, normalVectors, binormalVectors, width, h, h) + const width = widthValues[0]; + const height = heightValues[0]; + const h = arrowHeight === 0 ? height : arrowHeight; + addCap(0, state, controlPoints, normalVectors, binormalVectors, width, h, h); } else if (arrowHeight > 0) { - const width = widthValues[0] - const height = heightValues[0] - addCap(0, state, controlPoints, normalVectors, binormalVectors, width, arrowHeight, -height) - addCap(0, state, controlPoints, normalVectors, binormalVectors, width, -arrowHeight, height) + const width = widthValues[0]; + const height = heightValues[0]; + addCap(0, state, controlPoints, normalVectors, binormalVectors, width, arrowHeight, -height); + addCap(0, state, controlPoints, normalVectors, binormalVectors, width, -arrowHeight, height); } if (endCap && arrowHeight === 0) { - const width = widthValues[linearSegments] - const height = heightValues[linearSegments] + const width = widthValues[linearSegments]; + const height = heightValues[linearSegments]; // use negative height to flip the direction the cap's triangles are facing - addCap(linearSegments * 3, state, controlPoints, normalVectors, binormalVectors, width, -height, -height) + addCap(linearSegments * 3, state, controlPoints, normalVectors, binormalVectors, width, -height, -height); } const addedVertexCount = (linearSegments + 1) * 8 + (startCap ? 4 : (arrowHeight > 0 ? 8 : 0)) + - (endCap && arrowHeight === 0 ? 4 : 0) - for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup) + (endCap && arrowHeight === 0 ? 4 : 0); + for (let i = 0, il = addedVertexCount; i < il; ++i) ChunkedArray.add(groups, currentGroup); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/sphere.ts b/src/mol-geo/geometry/mesh/builder/sphere.ts index 041c62e5ff4f14ebf23f310faec76e847a76cf8e..0e45a87cd258ac0dd2acc08946dab67df4cb42c4 100644 --- a/src/mol-geo/geometry/mesh/builder/sphere.ts +++ b/src/mol-geo/geometry/mesh/builder/sphere.ts @@ -9,22 +9,22 @@ import { MeshBuilder } from '../mesh-builder'; import { Primitive } from '../../../primitive/primitive'; import { Sphere } from '../../../primitive/sphere'; -const sphereMap = new Map<number, Primitive>() -const tmpSphereMat = Mat4.identity() +const sphereMap = new Map<number, Primitive>(); +const tmpSphereMat = Mat4.identity(); function setSphereMat(m: Mat4, center: Vec3, radius: number) { - return Mat4.scaleUniformly(m, Mat4.fromTranslation(m, center), radius) + return Mat4.scaleUniformly(m, Mat4.fromTranslation(m, center), radius); } export function getSphere(detail: number) { - let sphere = sphereMap.get(detail) + let sphere = sphereMap.get(detail); if (sphere === undefined) { - sphere = Sphere(detail) - sphereMap.set(detail, sphere) + sphere = Sphere(detail); + sphereMap.set(detail, sphere); } - return sphere + return sphere; } export function addSphere(state: MeshBuilder.State, center: Vec3, radius: number, detail: number) { - MeshBuilder.addPrimitive(state, setSphereMat(tmpSphereMat, center, radius), getSphere(detail)) + MeshBuilder.addPrimitive(state, setSphereMat(tmpSphereMat, center, radius), getSphere(detail)); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/builder/tube.ts b/src/mol-geo/geometry/mesh/builder/tube.ts index 401b753c6e018df32faf22fecdaed161947103d9..03cf4b9149b182ff307314a0e3e6363431d04f92 100644 --- a/src/mol-geo/geometry/mesh/builder/tube.ts +++ b/src/mol-geo/geometry/mesh/builder/tube.ts @@ -9,11 +9,11 @@ import { Vec3 } from '../../../../mol-math/linear-algebra'; import { ChunkedArray } from '../../../../mol-data/util'; import { MeshBuilder } from '../mesh-builder'; -const normalVector = Vec3.zero() -const surfacePoint = Vec3.zero() -const controlPoint = Vec3.zero() -const u = Vec3.zero() -const v = Vec3.zero() +const normalVector = Vec3.zero(); +const surfacePoint = Vec3.zero(); +const controlPoint = Vec3.zero(); +const u = Vec3.zero(); +const v = Vec3.zero(); function add2AndScale2(out: Vec3, a: Vec3, b: Vec3, sa: number, sb: number) { out[0] = (a[0] * sa) + (b[0] * sb); @@ -28,19 +28,19 @@ function add3AndScale2(out: Vec3, a: Vec3, b: Vec3, c: Vec3, sa: number, sb: num } export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, radialSegments: number, widthValues: ArrayLike<number>, heightValues: ArrayLike<number>, waveFactor: number, startCap: boolean, endCap: boolean) { - const { currentGroup, vertices, normals, indices, groups } = state + const { currentGroup, vertices, normals, indices, groups } = state; - let vertexCount = vertices.elementCount - const di = 1 / linearSegments + let vertexCount = vertices.elementCount; + const di = 1 / linearSegments; for (let i = 0; i <= linearSegments; ++i) { - const i3 = i * 3 - Vec3.fromArray(u, normalVectors, i3) - Vec3.fromArray(v, binormalVectors, i3) - Vec3.fromArray(controlPoint, controlPoints, i3) + const i3 = i * 3; + Vec3.fromArray(u, normalVectors, i3); + Vec3.fromArray(v, binormalVectors, i3); + Vec3.fromArray(controlPoint, controlPoints, i3); - const width = widthValues[i] - const height = heightValues[i] + const width = widthValues[i]; + const height = heightValues[i]; const tt = di * i - 0.5; const ff = 1 + (waveFactor - 1) * (Math.cos(2 * Math.PI * tt) + 1); @@ -49,17 +49,17 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<numbe for (let j = 0; j < radialSegments; ++j) { const t = 2 * Math.PI * j / radialSegments; - add3AndScale2(surfacePoint, u, v, controlPoint, h * Math.cos(t), w * Math.sin(t)) + add3AndScale2(surfacePoint, u, v, controlPoint, h * Math.cos(t), w * Math.sin(t)); if (radialSegments === 2) { // add2AndScale2(normalVector, u, v, w * Math.cos(t), h * Math.sin(t)) - Vec3.copy(normalVector, v) - console.log(i, t) - Vec3.normalize(normalVector, normalVector) - if (t !== 0 || i % 2 === 0) Vec3.negate(normalVector, normalVector) + Vec3.copy(normalVector, v); + console.log(i, t); + Vec3.normalize(normalVector, normalVector); + if (t !== 0 || i % 2 === 0) Vec3.negate(normalVector, normalVector); } else { - add2AndScale2(normalVector, u, v, w * Math.cos(t), h * Math.sin(t)) + add2AndScale2(normalVector, u, v, w * Math.cos(t), h * Math.sin(t)); } - Vec3.normalize(normalVector, normalVector) + Vec3.normalize(normalVector, normalVector); ChunkedArray.add3(vertices, surfacePoint[0], surfacePoint[1], surfacePoint[2]); ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]); @@ -84,24 +84,24 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<numbe } if (startCap) { - const offset = 0 - const centerVertex = vertices.elementCount - Vec3.fromArray(u, normalVectors, offset) - Vec3.fromArray(v, binormalVectors, offset) - Vec3.fromArray(controlPoint, controlPoints, offset) - Vec3.cross(normalVector, v, u) + const offset = 0; + const centerVertex = vertices.elementCount; + Vec3.fromArray(u, normalVectors, offset); + Vec3.fromArray(v, binormalVectors, offset); + Vec3.fromArray(controlPoint, controlPoints, offset); + Vec3.cross(normalVector, v, u); ChunkedArray.add3(vertices, controlPoint[0], controlPoint[1], controlPoint[2]); ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]); - const width = widthValues[0] - const height = heightValues[0] + const width = widthValues[0]; + const height = heightValues[0]; - vertexCount = vertices.elementCount + vertexCount = vertices.elementCount; for (let i = 0; i < radialSegments; ++i) { const t = 2 * Math.PI * i / radialSegments; - add3AndScale2(surfacePoint, u, v, controlPoint, height * Math.cos(t), width * Math.sin(t)) + add3AndScale2(surfacePoint, u, v, controlPoint, height * Math.cos(t), width * Math.sin(t)); ChunkedArray.add3(vertices, surfacePoint[0], surfacePoint[1], surfacePoint[2]); ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]); @@ -116,24 +116,24 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<numbe } if (endCap) { - const offset = linearSegments * 3 - const centerVertex = vertices.elementCount - Vec3.fromArray(u, normalVectors, offset) - Vec3.fromArray(v, binormalVectors, offset) - Vec3.fromArray(controlPoint, controlPoints, offset) - Vec3.cross(normalVector, u, v) + const offset = linearSegments * 3; + const centerVertex = vertices.elementCount; + Vec3.fromArray(u, normalVectors, offset); + Vec3.fromArray(v, binormalVectors, offset); + Vec3.fromArray(controlPoint, controlPoints, offset); + Vec3.cross(normalVector, u, v); ChunkedArray.add3(vertices, controlPoint[0], controlPoint[1], controlPoint[2]); ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]); - const width = widthValues[linearSegments] - const height = heightValues[linearSegments] + const width = widthValues[linearSegments]; + const height = heightValues[linearSegments]; - vertexCount = vertices.elementCount + vertexCount = vertices.elementCount; for (let i = 0; i < radialSegments; ++i) { - const t = 2 * Math.PI * i / radialSegments + const t = 2 * Math.PI * i / radialSegments; - add3AndScale2(surfacePoint, u, v, controlPoint, height * Math.cos(t), width * Math.sin(t)) + add3AndScale2(surfacePoint, u, v, controlPoint, height * Math.cos(t), width * Math.sin(t)); ChunkedArray.add3(vertices, surfacePoint[0], surfacePoint[1], surfacePoint[2]); ChunkedArray.add3(normals, normalVector[0], normalVector[1], normalVector[2]); @@ -147,6 +147,6 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<numbe } } - const addedVertexCount = (linearSegments + 1) * radialSegments + (startCap ? radialSegments + 1 : 0) + (endCap ? radialSegments + 1 : 0) - ChunkedArray.addRepeat(groups, addedVertexCount, currentGroup) + const addedVertexCount = (linearSegments + 1) * radialSegments + (startCap ? radialSegments + 1 : 0) + (endCap ? radialSegments + 1 : 0); + ChunkedArray.addRepeat(groups, addedVertexCount, currentGroup); } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/mesh-builder.ts b/src/mol-geo/geometry/mesh/mesh-builder.ts index 5c810888f809cdb92dfa6abf043e5982bfb94f58..b45d90740af66de65cf6d6ba87dc6cfcb1ecd7cb 100644 --- a/src/mol-geo/geometry/mesh/mesh-builder.ts +++ b/src/mol-geo/geometry/mesh/mesh-builder.ts @@ -12,12 +12,12 @@ import { Cage } from '../../../mol-geo/primitive/cage'; import { addSphere } from './builder/sphere'; import { addCylinder } from './builder/cylinder'; -const tmpV = Vec3.zero() -const tmpMat3 = Mat3.zero() -const tmpVecA = Vec3.zero() -const tmpVecB = Vec3.zero() -const tmpVecC = Vec3.zero() -const tmpVecD = Vec3.zero() +const tmpV = Vec3.zero(); +const tmpMat3 = Mat3.zero(); +const tmpVecA = Vec3.zero(); +const tmpVecB = Vec3.zero(); +const tmpVecC = Vec3.zero(); +const tmpVecD = Vec3.zero(); export namespace MeshBuilder { export interface State { @@ -37,19 +37,19 @@ export namespace MeshBuilder { indices: ChunkedArray.create(Uint32Array, 3, chunkSize * 3, mesh ? mesh.indexBuffer.ref.value : initialCount * 3), groups: ChunkedArray.create(Float32Array, 1, chunkSize, mesh ? mesh.groupBuffer.ref.value : initialCount), mesh - } + }; } export function addTriangle(state: State, a: Vec3, b: Vec3, c: Vec3) { - const { vertices, normals, indices, groups, currentGroup } = state - const offset = vertices.elementCount + const { vertices, normals, indices, groups, currentGroup } = state; + const offset = vertices.elementCount; // positions ChunkedArray.add3(vertices, a[0], a[1], a[2]); ChunkedArray.add3(vertices, b[0], b[1], b[2]); ChunkedArray.add3(vertices, c[0], c[1], c[2]); - Vec3.triangleNormal(tmpV, a, b, c) + Vec3.triangleNormal(tmpV, a, b, c); for (let i = 0; i < 3; ++i) { ChunkedArray.add3(normals, tmpV[0], tmpV[1], tmpV[2]); // normal ChunkedArray.add(groups, currentGroup); // group @@ -58,38 +58,38 @@ export namespace MeshBuilder { } export function addTriangleStrip(state: State, vertices: ArrayLike<number>, indices: ArrayLike<number>) { - Vec3.fromArray(tmpVecC, vertices, indices[0] * 3) - Vec3.fromArray(tmpVecD, vertices, indices[1] * 3) + Vec3.fromArray(tmpVecC, vertices, indices[0] * 3); + Vec3.fromArray(tmpVecD, vertices, indices[1] * 3); for (let i = 2, il = indices.length; i < il; i += 2) { - Vec3.copy(tmpVecA, tmpVecC) - Vec3.copy(tmpVecB, tmpVecD) - Vec3.fromArray(tmpVecC, vertices, indices[i] * 3) - Vec3.fromArray(tmpVecD, vertices, indices[i + 1] * 3) - addTriangle(state, tmpVecA, tmpVecB, tmpVecC) - addTriangle(state, tmpVecB, tmpVecD, tmpVecC) + Vec3.copy(tmpVecA, tmpVecC); + Vec3.copy(tmpVecB, tmpVecD); + Vec3.fromArray(tmpVecC, vertices, indices[i] * 3); + Vec3.fromArray(tmpVecD, vertices, indices[i + 1] * 3); + addTriangle(state, tmpVecA, tmpVecB, tmpVecC); + addTriangle(state, tmpVecB, tmpVecD, tmpVecC); } } export function addTriangleFan(state: State, vertices: ArrayLike<number>, indices: ArrayLike<number>) { - Vec3.fromArray(tmpVecA, vertices, indices[0] * 3) + Vec3.fromArray(tmpVecA, vertices, indices[0] * 3); for (let i = 2, il = indices.length; i < il; ++i) { - Vec3.fromArray(tmpVecB, vertices, indices[i - 1] * 3) - Vec3.fromArray(tmpVecC, vertices, indices[i] * 3) - addTriangle(state, tmpVecA, tmpVecC, tmpVecB) + Vec3.fromArray(tmpVecB, vertices, indices[i - 1] * 3); + Vec3.fromArray(tmpVecC, vertices, indices[i] * 3); + addTriangle(state, tmpVecA, tmpVecC, tmpVecB); } } export function addPrimitive(state: State, t: Mat4, primitive: Primitive) { - const { vertices: va, normals: na, indices: ia } = primitive - const { vertices, normals, indices, groups, currentGroup } = state - const offset = vertices.elementCount - const n = Mat3.directionTransform(tmpMat3, t) + const { vertices: va, normals: na, indices: ia } = primitive; + const { vertices, normals, indices, groups, currentGroup } = state; + const offset = vertices.elementCount; + const n = Mat3.directionTransform(tmpMat3, t); for (let i = 0, il = va.length; i < il; i += 3) { // position - Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, va, i), t) + Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, va, i), t); ChunkedArray.add3(vertices, tmpV[0], tmpV[1], tmpV[2]); // normal - Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, na, i), n) + Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, na, i), n); ChunkedArray.add3(normals, tmpV[0], tmpV[1], tmpV[2]); // group ChunkedArray.add(groups, currentGroup); @@ -101,16 +101,16 @@ export namespace MeshBuilder { /** Flips triangle normals and winding order */ export function addPrimitiveFlipped(state: State, t: Mat4, primitive: Primitive) { - const { vertices: va, normals: na, indices: ia } = primitive - const { vertices, normals, indices, groups, currentGroup } = state - const offset = vertices.elementCount - const n = Mat3.directionTransform(tmpMat3, t) + const { vertices: va, normals: na, indices: ia } = primitive; + const { vertices, normals, indices, groups, currentGroup } = state; + const offset = vertices.elementCount; + const n = Mat3.directionTransform(tmpMat3, t); for (let i = 0, il = va.length; i < il; i += 3) { // position - Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, va, i), t) + Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, va, i), t); ChunkedArray.add3(vertices, tmpV[0], tmpV[1], tmpV[2]); // normal - Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, na, i), n) + Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, na, i), n); ChunkedArray.add3(normals, -tmpV[0], -tmpV[1], -tmpV[2]); // group ChunkedArray.add(groups, currentGroup); @@ -121,25 +121,25 @@ export namespace MeshBuilder { } export function addCage(state: State, t: Mat4, cage: Cage, radius: number, detail: number, radialSegments: number) { - const { vertices: va, edges: ea } = cage - const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments } + const { vertices: va, edges: ea } = cage; + const cylinderProps = { radiusTop: radius, radiusBottom: radius, radialSegments }; for (let i = 0, il = ea.length; i < il; i += 2) { - Vec3.fromArray(tmpVecA, va, ea[i] * 3) - Vec3.fromArray(tmpVecB, va, ea[i + 1] * 3) - Vec3.transformMat4(tmpVecA, tmpVecA, t) - Vec3.transformMat4(tmpVecB, tmpVecB, t) - addSphere(state, tmpVecA, radius, detail) - addSphere(state, tmpVecB, radius, detail) - addCylinder(state, tmpVecA, tmpVecB, 1, cylinderProps) + Vec3.fromArray(tmpVecA, va, ea[i] * 3); + Vec3.fromArray(tmpVecB, va, ea[i + 1] * 3); + Vec3.transformMat4(tmpVecA, tmpVecA, t); + Vec3.transformMat4(tmpVecB, tmpVecB, t); + addSphere(state, tmpVecA, radius, detail); + addSphere(state, tmpVecB, radius, detail); + addCylinder(state, tmpVecA, tmpVecB, 1, cylinderProps); } } export function getMesh (state: State): Mesh { - const { vertices, normals, indices, groups, mesh } = state - const vb = ChunkedArray.compact(vertices, true) as Float32Array - const ib = ChunkedArray.compact(indices, true) as Uint32Array - const nb = ChunkedArray.compact(normals, true) as Float32Array - const gb = ChunkedArray.compact(groups, true) as Float32Array - return Mesh.create(vb, ib, nb, gb, state.vertices.elementCount, state.indices.elementCount, mesh) + const { vertices, normals, indices, groups, mesh } = state; + const vb = ChunkedArray.compact(vertices, true) as Float32Array; + const ib = ChunkedArray.compact(indices, true) as Uint32Array; + const nb = ChunkedArray.compact(normals, true) as Float32Array; + const gb = ChunkedArray.compact(groups, true) as Float32Array; + return Mesh.create(vb, ib, nb, gb, state.vertices.elementCount, state.indices.elementCount, mesh); } } \ No newline at end of file diff --git a/src/mol-geo/geometry/mesh/mesh.ts b/src/mol-geo/geometry/mesh/mesh.ts index 8312a55eb631076a31c8c92b77387a47c82d5b9a..dc20ed0e2b31f90f49ff8e71923d7962c1a7d86b 100644 --- a/src/mol-geo/geometry/mesh/mesh.ts +++ b/src/mol-geo/geometry/mesh/mesh.ts @@ -5,9 +5,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { ValueCell } from '../../../mol-util' -import { Vec3, Mat4, Mat3 } from '../../../mol-math/linear-algebra' -import { Sphere3D } from '../../../mol-math/geometry' +import { ValueCell } from '../../../mol-util'; +import { Vec3, Mat4, Mat3 } from '../../../mol-math/linear-algebra'; +import { Sphere3D } from '../../../mol-math/geometry'; import { transformPositionArray, transformDirectionArray, computeIndexedVertexNormals, GroupMapping, createGroupMapping} from '../../util'; import { GeometryUtils } from '../geometry'; import { createMarkers } from '../marker-data'; @@ -53,15 +53,15 @@ export namespace Mesh { export function create(vertices: Float32Array, indices: Uint32Array, normals: Float32Array, groups: Float32Array, vertexCount: number, triangleCount: number, mesh?: Mesh): Mesh { return mesh ? update(vertices, indices, normals, groups, vertexCount, triangleCount, mesh) : - fromArrays(vertices, indices, normals, groups, vertexCount, triangleCount) + fromArrays(vertices, indices, normals, groups, vertexCount, triangleCount); } export function createEmpty(mesh?: Mesh): Mesh { - const vb = mesh ? mesh.vertexBuffer.ref.value : new Float32Array(0) - const ib = mesh ? mesh.indexBuffer.ref.value : new Uint32Array(0) - const nb = mesh ? mesh.normalBuffer.ref.value : new Float32Array(0) - const gb = mesh ? mesh.groupBuffer.ref.value : new Float32Array(0) - return create(vb, ib, nb, gb, 0, 0, mesh) + const vb = mesh ? mesh.vertexBuffer.ref.value : new Float32Array(0); + const ib = mesh ? mesh.indexBuffer.ref.value : new Uint32Array(0); + const nb = mesh ? mesh.normalBuffer.ref.value : new Float32Array(0); + const gb = mesh ? mesh.groupBuffer.ref.value : new Float32Array(0); + return create(vb, ib, nb, gb, 0, 0, mesh); } function hashCode(mesh: Mesh) { @@ -69,16 +69,16 @@ export namespace Mesh { mesh.vertexCount, mesh.triangleCount, mesh.vertexBuffer.ref.version, mesh.indexBuffer.ref.version, mesh.normalBuffer.ref.version, mesh.groupBuffer.ref.version - ]) + ]); } function fromArrays(vertices: Float32Array, indices: Uint32Array, normals: Float32Array, groups: Float32Array, vertexCount: number, triangleCount: number): Mesh { - const boundingSphere = Sphere3D() - let groupMapping: GroupMapping + const boundingSphere = Sphere3D(); + let groupMapping: GroupMapping; - let currentHash = -1 - let currentGroup = -1 + let currentHash = -1; + let currentGroup = -1; const mesh = { kind: 'mesh' as const, @@ -89,85 +89,85 @@ export namespace Mesh { normalBuffer: ValueCell.create(normals), groupBuffer: ValueCell.create(groups), get boundingSphere() { - const newHash = hashCode(mesh) + const newHash = hashCode(mesh); if (newHash !== currentHash) { - const b = calculateInvariantBoundingSphere(mesh.vertexBuffer.ref.value, mesh.vertexCount, 1) - Sphere3D.copy(boundingSphere, b) - currentHash = newHash + const b = calculateInvariantBoundingSphere(mesh.vertexBuffer.ref.value, mesh.vertexCount, 1); + Sphere3D.copy(boundingSphere, b); + currentHash = newHash; } - return boundingSphere + return boundingSphere; }, get groupMapping() { if (mesh.groupBuffer.ref.version !== currentGroup) { - groupMapping = createGroupMapping(mesh.groupBuffer.ref.value, mesh.vertexCount) - currentGroup = mesh.groupBuffer.ref.version + groupMapping = createGroupMapping(mesh.groupBuffer.ref.value, mesh.vertexCount); + currentGroup = mesh.groupBuffer.ref.version; } - return groupMapping + return groupMapping; }, setBoundingSphere(sphere: Sphere3D) { - Sphere3D.copy(boundingSphere, sphere) - currentHash = hashCode(mesh) + Sphere3D.copy(boundingSphere, sphere); + currentHash = hashCode(mesh); } - } - return mesh + }; + return mesh; } function update(vertices: Float32Array, indices: Uint32Array, normals: Float32Array, groups: Float32Array, vertexCount: number, triangleCount: number, mesh: Mesh) { - mesh.vertexCount = vertexCount - mesh.triangleCount = triangleCount - ValueCell.update(mesh.vertexBuffer, vertices) - ValueCell.update(mesh.indexBuffer, indices) - ValueCell.update(mesh.normalBuffer, normals) - ValueCell.update(mesh.groupBuffer, groups) - return mesh + mesh.vertexCount = vertexCount; + mesh.triangleCount = triangleCount; + ValueCell.update(mesh.vertexBuffer, vertices); + ValueCell.update(mesh.indexBuffer, indices); + ValueCell.update(mesh.normalBuffer, normals); + ValueCell.update(mesh.groupBuffer, groups); + return mesh; } export function computeNormals(mesh: Mesh) { - const { vertexCount, triangleCount } = mesh - const vertices = mesh.vertexBuffer.ref.value - const indices = mesh.indexBuffer.ref.value + const { vertexCount, triangleCount } = mesh; + const vertices = mesh.vertexBuffer.ref.value; + const indices = mesh.indexBuffer.ref.value; const normals = mesh.normalBuffer.ref.value.length >= vertexCount * 3 ? mesh.normalBuffer.ref.value : new Float32Array(vertexCount * 3); if (normals === mesh.normalBuffer.ref.value) { - normals.fill(0, 0, vertexCount * 3) + normals.fill(0, 0, vertexCount * 3); } - computeIndexedVertexNormals(vertices, indices, normals, vertexCount, triangleCount) + computeIndexedVertexNormals(vertices, indices, normals, vertexCount, triangleCount); ValueCell.update(mesh.normalBuffer, normals); } export function checkForDuplicateVertices(mesh: Mesh, fractionDigits = 3) { - const v = mesh.vertexBuffer.ref.value + const v = mesh.vertexBuffer.ref.value; - const map = new Map<string, number>() - const hash = (v: Vec3, d: number) => `${v[0].toFixed(d)}|${v[1].toFixed(d)}|${v[2].toFixed(d)}` - let duplicates = 0 + const map = new Map<string, number>(); + const hash = (v: Vec3, d: number) => `${v[0].toFixed(d)}|${v[1].toFixed(d)}|${v[2].toFixed(d)}`; + let duplicates = 0; - const a = Vec3() + const a = Vec3(); for (let i = 0, il = mesh.vertexCount; i < il; ++i) { - Vec3.fromArray(a, v, i * 3) - const k = hash(a, fractionDigits) - const count = map.get(k) + Vec3.fromArray(a, v, i * 3); + const k = hash(a, fractionDigits); + const count = map.get(k); if (count !== undefined) { - duplicates += 1 - map.set(k, count + 1) + duplicates += 1; + map.set(k, count + 1); } else { - map.set(k, 1) + map.set(k, 1); } } - return duplicates + return duplicates; } - const tmpMat3 = Mat3() + const tmpMat3 = Mat3(); export function transform(mesh: Mesh, t: Mat4) { - const v = mesh.vertexBuffer.ref.value - transformPositionArray(t, v, 0, mesh.vertexCount) + const v = mesh.vertexBuffer.ref.value; + transformPositionArray(t, v, 0, mesh.vertexCount); if (!Mat4.isTranslationAndUniformScaling(t)) { - const n = Mat3.directionTransform(tmpMat3, t) - transformDirectionArray(n, mesh.normalBuffer.ref.value, 0, mesh.vertexCount) + const n = Mat3.directionTransform(tmpMat3, t); + transformDirectionArray(n, mesh.normalBuffer.ref.value, 0, mesh.vertexCount); } ValueCell.update(mesh.vertexBuffer, v); } @@ -177,150 +177,150 @@ export namespace Mesh { * Note that normals are copied over and can't be re-created from the new mesh. */ export function uniformTriangleGroup(mesh: Mesh, splitTriangles = true) { - const { indexBuffer, vertexBuffer, groupBuffer, normalBuffer, triangleCount, vertexCount } = mesh - const ib = indexBuffer.ref.value - const vb = vertexBuffer.ref.value - const gb = groupBuffer.ref.value - const nb = normalBuffer.ref.value + const { indexBuffer, vertexBuffer, groupBuffer, normalBuffer, triangleCount, vertexCount } = mesh; + const ib = indexBuffer.ref.value; + const vb = vertexBuffer.ref.value; + const gb = groupBuffer.ref.value; + const nb = normalBuffer.ref.value; // new - const index = ChunkedArray.create(Uint32Array, 3, 1024, triangleCount) + const index = ChunkedArray.create(Uint32Array, 3, 1024, triangleCount); // re-use - const vertex = ChunkedArray.create(Float32Array, 3, 1024, vb) - vertex.currentIndex = vertexCount * 3 - vertex.elementCount = vertexCount - const normal = ChunkedArray.create(Float32Array, 3, 1024, nb) - normal.currentIndex = vertexCount * 3 - normal.elementCount = vertexCount - const group = ChunkedArray.create(Float32Array, 1, 1024, gb) - group.currentIndex = vertexCount - group.elementCount = vertexCount - - const vi = Vec3() - const vj = Vec3() - const vk = Vec3() - const ni = Vec3() - const nj = Vec3() - const nk = Vec3() + const vertex = ChunkedArray.create(Float32Array, 3, 1024, vb); + vertex.currentIndex = vertexCount * 3; + vertex.elementCount = vertexCount; + const normal = ChunkedArray.create(Float32Array, 3, 1024, nb); + normal.currentIndex = vertexCount * 3; + normal.elementCount = vertexCount; + const group = ChunkedArray.create(Float32Array, 1, 1024, gb); + group.currentIndex = vertexCount; + group.elementCount = vertexCount; + + const vi = Vec3(); + const vj = Vec3(); + const vk = Vec3(); + const ni = Vec3(); + const nj = Vec3(); + const nk = Vec3(); function add(i: number) { - Vec3.fromArray(vi, vb, i * 3) - Vec3.fromArray(ni, nb, i * 3) - ChunkedArray.add3(vertex, vi[0], vi[1], vi[2]) - ChunkedArray.add3(normal, ni[0], ni[1], ni[2]) + Vec3.fromArray(vi, vb, i * 3); + Vec3.fromArray(ni, nb, i * 3); + ChunkedArray.add3(vertex, vi[0], vi[1], vi[2]); + ChunkedArray.add3(normal, ni[0], ni[1], ni[2]); } function addMid(i: number, j: number) { - Vec3.fromArray(vi, vb, i * 3) - Vec3.fromArray(vj, vb, j * 3) - Vec3.scale(vi, Vec3.add(vi, vi, vj), 0.5) - Vec3.fromArray(ni, nb, i * 3) - Vec3.fromArray(nj, nb, j * 3) - Vec3.scale(ni, Vec3.add(ni, ni, nj), 0.5) - ChunkedArray.add3(vertex, vi[0], vi[1], vi[2]) - ChunkedArray.add3(normal, ni[0], ni[1], ni[2]) + Vec3.fromArray(vi, vb, i * 3); + Vec3.fromArray(vj, vb, j * 3); + Vec3.scale(vi, Vec3.add(vi, vi, vj), 0.5); + Vec3.fromArray(ni, nb, i * 3); + Vec3.fromArray(nj, nb, j * 3); + Vec3.scale(ni, Vec3.add(ni, ni, nj), 0.5); + ChunkedArray.add3(vertex, vi[0], vi[1], vi[2]); + ChunkedArray.add3(normal, ni[0], ni[1], ni[2]); } function addCenter(i: number, j: number, k: number) { - Vec3.fromArray(vi, vb, i * 3) - Vec3.fromArray(vj, vb, j * 3) - Vec3.fromArray(vk, vb, k * 3) - Vec3.scale(vi, Vec3.add(vi, Vec3.add(vi, vi, vj), vk), 1 / 3) - Vec3.fromArray(ni, nb, i * 3) - Vec3.fromArray(nj, nb, j * 3) - Vec3.fromArray(nk, nb, k * 3) - Vec3.scale(ni, Vec3.add(ni, Vec3.add(ni, ni, nj), nk), 1 / 3) - ChunkedArray.add3(vertex, vi[0], vi[1], vi[2]) - ChunkedArray.add3(normal, ni[0], ni[1], ni[2]) + Vec3.fromArray(vi, vb, i * 3); + Vec3.fromArray(vj, vb, j * 3); + Vec3.fromArray(vk, vb, k * 3); + Vec3.scale(vi, Vec3.add(vi, Vec3.add(vi, vi, vj), vk), 1 / 3); + Vec3.fromArray(ni, nb, i * 3); + Vec3.fromArray(nj, nb, j * 3); + Vec3.fromArray(nk, nb, k * 3); + Vec3.scale(ni, Vec3.add(ni, Vec3.add(ni, ni, nj), nk), 1 / 3); + ChunkedArray.add3(vertex, vi[0], vi[1], vi[2]); + ChunkedArray.add3(normal, ni[0], ni[1], ni[2]); } function split2(i0: number, i1: number, i2: number, g0: number, g1: number) { - ++newTriangleCount + ++newTriangleCount; add(i0); addMid(i0, i1); addMid(i0, i2); - ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 2) - for (let j = 0; j < 3; ++j) ChunkedArray.add(group, g0) - newVertexCount += 3 + ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 2); + for (let j = 0; j < 3; ++j) ChunkedArray.add(group, g0); + newVertexCount += 3; - newTriangleCount += 2 + newTriangleCount += 2; add(i1); add(i2); addMid(i0, i1); addMid(i0, i2); - ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 3) - ChunkedArray.add3(index, newVertexCount, newVertexCount + 3, newVertexCount + 2) - for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g1) - newVertexCount += 4 + ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 3); + ChunkedArray.add3(index, newVertexCount, newVertexCount + 3, newVertexCount + 2); + for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g1); + newVertexCount += 4; } - let newVertexCount = vertexCount - let newTriangleCount = 0 + let newVertexCount = vertexCount; + let newTriangleCount = 0; if (splitTriangles) { for (let i = 0, il = triangleCount; i < il; ++i) { - const i0 = ib[i * 3], i1 = ib[i * 3 + 1], i2 = ib[i * 3 + 2] - const g0 = gb[i0], g1 = gb[i1], g2 = gb[i2] + const i0 = ib[i * 3], i1 = ib[i * 3 + 1], i2 = ib[i * 3 + 2]; + const g0 = gb[i0], g1 = gb[i1], g2 = gb[i2]; if (g0 === g1 && g0 === g2) { - ++newTriangleCount - ChunkedArray.add3(index, i0, i1, i2) + ++newTriangleCount; + ChunkedArray.add3(index, i0, i1, i2); } else if (g0 === g1) { - split2(i2, i0, i1, g2, g0) + split2(i2, i0, i1, g2, g0); } else if (g0 === g2) { - split2(i1, i2, i0, g1, g2) + split2(i1, i2, i0, g1, g2); } else if (g1 === g2) { - split2(i0, i1, i2, g0, g1) + split2(i0, i1, i2, g0, g1); } else { - newTriangleCount += 2 + newTriangleCount += 2; add(i0); addMid(i0, i1); addMid(i0, i2); addCenter(i0, i1, i2); - ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 3) - ChunkedArray.add3(index, newVertexCount, newVertexCount + 3, newVertexCount + 2) - for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g0) - newVertexCount += 4 + ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 3); + ChunkedArray.add3(index, newVertexCount, newVertexCount + 3, newVertexCount + 2); + for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g0); + newVertexCount += 4; - newTriangleCount += 2 + newTriangleCount += 2; add(i1); addMid(i1, i2); addMid(i1, i0); addCenter(i0, i1, i2); - ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 3) - ChunkedArray.add3(index, newVertexCount, newVertexCount + 3, newVertexCount + 2) - for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g1) - newVertexCount += 4 + ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 3); + ChunkedArray.add3(index, newVertexCount, newVertexCount + 3, newVertexCount + 2); + for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g1); + newVertexCount += 4; - newTriangleCount += 2 + newTriangleCount += 2; add(i2); addMid(i2, i1); addMid(i2, i0); addCenter(i0, i1, i2); - ChunkedArray.add3(index, newVertexCount + 3, newVertexCount + 1, newVertexCount) - ChunkedArray.add3(index, newVertexCount + 2, newVertexCount + 3, newVertexCount) - for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g2) - newVertexCount += 4 + ChunkedArray.add3(index, newVertexCount + 3, newVertexCount + 1, newVertexCount); + ChunkedArray.add3(index, newVertexCount + 2, newVertexCount + 3, newVertexCount); + for (let j = 0; j < 4; ++j) ChunkedArray.add(group, g2); + newVertexCount += 4; } } } else { for (let i = 0, il = triangleCount; i < il; ++i) { - const i0 = ib[i * 3], i1 = ib[i * 3 + 1], i2 = ib[i * 3 + 2] - const g0 = gb[i0], g1 = gb[i1], g2 = gb[i2] + const i0 = ib[i * 3], i1 = ib[i * 3 + 1], i2 = ib[i * 3 + 2]; + const g0 = gb[i0], g1 = gb[i1], g2 = gb[i2]; if (g0 !== g1 || g0 !== g2) { - ++newTriangleCount - add(i0); add(i1); add(i2) - ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 2) - const g = g1 === g2 ? g1 : g0 - for (let j = 0; j < 3; ++j) ChunkedArray.add(group, g) - newVertexCount += 3 + ++newTriangleCount; + add(i0); add(i1); add(i2); + ChunkedArray.add3(index, newVertexCount, newVertexCount + 1, newVertexCount + 2); + const g = g1 === g2 ? g1 : g0; + for (let j = 0; j < 3; ++j) ChunkedArray.add(group, g); + newVertexCount += 3; } else { - ++newTriangleCount - ChunkedArray.add3(index, i0, i1, i2) + ++newTriangleCount; + ChunkedArray.add3(index, i0, i1, i2); } } } - const newIb = ChunkedArray.compact(index) - const newVb = ChunkedArray.compact(vertex) - const newNb = ChunkedArray.compact(normal) - const newGb = ChunkedArray.compact(group) + const newIb = ChunkedArray.compact(index); + const newVb = ChunkedArray.compact(vertex); + const newNb = ChunkedArray.compact(normal); + const newGb = ChunkedArray.compact(group); - mesh.vertexCount = newVertexCount - mesh.triangleCount = newTriangleCount + mesh.vertexCount = newVertexCount; + mesh.triangleCount = newTriangleCount; - ValueCell.update(vertexBuffer, newVb) as ValueCell<Float32Array> - ValueCell.update(groupBuffer, newGb) as ValueCell<Float32Array> - ValueCell.update(indexBuffer, newIb) as ValueCell<Uint32Array> - ValueCell.update(normalBuffer, newNb) as ValueCell<Float32Array> + ValueCell.update(vertexBuffer, newVb) as ValueCell<Float32Array>; + ValueCell.update(groupBuffer, newGb) as ValueCell<Float32Array>; + ValueCell.update(indexBuffer, newIb) as ValueCell<Uint32Array>; + ValueCell.update(normalBuffer, newNb) as ValueCell<Float32Array>; - return mesh + return mesh; } // @@ -331,7 +331,7 @@ export namespace Mesh { flipSided: PD.Boolean(false, BaseGeometry.ShadingCategory), flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory), ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<Mesh, Params> = { @@ -343,23 +343,23 @@ export namespace Mesh { updateBoundingSphere, createRenderableState: BaseGeometry.createRenderableState, updateRenderableState: BaseGeometry.updateRenderableState - } + }; function createValues(mesh: Mesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): MeshValues { - const { instanceCount, groupCount } = locationIt + const { instanceCount, groupCount } = locationIt; if (instanceCount !== transform.instanceCount.ref.value) { - throw new Error('instanceCount values in TransformData and LocationIterator differ') + throw new Error('instanceCount values in TransformData and LocationIterator differ'); } - const color = createColors(locationIt, theme.color) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const color = createColors(locationIt, theme.color); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount } + const counts = { drawCount: mesh.triangleCount * 3, groupCount, instanceCount }; - const invariantBoundingSphere = Sphere3D.clone(mesh.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount) + const invariantBoundingSphere = Sphere3D.clone(mesh.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount); return { aPosition: mesh.vertexBuffer, @@ -379,32 +379,32 @@ export namespace Mesh { dFlatShaded: ValueCell.create(props.flatShaded), dFlipSided: ValueCell.create(props.flipSided), dIgnoreLight: ValueCell.create(props.ignoreLight), - } + }; } function createValuesSimple(mesh: Mesh, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(mesh, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(mesh, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: MeshValues, props: PD.Values<Params>) { - BaseGeometry.updateValues(values, props) - ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided) - ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded) - ValueCell.updateIfChanged(values.dFlipSided, props.flipSided) - ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight) + BaseGeometry.updateValues(values, props); + ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided); + ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded); + ValueCell.updateIfChanged(values.dFlipSided, props.flipSided); + ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight); } function updateBoundingSphere(values: MeshValues, mesh: Mesh) { - const invariantBoundingSphere = Sphere3D.clone(mesh.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const invariantBoundingSphere = Sphere3D.clone(mesh.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } } } diff --git a/src/mol-geo/geometry/overpaint-data.ts b/src/mol-geo/geometry/overpaint-data.ts index 08e753594ec85ced455e351a65efc360b316d7ac..86b461dce25786191b633336b1eb23694ff3efc5 100644 --- a/src/mol-geo/geometry/overpaint-data.ts +++ b/src/mol-geo/geometry/overpaint-data.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from '../../mol-util/value-cell' -import { Vec2 } from '../../mol-math/linear-algebra' +import { ValueCell } from '../../mol-util/value-cell'; +import { Vec2 } from '../../mol-math/linear-algebra'; import { TextureImage, createTextureImage } from '../../mol-gl/renderable/util'; import { Color } from '../../mol-util/color'; @@ -17,44 +17,44 @@ export type OverpaintData = { export function applyOverpaintColor(array: Uint8Array, start: number, end: number, color: Color, alpha: number) { for (let i = start; i < end; ++i) { - Color.toArray(color, array, i * 4) - array[i * 4 + 3] = alpha * 255 + Color.toArray(color, array, i * 4); + array[i * 4 + 3] = alpha * 255; } - return true + return true; } export function clearOverpaint(array: Uint8Array, start: number, end: number) { - array.fill(0, start * 4, end * 4) - return true + array.fill(0, start * 4, end * 4); + return true; } export function createOverpaint(count: number, overpaintData?: OverpaintData): OverpaintData { - const overpaint = createTextureImage(Math.max(1, count), 4, Uint8Array, overpaintData && overpaintData.tOverpaint.ref.value.array) + const overpaint = createTextureImage(Math.max(1, count), 4, Uint8Array, overpaintData && overpaintData.tOverpaint.ref.value.array); if (overpaintData) { - ValueCell.update(overpaintData.tOverpaint, overpaint) - ValueCell.update(overpaintData.uOverpaintTexDim, Vec2.create(overpaint.width, overpaint.height)) - ValueCell.update(overpaintData.dOverpaint, count > 0) - return overpaintData + ValueCell.update(overpaintData.tOverpaint, overpaint); + ValueCell.update(overpaintData.uOverpaintTexDim, Vec2.create(overpaint.width, overpaint.height)); + ValueCell.update(overpaintData.dOverpaint, count > 0); + return overpaintData; } else { return { tOverpaint: ValueCell.create(overpaint), uOverpaintTexDim: ValueCell.create(Vec2.create(overpaint.width, overpaint.height)), dOverpaint: ValueCell.create(count > 0), - } + }; } } -const emptyOverpaintTexture = { array: new Uint8Array(4), width: 1, height: 1 } +const emptyOverpaintTexture = { array: new Uint8Array(4), width: 1, height: 1 }; export function createEmptyOverpaint(overpaintData?: OverpaintData): OverpaintData { if (overpaintData) { - ValueCell.update(overpaintData.tOverpaint, emptyOverpaintTexture) - ValueCell.update(overpaintData.uOverpaintTexDim, Vec2.create(1, 1)) - return overpaintData + ValueCell.update(overpaintData.tOverpaint, emptyOverpaintTexture); + ValueCell.update(overpaintData.uOverpaintTexDim, Vec2.create(1, 1)); + return overpaintData; } else { return { tOverpaint: ValueCell.create(emptyOverpaintTexture), uOverpaintTexDim: ValueCell.create(Vec2.create(1, 1)), dOverpaint: ValueCell.create(false), - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/points/points-builder.ts b/src/mol-geo/geometry/points/points-builder.ts index 08c784c63d27e3a36dff6f6c3be8ac1326482bcf..dfcd7f746e2248258bb258f624694a04a0659219 100644 --- a/src/mol-geo/geometry/points/points-builder.ts +++ b/src/mol-geo/geometry/points/points-builder.ts @@ -23,10 +23,10 @@ export namespace PointsBuilder { ChunkedArray.add(groups, group); }, getPoints: () => { - const cb = ChunkedArray.compact(centers, true) as Float32Array - const gb = ChunkedArray.compact(groups, true) as Float32Array - return Points.create(cb, gb, centers.elementCount, points) + const cb = ChunkedArray.compact(centers, true) as Float32Array; + const gb = ChunkedArray.compact(groups, true) as Float32Array; + return Points.create(cb, gb, centers.elementCount, points); } - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/points/points.ts b/src/mol-geo/geometry/points/points.ts index 780ad475aaef7e19b799839e028aad5e7f9bacf3..4da859edf03b76637dfaf1b0720a22a93fd9ae70 100644 --- a/src/mol-geo/geometry/points/points.ts +++ b/src/mol-geo/geometry/points/points.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from '../../../mol-util' -import { Mat4 } from '../../../mol-math/linear-algebra' +import { ValueCell } from '../../../mol-util'; +import { Mat4 } from '../../../mol-math/linear-algebra'; import { transformPositionArray, GroupMapping, createGroupMapping} from '../../util'; import { GeometryUtils } from '../geometry'; import { createColors } from '../color-data'; @@ -49,28 +49,28 @@ export namespace Points { export function create(centers: Float32Array, groups: Float32Array, pointCount: number, points?: Points): Points { return points ? update(centers, groups, pointCount, points) : - fromArrays(centers, groups, pointCount) + fromArrays(centers, groups, pointCount); } export function createEmpty(points?: Points): Points { - const cb = points ? points.centerBuffer.ref.value : new Float32Array(0) - const gb = points ? points.groupBuffer.ref.value : new Float32Array(0) - return create(cb, gb, 0, points) + const cb = points ? points.centerBuffer.ref.value : new Float32Array(0); + const gb = points ? points.groupBuffer.ref.value : new Float32Array(0); + return create(cb, gb, 0, points); } function hashCode(points: Points) { return hashFnv32a([ points.pointCount, points.centerBuffer.ref.version, points.groupBuffer.ref.version, - ]) + ]); } function fromArrays(centers: Float32Array, groups: Float32Array, pointCount: number): Points { - const boundingSphere = Sphere3D() - let groupMapping: GroupMapping + const boundingSphere = Sphere3D(); + let groupMapping: GroupMapping; - let currentHash = -1 - let currentGroup = -1 + let currentHash = -1; + let currentGroup = -1; const points = { kind: 'points' as const, @@ -78,39 +78,39 @@ export namespace Points { centerBuffer: ValueCell.create(centers), groupBuffer: ValueCell.create(groups), get boundingSphere() { - const newHash = hashCode(points) + const newHash = hashCode(points); if (newHash !== currentHash) { - const b = calculateInvariantBoundingSphere(points.centerBuffer.ref.value, points.pointCount, 1) - Sphere3D.copy(boundingSphere, b) - currentHash = newHash + const b = calculateInvariantBoundingSphere(points.centerBuffer.ref.value, points.pointCount, 1); + Sphere3D.copy(boundingSphere, b); + currentHash = newHash; } - return boundingSphere + return boundingSphere; }, get groupMapping() { if (points.groupBuffer.ref.version !== currentGroup) { - groupMapping = createGroupMapping(points.groupBuffer.ref.value, points.pointCount) - currentGroup = points.groupBuffer.ref.version + groupMapping = createGroupMapping(points.groupBuffer.ref.value, points.pointCount); + currentGroup = points.groupBuffer.ref.version; } - return groupMapping + return groupMapping; }, setBoundingSphere(sphere: Sphere3D) { - Sphere3D.copy(boundingSphere, sphere) - currentHash = hashCode(points) + Sphere3D.copy(boundingSphere, sphere); + currentHash = hashCode(points); } - } - return points + }; + return points; } function update(centers: Float32Array, groups: Float32Array, pointCount: number, points: Points) { - points.pointCount = pointCount - ValueCell.update(points.centerBuffer, centers) - ValueCell.update(points.groupBuffer, groups) - return points + points.pointCount = pointCount; + ValueCell.update(points.centerBuffer, centers); + ValueCell.update(points.groupBuffer, groups); + return points; } export function transform(points: Points, t: Mat4) { - const c = points.centerBuffer.ref.value - transformPositionArray(t, c, 0, points.pointCount) + const c = points.centerBuffer.ref.value; + transformPositionArray(t, c, 0, points.pointCount); ValueCell.update(points.centerBuffer, c); } @@ -122,7 +122,7 @@ export namespace Points { pointSizeAttenuation: PD.Boolean(false), pointFilledCircle: PD.Boolean(false), pointEdgeBleach: PD.Numeric(0.2, { min: 0, max: 1, step: 0.05 }), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<Points, Params> = { @@ -134,20 +134,20 @@ export namespace Points { updateBoundingSphere, createRenderableState, updateRenderableState - } + }; function createValues(points: Points, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): PointsValues { - const { instanceCount, groupCount } = locationIt - const color = createColors(locationIt, theme.color) - const size = createSizes(locationIt, theme.size) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const { instanceCount, groupCount } = locationIt; + const color = createColors(locationIt, theme.color); + const size = createSizes(locationIt, theme.size); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: points.pointCount, groupCount, instanceCount } + const counts = { drawCount: points.pointCount, groupCount, instanceCount }; - const invariantBoundingSphere = Sphere3D.clone(points.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount) + const invariantBoundingSphere = Sphere3D.clone(points.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount); return { aPosition: points.centerBuffer, @@ -166,46 +166,46 @@ export namespace Points { dPointSizeAttenuation: ValueCell.create(props.pointSizeAttenuation), dPointFilledCircle: ValueCell.create(props.pointFilledCircle), uPointEdgeBleach: ValueCell.create(props.pointEdgeBleach), - } + }; } function createValuesSimple(points: Points, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(points, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(points, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: PointsValues, props: PD.Values<Params>) { - BaseGeometry.updateValues(values, props) - ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor) - ValueCell.updateIfChanged(values.dPointSizeAttenuation, props.pointSizeAttenuation) - ValueCell.updateIfChanged(values.dPointFilledCircle, props.pointFilledCircle) - ValueCell.updateIfChanged(values.uPointEdgeBleach, props.pointEdgeBleach) + BaseGeometry.updateValues(values, props); + ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor); + ValueCell.updateIfChanged(values.dPointSizeAttenuation, props.pointSizeAttenuation); + ValueCell.updateIfChanged(values.dPointFilledCircle, props.pointFilledCircle); + ValueCell.updateIfChanged(values.uPointEdgeBleach, props.pointEdgeBleach); } function updateBoundingSphere(values: PointsValues, points: Points) { - const invariantBoundingSphere = Sphere3D.clone(points.boundingSphere) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const invariantBoundingSphere = Sphere3D.clone(points.boundingSphere); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } } function createRenderableState(props: PD.Values<Params>): RenderableState { - const state = BaseGeometry.createRenderableState(props) - updateRenderableState(state, props) - return state + const state = BaseGeometry.createRenderableState(props); + updateRenderableState(state, props); + return state; } function updateRenderableState(state: RenderableState, props: PD.Values<Params>) { - BaseGeometry.updateRenderableState(state, props) + BaseGeometry.updateRenderableState(state, props); state.opaque = state.opaque && ( !props.pointFilledCircle || (props.pointFilledCircle && props.pointEdgeBleach === 0) - ) + ); } } \ No newline at end of file diff --git a/src/mol-geo/geometry/size-data.ts b/src/mol-geo/geometry/size-data.ts index 14815ece308554267191255e4bf816b57ce95f56..b1e99d125371af472d1f600ec2544c919733b9a8 100644 --- a/src/mol-geo/geometry/size-data.ts +++ b/src/mol-geo/geometry/size-data.ts @@ -24,114 +24,114 @@ export type SizeData = { export function createSizes(locationIt: LocationIterator, sizeTheme: SizeTheme<any>, sizeData?: SizeData): SizeData { switch (Geometry.getGranularity(locationIt, sizeTheme.granularity)) { - case 'uniform': return createUniformSize(locationIt, sizeTheme.size, sizeData) - case 'group': return createGroupSize(locationIt, sizeTheme.size, sizeData) - case 'groupInstance': return createGroupInstanceSize(locationIt, sizeTheme.size, sizeData) - case 'instance': return createInstanceSize(locationIt, sizeTheme.size, sizeData) + case 'uniform': return createUniformSize(locationIt, sizeTheme.size, sizeData); + case 'group': return createGroupSize(locationIt, sizeTheme.size, sizeData); + case 'groupInstance': return createGroupInstanceSize(locationIt, sizeTheme.size, sizeData); + case 'instance': return createInstanceSize(locationIt, sizeTheme.size, sizeData); } } export function getMaxSize(sizeData: SizeData): number { - const type = sizeData.dSizeType.ref.value as SizeType + const type = sizeData.dSizeType.ref.value as SizeType; switch (type) { case 'uniform': - return sizeData.uSize.ref.value + return sizeData.uSize.ref.value; case 'instance': case 'group': case 'groupInstance': - let maxSize = 0 - const array = sizeData.tSize.ref.value.array + let maxSize = 0; + const array = sizeData.tSize.ref.value.array; for (let i = 0, il = array.length; i < il; ++i) { - const value = decodeFloatLog(array[i] / 255) - if (maxSize < value) maxSize = value + const value = decodeFloatLog(array[i] / 255); + if (maxSize < value) maxSize = value; } - return maxSize + return maxSize; } } export type LocationSize = (location: Location) => number -const emptySizeTexture = { array: new Uint8Array(1), width: 1, height: 1 } +const emptySizeTexture = { array: new Uint8Array(1), width: 1, height: 1 }; function createEmptySizeTexture() { return { tSize: ValueCell.create(emptySizeTexture), uSizeTexDim: ValueCell.create(Vec2.create(1, 1)) - } + }; } export function createValueSize(value: number, sizeData?: SizeData): SizeData { if (sizeData) { - ValueCell.update(sizeData.uSize, value) + ValueCell.update(sizeData.uSize, value); if (sizeData.dSizeType.ref.value !== 'uniform') { - ValueCell.update(sizeData.dSizeType, 'uniform') + ValueCell.update(sizeData.dSizeType, 'uniform'); } - return sizeData + return sizeData; } else { return { uSize: ValueCell.create(value), ...createEmptySizeTexture(), dSizeType: ValueCell.create('uniform'), - } + }; } } /** Creates size uniform */ export function createUniformSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { - return createValueSize(sizeFn(NullLocation), sizeData) + return createValueSize(sizeFn(NullLocation), sizeData); } export function createTextureSize(sizes: TextureImage<Uint8Array>, type: SizeType, sizeData?: SizeData): SizeData { if (sizeData) { - ValueCell.update(sizeData.tSize, sizes) - ValueCell.update(sizeData.uSizeTexDim, Vec2.create(sizes.width, sizes.height)) + ValueCell.update(sizeData.tSize, sizes); + ValueCell.update(sizeData.uSizeTexDim, Vec2.create(sizes.width, sizes.height)); if (sizeData.dSizeType.ref.value !== type) { - ValueCell.update(sizeData.dSizeType, type) + ValueCell.update(sizeData.dSizeType, type); } - return sizeData + return sizeData; } else { return { uSize: ValueCell.create(0), tSize: ValueCell.create(sizes), uSizeTexDim: ValueCell.create(Vec2.create(sizes.width, sizes.height)), dSizeType: ValueCell.create(type), - } + }; } } /** Creates size texture with size for each instance/unit */ export function createInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { - const { instanceCount} = locationIt - const sizes = createTextureImage(Math.max(1, instanceCount), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array) - locationIt.reset() + const { instanceCount} = locationIt; + const sizes = createTextureImage(Math.max(1, instanceCount), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array); + locationIt.reset(); while (locationIt.hasNext && !locationIt.isNextNewInstance) { - const v = locationIt.move() - sizes.array[v.instanceIndex] = encodeFloatLog(sizeFn(v.location)) * 255 - locationIt.skipInstance() + const v = locationIt.move(); + sizes.array[v.instanceIndex] = encodeFloatLog(sizeFn(v.location)) * 255; + locationIt.skipInstance(); } - return createTextureSize(sizes, 'instance', sizeData) + return createTextureSize(sizes, 'instance', sizeData); } /** Creates size texture with size for each group (i.e. shared across instances/units) */ export function createGroupSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { - const { groupCount } = locationIt - const sizes = createTextureImage(Math.max(1, groupCount), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array) - locationIt.reset() + const { groupCount } = locationIt; + const sizes = createTextureImage(Math.max(1, groupCount), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array); + locationIt.reset(); while (locationIt.hasNext && !locationIt.isNextNewInstance) { - const v = locationIt.move() - sizes.array[v.groupIndex] = encodeFloatLog(sizeFn(v.location)) * 255 + const v = locationIt.move(); + sizes.array[v.groupIndex] = encodeFloatLog(sizeFn(v.location)) * 255; } - return createTextureSize(sizes, 'group', sizeData) + return createTextureSize(sizes, 'group', sizeData); } /** Creates size texture with size for each group in each instance (i.e. for each unit) */ export function createGroupInstanceSize(locationIt: LocationIterator, sizeFn: LocationSize, sizeData?: SizeData): SizeData { - const { groupCount, instanceCount } = locationIt - const count = instanceCount * groupCount - const sizes = createTextureImage(Math.max(1, count), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array) - locationIt.reset() + const { groupCount, instanceCount } = locationIt; + const count = instanceCount * groupCount; + const sizes = createTextureImage(Math.max(1, count), 1, Uint8Array, sizeData && sizeData.tSize.ref.value.array); + locationIt.reset(); while (locationIt.hasNext && !locationIt.isNextNewInstance) { - const v = locationIt.move() - sizes.array[v.index] = encodeFloatLog(sizeFn(v.location)) * 255 + const v = locationIt.move(); + sizes.array[v.index] = encodeFloatLog(sizeFn(v.location)) * 255; } - return createTextureSize(sizes, 'groupInstance', sizeData) + return createTextureSize(sizes, 'groupInstance', sizeData); } \ No newline at end of file diff --git a/src/mol-geo/geometry/spheres/spheres-builder.ts b/src/mol-geo/geometry/spheres/spheres-builder.ts index 127d48754190c6e2f3f84c9fff9fb4db03be9a66..c9e957eb8a66a6654039d80606a243469f39da70 100644 --- a/src/mol-geo/geometry/spheres/spheres-builder.ts +++ b/src/mol-geo/geometry/spheres/spheres-builder.ts @@ -12,12 +12,12 @@ const quadMapping = new Float32Array([ -1.0, -1.0, 1.0, 1.0, 1.0, -1.0 -]) +]); const quadIndices = new Uint16Array([ 0, 1, 2, 1, 3, 2 -]) +]); export interface SpheresBuilder { add(x: number, y: number, z: number, group: number): void @@ -26,8 +26,8 @@ export interface SpheresBuilder { export namespace SpheresBuilder { export function create(initialCount = 2048, chunkSize = 1024, spheres?: Spheres): SpheresBuilder { - initialCount *= 4 - chunkSize *= 4 + initialCount *= 4; + chunkSize *= 4; const centers = ChunkedArray.create(Float32Array, 3, chunkSize, spheres ? spheres.centerBuffer.ref.value : initialCount); const mappings = ChunkedArray.create(Float32Array, 2, chunkSize, spheres ? spheres.mappingBuffer.ref.value : initialCount); const indices = ChunkedArray.create(Uint32Array, 3, chunkSize / 2, spheres ? spheres.indexBuffer.ref.value : initialCount / 2); @@ -35,22 +35,22 @@ export namespace SpheresBuilder { return { add: (x: number, y: number, z: number, group: number) => { - const offset = centers.elementCount + const offset = centers.elementCount; for (let i = 0; i < 4; ++i) { - ChunkedArray.add3(centers, x, y, z) - ChunkedArray.add2(mappings, quadMapping[i * 2], quadMapping[i * 2 + 1]) - ChunkedArray.add(groups, group) + ChunkedArray.add3(centers, x, y, z); + ChunkedArray.add2(mappings, quadMapping[i * 2], quadMapping[i * 2 + 1]); + ChunkedArray.add(groups, group); } - ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]) - ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]) + ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]); + ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]); }, getSpheres: () => { - const cb = ChunkedArray.compact(centers, true) as Float32Array - const mb = ChunkedArray.compact(mappings, true) as Float32Array - const ib = ChunkedArray.compact(indices, true) as Uint32Array - const gb = ChunkedArray.compact(groups, true) as Float32Array - return Spheres.create(cb, mb, ib, gb, centers.elementCount / 4, spheres) + const cb = ChunkedArray.compact(centers, true) as Float32Array; + const mb = ChunkedArray.compact(mappings, true) as Float32Array; + const ib = ChunkedArray.compact(indices, true) as Uint32Array; + const gb = ChunkedArray.compact(groups, true) as Float32Array; + return Spheres.create(cb, mb, ib, gb, centers.elementCount / 4, spheres); } - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/spheres/spheres.ts b/src/mol-geo/geometry/spheres/spheres.ts index f7333fdb05bcf23e500aa55173b8be9c78bfba1b..85266d2756547da653b13b9a2704ae624ef30c5c 100644 --- a/src/mol-geo/geometry/spheres/spheres.ts +++ b/src/mol-geo/geometry/spheres/spheres.ts @@ -50,15 +50,15 @@ export namespace Spheres { export function create(centers: Float32Array, mappings: Float32Array, indices: Uint32Array, groups: Float32Array, sphereCount: number, spheres?: Spheres): Spheres { return spheres ? update(centers, mappings, indices, groups, sphereCount, spheres) : - fromArrays(centers, mappings, indices, groups, sphereCount) + fromArrays(centers, mappings, indices, groups, sphereCount); } export function createEmpty(spheres?: Spheres): Spheres { - const cb = spheres ? spheres.centerBuffer.ref.value : new Float32Array(0) - const mb = spheres ? spheres.mappingBuffer.ref.value : new Float32Array(0) - const ib = spheres ? spheres.indexBuffer.ref.value : new Uint32Array(0) - const gb = spheres ? spheres.groupBuffer.ref.value : new Float32Array(0) - return create(cb, mb, ib, gb, 0, spheres) + const cb = spheres ? spheres.centerBuffer.ref.value : new Float32Array(0); + const mb = spheres ? spheres.mappingBuffer.ref.value : new Float32Array(0); + const ib = spheres ? spheres.indexBuffer.ref.value : new Uint32Array(0); + const gb = spheres ? spheres.groupBuffer.ref.value : new Float32Array(0); + return create(cb, mb, ib, gb, 0, spheres); } function hashCode(spheres: Spheres) { @@ -66,16 +66,16 @@ export namespace Spheres { spheres.sphereCount, spheres.centerBuffer.ref.version, spheres.mappingBuffer.ref.version, spheres.indexBuffer.ref.version, spheres.groupBuffer.ref.version - ]) + ]); } function fromArrays(centers: Float32Array, mappings: Float32Array, indices: Uint32Array, groups: Float32Array, sphereCount: number): Spheres { - const boundingSphere = Sphere3D() - let groupMapping: GroupMapping + const boundingSphere = Sphere3D(); + let groupMapping: GroupMapping; - let currentHash = -1 - let currentGroup = -1 + let currentHash = -1; + let currentGroup = -1; const spheres = { kind: 'spheres' as const, @@ -85,36 +85,36 @@ export namespace Spheres { indexBuffer: ValueCell.create(indices), groupBuffer: ValueCell.create(groups), get boundingSphere() { - const newHash = hashCode(spheres) + const newHash = hashCode(spheres); if (newHash !== currentHash) { - const b = calculateInvariantBoundingSphere(spheres.centerBuffer.ref.value, spheres.sphereCount * 4, 4) - Sphere3D.copy(boundingSphere, b) - currentHash = newHash + const b = calculateInvariantBoundingSphere(spheres.centerBuffer.ref.value, spheres.sphereCount * 4, 4); + Sphere3D.copy(boundingSphere, b); + currentHash = newHash; } - return boundingSphere + return boundingSphere; }, get groupMapping() { if (spheres.groupBuffer.ref.version !== currentGroup) { - groupMapping = createGroupMapping(spheres.groupBuffer.ref.value, spheres.sphereCount, 4) - currentGroup = spheres.groupBuffer.ref.version + groupMapping = createGroupMapping(spheres.groupBuffer.ref.value, spheres.sphereCount, 4); + currentGroup = spheres.groupBuffer.ref.version; } - return groupMapping + return groupMapping; }, setBoundingSphere(sphere: Sphere3D) { - Sphere3D.copy(boundingSphere, sphere) - currentHash = hashCode(spheres) + Sphere3D.copy(boundingSphere, sphere); + currentHash = hashCode(spheres); } - } - return spheres + }; + return spheres; } function update(centers: Float32Array, mappings: Float32Array, indices: Uint32Array, groups: Float32Array, sphereCount: number, spheres: Spheres) { - spheres.sphereCount = sphereCount - ValueCell.update(spheres.centerBuffer, centers) - ValueCell.update(spheres.mappingBuffer, mappings) - ValueCell.update(spheres.indexBuffer, indices) - ValueCell.update(spheres.groupBuffer, groups) - return spheres + spheres.sphereCount = sphereCount; + ValueCell.update(spheres.centerBuffer, centers); + ValueCell.update(spheres.mappingBuffer, mappings); + ValueCell.update(spheres.indexBuffer, indices); + ValueCell.update(spheres.groupBuffer, groups); + return spheres; } export const Params = { @@ -122,7 +122,7 @@ export namespace Spheres { sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }), doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo), ignoreLight: PD.Boolean(false, BaseGeometry.ShadingCategory), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<Spheres, Params> = { @@ -134,25 +134,25 @@ export namespace Spheres { updateBoundingSphere, createRenderableState: BaseGeometry.createRenderableState, updateRenderableState: BaseGeometry.updateRenderableState - } + }; function createValues(spheres: Spheres, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): SpheresValues { - const { instanceCount, groupCount } = locationIt + const { instanceCount, groupCount } = locationIt; if (instanceCount !== transform.instanceCount.ref.value) { - throw new Error('instanceCount values in TransformData and LocationIterator differ') + throw new Error('instanceCount values in TransformData and LocationIterator differ'); } - const color = createColors(locationIt, theme.color) - const size = createSizes(locationIt, theme.size) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const color = createColors(locationIt, theme.color); + const size = createSizes(locationIt, theme.size); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: spheres.sphereCount * 2 * 3, groupCount, instanceCount } + const counts = { drawCount: spheres.sphereCount * 2 * 3, groupCount, instanceCount }; - const padding = getMaxSize(size) - const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), spheres.boundingSphere, padding) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount) + const padding = getMaxSize(size); + const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), spheres.boundingSphere, padding); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount); return { aPosition: spheres.centerBuffer, @@ -174,33 +174,33 @@ export namespace Spheres { uSizeFactor: ValueCell.create(props.sizeFactor), dDoubleSided: ValueCell.create(props.doubleSided), dIgnoreLight: ValueCell.create(props.ignoreLight), - } + }; } function createValuesSimple(spheres: Spheres, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(spheres, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(spheres, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: SpheresValues, props: PD.Values<Params>) { - BaseGeometry.updateValues(values, props) - ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor) - ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided) - ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight) + BaseGeometry.updateValues(values, props); + ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor); + ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided); + ValueCell.updateIfChanged(values.dIgnoreLight, props.ignoreLight); } function updateBoundingSphere(values: SpheresValues, spheres: Spheres) { - const padding = getMaxSize(values) - const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), spheres.boundingSphere, padding) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const padding = getMaxSize(values); + const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), spheres.boundingSphere, padding); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } - ValueCell.update(values.padding, padding) + ValueCell.update(values.padding, padding); } } \ No newline at end of file diff --git a/src/mol-geo/geometry/text/font-atlas.ts b/src/mol-geo/geometry/text/font-atlas.ts index 44e2b05474113fb1b96b309d7f10e062a432b448..a650a9e0b8a1728db504556a81637057b999f87b 100644 --- a/src/mol-geo/geometry/text/font-atlas.ts +++ b/src/mol-geo/geometry/text/font-atlas.ts @@ -8,14 +8,14 @@ import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { edt } from '../../../mol-math/geometry/distance-transform'; import { createTextureImage, TextureImage } from '../../../mol-gl/renderable/util'; -const TextAtlasCache: { [k: string]: FontAtlas } = {} +const TextAtlasCache: { [k: string]: FontAtlas } = {}; export function getFontAtlas (props: Partial<FontAtlasProps>) { - const hash = JSON.stringify(props) + const hash = JSON.stringify(props); if (TextAtlasCache[hash] === undefined) { - TextAtlasCache[hash] = new FontAtlas(props) + TextAtlasCache[hash] = new FontAtlas(props); } - return TextAtlasCache[hash] + return TextAtlasCache[hash]; } export type FontFamily = 'sans-serif' | 'monospace' | 'serif' | 'cursive' @@ -29,7 +29,7 @@ export const FontAtlasParams = { fontStyle: PD.Select('normal', [['normal', 'Normal'], ['italic', 'Italic'], ['oblique', 'Oblique']] as [FontStyle, string][]), fontVariant: PD.Select('normal', [['normal', 'Normal'], ['small-caps', 'Small Caps']] as [FontVariant, string][]), fontWeight: PD.Select('normal', [['normal', 'Normal'], ['bold', 'Bold']] as [FontWeight, string][]), -} +}; export type FontAtlasParams = typeof FontAtlasParams export type FontAtlasProps = PD.Values<FontAtlasParams> @@ -70,109 +70,109 @@ export class FontAtlas { private readonly middle: number constructor (props: Partial<FontAtlasProps> = {}) { - const p = { ...PD.getDefaultValues(FontAtlasParams), ...props } - this.props = p + const p = { ...PD.getDefaultValues(FontAtlasParams), ...props }; + this.props = p; // create measurements - const fontSize = 32 * (p.fontQuality + 1) - this.buffer = fontSize / 8 - this.radius = fontSize / 3 - this.lineHeight = Math.round(fontSize + 2 * this.buffer + this.radius) - this.maxWidth = Math.round(this.lineHeight * 0.75) + const fontSize = 32 * (p.fontQuality + 1); + this.buffer = fontSize / 8; + this.radius = fontSize / 3; + this.lineHeight = Math.round(fontSize + 2 * this.buffer + this.radius); + this.maxWidth = Math.round(this.lineHeight * 0.75); // create texture (for ~350 characters) - this.texture = createTextureImage(350 * this.lineHeight * this.maxWidth, 1, Uint8Array) + this.texture = createTextureImage(350 * this.lineHeight * this.maxWidth, 1, Uint8Array); // prepare scratch canvas - this.scratchCanvas = document.createElement('canvas') - this.scratchCanvas.width = this.maxWidth - this.scratchCanvas.height = this.lineHeight + this.scratchCanvas = document.createElement('canvas'); + this.scratchCanvas.width = this.maxWidth; + this.scratchCanvas.height = this.lineHeight; - this.scratchContext = this.scratchCanvas.getContext('2d')! - this.scratchContext.font = `${p.fontStyle} ${p.fontVariant} ${p.fontWeight} ${fontSize}px ${p.fontFamily}` - this.scratchContext.fillStyle = 'black' - this.scratchContext.textBaseline = 'middle' + this.scratchContext = this.scratchCanvas.getContext('2d')!; + this.scratchContext.font = `${p.fontStyle} ${p.fontVariant} ${p.fontWeight} ${fontSize}px ${p.fontFamily}`; + this.scratchContext.fillStyle = 'black'; + this.scratchContext.textBaseline = 'middle'; // SDF scratch values - this.scratchData = new Uint8Array(this.lineHeight * this.maxWidth) + this.scratchData = new Uint8Array(this.lineHeight * this.maxWidth); // temporary arrays for the distance transform - this.gridOuter = new Float64Array(this.lineHeight * this.maxWidth) - this.gridInner = new Float64Array(this.lineHeight * this.maxWidth) - this.f = new Float64Array(Math.max(this.lineHeight, this.maxWidth)) - this.d = new Float64Array(Math.max(this.lineHeight, this.maxWidth)) - this.z = new Float64Array(Math.max(this.lineHeight, this.maxWidth) + 1) - this.v = new Int16Array(Math.max(this.lineHeight, this.maxWidth)) + this.gridOuter = new Float64Array(this.lineHeight * this.maxWidth); + this.gridInner = new Float64Array(this.lineHeight * this.maxWidth); + this.f = new Float64Array(Math.max(this.lineHeight, this.maxWidth)); + this.d = new Float64Array(Math.max(this.lineHeight, this.maxWidth)); + this.z = new Float64Array(Math.max(this.lineHeight, this.maxWidth) + 1); + this.v = new Int16Array(Math.max(this.lineHeight, this.maxWidth)); - this.middle = Math.ceil(this.lineHeight / 2) + this.middle = Math.ceil(this.lineHeight / 2); // replacement Character - this.placeholder = this.get(String.fromCharCode(0xFFFD)) + this.placeholder = this.get(String.fromCharCode(0xFFFD)); } get (char: string) { if (this.mapped[char] === undefined) { - this.draw(char) + this.draw(char); - const { array, width, height } = this.texture - const data = this.scratchData + const { array, width, height } = this.texture; + const data = this.scratchData; if (this.currentX + this.scratchW > width) { - this.currentX = 0 - this.currentY += this.scratchH + this.currentX = 0; + this.currentY += this.scratchH; } if (this.currentY + this.scratchH > height) { - console.warn('canvas to small') - return this.placeholder + console.warn('canvas to small'); + return this.placeholder; } this.mapped[char] = { x: this.currentX, y: this.currentY, w: this.scratchW, h: this.scratchH, nw: this.scratchW / this.lineHeight, nh: this.scratchH / this.lineHeight - } + }; for (let y = 0; y < this.scratchH; ++y) { for (let x = 0; x < this.scratchW; ++x) { - array[width * (this.currentY + y) + this.currentX + x] = data[y * this.scratchW + x] + array[width * (this.currentY + y) + this.currentX + x] = data[y * this.scratchW + x]; } } - this.currentX += this.scratchW + this.currentX += this.scratchW; } - return this.mapped[char] + return this.mapped[char]; } draw (char: string) { - const h = this.lineHeight - const ctx = this.scratchContext - const data = this.scratchData + const h = this.lineHeight; + const ctx = this.scratchContext; + const data = this.scratchData; // measure text - const m = ctx.measureText(char) - const w = Math.min(this.maxWidth, Math.ceil(m.width + 2 * this.buffer)) - const n = w * h + const m = ctx.measureText(char); + const w = Math.min(this.maxWidth, Math.ceil(m.width + 2 * this.buffer)); + const n = w * h; - ctx.clearRect(0, 0, w, h) // clear scratch area - ctx.fillText(char, this.buffer, this.middle) // draw text - const imageData = ctx.getImageData(0, 0, w, h) + ctx.clearRect(0, 0, w, h); // clear scratch area + ctx.fillText(char, this.buffer, this.middle); // draw text + const imageData = ctx.getImageData(0, 0, w, h); for (let i = 0; i < n; i++) { - const a = imageData.data[i * 4 + 3] / 255 // alpha value - this.gridOuter[i] = a === 1 ? 0 : a === 0 ? Number.MAX_SAFE_INTEGER : Math.pow(Math.max(0, 0.5 - a), 2) - this.gridInner[i] = a === 1 ? Number.MAX_SAFE_INTEGER : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2) + const a = imageData.data[i * 4 + 3] / 255; // alpha value + this.gridOuter[i] = a === 1 ? 0 : a === 0 ? Number.MAX_SAFE_INTEGER : Math.pow(Math.max(0, 0.5 - a), 2); + this.gridInner[i] = a === 1 ? Number.MAX_SAFE_INTEGER : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2); } - edt(this.gridOuter, w, h, this.f, this.d, this.v, this.z) - edt(this.gridInner, w, h, this.f, this.d, this.v, this.z) + edt(this.gridOuter, w, h, this.f, this.d, this.v, this.z); + edt(this.gridInner, w, h, this.f, this.d, this.v, this.z); for (let i = 0; i < n; i++) { const d = this.gridOuter[i] - this.gridInner[i]; - data[i] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this.radius + this.cutoff)))) + data[i] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this.radius + this.cutoff)))); } - this.scratchW = w - this.scratchH = h + this.scratchW = w; + this.scratchH = h; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/text/text-builder.ts b/src/mol-geo/geometry/text/text-builder.ts index a5932c03840562668f5967b05a86b464151a63ce..c0b1f0c8d75b65664bb6d1a4450efbc7765ce8e5 100644 --- a/src/mol-geo/geometry/text/text-builder.ts +++ b/src/mol-geo/geometry/text/text-builder.ts @@ -12,7 +12,7 @@ import { getFontAtlas } from './font-atlas'; const quadIndices = new Uint16Array([ 0, 1, 2, 1, 3, 2 -]) +]); export interface TextBuilder { add(str: string, x: number, y: number, z: number, depth: number, scale: number, group: number): void @@ -21,8 +21,8 @@ export interface TextBuilder { export namespace TextBuilder { export function create(props: Partial<PD.Values<Text.Params>> = {}, initialCount = 2048, chunkSize = 1024, text?: Text): TextBuilder { - initialCount *= 2 - chunkSize *= 2 + initialCount *= 2; + chunkSize *= 2; const centers = ChunkedArray.create(Float32Array, 3, chunkSize, text ? text.centerBuffer.ref.value : initialCount); const mappings = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.mappingBuffer.ref.value : initialCount); const depths = ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.depthBuffer.ref.value : initialCount); @@ -30,267 +30,267 @@ export namespace TextBuilder { const groups = ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.groupBuffer.ref.value : initialCount); const tcoords = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.tcoordBuffer.ref.value : initialCount); - const p = { ...PD.getDefaultValues(Text.Params), ...props } - const { attachment, background, backgroundMargin, tether, tetherLength, tetherBaseWidth } = p + const p = { ...PD.getDefaultValues(Text.Params), ...props }; + const { attachment, background, backgroundMargin, tether, tetherLength, tetherBaseWidth } = p; - const fontAtlas = getFontAtlas(p) - const margin = (1 / 2.5) * backgroundMargin - const outline = fontAtlas.buffer / fontAtlas.lineHeight + const fontAtlas = getFontAtlas(p); + const margin = (1 / 2.5) * backgroundMargin; + const outline = fontAtlas.buffer / fontAtlas.lineHeight; const add = (x: number, y: number, z: number, depth: number, group: number) => { ChunkedArray.add3(centers, x, y, z); ChunkedArray.add(depths, depth); ChunkedArray.add(groups, group); - } + }; return { add: (str: string, x: number, y: number, z: number, depth: number, scale: number, group: number) => { - let bWidth = 0 - const nChar = str.length + let bWidth = 0; + const nChar = str.length; // calculate width for (let iChar = 0; iChar < nChar; ++iChar) { - const c = fontAtlas.get(str[iChar]) - bWidth += c.nw - 2 * outline + const c = fontAtlas.get(str[iChar]); + bWidth += c.nw - 2 * outline; } - const bHeight = 1 / 1.25 + const bHeight = 1 / 1.25; // attachment - let yShift: number, xShift: number + let yShift: number, xShift: number; // vertical if (attachment.startsWith('top')) { - yShift = bHeight + yShift = bHeight; } else if (attachment.startsWith('middle')) { - yShift = bHeight / 2 + yShift = bHeight / 2; } else { - yShift = 0 // "bottom" + yShift = 0; // "bottom" } // horizontal if (attachment.endsWith('right')) { - xShift = bWidth + xShift = bWidth; } else if (attachment.endsWith('center')) { - xShift = bWidth / 2 + xShift = bWidth / 2; } else { - xShift = 0 // "left" + xShift = 0; // "left" } if (tether) { switch (attachment) { case 'bottom-left': - xShift -= tetherLength / 2 + margin + 0.1 - yShift -= tetherLength / 2 + margin - break + xShift -= tetherLength / 2 + margin + 0.1; + yShift -= tetherLength / 2 + margin; + break; case 'bottom-center': - yShift -= tetherLength + margin - break + yShift -= tetherLength + margin; + break; case 'bottom-right': - xShift += tetherLength / 2 + margin + 0.1 - yShift -= tetherLength / 2 + margin - break + xShift += tetherLength / 2 + margin + 0.1; + yShift -= tetherLength / 2 + margin; + break; case 'middle-left': - xShift -= tetherLength + margin + 0.1 - break + xShift -= tetherLength + margin + 0.1; + break; case 'middle-center': - break + break; case 'middle-right': - xShift += tetherLength + margin + 0.1 - break + xShift += tetherLength + margin + 0.1; + break; case 'top-left': - xShift -= tetherLength / 2 + margin + 0.1 - yShift += tetherLength / 2 + margin - break + xShift -= tetherLength / 2 + margin + 0.1; + yShift += tetherLength / 2 + margin; + break; case 'top-center': - yShift += tetherLength + margin - break + yShift += tetherLength + margin; + break; case 'top-right': - xShift += tetherLength / 2 + margin + 0.1 - yShift += tetherLength / 2 + margin - break + xShift += tetherLength / 2 + margin + 0.1; + yShift += tetherLength / 2 + margin; + break; } } - const xLeft = (-xShift - margin - 0.1) * scale - const xRight = (bWidth - xShift + margin + 0.1) * scale - const yTop = (bHeight - yShift + margin) * scale - const yBottom = (-yShift - margin) * scale + const xLeft = (-xShift - margin - 0.1) * scale; + const xRight = (bWidth - xShift + margin + 0.1) * scale; + const yTop = (bHeight - yShift + margin) * scale; + const yBottom = (-yShift - margin) * scale; // background if (background) { - ChunkedArray.add2(mappings, xLeft, yTop) // top left - ChunkedArray.add2(mappings, xLeft, yBottom) // bottom left - ChunkedArray.add2(mappings, xRight, yTop) // top right - ChunkedArray.add2(mappings, xRight, yBottom) // bottom right + ChunkedArray.add2(mappings, xLeft, yTop); // top left + ChunkedArray.add2(mappings, xLeft, yBottom); // bottom left + ChunkedArray.add2(mappings, xRight, yTop); // top right + ChunkedArray.add2(mappings, xRight, yBottom); // bottom right - const offset = centers.elementCount + const offset = centers.elementCount; for (let i = 0; i < 4; ++i) { - ChunkedArray.add2(tcoords, 10, 10) - add(x, y, z, depth, group) + ChunkedArray.add2(tcoords, 10, 10); + add(x, y, z, depth, group); } - ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]) - ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]) + ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]); + ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]); } if (tether) { - let xTip: number, yTip: number - let xBaseA: number, yBaseA: number - let xBaseB: number, yBaseB: number - let xBaseCenter: number, yBaseCenter: number + let xTip: number, yTip: number; + let xBaseA: number, yBaseA: number; + let xBaseB: number, yBaseB: number; + let xBaseCenter: number, yBaseCenter: number; - const scaledTetherLength = tetherLength * scale - const scaledTetherBaseWidth = tetherBaseWidth * scale + const scaledTetherLength = tetherLength * scale; + const scaledTetherBaseWidth = tetherBaseWidth * scale; switch (attachment) { case 'bottom-left': - xTip = xLeft - scaledTetherLength / 2 - xBaseA = xLeft + scaledTetherBaseWidth / 2 - xBaseB = xLeft - xBaseCenter = xLeft - yTip = yBottom - scaledTetherLength / 2 - yBaseA = yBottom - yBaseB = yBottom + scaledTetherBaseWidth / 2 - yBaseCenter = yBottom - break + xTip = xLeft - scaledTetherLength / 2; + xBaseA = xLeft + scaledTetherBaseWidth / 2; + xBaseB = xLeft; + xBaseCenter = xLeft; + yTip = yBottom - scaledTetherLength / 2; + yBaseA = yBottom; + yBaseB = yBottom + scaledTetherBaseWidth / 2; + yBaseCenter = yBottom; + break; case 'bottom-center': - xTip = 0 - xBaseA = scaledTetherBaseWidth / 2 - xBaseB = -scaledTetherBaseWidth / 2 - xBaseCenter = 0 - yTip = yBottom - scaledTetherLength - yBaseA = yBottom - yBaseB = yBottom - yBaseCenter = yBottom - break + xTip = 0; + xBaseA = scaledTetherBaseWidth / 2; + xBaseB = -scaledTetherBaseWidth / 2; + xBaseCenter = 0; + yTip = yBottom - scaledTetherLength; + yBaseA = yBottom; + yBaseB = yBottom; + yBaseCenter = yBottom; + break; case 'bottom-right': - xTip = xRight + scaledTetherLength / 2 - xBaseA = xRight - xBaseB = xRight - scaledTetherBaseWidth / 2 - xBaseCenter = xRight - yTip = yBottom - scaledTetherLength / 2 - yBaseA = yBottom + scaledTetherBaseWidth / 2 - yBaseB = yBottom - yBaseCenter = yBottom - break + xTip = xRight + scaledTetherLength / 2; + xBaseA = xRight; + xBaseB = xRight - scaledTetherBaseWidth / 2; + xBaseCenter = xRight; + yTip = yBottom - scaledTetherLength / 2; + yBaseA = yBottom + scaledTetherBaseWidth / 2; + yBaseB = yBottom; + yBaseCenter = yBottom; + break; case 'middle-left': - xTip = xLeft - scaledTetherLength - xBaseA = xLeft - xBaseB = xLeft - xBaseCenter = xLeft - yTip = 0 - yBaseA = -scaledTetherBaseWidth / 2 - yBaseB = scaledTetherBaseWidth / 2 - yBaseCenter = 0 - break + xTip = xLeft - scaledTetherLength; + xBaseA = xLeft; + xBaseB = xLeft; + xBaseCenter = xLeft; + yTip = 0; + yBaseA = -scaledTetherBaseWidth / 2; + yBaseB = scaledTetherBaseWidth / 2; + yBaseCenter = 0; + break; case 'middle-center': - xTip = 0 - xBaseA = 0 - xBaseB = 0 - xBaseCenter = 0 - yTip = 0 - yBaseA = 0 - yBaseB = 0 - yBaseCenter = 0 - break + xTip = 0; + xBaseA = 0; + xBaseB = 0; + xBaseCenter = 0; + yTip = 0; + yBaseA = 0; + yBaseB = 0; + yBaseCenter = 0; + break; case 'middle-right': - xTip = xRight + scaledTetherLength - xBaseA = xRight - xBaseB = xRight - xBaseCenter = xRight - yTip = 0 - yBaseA = scaledTetherBaseWidth / 2 - yBaseB = -scaledTetherBaseWidth / 2 - yBaseCenter = 0 - break + xTip = xRight + scaledTetherLength; + xBaseA = xRight; + xBaseB = xRight; + xBaseCenter = xRight; + yTip = 0; + yBaseA = scaledTetherBaseWidth / 2; + yBaseB = -scaledTetherBaseWidth / 2; + yBaseCenter = 0; + break; case 'top-left': - xTip = xLeft - scaledTetherLength / 2 - xBaseA = xLeft + scaledTetherBaseWidth / 2 - xBaseB = xLeft - xBaseCenter = xLeft - yTip = yTop + scaledTetherLength / 2 - yBaseA = yTop - yBaseB = yTop - scaledTetherBaseWidth / 2 - yBaseCenter = yTop - break + xTip = xLeft - scaledTetherLength / 2; + xBaseA = xLeft + scaledTetherBaseWidth / 2; + xBaseB = xLeft; + xBaseCenter = xLeft; + yTip = yTop + scaledTetherLength / 2; + yBaseA = yTop; + yBaseB = yTop - scaledTetherBaseWidth / 2; + yBaseCenter = yTop; + break; case 'top-center': - xTip = 0 - xBaseA = scaledTetherBaseWidth / 2 - xBaseB = -scaledTetherBaseWidth / 2 - xBaseCenter = 0 - yTip = yTop + scaledTetherLength - yBaseA = yTop - yBaseB = yTop - yBaseCenter = yTop - break + xTip = 0; + xBaseA = scaledTetherBaseWidth / 2; + xBaseB = -scaledTetherBaseWidth / 2; + xBaseCenter = 0; + yTip = yTop + scaledTetherLength; + yBaseA = yTop; + yBaseB = yTop; + yBaseCenter = yTop; + break; case 'top-right': - xTip = xRight + scaledTetherLength / 2 - xBaseA = xRight - xBaseB = xRight - scaledTetherBaseWidth / 2 - xBaseCenter = xRight - yTip = yTop + scaledTetherLength / 2 - yBaseA = yTop - scaledTetherBaseWidth / 2 - yBaseB = yTop - yBaseCenter = yTop - break + xTip = xRight + scaledTetherLength / 2; + xBaseA = xRight; + xBaseB = xRight - scaledTetherBaseWidth / 2; + xBaseCenter = xRight; + yTip = yTop + scaledTetherLength / 2; + yBaseA = yTop - scaledTetherBaseWidth / 2; + yBaseB = yTop; + yBaseCenter = yTop; + break; default: - throw new Error('unsupported attachment') + throw new Error('unsupported attachment'); } - ChunkedArray.add2(mappings, xTip, yTip) // tip - ChunkedArray.add2(mappings, xBaseA, yBaseA) // base A - ChunkedArray.add2(mappings, xBaseB, yBaseB) // base B - ChunkedArray.add2(mappings, xBaseCenter, yBaseCenter) // base center + ChunkedArray.add2(mappings, xTip, yTip); // tip + ChunkedArray.add2(mappings, xBaseA, yBaseA); // base A + ChunkedArray.add2(mappings, xBaseB, yBaseB); // base B + ChunkedArray.add2(mappings, xBaseCenter, yBaseCenter); // base center - const offset = centers.elementCount + const offset = centers.elementCount; for (let i = 0; i < 4; ++i) { - ChunkedArray.add2(tcoords, 10, 10) - add(x, y, z, depth, group) + ChunkedArray.add2(tcoords, 10, 10); + add(x, y, z, depth, group); } - ChunkedArray.add3(indices, offset, offset + 1, offset + 3) - ChunkedArray.add3(indices, offset, offset + 3, offset + 2) + ChunkedArray.add3(indices, offset, offset + 1, offset + 3); + ChunkedArray.add3(indices, offset, offset + 3, offset + 2); } - xShift += outline - yShift += outline - let xadvance = 0 + xShift += outline; + yShift += outline; + let xadvance = 0; for (let iChar = 0; iChar < nChar; ++iChar) { - const c = fontAtlas.get(str[iChar]) + const c = fontAtlas.get(str[iChar]); - const left = (xadvance - xShift) * scale - const right = (xadvance + c.nw - xShift) * scale - const top = (c.nh - yShift) * scale - const bottom = (-yShift) * scale + const left = (xadvance - xShift) * scale; + const right = (xadvance + c.nw - xShift) * scale; + const top = (c.nh - yShift) * scale; + const bottom = (-yShift) * scale; - ChunkedArray.add2(mappings, left, top) - ChunkedArray.add2(mappings, left, bottom) - ChunkedArray.add2(mappings, right, top) - ChunkedArray.add2(mappings, right, bottom) + ChunkedArray.add2(mappings, left, top); + ChunkedArray.add2(mappings, left, bottom); + ChunkedArray.add2(mappings, right, top); + ChunkedArray.add2(mappings, right, bottom); - const texWidth = fontAtlas.texture.width - const texHeight = fontAtlas.texture.height + const texWidth = fontAtlas.texture.width; + const texHeight = fontAtlas.texture.height; - ChunkedArray.add2(tcoords, c.x / texWidth, c.y / texHeight) // top left - ChunkedArray.add2(tcoords, c.x / texWidth, (c.y + c.h) / texHeight) // bottom left - ChunkedArray.add2(tcoords, (c.x + c.w) / texWidth, c.y / texHeight) // top right - ChunkedArray.add2(tcoords, (c.x + c.w) / texWidth, (c.y + c.h) / texHeight) // bottom right + ChunkedArray.add2(tcoords, c.x / texWidth, c.y / texHeight); // top left + ChunkedArray.add2(tcoords, c.x / texWidth, (c.y + c.h) / texHeight); // bottom left + ChunkedArray.add2(tcoords, (c.x + c.w) / texWidth, c.y / texHeight); // top right + ChunkedArray.add2(tcoords, (c.x + c.w) / texWidth, (c.y + c.h) / texHeight); // bottom right - xadvance += c.nw - 2 * outline + xadvance += c.nw - 2 * outline; - const offset = centers.elementCount - for (let i = 0; i < 4; ++i) add(x, y, z, depth, group) - ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]) - ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]) + const offset = centers.elementCount; + for (let i = 0; i < 4; ++i) add(x, y, z, depth, group); + ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2]); + ChunkedArray.add3(indices, offset + quadIndices[3], offset + quadIndices[4], offset + quadIndices[5]); } }, getText: () => { - const ft = fontAtlas.texture - const cb = ChunkedArray.compact(centers, true) as Float32Array - const mb = ChunkedArray.compact(mappings, true) as Float32Array - const db = ChunkedArray.compact(depths, true) as Float32Array - const ib = ChunkedArray.compact(indices, true) as Uint32Array - const gb = ChunkedArray.compact(groups, true) as Float32Array - const tb = ChunkedArray.compact(tcoords, true) as Float32Array - return Text.create(ft, cb, mb, db, ib, gb, tb, indices.elementCount / 2, text) + const ft = fontAtlas.texture; + const cb = ChunkedArray.compact(centers, true) as Float32Array; + const mb = ChunkedArray.compact(mappings, true) as Float32Array; + const db = ChunkedArray.compact(depths, true) as Float32Array; + const ib = ChunkedArray.compact(indices, true) as Uint32Array; + const gb = ChunkedArray.compact(groups, true) as Float32Array; + const tb = ChunkedArray.compact(tcoords, true) as Float32Array; + return Text.create(ft, cb, mb, db, ib, gb, tb, indices.elementCount / 2, text); } - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/geometry/text/text.ts b/src/mol-geo/geometry/text/text.ts index bc958ffdf21c3fe856cc3bfbd10ec65927530b8e..0f8813d7bb7a9161b7a8e50c657fe7b4e8911856 100644 --- a/src/mol-geo/geometry/text/text.ts +++ b/src/mol-geo/geometry/text/text.ts @@ -70,18 +70,18 @@ export namespace Text { export function create(fontTexture: TextureImage<Uint8Array>, centers: Float32Array, mappings: Float32Array, depths: Float32Array, indices: Uint32Array, groups: Float32Array, tcoords: Float32Array, charCount: number, text?: Text): Text { return text ? update(fontTexture, centers, mappings, depths, indices, groups, tcoords, charCount, text) : - fromData(fontTexture, centers, mappings, depths, indices, groups, tcoords, charCount) + fromData(fontTexture, centers, mappings, depths, indices, groups, tcoords, charCount); } export function createEmpty(text?: Text): Text { - const ft = text ? text.fontTexture.ref.value : createTextureImage(0, 1, Uint8Array) - const cb = text ? text.centerBuffer.ref.value : new Float32Array(0) - const mb = text ? text.mappingBuffer.ref.value : new Float32Array(0) - const db = text ? text.depthBuffer.ref.value : new Float32Array(0) - const ib = text ? text.indexBuffer.ref.value : new Uint32Array(0) - const gb = text ? text.groupBuffer.ref.value : new Float32Array(0) - const tb = text ? text.tcoordBuffer.ref.value : new Float32Array(0) - return create(ft, cb, mb, db, ib, gb, tb, 0, text) + const ft = text ? text.fontTexture.ref.value : createTextureImage(0, 1, Uint8Array); + const cb = text ? text.centerBuffer.ref.value : new Float32Array(0); + const mb = text ? text.mappingBuffer.ref.value : new Float32Array(0); + const db = text ? text.depthBuffer.ref.value : new Float32Array(0); + const ib = text ? text.indexBuffer.ref.value : new Uint32Array(0); + const gb = text ? text.groupBuffer.ref.value : new Float32Array(0); + const tb = text ? text.tcoordBuffer.ref.value : new Float32Array(0); + return create(ft, cb, mb, db, ib, gb, tb, 0, text); } function hashCode(text: Text) { @@ -90,16 +90,16 @@ export namespace Text { text.centerBuffer.ref.version, text.mappingBuffer.ref.version, text.depthBuffer.ref.version, text.indexBuffer.ref.version, text.groupBuffer.ref.version, text.tcoordBuffer.ref.version - ]) + ]); } function fromData(fontTexture: TextureImage<Uint8Array>, centers: Float32Array, mappings: Float32Array, depths: Float32Array, indices: Uint32Array, groups: Float32Array, tcoords: Float32Array, charCount: number): Text { - const boundingSphere = Sphere3D() - let groupMapping: GroupMapping + const boundingSphere = Sphere3D(); + let groupMapping: GroupMapping; - let currentHash = -1 - let currentGroup = -1 + let currentHash = -1; + let currentGroup = -1; const text = { kind: 'text' as const, @@ -112,39 +112,39 @@ export namespace Text { groupBuffer: ValueCell.create(groups), tcoordBuffer: ValueCell.create(tcoords), get boundingSphere() { - const newHash = hashCode(text) + const newHash = hashCode(text); if (newHash !== currentHash) { - const b = calculateInvariantBoundingSphere(text.centerBuffer.ref.value, text.charCount * 4, 4) - Sphere3D.copy(boundingSphere, b) - currentHash = newHash + const b = calculateInvariantBoundingSphere(text.centerBuffer.ref.value, text.charCount * 4, 4); + Sphere3D.copy(boundingSphere, b); + currentHash = newHash; } - return boundingSphere + return boundingSphere; }, get groupMapping() { if (text.groupBuffer.ref.version !== currentGroup) { - groupMapping = createGroupMapping(text.groupBuffer.ref.value, text.charCount, 4) - currentGroup = text.groupBuffer.ref.version + groupMapping = createGroupMapping(text.groupBuffer.ref.value, text.charCount, 4); + currentGroup = text.groupBuffer.ref.version; } - return groupMapping + return groupMapping; }, setBoundingSphere(sphere: Sphere3D) { - Sphere3D.copy(boundingSphere, sphere) - currentHash = hashCode(text) + Sphere3D.copy(boundingSphere, sphere); + currentHash = hashCode(text); } - } - return text + }; + return text; } function update(fontTexture: TextureImage<Uint8Array>, centers: Float32Array, mappings: Float32Array, depths: Float32Array, indices: Uint32Array, groups: Float32Array, tcoords: Float32Array, charCount: number, text: Text) { - text.charCount = charCount - ValueCell.update(text.fontTexture, fontTexture) - ValueCell.update(text.centerBuffer, centers) - ValueCell.update(text.mappingBuffer, mappings) - ValueCell.update(text.depthBuffer, depths) - ValueCell.update(text.indexBuffer, indices) - ValueCell.update(text.groupBuffer, groups) - ValueCell.update(text.tcoordBuffer, tcoords) - return text + text.charCount = charCount; + ValueCell.update(text.fontTexture, fontTexture); + ValueCell.update(text.centerBuffer, centers); + ValueCell.update(text.mappingBuffer, mappings); + ValueCell.update(text.depthBuffer, depths); + ValueCell.update(text.indexBuffer, indices); + ValueCell.update(text.groupBuffer, groups); + ValueCell.update(text.tcoordBuffer, tcoords); + return text; } export const Params = { @@ -170,7 +170,7 @@ export namespace Text { ['middle-left', 'middle-left'], ['middle-center', 'middle-center'], ['middle-right', 'middle-right'], ['top-left', 'top-left'], ['top-center', 'top-center'], ['top-right', 'top-right'], ] as [TextAttachment, string][]), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<Text, Params> = { @@ -182,25 +182,25 @@ export namespace Text { updateBoundingSphere, createRenderableState, updateRenderableState, - } + }; function createValues(text: Text, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): TextValues { - const { instanceCount, groupCount } = locationIt + const { instanceCount, groupCount } = locationIt; if (instanceCount !== transform.instanceCount.ref.value) { - throw new Error('instanceCount values in TransformData and LocationIterator differ') + throw new Error('instanceCount values in TransformData and LocationIterator differ'); } - const color = createColors(locationIt, theme.color) - const size = createSizes(locationIt, theme.size) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const color = createColors(locationIt, theme.color); + const size = createSizes(locationIt, theme.size); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: text.charCount * 2 * 3, groupCount, instanceCount } + const counts = { drawCount: text.charCount * 2 * 3, groupCount, instanceCount }; - const padding = getPadding(text.mappingBuffer.ref.value, text.depthBuffer.ref.value, text.charCount, getMaxSize(size)) - const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), text.boundingSphere, padding) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount) + const padding = getPadding(text.mappingBuffer.ref.value, text.depthBuffer.ref.value, text.charCount, getMaxSize(size)); + const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), text.boundingSphere, padding); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform.aTransform.ref.value, instanceCount); return { aPosition: text.centerBuffer, @@ -231,74 +231,74 @@ export namespace Text { uOffsetZ: ValueCell.create(props.offsetZ), uBackgroundColor: ValueCell.create(Color.toArrayNormalized(props.backgroundColor, Vec3.zero(), 0)), uBackgroundOpacity: ValueCell.create(props.backgroundOpacity), - } + }; } function createValuesSimple(text: Text, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(text, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(text, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: TextValues, props: PD.Values<Params>) { - BaseGeometry.updateValues(values, props) - ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor) + BaseGeometry.updateValues(values, props); + ValueCell.updateIfChanged(values.uSizeFactor, props.sizeFactor); - ValueCell.updateIfChanged(values.uBorderWidth, props.borderWidth) + ValueCell.updateIfChanged(values.uBorderWidth, props.borderWidth); if (Color.fromNormalizedArray(values.uBorderColor.ref.value, 0) !== props.borderColor) { - Color.toArrayNormalized(props.borderColor, values.uBorderColor.ref.value, 0) - ValueCell.update(values.uBorderColor, values.uBorderColor.ref.value) + Color.toArrayNormalized(props.borderColor, values.uBorderColor.ref.value, 0); + ValueCell.update(values.uBorderColor, values.uBorderColor.ref.value); } - ValueCell.updateIfChanged(values.uOffsetX, props.offsetX) - ValueCell.updateIfChanged(values.uOffsetY, props.offsetY) - ValueCell.updateIfChanged(values.uOffsetZ, props.offsetZ) + ValueCell.updateIfChanged(values.uOffsetX, props.offsetX); + ValueCell.updateIfChanged(values.uOffsetY, props.offsetY); + ValueCell.updateIfChanged(values.uOffsetZ, props.offsetZ); if (Color.fromNormalizedArray(values.uBackgroundColor.ref.value, 0) !== props.backgroundColor) { - Color.toArrayNormalized(props.backgroundColor, values.uBackgroundColor.ref.value, 0) - ValueCell.update(values.uBackgroundColor, values.uBackgroundColor.ref.value) + Color.toArrayNormalized(props.backgroundColor, values.uBackgroundColor.ref.value, 0); + ValueCell.update(values.uBackgroundColor, values.uBackgroundColor.ref.value); } - ValueCell.updateIfChanged(values.uBackgroundOpacity, props.backgroundOpacity) + ValueCell.updateIfChanged(values.uBackgroundOpacity, props.backgroundOpacity); } function updateBoundingSphere(values: TextValues, text: Text) { - const padding = getPadding(values.aMapping.ref.value, values.aDepth.ref.value, text.charCount, getMaxSize(values)) - const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), text.boundingSphere, padding) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const padding = getPadding(values.aMapping.ref.value, values.aDepth.ref.value, text.charCount, getMaxSize(values)); + const invariantBoundingSphere = Sphere3D.expand(Sphere3D(), text.boundingSphere, padding); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } - ValueCell.update(values.padding, padding) + ValueCell.update(values.padding, padding); } function createRenderableState(props: PD.Values<Params>): RenderableState { - const state = BaseGeometry.createRenderableState(props) - updateRenderableState(state, props) - return state + const state = BaseGeometry.createRenderableState(props); + updateRenderableState(state, props); + return state; } function updateRenderableState(state: RenderableState, props: PD.Values<Params>) { - BaseGeometry.updateRenderableState(state, props) - state.pickable = false - state.opaque = false + BaseGeometry.updateRenderableState(state, props); + state.pickable = false; + state.opaque = false; } } function getPadding(mappings: Float32Array, depths: Float32Array, charCount: number, maxSize: number) { - let maxOffset = 0 - let maxDepth = 0 + let maxOffset = 0; + let maxDepth = 0; for (let i = 0, il = charCount * 4; i < il; ++i) { - const i2 = 2 * i - const ox = Math.abs(mappings[i2]) - if (ox > maxOffset) maxOffset = ox - const oy = Math.abs(mappings[i2 + 1]) - if (oy > maxOffset) maxOffset = oy - const d = Math.abs(depths[i]) - if (d > maxDepth) maxDepth = d + const i2 = 2 * i; + const ox = Math.abs(mappings[i2]); + if (ox > maxOffset) maxOffset = ox; + const oy = Math.abs(mappings[i2 + 1]); + if (oy > maxOffset) maxOffset = oy; + const d = Math.abs(depths[i]); + if (d > maxDepth) maxDepth = d; } // console.log(maxDepth + maxSize, maxDepth, maxSize, maxSize + maxSize * maxOffset, depths) - return Math.max(maxDepth, maxSize + maxSize * maxOffset) + return Math.max(maxDepth, maxSize + maxSize * maxOffset); // return maxSize + maxSize * maxOffset + maxDepth } \ No newline at end of file diff --git a/src/mol-geo/geometry/texture-mesh/texture-mesh.ts b/src/mol-geo/geometry/texture-mesh/texture-mesh.ts index cf91842a455dd8a1016e236dec4e60979070260d..255bd4ff69ab3a29875da2547284dc1c45c074fb 100644 --- a/src/mol-geo/geometry/texture-mesh/texture-mesh.ts +++ b/src/mol-geo/geometry/texture-mesh/texture-mesh.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from '../../../mol-util' -import { Sphere3D } from '../../../mol-math/geometry' +import { ValueCell } from '../../../mol-util'; +import { Sphere3D } from '../../../mol-math/geometry'; import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { LocationIterator } from '../../../mol-geo/util/location-iterator'; import { TransformData } from '../transform-data'; @@ -41,16 +41,16 @@ export interface TextureMesh { export namespace TextureMesh { export function create(vertexCount: number, groupCount: number, vertexGroupTexture: Texture, normalTexture: Texture, boundingSphere: Sphere3D, textureMesh?: TextureMesh): TextureMesh { - const width = vertexGroupTexture.getWidth() - const height = vertexGroupTexture.getHeight() + const width = vertexGroupTexture.getWidth(); + const height = vertexGroupTexture.getHeight(); if (textureMesh) { - textureMesh.vertexCount = vertexCount - textureMesh.groupCount = groupCount - ValueCell.update(textureMesh.geoTextureDim, Vec2.set(textureMesh.geoTextureDim.ref.value, width, height)) - ValueCell.update(textureMesh.vertexGroupTexture, vertexGroupTexture) - ValueCell.update(textureMesh.normalTexture, normalTexture) - Sphere3D.copy(textureMesh.boundingSphere, boundingSphere) - return textureMesh + textureMesh.vertexCount = vertexCount; + textureMesh.groupCount = groupCount; + ValueCell.update(textureMesh.geoTextureDim, Vec2.set(textureMesh.geoTextureDim.ref.value, width, height)); + ValueCell.update(textureMesh.vertexGroupTexture, vertexGroupTexture); + ValueCell.update(textureMesh.normalTexture, normalTexture); + Sphere3D.copy(textureMesh.boundingSphere, boundingSphere); + return textureMesh; } else { return { kind: 'texture-mesh', @@ -60,12 +60,12 @@ export namespace TextureMesh { vertexGroupTexture: ValueCell.create(vertexGroupTexture), normalTexture: ValueCell.create(normalTexture), boundingSphere: Sphere3D.clone(boundingSphere), - } + }; } } export function createEmpty(textureMesh?: TextureMesh): TextureMesh { - return {} as TextureMesh // TODO + return {} as TextureMesh; // TODO } export const Params = { @@ -73,7 +73,7 @@ export namespace TextureMesh { doubleSided: PD.Boolean(false, BaseGeometry.CustomQualityParamInfo), flipSided: PD.Boolean(false, BaseGeometry.ShadingCategory), flatShaded: PD.Boolean(false, BaseGeometry.ShadingCategory), - } + }; export type Params = typeof Params export const Utils: GeometryUtils<TextureMesh, Params> = { @@ -85,18 +85,18 @@ export namespace TextureMesh { updateBoundingSphere, createRenderableState: BaseGeometry.createRenderableState, updateRenderableState: BaseGeometry.updateRenderableState - } + }; function createValues(textureMesh: TextureMesh, transform: TransformData, locationIt: LocationIterator, theme: Theme, props: PD.Values<Params>): TextureMeshValues { - const { instanceCount, groupCount } = locationIt - const color = createColors(locationIt, theme.color) - const marker = createMarkers(instanceCount * groupCount) - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() + const { instanceCount, groupCount } = locationIt; + const color = createColors(locationIt, theme.color); + const marker = createMarkers(instanceCount * groupCount); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); - const counts = { drawCount: textureMesh.vertexCount, groupCount, instanceCount } + const counts = { drawCount: textureMesh.vertexCount, groupCount, instanceCount }; - const transformBoundingSphere = calculateTransformBoundingSphere(textureMesh.boundingSphere, transform.aTransform.ref.value, transform.instanceCount.ref.value) + const transformBoundingSphere = calculateTransformBoundingSphere(textureMesh.boundingSphere, transform.aTransform.ref.value, transform.instanceCount.ref.value); return { uGeoTexDim: textureMesh.geoTextureDim, @@ -119,36 +119,36 @@ export namespace TextureMesh { dFlatShaded: ValueCell.create(props.flatShaded), dFlipSided: ValueCell.create(props.flipSided), dGeoTexture: ValueCell.create(true), - } + }; } function createValuesSimple(textureMesh: TextureMesh, props: Partial<PD.Values<Params>>, colorValue: Color, sizeValue: number, transform?: TransformData) { - const s = BaseGeometry.createSimple(colorValue, sizeValue, transform) - const p = { ...PD.getDefaultValues(Params), ...props } - return createValues(textureMesh, s.transform, s.locationIterator, s.theme, p) + const s = BaseGeometry.createSimple(colorValue, sizeValue, transform); + const p = { ...PD.getDefaultValues(Params), ...props }; + return createValues(textureMesh, s.transform, s.locationIterator, s.theme, p); } function updateValues(values: TextureMeshValues, props: PD.Values<Params>) { - ValueCell.updateIfChanged(values.alpha, props.alpha) // `uAlpha` is set in renderable.render + ValueCell.updateIfChanged(values.alpha, props.alpha); // `uAlpha` is set in renderable.render - ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided) - ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded) - ValueCell.updateIfChanged(values.dFlipSided, props.flipSided) + ValueCell.updateIfChanged(values.dDoubleSided, props.doubleSided); + ValueCell.updateIfChanged(values.dFlatShaded, props.flatShaded); + ValueCell.updateIfChanged(values.dFlipSided, props.flipSided); if (values.drawCount.ref.value > values.aGroup.ref.value.length) { // console.log('updating vertex ids in aGroup to handle larger drawCount') - ValueCell.update(values.aGroup, fillSerial(new Float32Array(values.drawCount.ref.value))) + ValueCell.update(values.aGroup, fillSerial(new Float32Array(values.drawCount.ref.value))); } } function updateBoundingSphere(values: TextureMeshValues, textureMesh: TextureMesh) { - const invariantBoundingSphere = textureMesh.boundingSphere - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value) + const invariantBoundingSphere = textureMesh.boundingSphere; + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, values.aTransform.ref.value, values.instanceCount.ref.value); if (!Sphere3D.equals(boundingSphere, values.boundingSphere.ref.value)) { - ValueCell.update(values.boundingSphere, boundingSphere) + ValueCell.update(values.boundingSphere, boundingSphere); } if (!Sphere3D.equals(invariantBoundingSphere, values.invariantBoundingSphere.ref.value)) { - ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere) + ValueCell.update(values.invariantBoundingSphere, invariantBoundingSphere); } } } \ No newline at end of file diff --git a/src/mol-geo/geometry/transform-data.ts b/src/mol-geo/geometry/transform-data.ts index 748f8ed74ad6f442b38675dc49b3bda0a891b2d6..5c6961eef29d41fc0666c08f05b24bebb2324fa2 100644 --- a/src/mol-geo/geometry/transform-data.ts +++ b/src/mol-geo/geometry/transform-data.ts @@ -28,24 +28,24 @@ export type TransformData = { export function createTransform(transformArray: Float32Array, instanceCount: number, transformData?: TransformData): TransformData { if (transformData) { - ValueCell.update(transformData.matrix, transformData.matrix.ref.value) - ValueCell.update(transformData.transform, transformArray) - ValueCell.update(transformData.uInstanceCount, instanceCount) - ValueCell.update(transformData.instanceCount, instanceCount) + ValueCell.update(transformData.matrix, transformData.matrix.ref.value); + ValueCell.update(transformData.transform, transformArray); + ValueCell.update(transformData.uInstanceCount, instanceCount); + ValueCell.update(transformData.instanceCount, instanceCount); - const aTransform = transformData.aTransform.ref.value.length >= instanceCount * 16 ? transformData.aTransform.ref.value : new Float32Array(instanceCount * 16) - aTransform.set(transformArray) - ValueCell.update(transformData.aTransform, aTransform) + const aTransform = transformData.aTransform.ref.value.length >= instanceCount * 16 ? transformData.aTransform.ref.value : new Float32Array(instanceCount * 16); + aTransform.set(transformArray); + ValueCell.update(transformData.aTransform, aTransform); // Note that this sets `extraTransform` to identity transforms - const extraTransform = transformData.extraTransform.ref.value.length >= instanceCount * 16 ? transformData.extraTransform.ref.value : new Float32Array(instanceCount * 16) - ValueCell.update(transformData.extraTransform, fillIdentityTransform(extraTransform, instanceCount)) + const extraTransform = transformData.extraTransform.ref.value.length >= instanceCount * 16 ? transformData.extraTransform.ref.value : new Float32Array(instanceCount * 16); + ValueCell.update(transformData.extraTransform, fillIdentityTransform(extraTransform, instanceCount)); - const aInstance = transformData.aInstance.ref.value.length >= instanceCount ? transformData.aInstance.ref.value : new Float32Array(instanceCount) - ValueCell.update(transformData.aInstance, fillSerial(aInstance, instanceCount)) + const aInstance = transformData.aInstance.ref.value.length >= instanceCount ? transformData.aInstance.ref.value : new Float32Array(instanceCount); + ValueCell.update(transformData.aInstance, fillSerial(aInstance, instanceCount)); - updateTransformData(transformData) - return transformData + updateTransformData(transformData); + return transformData; } else { return { aTransform: ValueCell.create(new Float32Array(transformArray)), @@ -55,22 +55,22 @@ export function createTransform(transformArray: Float32Array, instanceCount: num uInstanceCount: ValueCell.create(instanceCount), instanceCount: ValueCell.create(instanceCount), aInstance: ValueCell.create(fillSerial(new Float32Array(instanceCount))) - } + }; } } -const identityTransform = new Float32Array(16) -Mat4.toArray(Mat4.identity(), identityTransform, 0) +const identityTransform = new Float32Array(16); +Mat4.toArray(Mat4.identity(), identityTransform, 0); export function createIdentityTransform(transformData?: TransformData): TransformData { - return createTransform(new Float32Array(identityTransform), 1, transformData) + return createTransform(new Float32Array(identityTransform), 1, transformData); } export function fillIdentityTransform(transform: Float32Array, count: number) { for (let i = 0; i < count; i++) { - transform.set(identityTransform, i * 16) + transform.set(identityTransform, i * 16); } - return transform + return transform; } /** @@ -78,15 +78,15 @@ export function fillIdentityTransform(transform: Float32Array, count: number) { * `aTransform[i] = matrix * transform[i] * extraTransform[i]` */ export function updateTransformData(transformData: TransformData) { - const aTransform = transformData.aTransform.ref.value - const instanceCount = transformData.instanceCount.ref.value - const matrix = transformData.matrix.ref.value - const transform = transformData.transform.ref.value - const extraTransform = transformData.extraTransform.ref.value + const aTransform = transformData.aTransform.ref.value; + const instanceCount = transformData.instanceCount.ref.value; + const matrix = transformData.matrix.ref.value; + const transform = transformData.transform.ref.value; + const extraTransform = transformData.extraTransform.ref.value; for (let i = 0; i < instanceCount; i++) { - const i16 = i * 16 - Mat4.mulOffset(aTransform, extraTransform, transform, i16, i16, i16) - Mat4.mulOffset(aTransform, matrix, aTransform, i16, 0, i16) + const i16 = i * 16; + Mat4.mulOffset(aTransform, extraTransform, transform, i16, i16, i16); + Mat4.mulOffset(aTransform, matrix, aTransform, i16, 0, i16); } - ValueCell.update(transformData.aTransform, aTransform) + ValueCell.update(transformData.aTransform, aTransform); } \ No newline at end of file diff --git a/src/mol-geo/geometry/transparency-data.ts b/src/mol-geo/geometry/transparency-data.ts index e463d6aff4c02f80a0848d6c9dbae4603b5ad7c0..4ffda655508b5f4218dd7868016a5f1224c63232 100644 --- a/src/mol-geo/geometry/transparency-data.ts +++ b/src/mol-geo/geometry/transparency-data.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ValueCell } from '../../mol-util/value-cell' -import { Vec2 } from '../../mol-math/linear-algebra' +import { ValueCell } from '../../mol-util/value-cell'; +import { Vec2 } from '../../mol-math/linear-algebra'; import { TextureImage, createTextureImage } from '../../mol-gl/renderable/util'; import { Transparency } from '../../mol-theme/transparency'; @@ -18,45 +18,45 @@ export type TransparencyData = { export function applyTransparencyValue(array: Uint8Array, start: number, end: number, value: number) { for (let i = start; i < end; ++i) { - array[i] = value * 255 + array[i] = value * 255; } - return true + return true; } export function clearTransparency(array: Uint8Array, start: number, end: number) { - array.fill(0, start, end) + array.fill(0, start, end); } export function createTransparency(count: number, variant: Transparency.Variant, transparencyData?: TransparencyData): TransparencyData { - const transparency = createTextureImage(Math.max(1, count), 1, Uint8Array, transparencyData && transparencyData.tTransparency.ref.value.array) + const transparency = createTextureImage(Math.max(1, count), 1, Uint8Array, transparencyData && transparencyData.tTransparency.ref.value.array); if (transparencyData) { - ValueCell.update(transparencyData.tTransparency, transparency) - ValueCell.update(transparencyData.uTransparencyTexDim, Vec2.create(transparency.width, transparency.height)) - ValueCell.update(transparencyData.dTransparency, count > 0) - ValueCell.update(transparencyData.dTransparencyVariant, variant) - return transparencyData + ValueCell.update(transparencyData.tTransparency, transparency); + ValueCell.update(transparencyData.uTransparencyTexDim, Vec2.create(transparency.width, transparency.height)); + ValueCell.update(transparencyData.dTransparency, count > 0); + ValueCell.update(transparencyData.dTransparencyVariant, variant); + return transparencyData; } else { return { tTransparency: ValueCell.create(transparency), uTransparencyTexDim: ValueCell.create(Vec2.create(transparency.width, transparency.height)), dTransparency: ValueCell.create(count > 0), dTransparencyVariant: ValueCell.create(variant), - } + }; } } -const emptyTransparencyTexture = { array: new Uint8Array(1), width: 1, height: 1 } +const emptyTransparencyTexture = { array: new Uint8Array(1), width: 1, height: 1 }; export function createEmptyTransparency(transparencyData?: TransparencyData): TransparencyData { if (transparencyData) { - ValueCell.update(transparencyData.tTransparency, emptyTransparencyTexture) - ValueCell.update(transparencyData.uTransparencyTexDim, Vec2.create(1, 1)) - return transparencyData + ValueCell.update(transparencyData.tTransparency, emptyTransparencyTexture); + ValueCell.update(transparencyData.uTransparencyTexDim, Vec2.create(1, 1)); + return transparencyData; } else { return { tTransparency: ValueCell.create(emptyTransparencyTexture), uTransparencyTexDim: ValueCell.create(Vec2.create(1, 1)), dTransparency: ValueCell.create(false), dTransparencyVariant: ValueCell.create('single'), - } + }; } } \ No newline at end of file diff --git a/src/mol-geo/primitive/box.ts b/src/mol-geo/primitive/box.ts index da8c23981c73ff05317659935971414adb9548a9..0701a03ccb5a81afe802d4f3fb37c3fb677c7b8f 100644 --- a/src/mol-geo/primitive/box.ts +++ b/src/mol-geo/primitive/box.ts @@ -4,61 +4,61 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3 } from '../../mol-math/linear-algebra' +import { Vec3 } from '../../mol-math/linear-algebra'; import { Primitive, PrimitiveBuilder } from './primitive'; -import { polygon } from './polygon' +import { polygon } from './polygon'; import { Cage, createCage } from './cage'; -const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero() -const points = polygon(4, true) +const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero(); +const points = polygon(4, true); /** * Create a box */ function createBox(perforated: boolean): Primitive { - const builder = PrimitiveBuilder(12) + const builder = PrimitiveBuilder(12); // create sides for (let i = 0; i < 4; ++i) { - const ni = (i + 1) % 4 - Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5) - Vec3.set(c, points[ni * 3], points[ni * 3 + 1], 0.5) - Vec3.set(d, points[i * 3], points[i * 3 + 1], 0.5) - builder.add(a, b, c) - if (!perforated) builder.add(c, d, a) + const ni = (i + 1) % 4; + Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5); + Vec3.set(c, points[ni * 3], points[ni * 3 + 1], 0.5); + Vec3.set(d, points[i * 3], points[i * 3 + 1], 0.5); + builder.add(a, b, c); + if (!perforated) builder.add(c, d, a); } // create bases - Vec3.set(a, points[0], points[1], -0.5) - Vec3.set(b, points[3], points[4], -0.5) - Vec3.set(c, points[6], points[7], -0.5) - Vec3.set(d, points[9], points[10], -0.5) - builder.add(c, b, a) - if (!perforated) builder.add(a, d, c) - Vec3.set(a, points[0], points[1], 0.5) - Vec3.set(b, points[3], points[4], 0.5) - Vec3.set(c, points[6], points[7], 0.5) - Vec3.set(d, points[9], points[10], 0.5) - builder.add(a, b, c) - if (!perforated) builder.add(c, d, a) + Vec3.set(a, points[0], points[1], -0.5); + Vec3.set(b, points[3], points[4], -0.5); + Vec3.set(c, points[6], points[7], -0.5); + Vec3.set(d, points[9], points[10], -0.5); + builder.add(c, b, a); + if (!perforated) builder.add(a, d, c); + Vec3.set(a, points[0], points[1], 0.5); + Vec3.set(b, points[3], points[4], 0.5); + Vec3.set(c, points[6], points[7], 0.5); + Vec3.set(d, points[9], points[10], 0.5); + builder.add(a, b, c); + if (!perforated) builder.add(c, d, a); - return builder.getPrimitive() + return builder.getPrimitive(); } -let box: Primitive +let box: Primitive; export function Box() { - if (!box) box = createBox(false) - return box + if (!box) box = createBox(false); + return box; } -let perforatedBox: Primitive +let perforatedBox: Primitive; export function PerforatedBox() { - if (!perforatedBox) perforatedBox = createBox(true) - return perforatedBox + if (!perforatedBox) perforatedBox = createBox(true); + return perforatedBox; } -let boxCage: Cage +let boxCage: Cage; export function BoxCage() { if (!boxCage) { boxCage = createCage([ @@ -74,7 +74,7 @@ export function BoxCage() { 0, 4, 1, 5, 2, 6, 3, 7, // sides 0, 1, 1, 2, 2, 3, 3, 0, // bottom base 4, 5, 5, 6, 6, 7, 7, 4 // top base - ]) + ]); } - return boxCage + return boxCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/cage.ts b/src/mol-geo/primitive/cage.ts index 8911c1ece86db5184dc2ccd256555a2252799a2d..3cf92f279ba3af7ea032c214cc41f0cdecc81104 100644 --- a/src/mol-geo/primitive/cage.ts +++ b/src/mol-geo/primitive/cage.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Mat4, Vec3 } from '../../mol-math/linear-algebra' -import { NumberArray } from '../../mol-util/type-helpers' +import { Mat4, Vec3 } from '../../mol-math/linear-algebra'; +import { NumberArray } from '../../mol-util/type-helpers'; export interface Cage { readonly vertices: ArrayLike<number> @@ -13,25 +13,25 @@ export interface Cage { } export function createCage(vertices: ArrayLike<number>, edges: ArrayLike<number>): Cage { - return { vertices, edges } + return { vertices, edges }; } export function cloneCage(cage: Cage): Cage { return { vertices: new Float32Array(cage.vertices), edges: new Uint32Array(cage.edges) - } + }; } -const tmpV = Vec3.zero() +const tmpV = Vec3.zero(); /** Transform primitive in-place */ export function transformCage(cage: Cage, t: Mat4) { - const { vertices } = cage + const { vertices } = cage; for (let i = 0, il = vertices.length; i < il; i += 3) { // position - Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, vertices, i), t) - Vec3.toArray(tmpV, vertices as NumberArray, i) + Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, vertices, i), t); + Vec3.toArray(tmpV, vertices as NumberArray, i); } - return cage + return cage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/circle.ts b/src/mol-geo/primitive/circle.ts index 89aa21bdcf7f8554c8092a7416779d07f2458bdf..15ccc5d3c8c21fbf39d9b8359af92973a2c8356c 100644 --- a/src/mol-geo/primitive/circle.ts +++ b/src/mol-geo/primitive/circle.ts @@ -11,18 +11,18 @@ export const DefaultCircleProps = { segments: 36, thetaStart: 0, thetaLength: Math.PI * 2 -} +}; export type CirclerProps = Partial<typeof DefaultCircleProps> export function Circle(props?: CirclerProps): Primitive { - const { radius, segments, thetaStart, thetaLength } = { ...DefaultCircleProps, ...props } + const { radius, segments, thetaStart, thetaLength } = { ...DefaultCircleProps, ...props }; - const isFull = thetaLength === Math.PI * 2 - const count = isFull ? segments + 1 : segments + 2 + const isFull = thetaLength === Math.PI * 2; + const count = isFull ? segments + 1 : segments + 2; - const vertices = new Float32Array(count * 3) - const normals = new Float32Array(count * 3) - const indices = new Uint32Array(segments * 3) + const vertices = new Float32Array(count * 3); + const normals = new Float32Array(count * 3); + const indices = new Uint32Array(segments * 3); // center vertices[0] = 0; vertices[1] = 0; vertices[2] = 0; @@ -32,9 +32,9 @@ export function Circle(props?: CirclerProps): Primitive { for (let s = 0, i = 3; s < segments; ++s, i += 3) { const segment = thetaStart + s / segments * thetaLength; - vertices[i] = radius * Math.sin(segment) - vertices[i + 1] = 0 - vertices[i + 2] = radius * Math.cos(segment) + vertices[i] = radius * Math.sin(segment); + vertices[i + 1] = 0; + vertices[i + 2] = radius * Math.cos(segment); normals[i] = 0; normals[i + 1] = 1; normals[i + 2] = 0; } @@ -45,25 +45,25 @@ export function Circle(props?: CirclerProps): Primitive { } if (isFull) { - const j = (segments - 1) * 3 - indices[j] = segments - indices[j + 1] = 1 - indices[j + 2] = 0 + const j = (segments - 1) * 3; + indices[j] = segments; + indices[j + 1] = 1; + indices[j + 2] = 0; } else { const segment = thetaStart + thetaLength; - const i = (segments + 1) * 3 + const i = (segments + 1) * 3; - vertices[i] = radius * Math.sin(segment) - vertices[i + 1] = 0 - vertices[i + 2] = radius * Math.cos(segment) + vertices[i] = radius * Math.sin(segment); + vertices[i + 1] = 0; + vertices[i + 2] = radius * Math.cos(segment); normals[i] = 0; normals[i + 1] = 1; normals[i + 2] = 0; - const j = (segments - 1) * 3 - indices[j] = segments - indices[j + 1] = segments + 1 - indices[j + 2] = 0 + const j = (segments - 1) * 3; + indices[j] = segments; + indices[j + 1] = segments + 1; + indices[j + 2] = 0; } - return { vertices, normals, indices } + return { vertices, normals, indices }; } \ No newline at end of file diff --git a/src/mol-geo/primitive/cylinder.ts b/src/mol-geo/primitive/cylinder.ts index 1760c3b10dc5f101c3f9d923c3ccb8d4c1395b04..8bf9f52f988a492bef00ae20e2378cf0aeec5af5 100644 --- a/src/mol-geo/primitive/cylinder.ts +++ b/src/mol-geo/primitive/cylinder.ts @@ -6,7 +6,7 @@ // adapted from three.js, MIT License Copyright 2010-2018 three.js authors -import { Vec3 } from '../../mol-math/linear-algebra' +import { Vec3 } from '../../mol-math/linear-algebra'; import { Primitive } from './primitive'; export const DefaultCylinderProps = { @@ -19,7 +19,7 @@ export const DefaultCylinderProps = { bottomCap: false, thetaStart: 0.0, thetaLength: Math.PI * 2 -} +}; export type CylinderProps = Partial<typeof DefaultCylinderProps> export function Cylinder(props?: CylinderProps): Primitive { @@ -45,10 +45,10 @@ export function Cylinder(props?: CylinderProps): Primitive { vertices: new Float32Array(vertices), normals: new Float32Array(normals), indices: new Uint32Array(indices) - } + }; function generateTorso() { - const normal = Vec3.zero() + const normal = Vec3.zero(); // this will be used to calculate the normal const slope = (radiusBottom - radiusTop) / height; diff --git a/src/mol-geo/primitive/dodecahedron.ts b/src/mol-geo/primitive/dodecahedron.ts index e88f34bc109931ffde8f392b53ee61fe4d45f1e1..7b826ffc4a8bfc1cdb24433133947fff4e2a8fc6 100644 --- a/src/mol-geo/primitive/dodecahedron.ts +++ b/src/mol-geo/primitive/dodecahedron.ts @@ -55,15 +55,15 @@ const dodecahedronEdges: ReadonlyArray<number> = [ 0, 1, 0, 4, 0, 5, 1, 2, 1, 7, 2, 3, 2, 17, 3, 4, 3, 14, 4, 16, 5, 6, 5, 19, 6, 7, 6, 11, 7, 18, 8, 9, 8, 12, 8, 13, 9, 10, 9, 15, 10, 11, 10, 18, 11, 12, 12, 19, 13, 14, 13, 16, 14, 15, 15, 17, 16, 19, 17, 18, -] +]; -let dodecahedron: Primitive +let dodecahedron: Primitive; export function Dodecahedron(): Primitive { - if (!dodecahedron) dodecahedron = createPrimitive(dodecahedronVertices, dodecahedronIndices) - return dodecahedron + if (!dodecahedron) dodecahedron = createPrimitive(dodecahedronVertices, dodecahedronIndices); + return dodecahedron; } -const dodecahedronCage = createCage(dodecahedronVertices, dodecahedronEdges) +const dodecahedronCage = createCage(dodecahedronVertices, dodecahedronEdges); export function DodecahedronCage(): Cage { - return dodecahedronCage + return dodecahedronCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/icosahedron.ts b/src/mol-geo/primitive/icosahedron.ts index 8275823ac6fe3b05acc3190c548fe8cb877ccd27..14742232e79d32f6dba61c251a6f716d958f9fe3 100644 --- a/src/mol-geo/primitive/icosahedron.ts +++ b/src/mol-geo/primitive/icosahedron.ts @@ -26,15 +26,15 @@ const icosahedronEdges: ReadonlyArray<number> = [ 0, 11, 5, 11, 0, 5, 1, 5, 0, 1, 1, 7, 0, 7, 7, 10, 0, 10, 10, 11, 5, 9, 4, 11, 2, 10, 6, 7, 1, 8, 3, 9, 4, 9, 3, 4, 2, 4, 2, 3, 2, 6, 3, 6, 6, 8, 3, 8, 8, 9, 4, 5, 2, 11, 6, 10, 7, 8, 1, 9 -] +]; -let icosahedron: Primitive +let icosahedron: Primitive; export function Icosahedron(): Primitive { - if (!icosahedron) icosahedron = createPrimitive(icosahedronVertices, icosahedronIndices) - return icosahedron + if (!icosahedron) icosahedron = createPrimitive(icosahedronVertices, icosahedronIndices); + return icosahedron; } -const icosahedronCage = createCage(icosahedronVertices, icosahedronEdges) +const icosahedronCage = createCage(icosahedronVertices, icosahedronEdges); export function IcosahedronCage(): Cage { - return icosahedronCage + return icosahedronCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/octahedron.ts b/src/mol-geo/primitive/octahedron.ts index 989526767fff67b6824c9ebb412f32742434904e..e01bb778e52277198ec284602128f4c436d1a008 100644 --- a/src/mol-geo/primitive/octahedron.ts +++ b/src/mol-geo/primitive/octahedron.ts @@ -29,21 +29,21 @@ const octahedronEdges: ReadonlyArray<number> = [ 0, 2, 1, 3, 2, 1, 3, 0, 0, 4, 1, 4, 2, 4, 3, 4, 0, 5, 1, 5, 2, 5, 3, 5, -] +]; -let octahedron: Primitive +let octahedron: Primitive; export function Octahedron(): Primitive { - if (!octahedron) octahedron = createPrimitive(octahedronVertices, octahedronIndices) - return octahedron + if (!octahedron) octahedron = createPrimitive(octahedronVertices, octahedronIndices); + return octahedron; } -let perforatedOctahedron: Primitive +let perforatedOctahedron: Primitive; export function PerforatedOctahedron(): Primitive { - if (!perforatedOctahedron) perforatedOctahedron = createPrimitive(octahedronVertices, perforatedOctahedronIndices) - return perforatedOctahedron + if (!perforatedOctahedron) perforatedOctahedron = createPrimitive(octahedronVertices, perforatedOctahedronIndices); + return perforatedOctahedron; } -const octahedronCage = createCage(octahedronVertices, octahedronEdges) +const octahedronCage = createCage(octahedronVertices, octahedronEdges); export function OctahedronCage(): Cage { - return octahedronCage + return octahedronCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/plane.ts b/src/mol-geo/primitive/plane.ts index fbfb2194e5891020ed7690a3b5f66bd2e9eb749c..b919e8bd02656398ea4b6e191704290cee3400c0 100644 --- a/src/mol-geo/primitive/plane.ts +++ b/src/mol-geo/primitive/plane.ts @@ -24,17 +24,17 @@ const plane: Primitive = { 0, 2, 1, 1, 2, 3 ]) -} +}; const planeCage: Cage = { vertices: plane.vertices, edges: new Uint32Array([ 0, 1, 2, 3, 3, 1, 2, 0 ]) -} +}; export function Plane(): Primitive { - return plane + return plane; } export function PlaneCage(): Cage { - return planeCage + return planeCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/polygon.ts b/src/mol-geo/primitive/polygon.ts index a440e579978137daab31ebb1af34dee3e7c06f20..6695a20583f574ef9fd7ae2e15273766ec50f345 100644 --- a/src/mol-geo/primitive/polygon.ts +++ b/src/mol-geo/primitive/polygon.ts @@ -9,18 +9,18 @@ * 3 for a triangle, 4 for a rectangle, 5 for a pentagon, 6 for a hexagon... */ export function polygon(sideCount: number, shift: boolean, radius = -1) { - const points = new Float32Array(sideCount * 3) + const points = new Float32Array(sideCount * 3); const r = radius === -1 ? (sideCount <= 4 ? Math.sqrt(2) / 2 : 0.6) - : radius + : radius; - const offset = shift ? 1 : 0 + const offset = shift ? 1 : 0; for (let i = 0, il = sideCount; i < il; ++i) { - const c = (i * 2 + offset) / sideCount * Math.PI - points[i * 3] = Math.cos(c) * r - points[i * 3 + 1] = Math.sin(c) * r - points[i * 3 + 2] = 0 + const c = (i * 2 + offset) / sideCount * Math.PI; + points[i * 3] = Math.cos(c) * r; + points[i * 3 + 1] = Math.sin(c) * r; + points[i * 3 + 2] = 0; } - return points + return points; } \ No newline at end of file diff --git a/src/mol-geo/primitive/polyhedron.ts b/src/mol-geo/primitive/polyhedron.ts index b32c48f37ec4272b5b8fa3e0f9b25cc30ad1c91d..2b2698d234a7a29d0189cb5204088b38f258f9c8 100644 --- a/src/mol-geo/primitive/polyhedron.ts +++ b/src/mol-geo/primitive/polyhedron.ts @@ -6,20 +6,20 @@ // adapted from three.js, MIT License Copyright 2010-2018 three.js authors -import { Vec3 } from '../../mol-math/linear-algebra' -import { computeIndexedVertexNormals, appplyRadius } from '../util' +import { Vec3 } from '../../mol-math/linear-algebra'; +import { computeIndexedVertexNormals, appplyRadius } from '../util'; import { Primitive } from './primitive'; export const DefaultPolyhedronProps = { radius: 1, detail: 0 -} +}; export type PolyhedronProps = Partial<typeof DefaultPolyhedronProps> export function Polyhedron(_vertices: ArrayLike<number>, _indices: ArrayLike<number>, props?: PolyhedronProps): Primitive { - const { radius, detail } = { ...DefaultPolyhedronProps, ...props } - const builder = createBuilder() - const { vertices, indices } = builder + const { radius, detail } = { ...DefaultPolyhedronProps, ...props }; + const builder = createBuilder(); + const { vertices, indices } = builder; // the subdivision creates the vertex buffer data subdivide(detail); @@ -28,59 +28,59 @@ export function Polyhedron(_vertices: ArrayLike<number>, _indices: ArrayLike<num appplyRadius(vertices, radius); const normals = new Float32Array(vertices.length); - computeIndexedVertexNormals(vertices, indices, normals, vertices.length / 3, indices.length / 3) + computeIndexedVertexNormals(vertices, indices, normals, vertices.length / 3, indices.length / 3); return { vertices: new Float32Array(vertices), normals: new Float32Array(normals), indices: new Uint32Array(indices) - } + }; // helper functions function subdivide(detail: number) { - const a = Vec3() - const b = Vec3() - const c = Vec3() + const a = Vec3(); + const b = Vec3(); + const c = Vec3(); // iterate over all faces and apply a subdivison with the given detail value for (let i = 0; i < _indices.length; i += 3) { // get the vertices of the face - Vec3.fromArray(a, _vertices, _indices[ i + 0 ] * 3) - Vec3.fromArray(b, _vertices, _indices[ i + 1 ] * 3) - Vec3.fromArray(c, _vertices, _indices[ i + 2 ] * 3) + Vec3.fromArray(a, _vertices, _indices[ i + 0 ] * 3); + Vec3.fromArray(b, _vertices, _indices[ i + 1 ] * 3); + Vec3.fromArray(c, _vertices, _indices[ i + 2 ] * 3); // perform subdivision - subdivideFace(a, b, c, detail) + subdivideFace(a, b, c, detail); } } function subdivideFace(a: Vec3, b: Vec3, c: Vec3, detail: number) { - const cols = Math.pow(2, detail) + const cols = Math.pow(2, detail); // we use this multidimensional array as a data structure for creating the subdivision - const v: Vec3[][] = [] + const v: Vec3[][] = []; // construct all of the vertices for this subdivision for (let i = 0; i <= cols; ++i) { - v[i] = [] + v[i] = []; - const aj = Vec3() - Vec3.lerp(aj, a, c, i / cols) + const aj = Vec3(); + Vec3.lerp(aj, a, c, i / cols); - const bj = Vec3() - Vec3.lerp(bj, b, c, i / cols) + const bj = Vec3(); + Vec3.lerp(bj, b, c, i / cols); - const rows = cols - i + const rows = cols - i; for (let j = 0; j <= rows; ++j) { if (j === 0 && i === cols) { - v[i][j] = aj + v[i][j] = aj; } else { - const abj = Vec3() - Vec3.lerp(abj, aj, bj, j / rows) + const abj = Vec3(); + Vec3.lerp(abj, aj, bj, j / rows); - v[i][j] = abj + v[i][j] = abj; } } } @@ -88,11 +88,11 @@ export function Polyhedron(_vertices: ArrayLike<number>, _indices: ArrayLike<num // construct all of the faces for (let i = 0; i < cols; ++i) { for (let j = 0; j < 2 * (cols - i) - 1; ++j) { - const k = Math.floor(j / 2) + const k = Math.floor(j / 2); if (j % 2 === 0) { - builder.add(v[i][k + 1], v[i + 1][k], v[i][k]) + builder.add(v[i][k + 1], v[i + 1][k], v[i][k]); } else { - builder.add(v[i][k + 1], v[i + 1][k + 1], v[i + 1][k]) + builder.add(v[i][k + 1], v[i + 1][k + 1], v[i + 1][k]); } } } @@ -106,27 +106,27 @@ interface Builder { } function createBuilder(): Builder { - const vertices: number[] = [] - const indices: number[] = [] + const vertices: number[] = []; + const indices: number[] = []; - const vertexMap = new Map<string, number>() + const vertexMap = new Map<string, number>(); function addVertex(v: Vec3) { - const key = `${v[0].toFixed(5)}|${v[1].toFixed(5)}|${v[2].toFixed(5)}` - let idx = vertexMap.get(key) + const key = `${v[0].toFixed(5)}|${v[1].toFixed(5)}|${v[2].toFixed(5)}`; + let idx = vertexMap.get(key); if (idx === undefined) { - idx = vertices.length / 3 - vertexMap.set(key, idx) - vertices.push(...v) + idx = vertices.length / 3; + vertexMap.set(key, idx); + vertices.push(...v); } - return idx + return idx; } return { vertices, indices, add: (v1: Vec3, v2: Vec3, v3: Vec3) => { - indices.push(addVertex(v1), addVertex(v2), addVertex(v3)) + indices.push(addVertex(v1), addVertex(v2), addVertex(v3)); } - } + }; } \ No newline at end of file diff --git a/src/mol-geo/primitive/primitive.ts b/src/mol-geo/primitive/primitive.ts index 991feb53b7dc6ed1ffe633242f1151238175ef21..2de5ee9edd4db9793ae79f80b21b27409cae7045 100644 --- a/src/mol-geo/primitive/primitive.ts +++ b/src/mol-geo/primitive/primitive.ts @@ -13,20 +13,20 @@ export interface Primitive { indices: ArrayLike<number> } -const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero() +const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(); /** Create primitive with face normals from vertices and indices */ export function createPrimitive(vertices: ArrayLike<number>, indices: ArrayLike<number>): Primitive { - const count = indices.length - const builder = PrimitiveBuilder(count / 3) + const count = indices.length; + const builder = PrimitiveBuilder(count / 3); for (let i = 0; i < count; i += 3) { - Vec3.fromArray(a, vertices, indices[i] * 3) - Vec3.fromArray(b, vertices, indices[i + 1] * 3) - Vec3.fromArray(c, vertices, indices[i + 2] * 3) - builder.add(a, b, c) + Vec3.fromArray(a, vertices, indices[i] * 3); + Vec3.fromArray(b, vertices, indices[i + 1] * 3); + Vec3.fromArray(c, vertices, indices[i + 2] * 3); + builder.add(a, b, c); } - return builder.getPrimitive() + return builder.getPrimitive(); } export function copyPrimitive(primitive: Primitive): Primitive { @@ -34,7 +34,7 @@ export function copyPrimitive(primitive: Primitive): Primitive { vertices: new Float32Array(primitive.vertices), normals: new Float32Array(primitive.normals), indices: new Uint32Array(primitive.indices) - } + }; } export interface PrimitiveBuilder { @@ -42,45 +42,45 @@ export interface PrimitiveBuilder { getPrimitive(): Primitive } -const vn = Vec3.zero() +const vn = Vec3.zero(); /** Builder to create primitive with face normals */ export function PrimitiveBuilder(triangleCount: number): PrimitiveBuilder { - const vertices = new Float32Array(triangleCount * 3 * 3) - const normals = new Float32Array(triangleCount * 3 * 3) - const indices = new Uint32Array(triangleCount * 3) - let offset = 0 + const vertices = new Float32Array(triangleCount * 3 * 3); + const normals = new Float32Array(triangleCount * 3 * 3); + const indices = new Uint32Array(triangleCount * 3); + let offset = 0; return { add: (a: Vec3, b: Vec3, c: Vec3) => { - Vec3.toArray(a, vertices, offset) - Vec3.toArray(b, vertices, offset + 3) - Vec3.toArray(c, vertices, offset + 6) - Vec3.triangleNormal(vn, a, b, c) + Vec3.toArray(a, vertices, offset); + Vec3.toArray(b, vertices, offset + 3); + Vec3.toArray(c, vertices, offset + 6); + Vec3.triangleNormal(vn, a, b, c); for (let j = 0; j < 3; ++j) { - Vec3.toArray(vn, normals, offset + 3 * j) - indices[offset / 3 + j] = offset / 3 + j + Vec3.toArray(vn, normals, offset + 3 * j); + indices[offset / 3 + j] = offset / 3 + j; } - offset += 9 + offset += 9; }, getPrimitive: () => ({ vertices, normals, indices }) - } + }; } -const tmpV = Vec3.zero() -const tmpMat3 = Mat3.zero() +const tmpV = Vec3.zero(); +const tmpMat3 = Mat3.zero(); /** Transform primitive in-place */ export function transformPrimitive(primitive: Primitive, t: Mat4) { - const { vertices, normals } = primitive - const n = Mat3.directionTransform(tmpMat3, t) + const { vertices, normals } = primitive; + const n = Mat3.directionTransform(tmpMat3, t); for (let i = 0, il = vertices.length; i < il; i += 3) { // position - Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, vertices, i), t) - Vec3.toArray(tmpV, vertices as NumberArray, i) + Vec3.transformMat4(tmpV, Vec3.fromArray(tmpV, vertices, i), t); + Vec3.toArray(tmpV, vertices as NumberArray, i); // normal - Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, normals, i), n) - Vec3.toArray(tmpV, normals as NumberArray, i) + Vec3.transformMat3(tmpV, Vec3.fromArray(tmpV, normals, i), n); + Vec3.toArray(tmpV, normals as NumberArray, i); } - return primitive + return primitive; } \ No newline at end of file diff --git a/src/mol-geo/primitive/prism.ts b/src/mol-geo/primitive/prism.ts index f019a5bef2e63f29618b125229bd2213282f321e..e2f652ff7302cabf394c8ec25a9d8f1a3737ca5b 100644 --- a/src/mol-geo/primitive/prism.ts +++ b/src/mol-geo/primitive/prism.ts @@ -4,94 +4,94 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3 } from '../../mol-math/linear-algebra' +import { Vec3 } from '../../mol-math/linear-algebra'; import { Primitive, PrimitiveBuilder } from './primitive'; -import { polygon } from './polygon' +import { polygon } from './polygon'; import { Cage } from './cage'; -const on = Vec3(), op = Vec3() -const a = Vec3(), b = Vec3(), c = Vec3(), d = Vec3() +const on = Vec3(), op = Vec3(); +const a = Vec3(), b = Vec3(), c = Vec3(), d = Vec3(); export const DefaultPrismProps = { height: 1, topCap: true, bottomCap: true, -} +}; export type PrismProps = Partial<typeof DefaultPrismProps> /** * Create a prism with a base of 4 or more points */ export function Prism(points: ArrayLike<number>, props?: PrismProps): Primitive { - const sideCount = points.length / 3 - if (sideCount < 4) throw new Error('need at least 4 points to build a prism') + const sideCount = points.length / 3; + if (sideCount < 4) throw new Error('need at least 4 points to build a prism'); const { height, topCap, bottomCap } = { ...DefaultPrismProps, ...props }; - const count = 4 * sideCount - const builder = PrimitiveBuilder(count) - const halfHeight = height * 0.5 + const count = 4 * sideCount; + const builder = PrimitiveBuilder(count); + const halfHeight = height * 0.5; - Vec3.set(on, 0, 0, -halfHeight) - Vec3.set(op, 0, 0, halfHeight) + Vec3.set(on, 0, 0, -halfHeight); + Vec3.set(op, 0, 0, halfHeight); // create sides for (let i = 0; i < sideCount; ++i) { - const ni = (i + 1) % sideCount - Vec3.set(a, points[i * 3], points[i * 3 + 1], -halfHeight) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -halfHeight) - Vec3.set(c, points[ni * 3], points[ni * 3 + 1], halfHeight) - Vec3.set(d, points[i * 3], points[i * 3 + 1], halfHeight) - builder.add(a, b, c) - builder.add(c, d, a) + const ni = (i + 1) % sideCount; + Vec3.set(a, points[i * 3], points[i * 3 + 1], -halfHeight); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -halfHeight); + Vec3.set(c, points[ni * 3], points[ni * 3 + 1], halfHeight); + Vec3.set(d, points[i * 3], points[i * 3 + 1], halfHeight); + builder.add(a, b, c); + builder.add(c, d, a); } // create bases for (let i = 0; i < sideCount; ++i) { - const ni = (i + 1) % sideCount + const ni = (i + 1) % sideCount; if (topCap) { - Vec3.set(a, points[i * 3], points[i * 3 + 1], -halfHeight) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -halfHeight) - builder.add(on, b, a) + Vec3.set(a, points[i * 3], points[i * 3 + 1], -halfHeight); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -halfHeight); + builder.add(on, b, a); } if (bottomCap) { - Vec3.set(a, points[i * 3], points[i * 3 + 1], halfHeight) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], halfHeight) - builder.add(a, b, op) + Vec3.set(a, points[i * 3], points[i * 3 + 1], halfHeight); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], halfHeight); + builder.add(a, b, op); } } - return builder.getPrimitive() + return builder.getPrimitive(); } -let diamond: Primitive +let diamond: Primitive; export function DiamondPrism() { - if (!diamond) diamond = Prism(polygon(4, false)) - return diamond + if (!diamond) diamond = Prism(polygon(4, false)); + return diamond; } -let pentagonalPrism: Primitive +let pentagonalPrism: Primitive; export function PentagonalPrism() { - if (!pentagonalPrism) pentagonalPrism = Prism(polygon(5, false)) - return pentagonalPrism + if (!pentagonalPrism) pentagonalPrism = Prism(polygon(5, false)); + return pentagonalPrism; } -let hexagonalPrism: Primitive +let hexagonalPrism: Primitive; export function HexagonalPrism() { - if (!hexagonalPrism) hexagonalPrism = Prism(polygon(6, false)) - return hexagonalPrism + if (!hexagonalPrism) hexagonalPrism = Prism(polygon(6, false)); + return hexagonalPrism; } -let shiftedHexagonalPrism: Primitive +let shiftedHexagonalPrism: Primitive; export function ShiftedHexagonalPrism() { - if (!shiftedHexagonalPrism) shiftedHexagonalPrism = Prism(polygon(6, true)) - return shiftedHexagonalPrism + if (!shiftedHexagonalPrism) shiftedHexagonalPrism = Prism(polygon(6, true)); + return shiftedHexagonalPrism; } -let heptagonalPrism: Primitive +let heptagonalPrism: Primitive; export function HeptagonalPrism() { - if (!heptagonalPrism) heptagonalPrism = Prism(polygon(7, false)) - return heptagonalPrism + if (!heptagonalPrism) heptagonalPrism = Prism(polygon(7, false)); + return heptagonalPrism; } // @@ -100,51 +100,51 @@ export function HeptagonalPrism() { * Create a prism cage */ export function PrismCage(points: ArrayLike<number>, height = 1): Cage { - const sideCount = points.length / 3 + const sideCount = points.length / 3; - const vertices: number[] = [] - const edges: number[] = [] + const vertices: number[] = []; + const edges: number[] = []; - const halfHeight = height * 0.5 + const halfHeight = height * 0.5; - let offset = 0 + let offset = 0; // vertices and side edges for (let i = 0; i < sideCount; ++i) { vertices.push( points[i * 3], points[i * 3 + 1], -halfHeight, points[i * 3], points[i * 3 + 1], halfHeight - ) - edges.push(offset, offset + 1) - offset += 2 + ); + edges.push(offset, offset + 1); + offset += 2; } // bases edges for (let i = 0; i < sideCount; ++i) { - const ni = (i + 1) % sideCount + const ni = (i + 1) % sideCount; edges.push( i * 2, ni * 2, i * 2 + 1, ni * 2 + 1 - ) + ); } - return { vertices, edges } + return { vertices, edges }; } -let diamondCage: Cage +let diamondCage: Cage; export function DiamondPrismCage() { - if (!diamondCage) diamondCage = PrismCage(polygon(4, false)) - return diamondCage + if (!diamondCage) diamondCage = PrismCage(polygon(4, false)); + return diamondCage; } -let pentagonalPrismCage: Cage +let pentagonalPrismCage: Cage; export function PentagonalPrismCage() { - if (!pentagonalPrismCage) pentagonalPrismCage = PrismCage(polygon(5, false)) - return pentagonalPrismCage + if (!pentagonalPrismCage) pentagonalPrismCage = PrismCage(polygon(5, false)); + return pentagonalPrismCage; } -let hexagonalPrismCage: Cage +let hexagonalPrismCage: Cage; export function HexagonalPrismCage() { - if (!hexagonalPrismCage) hexagonalPrismCage = PrismCage(polygon(6, false)) - return hexagonalPrismCage + if (!hexagonalPrismCage) hexagonalPrismCage = PrismCage(polygon(6, false)); + return hexagonalPrismCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/pyramid.ts b/src/mol-geo/primitive/pyramid.ts index 04f9cc0b4538eb10a8469387efe3120a035dd08a..3c674f5655855bb7311546e637805b797ddacbf6 100644 --- a/src/mol-geo/primitive/pyramid.ts +++ b/src/mol-geo/primitive/pyramid.ts @@ -4,91 +4,91 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3 } from '../../mol-math/linear-algebra' +import { Vec3 } from '../../mol-math/linear-algebra'; import { Primitive, PrimitiveBuilder, createPrimitive } from './primitive'; -import { polygon } from './polygon' +import { polygon } from './polygon'; import { Cage } from './cage'; -const on = Vec3.create(0, 0, -0.5), op = Vec3.create(0, 0, 0.5) -const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero() +const on = Vec3.create(0, 0, -0.5), op = Vec3.create(0, 0, 0.5); +const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero(); /** * Create a pyramid with a polygonal base */ export function Pyramid(points: ArrayLike<number>): Primitive { - const sideCount = points.length / 3 - const baseCount = sideCount === 3 ? 1 : sideCount === 4 ? 2 : sideCount - const count = 2 * baseCount + 2 * sideCount - const builder = PrimitiveBuilder(count) + const sideCount = points.length / 3; + const baseCount = sideCount === 3 ? 1 : sideCount === 4 ? 2 : sideCount; + const count = 2 * baseCount + 2 * sideCount; + const builder = PrimitiveBuilder(count); // create sides for (let i = 0; i < sideCount; ++i) { - const ni = (i + 1) % sideCount - Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5) - builder.add(a, b, op) + const ni = (i + 1) % sideCount; + Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5); + builder.add(a, b, op); } // create base if (sideCount === 3) { - Vec3.set(a, points[0], points[1], -0.5) - Vec3.set(b, points[3], points[4], -0.5) - Vec3.set(c, points[6], points[7], -0.5) - builder.add(c, b, a) + Vec3.set(a, points[0], points[1], -0.5); + Vec3.set(b, points[3], points[4], -0.5); + Vec3.set(c, points[6], points[7], -0.5); + builder.add(c, b, a); } else if (sideCount === 4) { - Vec3.set(a, points[0], points[1], -0.5) - Vec3.set(b, points[3], points[4], -0.5) - Vec3.set(c, points[6], points[7], -0.5) - Vec3.set(d, points[9], points[10], -0.5) - builder.add(c, b, a) - builder.add(a, d, c) + Vec3.set(a, points[0], points[1], -0.5); + Vec3.set(b, points[3], points[4], -0.5); + Vec3.set(c, points[6], points[7], -0.5); + Vec3.set(d, points[9], points[10], -0.5); + builder.add(c, b, a); + builder.add(a, d, c); } else { for (let i = 0; i < sideCount; ++i) { - const ni = (i + 1) % sideCount - Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5) - builder.add(on, b, a) + const ni = (i + 1) % sideCount; + Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5); + builder.add(on, b, a); } } - return builder.getPrimitive() + return builder.getPrimitive(); } -let triangularPyramid: Primitive +let triangularPyramid: Primitive; export function TriangularPyramid() { - if (!triangularPyramid) triangularPyramid = Pyramid(polygon(3, true)) - return triangularPyramid + if (!triangularPyramid) triangularPyramid = Pyramid(polygon(3, true)); + return triangularPyramid; } -let octagonalPyramid: Primitive +let octagonalPyramid: Primitive; export function OctagonalPyramid() { - if (!octagonalPyramid) octagonalPyramid = Pyramid(polygon(8, true)) - return octagonalPyramid + if (!octagonalPyramid) octagonalPyramid = Pyramid(polygon(8, true)); + return octagonalPyramid; } -let perforatedOctagonalPyramid: Primitive +let perforatedOctagonalPyramid: Primitive; export function PerforatedOctagonalPyramid() { if (!perforatedOctagonalPyramid) { - const points = polygon(8, true) - const vertices = new Float32Array(8 * 3 + 6) + const points = polygon(8, true); + const vertices = new Float32Array(8 * 3 + 6); for (let i = 0; i < 8; ++i) { - vertices[i * 3] = points[i * 3] - vertices[i * 3 + 1] = points[i * 3 + 1] - vertices[i * 3 + 2] = -0.5 + vertices[i * 3] = points[i * 3]; + vertices[i * 3 + 1] = points[i * 3 + 1]; + vertices[i * 3 + 2] = -0.5; } - vertices[8 * 3] = 0 - vertices[8 * 3 + 1] = 0 - vertices[8 * 3 + 2] = -0.5 - vertices[8 * 3 + 3] = 0 - vertices[8 * 3 + 4] = 0 - vertices[8 * 3 + 5] = 0.5 + vertices[8 * 3] = 0; + vertices[8 * 3 + 1] = 0; + vertices[8 * 3 + 2] = -0.5; + vertices[8 * 3 + 3] = 0; + vertices[8 * 3 + 4] = 0; + vertices[8 * 3 + 5] = 0.5; const indices: ReadonlyArray<number> = [ 0, 1, 8, 1, 2, 8, 4, 5, 8, 5, 6, 8, 2, 3, 9, 3, 4, 9, 6, 7, 9, 7, 0, 9 ]; - perforatedOctagonalPyramid = createPrimitive(vertices, indices) + perforatedOctagonalPyramid = createPrimitive(vertices, indices); } - return perforatedOctagonalPyramid + return perforatedOctagonalPyramid; } // @@ -97,33 +97,33 @@ export function PerforatedOctagonalPyramid() { * Create a prism cage */ export function PyramidCage(points: ArrayLike<number>): Cage { - const sideCount = points.length / 3 + const sideCount = points.length / 3; // const count = 4 * sideCount - const vertices: number[] = [] - const edges: number[] = [] + const vertices: number[] = []; + const edges: number[] = []; - let offset = 1 - vertices.push(op[0], op[1], op[2]) + let offset = 1; + vertices.push(op[0], op[1], op[2]); // vertices and side edges for (let i = 0; i < sideCount; ++i) { - vertices.push(points[i * 3], points[i * 3 + 1], -0.5) - edges.push(0, offset) - offset += 1 + vertices.push(points[i * 3], points[i * 3 + 1], -0.5); + edges.push(0, offset); + offset += 1; } // bases edges for (let i = 0; i < sideCount; ++i) { - const ni = (i + 1) % sideCount - edges.push(i + 1, ni + 1) + const ni = (i + 1) % sideCount; + edges.push(i + 1, ni + 1); } - return { vertices, edges } + return { vertices, edges }; } -let octagonalPyramidCage: Cage +let octagonalPyramidCage: Cage; export function OctagonalPyramidCage() { - if (!octagonalPyramidCage) octagonalPyramidCage = PyramidCage(polygon(8, true)) - return octagonalPyramidCage + if (!octagonalPyramidCage) octagonalPyramidCage = PyramidCage(polygon(8, true)); + return octagonalPyramidCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/sphere.ts b/src/mol-geo/primitive/sphere.ts index 25704b7c1be233d7240a7521795d09db3cde41b2..392802a49bbaf8a62683d94df5e9dd5f3b18e102 100644 --- a/src/mol-geo/primitive/sphere.ts +++ b/src/mol-geo/primitive/sphere.ts @@ -4,18 +4,18 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Polyhedron } from './polyhedron' -import { Icosahedron } from './icosahedron' +import { Polyhedron } from './polyhedron'; +import { Icosahedron } from './icosahedron'; import { Primitive } from './primitive'; -const { vertices, indices } = Icosahedron() +const { vertices, indices } = Icosahedron(); /** Calculate vertex count for subdived icosahedron */ export function sphereVertexCount(detail: number) { - return 10 * Math.pow(Math.pow(2, detail), 2) + 2 + return 10 * Math.pow(Math.pow(2, detail), 2) + 2; } /** Create sphere by subdividing an icosahedron */ export function Sphere(detail: number): Primitive { - return Polyhedron(vertices, indices, { detail, radius: 1 }) + return Polyhedron(vertices, indices, { detail, radius: 1 }); } \ No newline at end of file diff --git a/src/mol-geo/primitive/spiked-ball.ts b/src/mol-geo/primitive/spiked-ball.ts index 8313c2da1425548881144fa49b7bbdfdedcb5602..8c46cfa5d89e322df864df928bb9ab6b19750c61 100644 --- a/src/mol-geo/primitive/spiked-ball.ts +++ b/src/mol-geo/primitive/spiked-ball.ts @@ -9,54 +9,54 @@ import { dodecahedronVertices, dodecahedronFaces } from './dodecahedron'; import { Vec3 } from '../../mol-math/linear-algebra'; function calcCenter(out: Vec3, ...vec3s: Vec3[]) { - Vec3.set(out, 0, 0, 0) + Vec3.set(out, 0, 0, 0); for (let i = 0, il = vec3s.length; i < il; ++i) { - Vec3.add(out, out, vec3s[i]) + Vec3.add(out, out, vec3s[i]); } - Vec3.scale(out, out, 1 / vec3s.length) - return out + Vec3.scale(out, out, 1 / vec3s.length); + return out; } -const center = Vec3.zero() -const dir = Vec3.zero() -const tip = Vec3.zero() +const center = Vec3.zero(); +const dir = Vec3.zero(); +const tip = Vec3.zero(); -const vecA = Vec3.zero() -const vecB = Vec3.zero() -const vecC = Vec3.zero() -const vecD = Vec3.zero() -const vecE = Vec3.zero() +const vecA = Vec3.zero(); +const vecB = Vec3.zero(); +const vecC = Vec3.zero(); +const vecD = Vec3.zero(); +const vecE = Vec3.zero(); /** * Create a spiked ball derived from a dodecahedron * @param radiusRatio ratio between inner radius (dodecahedron) and outher radius (spikes) */ export function SpikedBall(radiusRatio = 1): Primitive { - const vertices = dodecahedronVertices.slice(0) - const indices: number[] = [] + const vertices = dodecahedronVertices.slice(0); + const indices: number[] = []; - let offset = vertices.length / 3 + let offset = vertices.length / 3; for (let i = 0, il = dodecahedronFaces.length; i < il; i += 5) { - Vec3.fromArray(vecA, dodecahedronVertices, dodecahedronFaces[i] * 3) - Vec3.fromArray(vecB, dodecahedronVertices, dodecahedronFaces[i + 1] * 3) - Vec3.fromArray(vecC, dodecahedronVertices, dodecahedronFaces[i + 2] * 3) - Vec3.fromArray(vecD, dodecahedronVertices, dodecahedronFaces[i + 3] * 3) - Vec3.fromArray(vecE, dodecahedronVertices, dodecahedronFaces[i + 4] * 3) - - calcCenter(center, vecA, vecB, vecC, vecD, vecE) - Vec3.triangleNormal(dir, vecA, vecB, vecC) - Vec3.scaleAndAdd(tip, center, dir, radiusRatio) - - Vec3.toArray(tip, vertices, offset * 3) - indices.push(offset, dodecahedronFaces[i], dodecahedronFaces[i + 1]) - indices.push(offset, dodecahedronFaces[i + 1], dodecahedronFaces[i + 2]) - indices.push(offset, dodecahedronFaces[i + 2], dodecahedronFaces[i + 3]) - indices.push(offset, dodecahedronFaces[i + 3], dodecahedronFaces[i + 4]) - indices.push(offset, dodecahedronFaces[i + 4], dodecahedronFaces[i]) - - offset += 1 + Vec3.fromArray(vecA, dodecahedronVertices, dodecahedronFaces[i] * 3); + Vec3.fromArray(vecB, dodecahedronVertices, dodecahedronFaces[i + 1] * 3); + Vec3.fromArray(vecC, dodecahedronVertices, dodecahedronFaces[i + 2] * 3); + Vec3.fromArray(vecD, dodecahedronVertices, dodecahedronFaces[i + 3] * 3); + Vec3.fromArray(vecE, dodecahedronVertices, dodecahedronFaces[i + 4] * 3); + + calcCenter(center, vecA, vecB, vecC, vecD, vecE); + Vec3.triangleNormal(dir, vecA, vecB, vecC); + Vec3.scaleAndAdd(tip, center, dir, radiusRatio); + + Vec3.toArray(tip, vertices, offset * 3); + indices.push(offset, dodecahedronFaces[i], dodecahedronFaces[i + 1]); + indices.push(offset, dodecahedronFaces[i + 1], dodecahedronFaces[i + 2]); + indices.push(offset, dodecahedronFaces[i + 2], dodecahedronFaces[i + 3]); + indices.push(offset, dodecahedronFaces[i + 3], dodecahedronFaces[i + 4]); + indices.push(offset, dodecahedronFaces[i + 4], dodecahedronFaces[i]); + + offset += 1; } - return createPrimitive(vertices, indices) + return createPrimitive(vertices, indices); } \ No newline at end of file diff --git a/src/mol-geo/primitive/star.ts b/src/mol-geo/primitive/star.ts index ce5201114de4e1ffc276ee3f18e228cb72f9879d..790008a082801ec02572ab40f696bd43a02a31a2 100644 --- a/src/mol-geo/primitive/star.ts +++ b/src/mol-geo/primitive/star.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3 } from '../../mol-math/linear-algebra' +import { Vec3 } from '../../mol-math/linear-algebra'; import { Primitive, PrimitiveBuilder } from './primitive'; export const DefaultStarProps = { @@ -12,44 +12,44 @@ export const DefaultStarProps = { outerRadius: 1, innerRadius: 0.5, thickness: 0.3 -} +}; export type StarProps = Partial<typeof DefaultStarProps> -const op = Vec3.zero(), on = Vec3.zero() -const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero() +const op = Vec3.zero(), on = Vec3.zero(); +const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(); export function Star(props?: StarProps): Primitive { - const { outerRadius, innerRadius, thickness, pointCount } = { ...DefaultStarProps, ...props } + const { outerRadius, innerRadius, thickness, pointCount } = { ...DefaultStarProps, ...props }; - const triangleCount = pointCount * 2 * 2 - const builder = PrimitiveBuilder(triangleCount) + const triangleCount = pointCount * 2 * 2; + const builder = PrimitiveBuilder(triangleCount); - const innerPoints = new Float32Array(pointCount * 2) - const outerPoints = new Float32Array(pointCount * 2) + const innerPoints = new Float32Array(pointCount * 2); + const outerPoints = new Float32Array(pointCount * 2); for (let i = 0; i < pointCount; ++i) { - const io = i * 2, ii = i * 2 + 1 - const co = (io + 1) / pointCount * Math.PI, ci = (ii + 1) / pointCount * Math.PI - outerPoints[io] = Math.cos(co) * outerRadius - outerPoints[ii] = Math.sin(co) * outerRadius - innerPoints[io] = Math.cos(ci) * innerRadius - innerPoints[ii] = Math.sin(ci) * innerRadius + const io = i * 2, ii = i * 2 + 1; + const co = (io + 1) / pointCount * Math.PI, ci = (ii + 1) / pointCount * Math.PI; + outerPoints[io] = Math.cos(co) * outerRadius; + outerPoints[ii] = Math.sin(co) * outerRadius; + innerPoints[io] = Math.cos(ci) * innerRadius; + innerPoints[ii] = Math.sin(ci) * innerRadius; } - Vec3.set(op, 0, 0, thickness / 2) - Vec3.set(on, 0, 0, -thickness / 2) + Vec3.set(op, 0, 0, thickness / 2); + Vec3.set(on, 0, 0, -thickness / 2); for (let i = 0; i < pointCount; ++i) { - const ni = (i + 1) % pointCount - Vec3.set(a, outerPoints[i * 2], outerPoints[i * 2 + 1], 0) - Vec3.set(b, innerPoints[i * 2], innerPoints[i * 2 + 1], 0) - Vec3.set(c, outerPoints[ni * 2], outerPoints[ni * 2 + 1], 0) - - builder.add(op, a, b) - builder.add(b, a, on) - builder.add(op, b, c) - builder.add(c, b, on) + const ni = (i + 1) % pointCount; + Vec3.set(a, outerPoints[i * 2], outerPoints[i * 2 + 1], 0); + Vec3.set(b, innerPoints[i * 2], innerPoints[i * 2 + 1], 0); + Vec3.set(c, outerPoints[ni * 2], outerPoints[ni * 2 + 1], 0); + + builder.add(op, a, b); + builder.add(b, a, on); + builder.add(op, b, c); + builder.add(c, b, on); } - return builder.getPrimitive() + return builder.getPrimitive(); } \ No newline at end of file diff --git a/src/mol-geo/primitive/tetrahedron.ts b/src/mol-geo/primitive/tetrahedron.ts index f43c372417d9a503c1b1d31e745a2aaf3f1b27b6..940fe624f90afd1136ce9bcc8305cff97f5176e1 100644 --- a/src/mol-geo/primitive/tetrahedron.ts +++ b/src/mol-geo/primitive/tetrahedron.ts @@ -18,15 +18,15 @@ export const tetrahedronIndices: ReadonlyArray<number> = [ const tetrahedronEdges: ReadonlyArray<number> = [ 0, 1, 1, 2, 2, 0, 0, 3, 1, 3, 2, 3, -] +]; -let tetrahedron: Primitive +let tetrahedron: Primitive; export function Tetrahedron(): Primitive { - if (!tetrahedron) tetrahedron = createPrimitive(tetrahedronVertices, tetrahedronIndices) - return tetrahedron + if (!tetrahedron) tetrahedron = createPrimitive(tetrahedronVertices, tetrahedronIndices); + return tetrahedron; } -const tetrahedronCage = createCage(tetrahedronVertices, tetrahedronEdges) +const tetrahedronCage = createCage(tetrahedronVertices, tetrahedronEdges); export function TetrahedronCage(): Cage { - return tetrahedronCage + return tetrahedronCage; } \ No newline at end of file diff --git a/src/mol-geo/primitive/wedge.ts b/src/mol-geo/primitive/wedge.ts index c1bddeec299f2d802dbe3c5a86ad85f7f85f6965..e8a480010074e9b73789e8928b27d228bce70205 100644 --- a/src/mol-geo/primitive/wedge.ts +++ b/src/mol-geo/primitive/wedge.ts @@ -4,53 +4,53 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3 } from '../../mol-math/linear-algebra' +import { Vec3 } from '../../mol-math/linear-algebra'; import { Primitive, PrimitiveBuilder } from './primitive'; -import { polygon } from './polygon' +import { polygon } from './polygon'; import { PrismCage } from './prism'; import { Cage } from './cage'; -const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero() -const points = polygon(3, false) +const a = Vec3.zero(), b = Vec3.zero(), c = Vec3.zero(), d = Vec3.zero(); +const points = polygon(3, false); /** * Create a prism with a triangular base */ export function createWedge(): Primitive { - const builder = PrimitiveBuilder(8) + const builder = PrimitiveBuilder(8); // create sides for (let i = 0; i < 3; ++i) { - const ni = (i + 1) % 3 - Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5) - Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5) - Vec3.set(c, points[ni * 3], points[ni * 3 + 1], 0.5) - Vec3.set(d, points[i * 3], points[i * 3 + 1], 0.5) - builder.add(a, b, c) - builder.add(c, d, a) + const ni = (i + 1) % 3; + Vec3.set(a, points[i * 3], points[i * 3 + 1], -0.5); + Vec3.set(b, points[ni * 3], points[ni * 3 + 1], -0.5); + Vec3.set(c, points[ni * 3], points[ni * 3 + 1], 0.5); + Vec3.set(d, points[i * 3], points[i * 3 + 1], 0.5); + builder.add(a, b, c); + builder.add(c, d, a); } // create bases - Vec3.set(a, points[0], points[1], -0.5) - Vec3.set(b, points[3], points[4], -0.5) - Vec3.set(c, points[6], points[7], -0.5) - builder.add(c, b, a) - Vec3.set(a, points[0], points[1], 0.5) - Vec3.set(b, points[3], points[4], 0.5) - Vec3.set(c, points[6], points[7], 0.5) - builder.add(a, b, c) - - return builder.getPrimitive() + Vec3.set(a, points[0], points[1], -0.5); + Vec3.set(b, points[3], points[4], -0.5); + Vec3.set(c, points[6], points[7], -0.5); + builder.add(c, b, a); + Vec3.set(a, points[0], points[1], 0.5); + Vec3.set(b, points[3], points[4], 0.5); + Vec3.set(c, points[6], points[7], 0.5); + builder.add(a, b, c); + + return builder.getPrimitive(); } -let wedge: Primitive +let wedge: Primitive; export function Wedge() { - if (!wedge) wedge = createWedge() - return wedge + if (!wedge) wedge = createWedge(); + return wedge; } -let wedgeCage: Cage +let wedgeCage: Cage; export function WedgeCage() { - if (!wedgeCage) wedgeCage = PrismCage(points) - return wedgeCage + if (!wedgeCage) wedgeCage = PrismCage(points); + return wedgeCage; } \ No newline at end of file diff --git a/src/mol-geo/util.ts b/src/mol-geo/util.ts index 86da27722e29e80660930adf7190726c8f53aa68..43bc5f83e056d0c12511235fe54b3056ffa4fba5 100644 --- a/src/mol-geo/util.ts +++ b/src/mol-geo/util.ts @@ -4,56 +4,56 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3, Mat4, Mat3 } from '../mol-math/linear-algebra' +import { Vec3, Mat4, Mat3 } from '../mol-math/linear-algebra'; import { NumberArray } from '../mol-util/type-helpers'; import { arrayMax } from '../mol-util/array'; export function normalizeVec3Array<T extends NumberArray> (a: T, count: number) { for (let i = 0, il = count * 3; i < il; i += 3) { - const x = a[i] - const y = a[i + 1] - const z = a[i + 2] - const s = 1 / Math.sqrt(x * x + y * y + z * z) - a[i] = x * s - a[i + 1] = y * s - a[i + 2] = z * s + const x = a[i]; + const y = a[i + 1]; + const z = a[i + 2]; + const s = 1 / Math.sqrt(x * x + y * y + z * z); + a[i] = x * s; + a[i + 1] = y * s; + a[i + 2] = z * s; } - return a + return a; } -const tmpV3 = Vec3.zero() +const tmpV3 = Vec3.zero(); export function transformPositionArray (t: Mat4, array: NumberArray, offset: number, count: number) { for (let i = 0, il = count * 3; i < il; i += 3) { - Vec3.fromArray(tmpV3, array, offset + i) - Vec3.transformMat4(tmpV3, tmpV3, t) - Vec3.toArray(tmpV3, array, offset + i) + Vec3.fromArray(tmpV3, array, offset + i); + Vec3.transformMat4(tmpV3, tmpV3, t); + Vec3.toArray(tmpV3, array, offset + i); } } export function transformDirectionArray (n: Mat3, array: NumberArray, offset: number, count: number) { for (let i = 0, il = count * 3; i < il; i += 3) { - Vec3.fromArray(tmpV3, array, offset + i) - Vec3.transformMat3(tmpV3, tmpV3, n) - Vec3.toArray(tmpV3, array, offset + i) + Vec3.fromArray(tmpV3, array, offset + i); + Vec3.transformMat3(tmpV3, tmpV3, n); + Vec3.toArray(tmpV3, array, offset + i); } } /** iterate over the entire array and apply the radius to each vertex */ export function appplyRadius(vertices: NumberArray, radius: number) { for (let i = 0, il = vertices.length; i < il; i += 3) { - Vec3.fromArray(tmpV3, vertices, i) - Vec3.normalize(tmpV3, tmpV3) - Vec3.scale(tmpV3, tmpV3, radius) - Vec3.toArray(tmpV3, vertices, i) + Vec3.fromArray(tmpV3, vertices, i); + Vec3.normalize(tmpV3, tmpV3); + Vec3.scale(tmpV3, tmpV3, radius); + Vec3.toArray(tmpV3, vertices, i); } } -const a = Vec3() -const b = Vec3() -const c = Vec3() -const cb = Vec3() -const ab = Vec3() +const a = Vec3(); +const b = Vec3(); +const c = Vec3(); +const cb = Vec3(); +const ab = Vec3(); /** * indexed vertex normals weighted by triangle areas @@ -63,32 +63,32 @@ const ab = Vec3() export function computeIndexedVertexNormals<T extends NumberArray> (vertices: NumberArray, indices: NumberArray, normals: T, vertexCount: number, triangleCount: number) { for (let i = 0, il = triangleCount * 3; i < il; i += 3) { - const ai = indices[i] * 3 - const bi = indices[i + 1] * 3 - const ci = indices[i + 2] * 3 + const ai = indices[i] * 3; + const bi = indices[i + 1] * 3; + const ci = indices[i + 2] * 3; - Vec3.fromArray(a, vertices, ai) - Vec3.fromArray(b, vertices, bi) - Vec3.fromArray(c, vertices, ci) + Vec3.fromArray(a, vertices, ai); + Vec3.fromArray(b, vertices, bi); + Vec3.fromArray(c, vertices, ci); - Vec3.sub(cb, c, b) - Vec3.sub(ab, a, b) - Vec3.cross(cb, cb, ab) + Vec3.sub(cb, c, b); + Vec3.sub(ab, a, b); + Vec3.cross(cb, cb, ab); - normals[ai] += cb[0] - normals[ai + 1] += cb[1] - normals[ai + 2] += cb[2] + normals[ai] += cb[0]; + normals[ai + 1] += cb[1]; + normals[ai + 2] += cb[2]; - normals[bi] += cb[0] - normals[bi + 1] += cb[1] - normals[bi + 2] += cb[2] + normals[bi] += cb[0]; + normals[bi + 1] += cb[1]; + normals[bi + 2] += cb[2]; - normals[ci] += cb[0] - normals[ci + 1] += cb[1] - normals[ci + 2] += cb[2] + normals[ci] += cb[0]; + normals[ci + 1] += cb[1]; + normals[ci + 2] += cb[2]; } - return normalizeVec3Array(normals, vertexCount) + return normalizeVec3Array(normals, vertexCount); } /** @@ -97,28 +97,28 @@ export function computeIndexedVertexNormals<T extends NumberArray> (vertices: Nu */ export function computeVertexNormals<T extends NumberArray> (vertices: NumberArray, normals: T, vertexCount: number) { for (let i = 0, il = vertexCount * 3; i < il; i += 9) { - Vec3.fromArray(a, vertices, i) - Vec3.fromArray(b, vertices, i + 3) - Vec3.fromArray(c, vertices, i + 6) + Vec3.fromArray(a, vertices, i); + Vec3.fromArray(b, vertices, i + 3); + Vec3.fromArray(c, vertices, i + 6); - Vec3.sub(cb, c, b) - Vec3.sub(ab, a, b) - Vec3.cross(cb, cb, ab) + Vec3.sub(cb, c, b); + Vec3.sub(ab, a, b); + Vec3.cross(cb, cb, ab); - normals[i] = cb[0] - normals[i + 1] = cb[1] - normals[i + 2] = cb[2] + normals[i] = cb[0]; + normals[i + 1] = cb[1]; + normals[i + 2] = cb[2]; - normals[i + 3] = cb[0] - normals[i + 4] = cb[1] - normals[i + 5] = cb[2] + normals[i + 3] = cb[0]; + normals[i + 4] = cb[1]; + normals[i + 5] = cb[2]; - normals[i + 6] = cb[0] - normals[i + 7] = cb[1] - normals[i + 8] = cb[2] + normals[i + 6] = cb[0]; + normals[i + 7] = cb[1]; + normals[i + 8] = cb[2]; } - return normalizeVec3Array(normals, vertexCount) + return normalizeVec3Array(normals, vertexCount); } /** @@ -135,28 +135,28 @@ export type GroupMapping = { * The `step` parameter allows to skip over repeated values in `groups` */ export function createGroupMapping(groups: ArrayLike<number>, dataCount: number, step = 1): GroupMapping { - const maxId = arrayMax(groups) + const maxId = arrayMax(groups); - const offsets = new Int32Array(maxId + 2) - const bucketFill = new Int32Array(dataCount) - const bucketSizes = new Int32Array(dataCount) + const offsets = new Int32Array(maxId + 2); + const bucketFill = new Int32Array(dataCount); + const bucketSizes = new Int32Array(dataCount); - for (let i = 0, il = dataCount * step; i < il; i += step) ++bucketSizes[groups[i]] + for (let i = 0, il = dataCount * step; i < il; i += step) ++bucketSizes[groups[i]]; - let offset = 0 + let offset = 0; for (let i = 0; i < dataCount; i++) { - offsets[i] = offset - offset += bucketSizes[i] + offsets[i] = offset; + offset += bucketSizes[i]; } - offsets[dataCount] = offset + offsets[dataCount] = offset; - const indices = new Int32Array(offset) + const indices = new Int32Array(offset); for (let i = 0, il = dataCount * step; i < il; i += step) { - const g = groups[i] - const og = offsets[g] + bucketFill[g] - indices[og] = i - ++bucketFill[g] + const g = groups[i]; + const og = offsets[g] + bucketFill[g]; + indices[og] = i; + ++bucketFill[g]; } - return { indices, offsets } + return { indices, offsets }; } diff --git a/src/mol-geo/util/location-iterator.ts b/src/mol-geo/util/location-iterator.ts index c561f659a94d5ab538c0ab757a976246f19a5d56..801e9ea3ff2e1f88a8ba0eff3e5a9c40f5c2dd44 100644 --- a/src/mol-geo/util/location-iterator.ts +++ b/src/mol-geo/util/location-iterator.ts @@ -21,7 +21,7 @@ export const NullLocationValue: LocationValue = { groupIndex: 0, instanceIndex: 0, isSecondary: false -} +}; export interface LocationIterator extends Iterator<LocationValue> { readonly hasNext: boolean @@ -46,57 +46,57 @@ export function LocationIterator(groupCount: number, instanceCount: number, getL groupIndex: 0, instanceIndex: 0, isSecondary: false - } + }; - let hasNext = value.groupIndex < groupCount - let isNextNewInstance = false - let groupIndex = 0 - let instanceIndex = 0 + let hasNext = value.groupIndex < groupCount; + let isNextNewInstance = false; + let groupIndex = 0; + let instanceIndex = 0; return { - get hasNext () { return hasNext }, - get isNextNewInstance () { return isNextNewInstance }, + get hasNext () { return hasNext; }, + get isNextNewInstance () { return isNextNewInstance; }, groupCount, instanceCount, count: groupCount * instanceCount, isComplex, move() { if (hasNext) { - value.groupIndex = groupIndex - value.instanceIndex = instanceIndex - value.index = instanceIndex * groupCount + groupIndex - value.location = getLocation(groupIndex, instanceIndex) - value.isSecondary = isSecondary(groupIndex, instanceIndex) - ++groupIndex + value.groupIndex = groupIndex; + value.instanceIndex = instanceIndex; + value.index = instanceIndex * groupCount + groupIndex; + value.location = getLocation(groupIndex, instanceIndex); + value.isSecondary = isSecondary(groupIndex, instanceIndex); + ++groupIndex; if (groupIndex === groupCount) { - ++instanceIndex - isNextNewInstance = true - if (instanceIndex < instanceCount) groupIndex = 0 + ++instanceIndex; + isNextNewInstance = true; + if (instanceIndex < instanceCount) groupIndex = 0; } else { - isNextNewInstance = false + isNextNewInstance = false; } - hasNext = groupIndex < groupCount + hasNext = groupIndex < groupCount; } - return value + return value; }, reset() { - value.location = NullLocation - value.index = 0 - value.groupIndex = 0 - value.instanceIndex = 0 - value.isSecondary = false + value.location = NullLocation; + value.index = 0; + value.groupIndex = 0; + value.instanceIndex = 0; + value.isSecondary = false; - hasNext = value.groupIndex < groupCount - isNextNewInstance = false - groupIndex = 0 - instanceIndex = 0 + hasNext = value.groupIndex < groupCount; + isNextNewInstance = false; + groupIndex = 0; + instanceIndex = 0; }, skipInstance() { if (hasNext && value.instanceIndex === instanceIndex) { - ++instanceIndex - groupIndex = 0 - hasNext = instanceIndex < instanceCount + ++instanceIndex; + groupIndex = 0; + hasNext = instanceIndex < instanceCount; } } - } + }; } \ No newline at end of file diff --git a/src/mol-geo/util/marching-cubes/algorithm.ts b/src/mol-geo/util/marching-cubes/algorithm.ts index 006637f51c4011adca2d195d51e699ec29da1b71..2e4b5e4de34d41391f715b98775320accbea1bb0 100644 --- a/src/mol-geo/util/marching-cubes/algorithm.ts +++ b/src/mol-geo/util/marching-cubes/algorithm.ts @@ -5,11 +5,11 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Task, RuntimeContext } from '../../../mol-task' -import { Tensor } from '../../../mol-math/linear-algebra' -import { Mesh } from '../../geometry/mesh/mesh' -import { Index, EdgeIdInfo, CubeEdges, EdgeTable, TriTable } from './tables' -import { defaults } from '../../../mol-util' +import { Task, RuntimeContext } from '../../../mol-task'; +import { Tensor } from '../../../mol-math/linear-algebra'; +import { Mesh } from '../../geometry/mesh/mesh'; +import { Index, EdgeIdInfo, CubeEdges, EdgeTable, TriTable } from './tables'; +import { defaults } from '../../../mol-util'; import { MarchinCubesBuilder, MarchinCubesMeshBuilder, MarchinCubesLinesBuilder } from './builder'; import { Lines } from '../../geometry/lines/lines'; @@ -34,7 +34,7 @@ function getInputParams(params: MarchingCubesParams): MarchingCubesInputParams { ...params, bottomLeft: defaults(params.bottomLeft, [0, 0, 0] as ReadonlyArray<number>), topRight: defaults(params.topRight, params.scalarField.space.dimensions) - } + }; } function getExtent(inputParams: MarchingCubesInputParams) { @@ -42,30 +42,30 @@ function getExtent(inputParams: MarchingCubesInputParams) { dX: inputParams.topRight[0] - inputParams.bottomLeft[0], dY: inputParams.topRight[1] - inputParams.bottomLeft[1], dZ: inputParams.topRight[2] - inputParams.bottomLeft[2] - } + }; } export function computeMarchingCubesMesh(params: MarchingCubesParams, mesh?: Mesh) { return Task.create('Marching Cubes Mesh', async ctx => { - const inputParams = getInputParams(params) - const { dX, dY, dZ } = getExtent(inputParams) + const inputParams = getInputParams(params); + const { dX, dY, dZ } = getExtent(inputParams); // TODO should it be configurable? Scalar fields can produce meshes with vastly different densities. - const vertexChunkSize = Math.min(262144, Math.max(dX * dY * dZ / 32, 1024)) - const builder = MarchinCubesMeshBuilder(vertexChunkSize, mesh) - await (new MarchingCubesComputation(ctx, builder, inputParams)).run() - return builder.get() + const vertexChunkSize = Math.min(262144, Math.max(dX * dY * dZ / 32, 1024)); + const builder = MarchinCubesMeshBuilder(vertexChunkSize, mesh); + await (new MarchingCubesComputation(ctx, builder, inputParams)).run(); + return builder.get(); }); } export function computeMarchingCubesLines(params: MarchingCubesParams, lines?: Lines) { return Task.create('Marching Cubes Lines', async ctx => { - const inputParams = getInputParams(params) - const { dX, dY, dZ } = getExtent(inputParams) + const inputParams = getInputParams(params); + const { dX, dY, dZ } = getExtent(inputParams); // TODO should it be configurable? Scalar fields can produce meshes with vastly different densities. - const vertexChunkSize = Math.min(262144, Math.max(dX * dY * dZ / 32, 1024)) - const builder = MarchinCubesLinesBuilder(vertexChunkSize, lines) - await (new MarchingCubesComputation(ctx, builder, inputParams)).run() - return builder.get() + const vertexChunkSize = Math.min(262144, Math.max(dX * dY * dZ / 32, 1024)); + const builder = MarchinCubesLinesBuilder(vertexChunkSize, lines); + await (new MarchingCubesComputation(ctx, builder, inputParams)).run(); + return builder.get(); }); } @@ -81,7 +81,7 @@ class MarchingCubesComputation { private async doSlices() { let done = 0; - this.edgeFilter = 15 + this.edgeFilter = 15; for (let k = this.minZ; k < this.maxZ; k++, this.edgeFilter &= ~4) { this.slice(k); @@ -93,9 +93,9 @@ class MarchingCubesComputation { } private slice(k: number) { - this.edgeFilter |= 2 + this.edgeFilter |= 2; for (let j = this.minY; j < this.maxY; j++, this.edgeFilter &= ~2) { - this.edgeFilter |= 1 + this.edgeFilter |= 1; for (let i = this.minX; i < this.maxX; i++, this.edgeFilter &= ~1) { this.state.processCell(i, j, k, this.edgeFilter); } @@ -155,8 +155,8 @@ class MarchingCubesState { const ret = this.verticesOnEdges[edgeId]; if (ret > 0) return ret - 1; - const sf = this.scalarField - const sfg = this.scalarFieldGet + const sf = this.scalarField; + const sfg = this.scalarFieldGet; const edge = CubeEdges[edgeNum]; const a = edge.a, b = edge.b; @@ -168,12 +168,12 @@ class MarchingCubesState { if (this.idField) { const u = this.idFieldGet!(this.idField, li, lj, lk); - const v = this.idFieldGet!(this.idField, hi, hj, hk) + const v = this.idFieldGet!(this.idField, hi, hj, hk); let a = t < 0.5 ? u : v; // -1 means 'no id', check if the other cell has an id if (a === -1) a = t < 0.5 ? v : u; // -2 means 'ignore this cell' - if (a === -2) return -1 + if (a === -2) return -1; this.builder.addGroup(a); } else { this.builder.addGroup(0); @@ -188,19 +188,19 @@ class MarchingCubesState { // TODO cache scalarField differences for slices // TODO make calculation optional - const n0x = sfg(sf, Math.max(0, li - 1), lj, lk) - sfg(sf, Math.min(this.nX - 1, li + 1), lj, lk) - const n0y = sfg(sf, li, Math.max(0, lj - 1), lk) - sfg(sf, li, Math.min(this.nY - 1, lj + 1), lk) - const n0z = sfg(sf, li, lj, Math.max(0, lk - 1)) - sfg(sf, li, lj, Math.min(this.nZ, lk + 1)) + const n0x = sfg(sf, Math.max(0, li - 1), lj, lk) - sfg(sf, Math.min(this.nX - 1, li + 1), lj, lk); + const n0y = sfg(sf, li, Math.max(0, lj - 1), lk) - sfg(sf, li, Math.min(this.nY - 1, lj + 1), lk); + const n0z = sfg(sf, li, lj, Math.max(0, lk - 1)) - sfg(sf, li, lj, Math.min(this.nZ, lk + 1)); - const n1x = sfg(sf, Math.max(0, hi - 1), hj, hk) - sfg(sf, Math.min(this.nX - 1, hi + 1), hj, hk) - const n1y = sfg(sf, hi, Math.max(0, hj - 1), hk) - sfg(sf, hi, Math.min(this.nY - 1, hj + 1), hk) - const n1z = sfg(sf, hi, hj, Math.max(0, hk - 1)) - sfg(sf, hi, hj, Math.min(this.nZ - 1, hk + 1)) + const n1x = sfg(sf, Math.max(0, hi - 1), hj, hk) - sfg(sf, Math.min(this.nX - 1, hi + 1), hj, hk); + const n1y = sfg(sf, hi, Math.max(0, hj - 1), hk) - sfg(sf, hi, Math.min(this.nY - 1, hj + 1), hk); + const n1z = sfg(sf, hi, hj, Math.max(0, hk - 1)) - sfg(sf, hi, hj, Math.min(this.nZ - 1, hk + 1)); this.builder.addNormal( n0x + t * (n0x - n1x), n0y + t * (n0y - n1y), n0z + t * (n0z - n1z) - ) + ); return id; } @@ -255,7 +255,7 @@ class MarchingCubesState { const triInfo = TriTable[tableIndex]; for (let t = 0; t < triInfo.length; t += 3) { - this.builder.addTriangle(this.vertList, triInfo[t], triInfo[t + 1], triInfo[t + 2], edgeFilter) + this.builder.addTriangle(this.vertList, triInfo[t], triInfo[t + 1], triInfo[t + 2], edgeFilter); } } } \ No newline at end of file diff --git a/src/mol-geo/util/marching-cubes/builder.ts b/src/mol-geo/util/marching-cubes/builder.ts index 6b1ebeba1894e339691d14ef5afb1d85f3db6b32..7ef3bc46f858c343bf4c15880b0c01bf439d2c28 100644 --- a/src/mol-geo/util/marching-cubes/builder.ts +++ b/src/mol-geo/util/marching-cubes/builder.ts @@ -22,19 +22,19 @@ export interface MarchinCubesBuilder<T> { } export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): MarchinCubesBuilder<Mesh> { - const triangleChunkSize = Math.min(1 << 16, vertexChunkSize * 4) + const triangleChunkSize = Math.min(1 << 16, vertexChunkSize * 4); const vertices = ChunkedArray.create(Float32Array, 3, vertexChunkSize, mesh && mesh.vertexBuffer.ref.value); const normals = ChunkedArray.create(Float32Array, 3, vertexChunkSize, mesh && mesh.normalBuffer.ref.value); const groups = ChunkedArray.create(Float32Array, 1, vertexChunkSize, mesh && mesh.groupBuffer.ref.value); const indices = ChunkedArray.create(Uint32Array, 3, triangleChunkSize, mesh && mesh.indexBuffer.ref.value); - let vertexCount = 0 - let triangleCount = 0 + let vertexCount = 0; + let triangleCount = 0; return { addVertex: (x: number, y: number, z: number) => { - ++vertexCount + ++vertexCount; return ChunkedArray.add3(vertices, x, y, z ); }, addNormal: (x: number, y: number, z: number) => { @@ -44,12 +44,12 @@ export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): M ChunkedArray.add(groups, group); }, addTriangle: (vertList: number[], a: number, b: number, c: number) => { - const i = vertList[a], j = vertList[b], k = vertList[c] + const i = vertList[a], j = vertList[b], k = vertList[c]; // vertex indices <0 mean that the vertex was ignored and is not available // and hence we don't add a triangle when this occurs if (i >= 0 && j >= 0 && k >= 0) { - ++triangleCount - ChunkedArray.add3(indices, i, j, k) + ++triangleCount; + ChunkedArray.add3(indices, i, j, k); } }, get: () => { @@ -57,9 +57,9 @@ export function MarchinCubesMeshBuilder(vertexChunkSize: number, mesh?: Mesh): M const nb = ChunkedArray.compact(normals, true) as Float32Array; const ib = ChunkedArray.compact(indices, true) as Uint32Array; const gb = ChunkedArray.compact(groups, true) as Float32Array; - return Mesh.create(vb, ib, nb, gb, vertexCount, triangleCount, mesh) + return Mesh.create(vb, ib, nb, gb, vertexCount, triangleCount, mesh); } - } + }; } export function MarchinCubesLinesBuilder(vertexChunkSize: number, lines?: Lines): MarchinCubesBuilder<Lines> { @@ -67,7 +67,7 @@ export function MarchinCubesLinesBuilder(vertexChunkSize: number, lines?: Lines) const groups = ChunkedArray.create(Float32Array, 1, vertexChunkSize); const indices = ChunkedArray.create(Float32Array, 2, vertexChunkSize); - let linesCount = 0 + let linesCount = 0; return { addVertex: (x: number, y: number, z: number) => { @@ -78,21 +78,21 @@ export function MarchinCubesLinesBuilder(vertexChunkSize: number, lines?: Lines) ChunkedArray.add(groups, group); }, addTriangle: (vertList: number[], a: number, b: number, c: number, edgeFilter: number) => { - const i = vertList[a], j = vertList[b], k = vertList[c] + const i = vertList[a], j = vertList[b], k = vertList[c]; // vertex indices <0 mean that the vertex was ignored and is not available // and hence we don't add a triangle when this occurs if (i >= 0 && j >= 0 && k >= 0) { if (AllowedContours[a][b] & edgeFilter) { - ++linesCount - ChunkedArray.add2(indices, vertList[a], vertList[b]) + ++linesCount; + ChunkedArray.add2(indices, vertList[a], vertList[b]); } if (AllowedContours[b][c] & edgeFilter) { - ++linesCount - ChunkedArray.add2(indices, vertList[b], vertList[c]) + ++linesCount; + ChunkedArray.add2(indices, vertList[b], vertList[c]); } if (AllowedContours[a][c] & edgeFilter) { - ++linesCount - ChunkedArray.add2(indices, vertList[a], vertList[c]) + ++linesCount; + ChunkedArray.add2(indices, vertList[a], vertList[c]); } } }, @@ -101,18 +101,18 @@ export function MarchinCubesLinesBuilder(vertexChunkSize: number, lines?: Lines) const ib = ChunkedArray.compact(indices, true) as Uint32Array; const gb = ChunkedArray.compact(groups, true) as Float32Array; - const builder = LinesBuilder.create(linesCount, linesCount / 10, lines) + const builder = LinesBuilder.create(linesCount, linesCount / 10, lines); for (let i = 0; i < linesCount; ++i) { - const la = ib[i * 2], lb = ib[i * 2 + 1] + const la = ib[i * 2], lb = ib[i * 2 + 1]; builder.add( vb[la * 3], vb[la * 3 + 1], vb[la * 3 + 2], vb[lb * 3], vb[lb * 3 + 1], vb[lb * 3 + 2], gb[la] - ) + ); } - return builder.getLines() + return builder.getLines(); } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/_spec/gl.shim.ts b/src/mol-gl/_spec/gl.shim.ts index bcd8a6223bf5df1d81e4858aab69729d066a4576..f0304b670a71d0b5c6d7715969d12ca030585a15 100644 --- a/src/mol-gl/_spec/gl.shim.ts +++ b/src/mol-gl/_spec/gl.shim.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { idFactory } from '../../mol-util/id-factory' +import { idFactory } from '../../mol-util/id-factory'; const c = { ACTIVE_ATTRIBUTE_MAX_LENGTH: 35722, @@ -16,7 +16,7 @@ const c = { MAX_TEXTURE_MAX_ANISOTROPY_EXT: 0x84FF, MAX_TEXTURE_IMAGE_UNITS_NV: 0x8872 -} +}; const gl = { ACTIVE_ATTRIBUTES: 35721, @@ -316,16 +316,16 @@ const gl = { VERTEX_SHADER: 35633, VIEWPORT: 2978, ZERO: 0 -} +}; type gl = typeof gl export function createGl(width: number, height: number, contextAttributes: WebGLContextAttributes): WebGLRenderingContext { - const getNextId = idFactory() - const items: { [k: number]: any } = {} - const boundTextures: { [k: number]: any } = {} - const viewport = { x: 0, y: 0, width, height } - const depthRange = { zNear: 0, zFar: 1 } - const colorClearValue = { r: 0, g: 0, b: 0, a: 0 } + const getNextId = idFactory(); + const items: { [k: number]: any } = {}; + const boundTextures: { [k: number]: any } = {}; + const viewport = { x: 0, y: 0, width, height }; + const depthRange = { zNear: 0, zFar: 1 }; + const colorClearValue = { r: 0, g: 0, b: 0, a: 0 }; // let _activeFramebuffer: number // let _activeRenderbuffer: number @@ -336,12 +336,12 @@ export function createGl(width: number, height: number, contextAttributes: WebGL width, height } as HTMLCanvasElement, getAttachedShaders: function(program: WebGLProgram) { - return [] as WebGLShader[] + return [] as WebGLShader[]; }, getBufferParameter: function(target: number, pname: number) { - return 0 + return 0; }, - getContextAttributes: function() { return contextAttributes }, + getContextAttributes: function() { return contextAttributes; }, getFramebufferAttachmentParameter: function() {}, getProgramInfoLog: function() { return ''; }, getShaderInfoLog: function() { return ''; }, @@ -351,7 +351,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL precision: 0, rangeMax: 0, rangeMin: 0 - } + }; }, getShaderSource: function(shader: WebGLShader | null) { return ''; }, getTexParameter: function() {}, @@ -371,71 +371,71 @@ export function createGl(width: number, height: number, contextAttributes: WebGL case 'EXT_blend_minmax': return { MAX_EXT: 0, MIN_EXT: 0 - } as EXT_blend_minmax + } as EXT_blend_minmax; case 'EXT_texture_filter_anisotropic': return { MAX_TEXTURE_MAX_ANISOTROPY_EXT: 0, TEXTURE_MAX_ANISOTROPY_EXT: 0 - } as EXT_texture_filter_anisotropic - case 'EXT_frag_depth': return {} as EXT_frag_depth - case 'EXT_shader_texture_lod': return {} as EXT_shader_texture_lod + } as EXT_texture_filter_anisotropic; + case 'EXT_frag_depth': return {} as EXT_frag_depth; + case 'EXT_shader_texture_lod': return {} as EXT_shader_texture_lod; case 'EXT_sRGB': return { FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT: 0, SRGB8_ALPHA8_EXT: 0, SRGB_ALPHA_EXT: 0, SRGB_EXT: 0 - } as EXT_sRGB + } as EXT_sRGB; case 'OES_vertex_array_object': return { VERTEX_ARRAY_BINDING_OES: 0, bindVertexArrayOES: function(arrayObject: WebGLVertexArrayObjectOES) { }, - createVertexArrayOES: function(): WebGLVertexArrayObjectOES { return {} }, + createVertexArrayOES: function(): WebGLVertexArrayObjectOES { return {}; }, deleteVertexArrayOES: function(arrayObject: WebGLVertexArrayObjectOES) { }, isVertexArrayOES: function(value: any) { return true; } - } as OES_vertex_array_object + } as OES_vertex_array_object; case 'WEBGL_color_buffer_float': return { FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT: 0, RGB32F_EXT: 0, RGBA32F_EXT: 0, UNSIGNED_NORMALIZED_EXT: 0 - } as WEBGL_color_buffer_float - case 'WEBGL_compressed_texture_astc': return null - case 'WEBGL_compressed_texture_s3tc_srgb': return null + } as WEBGL_color_buffer_float; + case 'WEBGL_compressed_texture_astc': return null; + case 'WEBGL_compressed_texture_s3tc_srgb': return null; case 'WEBGL_debug_shaders': return { getTranslatedShaderSource(shader: WebGLShader) { return ''; } - } as WEBGL_debug_shaders - case 'WEBGL_draw_buffers': return null + } as WEBGL_debug_shaders; + case 'WEBGL_draw_buffers': return null; case 'WEBGL_lose_context': return { loseContext: function() { }, restoreContext: function() { }, - } as WEBGL_lose_context + } as WEBGL_lose_context; case 'WEBGL_depth_texture': return { UNSIGNED_INT_24_8_WEBGL: 0 - } as WEBGL_depth_texture + } as WEBGL_depth_texture; case 'WEBGL_debug_renderer_info': return { UNMASKED_RENDERER_WEBGL: 0, UNMASKED_VENDOR_WEBGL: 0 - } as WEBGL_debug_renderer_info - case 'WEBGL_compressed_texture_s3tc': return null - case 'OES_texture_half_float_linear': return {} as OES_texture_half_float_linear + } as WEBGL_debug_renderer_info; + case 'WEBGL_compressed_texture_s3tc': return null; + case 'OES_texture_half_float_linear': return {} as OES_texture_half_float_linear; case 'OES_texture_half_float': return { HALF_FLOAT_OES: 0 - } as OES_texture_half_float - case 'OES_texture_float_linear': return {} as OES_texture_float_linear - case 'OES_texture_float': return {} as OES_texture_float + } as OES_texture_half_float; + case 'OES_texture_float_linear': return {} as OES_texture_float_linear; + case 'OES_texture_float': return {} as OES_texture_float; case 'OES_standard_derivatives': return { FRAGMENT_SHADER_DERIVATIVE_HINT_OES: 0 - } as OES_standard_derivatives - case 'OES_element_index_uint': return {} as OES_element_index_uint + } as OES_standard_derivatives; + case 'OES_element_index_uint': return {} as OES_element_index_uint; case 'ANGLE_instanced_arrays': return { drawArraysInstancedANGLE: function(mode: number, first: number, count: number, primcount: number) {}, drawElementsInstancedANGLE: function(mode: number, count: number, type: number, offset: number, primcount: number) {}, vertexAttribDivisorANGLE: function(index: number, divisor: number) {}, VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: 0 - } as ANGLE_instanced_arrays + } as ANGLE_instanced_arrays; } - return null + return null; }, createBuffer: function () { - const id = getNextId() + const id = getNextId(); items[id] = { which: 'buffer', }; @@ -459,50 +459,50 @@ export function createGl(width: number, height: number, contextAttributes: WebGL // return _activeRenderbuffer case gl.TEXTURE_BINDING_2D: case gl.TEXTURE_BINDING_CUBE_MAP: - return null + return null; case gl.VERSION: - return '1.0.0' + return '1.0.0'; case gl.VENDOR: - return 'shim' + return 'shim'; case gl.RENDERER: - return 'shim-renderer' + return 'shim-renderer'; case gl.SHADING_LANGUAGE_VERSION: - return 'WebGL GLSL ES 1.0 shim' + return 'WebGL GLSL ES 1.0 shim'; case gl.COMPRESSED_TEXTURE_FORMATS: - return new Uint32Array(0) + return new Uint32Array(0); // Int arrays case gl.MAX_VIEWPORT_DIMS: case gl.SCISSOR_BOX: - return new Int32Array([ 0, 0, 4096, 4096 ]) + return new Int32Array([ 0, 0, 4096, 4096 ]); case gl.VIEWPORT: - const { x, y, width, height } = viewport - return new Int32Array([ x, y, width, height ]) + const { x, y, width, height } = viewport; + return new Int32Array([ x, y, width, height ]); // Float arrays case gl.ALIASED_LINE_WIDTH_RANGE: - return new Float32Array([0, 1]) + return new Float32Array([0, 1]); case gl.ALIASED_POINT_SIZE_RANGE: - return new Float32Array([0, 255]) + return new Float32Array([0, 255]); case gl.DEPTH_RANGE: - return new Float32Array([ depthRange.zNear, depthRange.zFar ]) + return new Float32Array([ depthRange.zNear, depthRange.zFar ]); case gl.BLEND_COLOR: - return new Float32Array([0, 0, 0, 0]) + return new Float32Array([0, 0, 0, 0]); case gl.COLOR_CLEAR_VALUE: - const { r, g, b, a } = colorClearValue - return new Float32Array([ r, g, b, a ]) + const { r, g, b, a } = colorClearValue; + return new Float32Array([ r, g, b, a ]); case gl.COLOR_WRITEMASK: - return 0 + return 0; case gl.DEPTH_CLEAR_VALUE: case gl.LINE_WIDTH: case gl.POLYGON_OFFSET_FACTOR: case gl.POLYGON_OFFSET_UNITS: case gl.SAMPLE_COVERAGE_VALUE: - return 1 + return 1; case gl.BLEND: case gl.CULL_FACE: @@ -590,7 +590,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL ]; }, createShader: function (type: number) { - const id = getNextId() + const id = getNextId(); items[id] = { which: 'shader', type: type, @@ -607,7 +607,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL shaderSource: function () { }, compileShader: function () { }, createProgram: function () { - const id = getNextId() + const id = getNextId(); items[id] = { which: 'program', shaders: [], @@ -634,16 +634,16 @@ export function createGl(width: number, height: number, contextAttributes: WebGL deleteShader: function () { }, deleteProgram: function () { }, viewport: function (x: number, y: number, width: number, height: number) { - viewport.x = x - viewport.y = y - viewport.width = width - viewport.height = height + viewport.x = x; + viewport.y = y; + viewport.width = width; + viewport.height = height; }, clearColor: function (red: number, green: number, blue: number, alpha: number) { - colorClearValue.r = red - colorClearValue.g = green - colorClearValue.b = blue - colorClearValue.a = alpha + colorClearValue.r = red; + colorClearValue.g = green; + colorClearValue.b = blue; + colorClearValue.a = alpha; }, clearDepth: function () { }, depthFunc: function () { }, @@ -653,7 +653,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL cullFace: function () { }, activeTexture: function () { }, createTexture: function () { - const id = getNextId() + const id = getNextId(); items[id] = { which: 'texture', }; @@ -707,7 +707,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL uniformMatrix2fv: function () { }, uniformMatrix3fv: function () { }, uniformMatrix4fv: function () { }, - getAttribLocation: function () { return 1 }, + getAttribLocation: function () { return 1; }, vertexAttribPointer: function () { }, enableVertexAttribArray: function () { }, disableVertexAttribArray: function () { }, @@ -715,13 +715,13 @@ export function createGl(width: number, height: number, contextAttributes: WebGL drawArrays: function () { }, depthMask: function () { }, depthRange: function (zNear: number, zFar: number) { - depthRange.zNear = zNear - depthRange.zFar = zFar + depthRange.zNear = zNear; + depthRange.zFar = zFar; }, bufferSubData: function () { }, blendFunc: function () { }, createFramebuffer: function () { - const id = getNextId() + const id = getNextId(); items[id] = { which: 'framebuffer', shaders: [], @@ -735,7 +735,7 @@ export function createGl(width: number, height: number, contextAttributes: WebGL }, deleteFramebuffer: function () { }, createRenderbuffer: function () { - const id = getNextId() + const id = getNextId(); items[id] = { which: 'renderbuffer', shaders: [], @@ -783,5 +783,5 @@ export function createGl(width: number, height: number, contextAttributes: WebGL stencilMaskSeparate: function () { }, stencilOp: function () { }, stencilOpSeparate: function () { }, - } + }; } \ No newline at end of file diff --git a/src/mol-gl/_spec/renderable.spec.ts b/src/mol-gl/_spec/renderable.spec.ts index 277ac20b8b98c7b5af62b43cebb6072701c11777..8afdcee3a9080f44ea4e4fbd3b49c12b69e708d4 100644 --- a/src/mol-gl/_spec/renderable.spec.ts +++ b/src/mol-gl/_spec/renderable.spec.ts @@ -12,7 +12,7 @@ describe('renderable', () => { 0, 0, 0, 1, 0, 0, -1, 0, 0, - ]) + ]); const transform = new Float32Array([ 1, 0, 0, 0, 0, 1, 0, 0, @@ -28,17 +28,17 @@ describe('renderable', () => { 0, 1, 0, 0, 0, 0, 1, 0, -1, 0, 0, 0 - ]) + ]); const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere( position, position.length / 3, transform, transform.length / 16 - ) + ); - expect(invariantBoundingSphere.extrema).toEqual([[0, 0, 0], [1, 0, 0], [-1, 0, 0]]) - expect(invariantBoundingSphere.radius).toBe(1) - expect(invariantBoundingSphere.center).toEqual([0, 0, 0]) - expect(boundingSphere.radius).toBe(2) - expect(boundingSphere.center).toEqual([0, 0, 0]) - }) -}) + expect(invariantBoundingSphere.extrema).toEqual([[0, 0, 0], [1, 0, 0], [-1, 0, 0]]); + expect(invariantBoundingSphere.radius).toBe(1); + expect(invariantBoundingSphere.center).toEqual([0, 0, 0]); + expect(boundingSphere.radius).toBe(2); + expect(boundingSphere.center).toEqual([0, 0, 0]); + }); +}); diff --git a/src/mol-gl/_spec/renderer.spec.ts b/src/mol-gl/_spec/renderer.spec.ts index c9fdde6ddda907376edb2dfab6f54cf894516b1d..8861f6214ce1df6699088bb1ba4d16936cffed2d 100644 --- a/src/mol-gl/_spec/renderer.spec.ts +++ b/src/mol-gl/_spec/renderer.spec.ts @@ -26,32 +26,32 @@ import { createEmptyOverpaint } from '../../mol-geo/geometry/overpaint-data'; import { createEmptyTransparency } from '../../mol-geo/geometry/transparency-data'; function createRenderer(gl: WebGLRenderingContext) { - const ctx = createContext(gl) + const ctx = createContext(gl); const camera = new Camera({ position: Vec3.create(0, 0, 50) - }) - const renderer = Renderer.create(ctx) - return { ctx, camera, renderer } + }); + const renderer = Renderer.create(ctx); + return { ctx, camera, renderer }; } function createPoints() { - const aPosition = ValueCell.create(new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0])) - const aGroup = ValueCell.create(fillSerial(new Float32Array(3))) - const aInstance = ValueCell.create(fillSerial(new Float32Array(1))) - const color = createValueColor(Color(0xFF0000)) - const size = createValueSize(1) - const marker = createEmptyMarkers() - const overpaint = createEmptyOverpaint() - const transparency = createEmptyTransparency() - - const aTransform = ValueCell.create(new Float32Array(16)) - const m4 = Mat4.identity() - Mat4.toArray(m4, aTransform.ref.value, 0) - const transform = ValueCell.create(new Float32Array(aTransform.ref.value)) - const extraTransform = ValueCell.create(new Float32Array(aTransform.ref.value)) - - const boundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2)) - const invariantBoundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2)) + const aPosition = ValueCell.create(new Float32Array([0, -1, 0, -1, 0, 0, 1, 1, 0])); + const aGroup = ValueCell.create(fillSerial(new Float32Array(3))); + const aInstance = ValueCell.create(fillSerial(new Float32Array(1))); + const color = createValueColor(Color(0xFF0000)); + const size = createValueSize(1); + const marker = createEmptyMarkers(); + const overpaint = createEmptyOverpaint(); + const transparency = createEmptyTransparency(); + + const aTransform = ValueCell.create(new Float32Array(16)); + const m4 = Mat4.identity(); + Mat4.toArray(m4, aTransform.ref.value, 0); + const transform = ValueCell.create(new Float32Array(aTransform.ref.value)); + const extraTransform = ValueCell.create(new Float32Array(aTransform.ref.value)); + + const boundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2)); + const invariantBoundingSphere = ValueCell.create(Sphere3D.create(Vec3.zero(), 2)); const values: PointsValues = { aPosition, @@ -81,25 +81,25 @@ function createPoints() { dPointSizeAttenuation: ValueCell.create(true), dPointFilledCircle: ValueCell.create(false), uPointEdgeBleach: ValueCell.create(0.5), - } + }; const state: RenderableState = { visible: true, alphaFactor: 1, pickable: true, opaque: true - } + }; - return createRenderObject('points', values, state, -1) + return createRenderObject('points', values, state, -1); } describe('renderer', () => { it('basic', () => { - const [ width, height ] = [ 32, 32 ] - const gl = createGl(width, height, { preserveDrawingBuffer: true }) - const { ctx, renderer } = createRenderer(gl) + const [ width, height ] = [ 32, 32 ]; + const gl = createGl(width, height, { preserveDrawingBuffer: true }); + const { ctx, renderer } = createRenderer(gl); - expect(ctx.gl.canvas.width).toBe(32) - expect(ctx.gl.canvas.height).toBe(32) + expect(ctx.gl.canvas.width).toBe(32); + expect(ctx.gl.canvas.height).toBe(32); expect(ctx.stats.resourceCounts.attribute).toBe(0); expect(ctx.stats.resourceCounts.texture).toBe(0); @@ -107,37 +107,37 @@ describe('renderer', () => { expect(ctx.stats.resourceCounts.program).toBe(0); expect(ctx.stats.resourceCounts.shader).toBe(0); - renderer.setViewport(0, 0, 64, 48) - expect(ctx.gl.getParameter(ctx.gl.VIEWPORT)[2]).toBe(64) - expect(ctx.gl.getParameter(ctx.gl.VIEWPORT)[3]).toBe(48) - }) + renderer.setViewport(0, 0, 64, 48); + expect(ctx.gl.getParameter(ctx.gl.VIEWPORT)[2]).toBe(64); + expect(ctx.gl.getParameter(ctx.gl.VIEWPORT)[3]).toBe(48); + }); it('points', async () => { - const [ width, height ] = [ 32, 32 ] - const gl = createGl(width, height, { preserveDrawingBuffer: true }) - const { ctx } = createRenderer(gl) - const scene = Scene.create(ctx) + const [ width, height ] = [ 32, 32 ]; + const gl = createGl(width, height, { preserveDrawingBuffer: true }); + const { ctx } = createRenderer(gl); + const scene = Scene.create(ctx); - const points = createPoints() + const points = createPoints(); - scene.add(points) - scene.commit() + scene.add(points); + scene.commit(); expect(ctx.stats.resourceCounts.attribute).toBe(4); expect(ctx.stats.resourceCounts.texture).toBe(5); expect(ctx.stats.resourceCounts.vertexArray).toBe(5); expect(ctx.stats.resourceCounts.program).toBe(5); expect(ctx.stats.resourceCounts.shader).toBe(10); - scene.remove(points) - scene.commit() + scene.remove(points); + scene.commit(); expect(ctx.stats.resourceCounts.attribute).toBe(0); expect(ctx.stats.resourceCounts.texture).toBe(0); expect(ctx.stats.resourceCounts.vertexArray).toBe(0); expect(ctx.stats.resourceCounts.program).toBe(5); expect(ctx.stats.resourceCounts.shader).toBe(10); - ctx.resources.destroy() + ctx.resources.destroy(); expect(ctx.stats.resourceCounts.program).toBe(0); expect(ctx.stats.resourceCounts.shader).toBe(0); - }) -}) \ No newline at end of file + }); +}); \ No newline at end of file diff --git a/src/mol-gl/commit-queue.ts b/src/mol-gl/commit-queue.ts index 2cfd37d6206dcdde6c600c8d0fe7e074be551d5b..c0355e3cc322d68f4813bd64a9b458a40ffbf8e7 100644 --- a/src/mol-gl/commit-queue.ts +++ b/src/mol-gl/commit-queue.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { LinkedList } from '../mol-data/generic' -import { GraphicsRenderObject } from './render-object' +import { LinkedList } from '../mol-data/generic'; +import { GraphicsRenderObject } from './render-object'; type N = LinkedList.Node<GraphicsRenderObject> diff --git a/src/mol-gl/compute/histogram-pyramid/reduction.ts b/src/mol-gl/compute/histogram-pyramid/reduction.ts index 4572cf64b6b1b3e7e8dee9093889362caef05840..6841c19ff1ab7bfdf5f5200ec112dca3d4f6c9b4 100644 --- a/src/mol-gl/compute/histogram-pyramid/reduction.ts +++ b/src/mol-gl/compute/histogram-pyramid/reduction.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { createComputeRenderable, ComputeRenderable } from '../../renderable' +import { createComputeRenderable, ComputeRenderable } from '../../renderable'; import { WebGLContext } from '../../webgl/context'; import { createComputeRenderItem } from '../../webgl/render-item'; import { Values, TextureSpec, UniformSpec } from '../../renderable/schema'; @@ -16,64 +16,64 @@ import { Vec2 } from '../../../mol-math/linear-algebra'; import { getHistopyramidSum } from './sum'; import { Framebuffer } from '../../../mol-gl/webgl/framebuffer'; import { isPowerOfTwo } from '../../../mol-math/misc'; -import quad_vert from '../../../mol-gl/shader/quad.vert' -import reduction_frag from '../../../mol-gl/shader/histogram-pyramid/reduction.frag' +import quad_vert from '../../../mol-gl/shader/quad.vert'; +import reduction_frag from '../../../mol-gl/shader/histogram-pyramid/reduction.frag'; const HistopyramidReductionSchema = { ...QuadSchema, tPreviousLevel: TextureSpec('texture', 'rgba', 'float', 'nearest'), uSize: UniformSpec('f'), uTexSize: UniformSpec('f'), -} +}; -let HistopyramidReductionRenderable: ComputeRenderable<Values<typeof HistopyramidReductionSchema>> +let HistopyramidReductionRenderable: ComputeRenderable<Values<typeof HistopyramidReductionSchema>>; function getHistopyramidReductionRenderable(ctx: WebGLContext, initialTexture: Texture) { if (HistopyramidReductionRenderable) { - ValueCell.update(HistopyramidReductionRenderable.values.tPreviousLevel, initialTexture) - HistopyramidReductionRenderable.update() - return HistopyramidReductionRenderable + ValueCell.update(HistopyramidReductionRenderable.values.tPreviousLevel, initialTexture); + HistopyramidReductionRenderable.update(); + return HistopyramidReductionRenderable; } else { const values: Values<typeof HistopyramidReductionSchema> = { ...QuadValues, tPreviousLevel: ValueCell.create(initialTexture), uSize: ValueCell.create(0), uTexSize: ValueCell.create(0), - } + }; - const schema = { ...HistopyramidReductionSchema } - const shaderCode = ShaderCode('reduction', quad_vert, reduction_frag) - const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values) + const schema = { ...HistopyramidReductionSchema }; + const shaderCode = ShaderCode('reduction', quad_vert, reduction_frag); + const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values); HistopyramidReductionRenderable = createComputeRenderable(renderItem, values); - return HistopyramidReductionRenderable + return HistopyramidReductionRenderable; } } type TextureFramebuffer = { texture: Texture, framebuffer: Framebuffer } -const LevelTexturesFramebuffers: TextureFramebuffer[] = [] +const LevelTexturesFramebuffers: TextureFramebuffer[] = []; function getLevelTextureFramebuffer(ctx: WebGLContext, level: number) { - let textureFramebuffer = LevelTexturesFramebuffers[level] - const size = Math.pow(2, level) + let textureFramebuffer = LevelTexturesFramebuffers[level]; + const size = Math.pow(2, level); if (textureFramebuffer === undefined) { - const texture = ctx.resources.texture('image-float32', 'rgba', 'float', 'nearest') - const framebuffer = ctx.resources.framebuffer() - texture.attachFramebuffer(framebuffer, 0) - textureFramebuffer = { texture, framebuffer } - textureFramebuffer.texture.define(size, size) - LevelTexturesFramebuffers[level] = textureFramebuffer + const texture = ctx.resources.texture('image-float32', 'rgba', 'float', 'nearest'); + const framebuffer = ctx.resources.framebuffer(); + texture.attachFramebuffer(framebuffer, 0); + textureFramebuffer = { texture, framebuffer }; + textureFramebuffer.texture.define(size, size); + LevelTexturesFramebuffers[level] = textureFramebuffer; } - return textureFramebuffer + return textureFramebuffer; } function setRenderingDefaults(ctx: WebGLContext) { - const { gl, state } = ctx - state.disable(gl.CULL_FACE) - state.disable(gl.BLEND) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) - state.colorMask(true, true, true, true) - state.clearColor(0, 0, 0, 0) + const { gl, state } = ctx; + state.disable(gl.CULL_FACE); + state.disable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); + state.colorMask(true, true, true, true); + state.clearColor(0, 0, 0, 0); } export interface HistogramPyramid { @@ -85,68 +85,68 @@ export interface HistogramPyramid { } export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture, scale: Vec2): HistogramPyramid { - const { gl, resources } = ctx + const { gl, resources } = ctx; // printTexture(ctx, inputTexture, 2) if (inputTexture.getWidth() !== inputTexture.getHeight() || !isPowerOfTwo(inputTexture.getWidth())) { - throw new Error('inputTexture must be of square power-of-two size') + throw new Error('inputTexture must be of square power-of-two size'); } // This part set the levels - const levels = Math.ceil(Math.log(inputTexture.getWidth()) / Math.log(2)) - const maxSize = Math.pow(2, levels) + const levels = Math.ceil(Math.log(inputTexture.getWidth()) / Math.log(2)); + const maxSize = Math.pow(2, levels); // console.log('levels', levels, 'maxSize', maxSize) - const pyramidTexture = resources.texture('image-float32', 'rgba', 'float', 'nearest') - pyramidTexture.define(maxSize, maxSize) + const pyramidTexture = resources.texture('image-float32', 'rgba', 'float', 'nearest'); + pyramidTexture.define(maxSize, maxSize); - const framebuffer = resources.framebuffer() - pyramidTexture.attachFramebuffer(framebuffer, 0) - gl.clear(gl.COLOR_BUFFER_BIT) + const framebuffer = resources.framebuffer(); + pyramidTexture.attachFramebuffer(framebuffer, 0); + gl.clear(gl.COLOR_BUFFER_BIT); - const levelTexturesFramebuffers: TextureFramebuffer[] = [] - for (let i = 0; i < levels; ++i) levelTexturesFramebuffers.push(getLevelTextureFramebuffer(ctx, i)) + const levelTexturesFramebuffers: TextureFramebuffer[] = []; + for (let i = 0; i < levels; ++i) levelTexturesFramebuffers.push(getLevelTextureFramebuffer(ctx, i)); - const renderable = getHistopyramidReductionRenderable(ctx, inputTexture) - ctx.state.currentRenderItemId = -1 - setRenderingDefaults(ctx) + const renderable = getHistopyramidReductionRenderable(ctx, inputTexture); + ctx.state.currentRenderItemId = -1; + setRenderingDefaults(ctx); let offset = 0; for (let i = 0; i < levels; i++) { - const currLevel = levels - 1 - i - const tf = levelTexturesFramebuffers[currLevel] - tf.framebuffer.bind() + const currLevel = levels - 1 - i; + const tf = levelTexturesFramebuffers[currLevel]; + tf.framebuffer.bind(); // levelTextures[currLevel].attachFramebuffer(framebuffer, 0) - const size = Math.pow(2, currLevel) + const size = Math.pow(2, currLevel); // console.log('size', size, 'draw-level', currLevel, 'read-level', levels - i) - gl.clear(gl.COLOR_BUFFER_BIT) - gl.viewport(0, 0, size, size) + gl.clear(gl.COLOR_BUFFER_BIT); + gl.viewport(0, 0, size, size); - ValueCell.update(renderable.values.uSize, Math.pow(2, i + 1) / maxSize) - ValueCell.update(renderable.values.uTexSize, size) + ValueCell.update(renderable.values.uSize, Math.pow(2, i + 1) / maxSize); + ValueCell.update(renderable.values.uTexSize, size); if (i > 0) { - ValueCell.update(renderable.values.tPreviousLevel, levelTexturesFramebuffers[levels - i].texture) - renderable.update() + ValueCell.update(renderable.values.tPreviousLevel, levelTexturesFramebuffers[levels - i].texture); + renderable.update(); } - ctx.state.currentRenderItemId = -1 - renderable.render() + ctx.state.currentRenderItemId = -1; + renderable.render(); - pyramidTexture.bind(0) + pyramidTexture.bind(0); gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, offset, 0, 0, 0, size, size); - pyramidTexture.unbind(0) + pyramidTexture.unbind(0); offset += size; } - gl.finish() + gl.finish(); // printTexture(ctx, pyramidTexture, 2) // - const finalCount = getHistopyramidSum(ctx, levelTexturesFramebuffers[0].texture) - const height = Math.ceil(finalCount / Math.pow(2, levels)) + const finalCount = getHistopyramidSum(ctx, levelTexturesFramebuffers[0].texture); + const height = Math.ceil(finalCount / Math.pow(2, levels)); // const scale = Vec2.create(maxSize / inputTexture.width, maxSize / inputTexture.height) // console.log('height', height, 'finalCount', finalCount, 'scale', scale) @@ -157,5 +157,5 @@ export function createHistogramPyramid(ctx: WebGLContext, inputTexture: Texture, height, levels, scale - } + }; } \ No newline at end of file diff --git a/src/mol-gl/compute/histogram-pyramid/sum.ts b/src/mol-gl/compute/histogram-pyramid/sum.ts index fee24cd6d6501de05d76a3fffa743c64aa03a6e6..4d7515c5b78b1ed34fa50044194bd71f0eb9d1ac 100644 --- a/src/mol-gl/compute/histogram-pyramid/sum.ts +++ b/src/mol-gl/compute/histogram-pyramid/sum.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { createComputeRenderable, ComputeRenderable } from '../../renderable' +import { createComputeRenderable, ComputeRenderable } from '../../renderable'; import { WebGLContext } from '../../webgl/context'; import { createComputeRenderItem } from '../../webgl/render-item'; import { Values, TextureSpec } from '../../renderable/schema'; @@ -13,72 +13,72 @@ import { ShaderCode } from '../../../mol-gl/shader-code'; import { ValueCell } from '../../../mol-util'; import { decodeFloatRGB } from '../../../mol-util/float-packing'; import { QuadSchema, QuadValues } from '../util'; -import quad_vert from '../../../mol-gl/shader/quad.vert' -import sum_frag from '../../../mol-gl/shader/histogram-pyramid/sum.frag' +import quad_vert from '../../../mol-gl/shader/quad.vert'; +import sum_frag from '../../../mol-gl/shader/histogram-pyramid/sum.frag'; const HistopyramidSumSchema = { ...QuadSchema, tTexture: TextureSpec('texture', 'rgba', 'float', 'nearest'), -} +}; -let HistopyramidSumRenderable: ComputeRenderable<Values<typeof HistopyramidSumSchema>> +let HistopyramidSumRenderable: ComputeRenderable<Values<typeof HistopyramidSumSchema>>; function getHistopyramidSumRenderable(ctx: WebGLContext, texture: Texture) { if (HistopyramidSumRenderable) { - ValueCell.update(HistopyramidSumRenderable.values.tTexture, texture) - HistopyramidSumRenderable.update() - return HistopyramidSumRenderable + ValueCell.update(HistopyramidSumRenderable.values.tTexture, texture); + HistopyramidSumRenderable.update(); + return HistopyramidSumRenderable; } else { const values: Values<typeof HistopyramidSumSchema> = { ...QuadValues, tTexture: ValueCell.create(texture), - } + }; - const schema = { ...HistopyramidSumSchema } - const shaderCode = ShaderCode('sum', quad_vert, sum_frag) - const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values) + const schema = { ...HistopyramidSumSchema }; + const shaderCode = ShaderCode('sum', quad_vert, sum_frag); + const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values); - HistopyramidSumRenderable = createComputeRenderable(renderItem, values) - return HistopyramidSumRenderable + HistopyramidSumRenderable = createComputeRenderable(renderItem, values); + return HistopyramidSumRenderable; } } -let SumTexture: Texture +let SumTexture: Texture; function getSumTexture(ctx: WebGLContext) { - if (SumTexture) return SumTexture - SumTexture = ctx.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest') - SumTexture.define(1, 1) - return SumTexture + if (SumTexture) return SumTexture; + SumTexture = ctx.resources.texture('image-uint8', 'rgba', 'ubyte', 'nearest'); + SumTexture.define(1, 1); + return SumTexture; } function setRenderingDefaults(ctx: WebGLContext) { - const { gl, state } = ctx - state.disable(gl.CULL_FACE) - state.disable(gl.BLEND) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) - state.colorMask(true, true, true, true) - state.clearColor(0, 0, 0, 0) + const { gl, state } = ctx; + state.disable(gl.CULL_FACE); + state.disable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); + state.colorMask(true, true, true, true); + state.clearColor(0, 0, 0, 0); } -const sumArray = new Uint8Array(4) +const sumArray = new Uint8Array(4); export function getHistopyramidSum(ctx: WebGLContext, pyramidTopTexture: Texture) { - const { gl, resources } = ctx + const { gl, resources } = ctx; - const renderable = getHistopyramidSumRenderable(ctx, pyramidTopTexture) - ctx.state.currentRenderItemId = -1 + const renderable = getHistopyramidSumRenderable(ctx, pyramidTopTexture); + ctx.state.currentRenderItemId = -1; - const framebuffer = resources.framebuffer() - const sumTexture = getSumTexture(ctx) - sumTexture.attachFramebuffer(framebuffer, 0) + const framebuffer = resources.framebuffer(); + const sumTexture = getSumTexture(ctx); + sumTexture.attachFramebuffer(framebuffer, 0); - setRenderingDefaults(ctx) + setRenderingDefaults(ctx); - gl.viewport(0, 0, 1, 1) - renderable.render() - gl.finish() - ctx.readPixels(0, 0, 1, 1, sumArray) - ctx.unbindFramebuffer() + gl.viewport(0, 0, 1, 1); + renderable.render(); + gl.finish(); + ctx.readPixels(0, 0, 1, 1, sumArray); + ctx.unbindFramebuffer(); - return decodeFloatRGB(sumArray[0], sumArray[1], sumArray[2]) + return decodeFloatRGB(sumArray[0], sumArray[1], sumArray[2]); } \ No newline at end of file diff --git a/src/mol-gl/compute/marching-cubes/active-voxels.ts b/src/mol-gl/compute/marching-cubes/active-voxels.ts index 61c7673178ca9ee21d1614fabd6cb0d026bd7b30..e08a469b6a12d47a5f0167405094f1566f7d1dfe 100644 --- a/src/mol-gl/compute/marching-cubes/active-voxels.ts +++ b/src/mol-gl/compute/marching-cubes/active-voxels.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { createComputeRenderable } from '../../renderable' +import { createComputeRenderable } from '../../renderable'; import { WebGLContext } from '../../webgl/context'; import { createComputeRenderItem } from '../../webgl/render-item'; import { Values, TextureSpec, UniformSpec } from '../../renderable/schema'; @@ -14,8 +14,8 @@ import { ValueCell } from '../../../mol-util'; import { Vec3, Vec2 } from '../../../mol-math/linear-algebra'; import { QuadSchema, QuadValues } from '../util'; import { getTriCount } from './tables'; -import quad_vert from '../../../mol-gl/shader/quad.vert' -import active_voxels_frag from '../../../mol-gl/shader/marching-cubes/active-voxels.frag' +import quad_vert from '../../../mol-gl/shader/quad.vert'; +import active_voxels_frag from '../../../mol-gl/shader/marching-cubes/active-voxels.frag'; const ActiveVoxelsSchema = { ...QuadSchema, @@ -28,7 +28,7 @@ const ActiveVoxelsSchema = { uGridTexDim: UniformSpec('v3'), uScale: UniformSpec('v2'), -} +}; function getActiveVoxelsRenderable(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, isoValue: number, scale: Vec2) { const values: Values<typeof ActiveVoxelsSchema> = { @@ -43,50 +43,50 @@ function getActiveVoxelsRenderable(ctx: WebGLContext, volumeData: Texture, gridD uGridTexDim: ValueCell.create(gridTexDim), uScale: ValueCell.create(scale), - } + }; - const schema = { ...ActiveVoxelsSchema } - const shaderCode = ShaderCode('active-voxels', quad_vert, active_voxels_frag) - const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values) + const schema = { ...ActiveVoxelsSchema }; + const shaderCode = ShaderCode('active-voxels', quad_vert, active_voxels_frag); + const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values); return createComputeRenderable(renderItem, values); } function setRenderingDefaults(ctx: WebGLContext) { - const { gl, state } = ctx - state.disable(gl.CULL_FACE) - state.disable(gl.BLEND) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) - state.colorMask(true, true, true, true) - state.clearColor(0, 0, 0, 0) + const { gl, state } = ctx; + state.disable(gl.CULL_FACE); + state.disable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); + state.colorMask(true, true, true, true); + state.clearColor(0, 0, 0, 0); } export function calcActiveVoxels(ctx: WebGLContext, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, isoValue: number, gridScale: Vec2) { - const { gl, resources } = ctx - const width = volumeData.getWidth() - const height = volumeData.getHeight() + const { gl, resources } = ctx; + const width = volumeData.getWidth(); + const height = volumeData.getHeight(); - const framebuffer = resources.framebuffer() - framebuffer.bind() + const framebuffer = resources.framebuffer(); + framebuffer.bind(); - const activeVoxelsTex = resources.texture('image-float32', 'rgba', 'float', 'nearest') - activeVoxelsTex.define(width, height) + const activeVoxelsTex = resources.texture('image-float32', 'rgba', 'float', 'nearest'); + activeVoxelsTex.define(width, height); - const renderable = getActiveVoxelsRenderable(ctx, volumeData, gridDim, gridTexDim, isoValue, gridScale) - ctx.state.currentRenderItemId = -1 + const renderable = getActiveVoxelsRenderable(ctx, volumeData, gridDim, gridTexDim, isoValue, gridScale); + ctx.state.currentRenderItemId = -1; - activeVoxelsTex.attachFramebuffer(framebuffer, 0) - setRenderingDefaults(ctx) - gl.viewport(0, 0, width, height) - renderable.render() + activeVoxelsTex.attachFramebuffer(framebuffer, 0); + setRenderingDefaults(ctx); + gl.viewport(0, 0, width, height); + renderable.render(); // console.log('gridScale', gridScale, 'gridTexDim', gridTexDim, 'gridDim', gridDim) // console.log('volumeData', volumeData) // console.log('at', readTexture(ctx, activeVoxelsTex)) - gl.finish() + gl.finish(); - return activeVoxelsTex + return activeVoxelsTex; } \ No newline at end of file diff --git a/src/mol-gl/compute/marching-cubes/isosurface.ts b/src/mol-gl/compute/marching-cubes/isosurface.ts index 72e4fb80db71a84fc6ae54ed4d84a7867059abfc..7b1f0a3aa32246d477c104d226bbbe8f588836ef 100644 --- a/src/mol-gl/compute/marching-cubes/isosurface.ts +++ b/src/mol-gl/compute/marching-cubes/isosurface.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { createComputeRenderable } from '../../renderable' +import { createComputeRenderable } from '../../renderable'; import { WebGLContext } from '../../webgl/context'; import { createComputeRenderItem } from '../../webgl/render-item'; import { Values, TextureSpec, UniformSpec } from '../../renderable/schema'; @@ -15,8 +15,8 @@ import { Vec3, Vec2, Mat4 } from '../../../mol-math/linear-algebra'; import { QuadSchema, QuadValues } from '../util'; import { HistogramPyramid } from '../histogram-pyramid/reduction'; import { getTriIndices } from './tables'; -import quad_vert from '../../../mol-gl/shader/quad.vert' -import isosurface_frag from '../../../mol-gl/shader/marching-cubes/isosurface.frag' +import quad_vert from '../../../mol-gl/shader/quad.vert'; +import isosurface_frag from '../../../mol-gl/shader/marching-cubes/isosurface.frag'; const IsosurfaceSchema = { ...QuadSchema, @@ -36,7 +36,7 @@ const IsosurfaceSchema = { uGridTransform: UniformSpec('m4'), uScale: UniformSpec('v2'), -} +}; function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture, activeVoxelsBase: Texture, volumeData: Texture, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, levels: number, scale: Vec2, count: number, height: number) { // console.log('uSize', Math.pow(2, levels)) @@ -59,53 +59,53 @@ function getIsosurfaceRenderable(ctx: WebGLContext, activeVoxelsPyramid: Texture uGridTransform: ValueCell.create(transform), uScale: ValueCell.create(scale), - } + }; - const schema = { ...IsosurfaceSchema } - const shaderCode = ShaderCode('isosurface', quad_vert, isosurface_frag, { drawBuffers: true }) - const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values) + const schema = { ...IsosurfaceSchema }; + const shaderCode = ShaderCode('isosurface', quad_vert, isosurface_frag, { drawBuffers: true }); + const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values); return createComputeRenderable(renderItem, values); } function setRenderingDefaults(ctx: WebGLContext) { - const { gl, state } = ctx - state.disable(gl.CULL_FACE) - state.disable(gl.BLEND) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) - state.colorMask(true, true, true, true) - state.clearColor(0, 0, 0, 0) + const { gl, state } = ctx; + state.disable(gl.CULL_FACE); + state.disable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); + state.colorMask(true, true, true, true); + state.clearColor(0, 0, 0, 0); } export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Texture, volumeData: Texture, histogramPyramid: HistogramPyramid, gridDim: Vec3, gridTexDim: Vec3, transform: Mat4, isoValue: number, vertexGroupTexture?: Texture, normalTexture?: Texture) { - const { gl, resources } = ctx - const { pyramidTex, height, levels, scale, count } = histogramPyramid + const { gl, resources } = ctx; + const { pyramidTex, height, levels, scale, count } = histogramPyramid; // console.log('iso', 'gridDim', gridDim, 'scale', scale, 'gridTexDim', gridTexDim) // console.log('iso volumeData', volumeData) - const framebuffer = resources.framebuffer() + const framebuffer = resources.framebuffer(); - let needsClear = false + let needsClear = false; if (!vertexGroupTexture) { - vertexGroupTexture = resources.texture('image-float32', 'rgba', 'float', 'nearest') - vertexGroupTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()) + vertexGroupTexture = resources.texture('image-float32', 'rgba', 'float', 'nearest'); + vertexGroupTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()); } else if (vertexGroupTexture.getWidth() !== pyramidTex.getWidth() || vertexGroupTexture.getHeight() !== pyramidTex.getHeight()) { - vertexGroupTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()) + vertexGroupTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()); } else { - needsClear = true + needsClear = true; } if (!normalTexture) { - normalTexture = resources.texture('image-float32', 'rgba', 'float', 'nearest') - normalTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()) + normalTexture = resources.texture('image-float32', 'rgba', 'float', 'nearest'); + normalTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()); } else if (normalTexture.getWidth() !== pyramidTex.getWidth() || normalTexture.getHeight() !== pyramidTex.getHeight()) { - normalTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()) + normalTexture.define(pyramidTex.getWidth(), pyramidTex.getHeight()); } else { - needsClear = true + needsClear = true; } // const infoTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest') @@ -123,19 +123,19 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex // const indexTex = createTexture(ctx, 'image-float32', 'rgba', 'float', 'nearest') // indexTex.define(pyramidTex.width, pyramidTex.height) - const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, height) - ctx.state.currentRenderItemId = -1 + const renderable = getIsosurfaceRenderable(ctx, pyramidTex, activeVoxelsBase, volumeData, gridDim, gridTexDim, transform, isoValue, levels, scale, count, height); + ctx.state.currentRenderItemId = -1; - vertexGroupTexture.attachFramebuffer(framebuffer, 0) - normalTexture.attachFramebuffer(framebuffer, 1) + vertexGroupTexture.attachFramebuffer(framebuffer, 0); + normalTexture.attachFramebuffer(framebuffer, 1); // infoTex.attachFramebuffer(framebuffer, 1) // pointTexA.attachFramebuffer(framebuffer, 2) // pointTexB.attachFramebuffer(framebuffer, 3) // coordTex.attachFramebuffer(framebuffer, 4) // indexTex.attachFramebuffer(framebuffer, 5) - const { drawBuffers } = ctx.extensions - if (!drawBuffers) throw new Error('need WebGL draw buffers') + const { drawBuffers } = ctx.extensions; + if (!drawBuffers) throw new Error('need WebGL draw buffers'); drawBuffers.drawBuffers([ drawBuffers.COLOR_ATTACHMENT0, @@ -144,14 +144,14 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex // drawBuffers.COLOR_ATTACHMENT3, // drawBuffers.COLOR_ATTACHMENT4, // drawBuffers.COLOR_ATTACHMENT5 - ]) + ]); - setRenderingDefaults(ctx) - gl.viewport(0, 0, pyramidTex.getWidth(), pyramidTex.getHeight()) - if (needsClear) gl.clear(gl.COLOR_BUFFER_BIT) - renderable.render() + setRenderingDefaults(ctx); + gl.viewport(0, 0, pyramidTex.getWidth(), pyramidTex.getHeight()); + if (needsClear) gl.clear(gl.COLOR_BUFFER_BIT); + renderable.render(); - gl.finish() + gl.finish(); // const vgt = readTexture(ctx, vertexGroupTexture, pyramidTex.width, height) // console.log('vertexGroupTexture', vgt.array.subarray(0, 4 * count)) @@ -193,5 +193,5 @@ export function createIsosurfaceBuffers(ctx: WebGLContext, activeVoxelsBase: Tex // console.log('valuesA', valuesA) // console.log('valuesB', valuesB) - return { vertexGroupTexture, normalTexture, vertexCount: count } + return { vertexGroupTexture, normalTexture, vertexCount: count }; } \ No newline at end of file diff --git a/src/mol-gl/compute/marching-cubes/tables.ts b/src/mol-gl/compute/marching-cubes/tables.ts index bdf983c5fdbe65141c41a1c8ea53bb22425867a2..0383e6a06fa7064d99139e8c9587cbf4c7290f4d 100644 --- a/src/mol-gl/compute/marching-cubes/tables.ts +++ b/src/mol-gl/compute/marching-cubes/tables.ts @@ -7,30 +7,30 @@ import { TriTable, } from '../../../mol-geo/util/marching-cubes/tables'; import { TextureImage, createTextureImage } from '../../../mol-gl/renderable/util'; -let TriCount: TextureImage<Uint8Array> | undefined +let TriCount: TextureImage<Uint8Array> | undefined; export function getTriCount(): TextureImage<Uint8Array> { - if (TriCount !== undefined) return TriCount - TriCount = createTextureImage(16 * 16, 1, Uint8Array) - const { array } = TriCount + if (TriCount !== undefined) return TriCount; + TriCount = createTextureImage(16 * 16, 1, Uint8Array); + const { array } = TriCount; for (let i = 0, il = TriTable.length; i < il; ++i) { - array[i] = TriTable[i].length / 3 + array[i] = TriTable[i].length / 3; } - return TriCount + return TriCount; } -let TriIndices: TextureImage<Uint8Array> | undefined +let TriIndices: TextureImage<Uint8Array> | undefined; export function getTriIndices(): TextureImage<Uint8Array> { - if (TriIndices !== undefined) return TriIndices - TriIndices = createTextureImage(64 * 64, 1, Uint8Array) - const { array } = TriIndices + if (TriIndices !== undefined) return TriIndices; + TriIndices = createTextureImage(64 * 64, 1, Uint8Array); + const { array } = TriIndices; for (let i = 0, il = TriTable.length; i < il; ++i) { for (let j = 0; j < 16; ++j) { if (j < TriTable[i].length) { - array[i * 16 + j] = TriTable[i][j] + array[i * 16 + j] = TriTable[i][j]; } else { - array[i * 16 + j] = 255 + array[i * 16 + j] = 255; } } } - return TriIndices + return TriIndices; } \ No newline at end of file diff --git a/src/mol-gl/compute/util.ts b/src/mol-gl/compute/util.ts index f88346d02404b7568cc578bf8d943d659bfa71ba..645d4b90146570e047a2a524ef4ea6039ee85132 100644 --- a/src/mol-gl/compute/util.ts +++ b/src/mol-gl/compute/util.ts @@ -15,46 +15,46 @@ import { GLRenderingContext } from '../../mol-gl/webgl/compat'; export const QuadPositions = new Float32Array([ 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, // First triangle -1.0, -1.0, 1.0, -1.0, 1.0, 1.0 // Second triangle -]) +]); export const QuadSchema = { drawCount: ValueSpec('number'), instanceCount: ValueSpec('number'), aPosition: AttributeSpec('float32', 2, 0), uQuadScale: UniformSpec('v2'), -} +}; export const QuadValues: Values<typeof QuadSchema> = { drawCount: ValueCell.create(6), instanceCount: ValueCell.create(1), aPosition: ValueCell.create(QuadPositions), uQuadScale: ValueCell.create(Vec2.create(1, 1)), -} +}; // function getArrayForTexture(gl: GLRenderingContext, texture: Texture, size: number) { switch (texture.type) { - case gl.UNSIGNED_BYTE: return new Uint8Array(size) - case gl.FLOAT: return new Float32Array(size) + case gl.UNSIGNED_BYTE: return new Uint8Array(size); + case gl.FLOAT: return new Float32Array(size); } - throw new Error('unknown/unsupported texture type') + throw new Error('unknown/unsupported texture type'); } export function readTexture(ctx: WebGLContext, texture: Texture, width?: number, height?: number) { - const { gl, resources } = ctx - width = defaults(width, texture.getWidth()) - height = defaults(height, texture.getHeight()) - const size = width * height * 4 - const framebuffer = resources.framebuffer() - const array = getArrayForTexture(gl, texture, size) - framebuffer.bind() - texture.attachFramebuffer(framebuffer, 0) - ctx.readPixels(0, 0, width, height, array) - - return { array, width, height } + const { gl, resources } = ctx; + width = defaults(width, texture.getWidth()); + height = defaults(height, texture.getHeight()); + const size = width * height * 4; + const framebuffer = resources.framebuffer(); + const array = getArrayForTexture(gl, texture, size); + framebuffer.bind(); + texture.attachFramebuffer(framebuffer, 0); + ctx.readPixels(0, 0, width, height, array); + + return { array, width, height }; } export function printTexture(ctx: WebGLContext, texture: Texture, scale: number) { - printTextureImage(readTexture(ctx, texture), scale) + printTextureImage(readTexture(ctx, texture), scale); } \ No newline at end of file diff --git a/src/mol-gl/object3d.ts b/src/mol-gl/object3d.ts index 81cba1020a59e3156e79fd6cb020aff928c86471..76cc3fd758475bdeb5cfd09d2e7e1873488aa9fe 100644 --- a/src/mol-gl/object3d.ts +++ b/src/mol-gl/object3d.ts @@ -20,12 +20,12 @@ export namespace Object3D { position: Vec3.create(0, 0, 0), direction: Vec3.create(0, 0, -1), up: Vec3.create(0, 1, 0), - } + }; } - const center = Vec3.zero() + const center = Vec3.zero(); export function update(object3d: Object3D) { - Vec3.add(center, object3d.position, object3d.direction) - Mat4.lookAt(object3d.view, object3d.position, center, object3d.up) + Vec3.add(center, object3d.position, object3d.direction); + Mat4.lookAt(object3d.view, object3d.position, center, object3d.up); } } \ No newline at end of file diff --git a/src/mol-gl/render-object.ts b/src/mol-gl/render-object.ts index bb11d58fb6bb4fcf555786a6749b1523005d6324..0e123e984f2f08414d4a249aaeb49d3cd9d26bb2 100644 --- a/src/mol-gl/render-object.ts +++ b/src/mol-gl/render-object.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { RenderableState, Renderable } from './renderable' +import { RenderableState, Renderable } from './renderable'; import { idFactory } from '../mol-util/id-factory'; import { WebGLContext } from './webgl/context'; import { DirectVolumeValues, DirectVolumeRenderable } from './renderable/direct-volume'; @@ -15,9 +15,9 @@ import { SpheresValues, SpheresRenderable } from './renderable/spheres'; import { TextValues, TextRenderable } from './renderable/text'; import { TextureMeshValues, TextureMeshRenderable } from './renderable/texture-mesh'; -const getNextId = idFactory(0, 0x7FFFFFFF) +const getNextId = idFactory(0, 0x7FFFFFFF); -export const getNextMaterialId = idFactory(0, 0x7FFFFFFF) +export const getNextMaterialId = idFactory(0, 0x7FFFFFFF); export interface GraphicsRenderObject<T extends RenderObjectType = RenderObjectType> { readonly id: number, @@ -41,18 +41,18 @@ export type RenderObjectValues<T extends RenderObjectType> = // export function createRenderObject<T extends RenderObjectType>(type: T, values: RenderObjectValues<T>, state: RenderableState, materialId: number): GraphicsRenderObject<T> { - return { id: getNextId(), type, values, state, materialId } as GraphicsRenderObject<T> + return { id: getNextId(), type, values, state, materialId } as GraphicsRenderObject<T>; } export function createRenderable<T extends RenderObjectType>(ctx: WebGLContext, o: GraphicsRenderObject<T>): Renderable<any> { switch (o.type) { - case 'mesh': return MeshRenderable(ctx, o.id, o.values as MeshValues, o.state, o.materialId) - case 'points': return PointsRenderable(ctx, o.id, o.values as PointsValues, o.state, o.materialId) - case 'spheres': return SpheresRenderable(ctx, o.id, o.values as SpheresValues, o.state, o.materialId) - case 'text': return TextRenderable(ctx, o.id, o.values as TextValues, o.state, o.materialId) - case 'lines': return LinesRenderable(ctx, o.id, o.values as LinesValues, o.state, o.materialId) - case 'direct-volume': return DirectVolumeRenderable(ctx, o.id, o.values as DirectVolumeValues, o.state, o.materialId) - case 'texture-mesh': return TextureMeshRenderable(ctx, o.id, o.values as TextureMeshValues, o.state, o.materialId) + case 'mesh': return MeshRenderable(ctx, o.id, o.values as MeshValues, o.state, o.materialId); + case 'points': return PointsRenderable(ctx, o.id, o.values as PointsValues, o.state, o.materialId); + case 'spheres': return SpheresRenderable(ctx, o.id, o.values as SpheresValues, o.state, o.materialId); + case 'text': return TextRenderable(ctx, o.id, o.values as TextValues, o.state, o.materialId); + case 'lines': return LinesRenderable(ctx, o.id, o.values as LinesValues, o.state, o.materialId); + case 'direct-volume': return DirectVolumeRenderable(ctx, o.id, o.values as DirectVolumeValues, o.state, o.materialId); + case 'texture-mesh': return TextureMeshRenderable(ctx, o.id, o.values as TextureMeshValues, o.state, o.materialId); } - throw new Error('unsupported type') + throw new Error('unsupported type'); } diff --git a/src/mol-gl/renderable.ts b/src/mol-gl/renderable.ts index 86df8c3f51947aa757bd392c59b4bf6d006bcec0..12639b8dd7d6b7a9ed1a34238eb87c48e92f35ad 100644 --- a/src/mol-gl/renderable.ts +++ b/src/mol-gl/renderable.ts @@ -11,7 +11,7 @@ import { ValueCell } from '../mol-util'; import { idFactory } from '../mol-util/id-factory'; import { clamp } from '../mol-math/interpolate'; -const getNextRenderableId = idFactory() +const getNextRenderableId = idFactory(); export type RenderableState = { visible: boolean @@ -41,17 +41,17 @@ export function createRenderable<T extends Values<RenderableSchema>>(renderItem: render: (variant: GraphicsRenderVariant) => { if (values.uAlpha && values.alpha) { - ValueCell.updateIfChanged(values.uAlpha, clamp(values.alpha.ref.value * state.alphaFactor, 0, 1)) + ValueCell.updateIfChanged(values.uAlpha, clamp(values.alpha.ref.value * state.alphaFactor, 0, 1)); } if (values.uPickable) { - ValueCell.updateIfChanged(values.uPickable, state.pickable ? 1 : 0) + ValueCell.updateIfChanged(values.uPickable, state.pickable ? 1 : 0); } - renderItem.render(variant) + renderItem.render(variant); }, getProgram: (variant: GraphicsRenderVariant) => renderItem.getProgram(variant), update: () => renderItem.update(), dispose: () => renderItem.destroy() - } + }; } // @@ -73,5 +73,5 @@ export function createComputeRenderable<T extends Values<RenderableSchema>>(rend render: () => renderItem.render('compute'), update: () => renderItem.update(), dispose: () => renderItem.destroy() - } + }; } \ No newline at end of file diff --git a/src/mol-gl/renderable/direct-volume.ts b/src/mol-gl/renderable/direct-volume.ts index 6049da42422d1b121e5e7b9b2e41976065263947..1ea5bed4de868c6ad51a437c6f81731f83cab5dd 100644 --- a/src/mol-gl/renderable/direct-volume.ts +++ b/src/mol-gl/renderable/direct-volume.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { AttributeSpec, Values, UniformSpec, GlobalUniformSchema, InternalSchema, TextureSpec, ValueSpec, ElementsSpec, DefineSpec, InternalValues } from './schema'; @@ -65,17 +65,17 @@ export const DirectVolumeSchema = { dGridTexType: DefineSpec('string', ['2d', '3d']), uGridTexDim: UniformSpec('v3'), tGridTex: TextureSpec('texture', 'rgba', 'float', 'nearest'), -} +}; export type DirectVolumeSchema = typeof DirectVolumeSchema export type DirectVolumeValues = Values<DirectVolumeSchema> export function DirectVolumeRenderable(ctx: WebGLContext, id: number, values: DirectVolumeValues, state: RenderableState, materialId: number): Renderable<DirectVolumeValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...DirectVolumeSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...DirectVolumeSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0), - } - const shaderCode = DirectVolumeShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = DirectVolumeShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId); return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/lines.ts b/src/mol-gl/renderable/lines.ts index d7b293dd97f9ab9854d1cbf8e2c01833fcd51424..8c1aace36825f5de564036bfae70fcbfbddcb7b9 100644 --- a/src/mol-gl/renderable/lines.ts +++ b/src/mol-gl/renderable/lines.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, DefineSpec, Values, InternalSchema, SizeSchema, ElementsSpec, InternalValues } from './schema'; @@ -21,18 +21,18 @@ export const LinesSchema = { dLineSizeAttenuation: DefineSpec('boolean'), dDoubleSided: DefineSpec('boolean'), dFlipSided: DefineSpec('boolean'), -} +}; export type LinesSchema = typeof LinesSchema export type LinesValues = Values<LinesSchema> export function LinesRenderable(ctx: WebGLContext, id: number, values: LinesValues, state: RenderableState, materialId: number): Renderable<LinesValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...LinesSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...LinesSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0) - } - const shaderCode = LinesShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = LinesShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId); return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/mesh.ts b/src/mol-gl/renderable/mesh.ts index c34240c379aa719f6def692d1cdb4f02f1e6e5f8..9687054b1a960f95f1d1d9981dba7654a24c9a07 100644 --- a/src/mol-gl/renderable/mesh.ts +++ b/src/mol-gl/renderable/mesh.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, ElementsSpec, DefineSpec, Values, InternalSchema, InternalValues } from './schema'; @@ -20,18 +20,18 @@ export const MeshSchema = { dDoubleSided: DefineSpec('boolean'), dFlipSided: DefineSpec('boolean'), dIgnoreLight: DefineSpec('boolean'), -} as const +} as const; export type MeshSchema = typeof MeshSchema export type MeshValues = Values<MeshSchema> export function MeshRenderable(ctx: WebGLContext, id: number, values: MeshValues, state: RenderableState, materialId: number): Renderable<MeshValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...MeshSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...MeshSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0) - } - const shaderCode = MeshShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = MeshShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId); - return createRenderable(renderItem, values, state) + return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/points.ts b/src/mol-gl/renderable/points.ts index 0ed8c58f79fabc8f75a5d219c98c8086465d27d0..fdd2f2dafd2dd7e94c363f729f7437e9fad0b6a1 100644 --- a/src/mol-gl/renderable/points.ts +++ b/src/mol-gl/renderable/points.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, DefineSpec, Values, InternalSchema, SizeSchema, InternalValues } from './schema'; @@ -18,17 +18,17 @@ export const PointsSchema = { dPointSizeAttenuation: DefineSpec('boolean'), dPointFilledCircle: DefineSpec('boolean'), uPointEdgeBleach: UniformSpec('f'), -} +}; export type PointsSchema = typeof PointsSchema export type PointsValues = Values<PointsSchema> export function PointsRenderable(ctx: WebGLContext, id: number, values: PointsValues, state: RenderableState, materialId: number): Renderable<PointsValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...PointsSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...PointsSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0) - } - const shaderCode = PointsShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = PointsShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId); return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/schema.ts b/src/mol-gl/renderable/schema.ts index e662b8be096020304c688f3d6f0582b6258de4ab..611f6c46409daf39670363350ac04269147e0342 100644 --- a/src/mol-gl/renderable/schema.ts +++ b/src/mol-gl/renderable/schema.ts @@ -65,64 +65,64 @@ export type KindValue = { export type Values<S extends RenderableSchema> = { readonly [k in keyof S]: ValueCell<KindValue[S[k]['kind']]> } export function splitValues(schema: RenderableSchema, values: RenderableValues) { - const attributeValues: AttributeValues = {} - const defineValues: DefineValues = {} - const textureValues: TextureValues = {} - const uniformValues: UniformValues = {} - const materialUniformValues: UniformValues = {} + const attributeValues: AttributeValues = {}; + const defineValues: DefineValues = {}; + const textureValues: TextureValues = {}; + const uniformValues: UniformValues = {}; + const materialUniformValues: UniformValues = {}; Object.keys(schema).forEach(k => { - const spec = schema[k] - if (spec.type === 'attribute') attributeValues[k] = values[k] - if (spec.type === 'define') defineValues[k] = values[k] - if (spec.type === 'texture') textureValues[k] = values[k] + const spec = schema[k]; + if (spec.type === 'attribute') attributeValues[k] = values[k]; + if (spec.type === 'define') defineValues[k] = values[k]; + if (spec.type === 'texture') textureValues[k] = values[k]; // check if k exists in values so that global uniforms are excluded here if (spec.type === 'uniform' && values[k] !== undefined) { - if (spec.isMaterial) materialUniformValues[k] = values[k] - else uniformValues[k] = values[k] + if (spec.isMaterial) materialUniformValues[k] = values[k]; + else uniformValues[k] = values[k]; } - }) - return { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues } + }); + return { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues }; } export type Versions<T extends RenderableValues> = { [k in keyof T]: number } export function getValueVersions<T extends RenderableValues>(values: T) { - const versions: Versions<any> = {} + const versions: Versions<any> = {}; Object.keys(values).forEach(k => { - versions[k] = values[k].ref.version - }) - return versions as Versions<T> + versions[k] = values[k].ref.version; + }); + return versions as Versions<T>; } // export type AttributeSpec<K extends AttributeKind> = { type: 'attribute', kind: K, itemSize: AttributeItemSize, divisor: number } export function AttributeSpec<K extends AttributeKind>(kind: K, itemSize: AttributeItemSize, divisor: number): AttributeSpec<K> { - return { type: 'attribute', kind, itemSize, divisor } + return { type: 'attribute', kind, itemSize, divisor }; } export type UniformSpec<K extends UniformKind> = { type: 'uniform', kind: K, isMaterial: boolean } export function UniformSpec<K extends UniformKind>(kind: K, isMaterial = false): UniformSpec<K> { - return { type: 'uniform', kind, isMaterial } + return { type: 'uniform', kind, isMaterial }; } export type TextureSpec<K extends TextureKind> = { type: 'texture', kind: K, format: TextureFormat, dataType: TextureType, filter: TextureFilter } export function TextureSpec<K extends TextureKind>(kind: K, format: TextureFormat, dataType: TextureType, filter: TextureFilter): TextureSpec<K> { - return { type: 'texture', kind, format, dataType, filter } + return { type: 'texture', kind, format, dataType, filter }; } export type ElementsSpec<K extends ElementsKind> = { type: 'elements', kind: K } export function ElementsSpec<K extends ElementsKind>(kind: K): ElementsSpec<K> { - return { type: 'elements', kind } + return { type: 'elements', kind }; } export type DefineSpec<K extends DefineKind> = { type: 'define', kind: K, options?: string[] } export function DefineSpec<K extends DefineKind>(kind: K, options?: string[]): DefineSpec<K> { - return { type: 'define', kind, options } + return { type: 'define', kind, options }; } export type ValueSpec<K extends ValueKind> = { type: 'value', kind: K } export function ValueSpec<K extends ValueKind>(kind: K): ValueSpec<K> { - return { type: 'value', kind } + return { type: 'value', kind }; } // @@ -181,14 +181,14 @@ export const GlobalUniformSchema = { uHighlightColor: UniformSpec('v3'), uSelectColor: UniformSpec('v3'), -} as const +} as const; export type GlobalUniformSchema = typeof GlobalUniformSchema export type GlobalUniformValues = Values<GlobalUniformSchema> // { [k in keyof GlobalUniformSchema]: ValueCell<any> } export const InternalSchema = { uObjectId: UniformSpec('i'), uPickable: UniformSpec('i', true), -} as const +} as const; export type InternalSchema = typeof InternalSchema export type InternalValues = { [k in keyof InternalSchema]: ValueCell<any> } @@ -198,7 +198,7 @@ export const ColorSchema = { uColorTexDim: UniformSpec('v2'), tColor: TextureSpec('image-uint8', 'rgb', 'ubyte', 'nearest'), dColorType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']), -} as const +} as const; export type ColorSchema = typeof ColorSchema export type ColorValues = Values<ColorSchema> @@ -209,14 +209,14 @@ export const SizeSchema = { tSize: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'), dSizeType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']), uSizeFactor: UniformSpec('f'), -} as const +} as const; export type SizeSchema = typeof SizeSchema export type SizeValues = Values<SizeSchema> export const MarkerSchema = { uMarkerTexDim: UniformSpec('v2'), tMarker: TextureSpec('image-uint8', 'alpha', 'ubyte', 'nearest'), -} as const +} as const; export type MarkerSchema = typeof MarkerSchema export type MarkerValues = Values<MarkerSchema> @@ -224,7 +224,7 @@ export const OverpaintSchema = { uOverpaintTexDim: UniformSpec('v2'), tOverpaint: TextureSpec('image-uint8', 'rgba', 'ubyte', 'nearest'), dOverpaint: DefineSpec('boolean'), -} as const +} as const; export type OverpaintSchema = typeof OverpaintSchema export type OverpaintValues = Values<OverpaintSchema> @@ -235,7 +235,7 @@ export const TransparencySchema = { dTransparency: DefineSpec('boolean'), // dTransparencyType: DefineSpec('string', ['uniform', 'attribute', 'instance', 'group', 'group_instance']), // TODO dTransparencyVariant: DefineSpec('string', ['single', 'multi']), -} as const +} as const; export type TransparencySchema = typeof TransparencySchema export type TransparencyValues = Values<TransparencySchema> @@ -277,6 +277,6 @@ export const BaseSchema = { boundingSphere: ValueSpec('sphere'), /** bounding sphere NOT taking aTransform into account */ invariantBoundingSphere: ValueSpec('sphere'), -} as const +} as const; export type BaseSchema = typeof BaseSchema export type BaseValues = Values<BaseSchema> \ No newline at end of file diff --git a/src/mol-gl/renderable/spheres.ts b/src/mol-gl/renderable/spheres.ts index 30b812954a241448a398f9e51c841ff25d56a0c1..399e641ef2995e03d290905f3e304367234b4c7d 100644 --- a/src/mol-gl/renderable/spheres.ts +++ b/src/mol-gl/renderable/spheres.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, Values, InternalSchema, SizeSchema, InternalValues, ElementsSpec, ValueSpec, DefineSpec } from './schema'; @@ -21,17 +21,17 @@ export const SpheresSchema = { padding: ValueSpec('number'), dDoubleSided: DefineSpec('boolean'), dIgnoreLight: DefineSpec('boolean'), -} +}; export type SpheresSchema = typeof SpheresSchema export type SpheresValues = Values<SpheresSchema> export function SpheresRenderable(ctx: WebGLContext, id: number, values: SpheresValues, state: RenderableState, materialId: number): Renderable<SpheresValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...SpheresSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...SpheresSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0) - } - const shaderCode = SpheresShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = SpheresShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId); return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/text.ts b/src/mol-gl/renderable/text.ts index 993feda41d0981a1f87df0ba2db8ace6ab21bd5b..90562ea3e71cca318913d13a460af883849f8f6e 100644 --- a/src/mol-gl/renderable/text.ts +++ b/src/mol-gl/renderable/text.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, AttributeSpec, UniformSpec, Values, InternalSchema, SizeSchema, InternalValues, TextureSpec, ElementsSpec, ValueSpec } from './schema'; @@ -30,17 +30,17 @@ export const TextSchema = { uOffsetZ: UniformSpec('f'), uBackgroundColor: UniformSpec('v3'), uBackgroundOpacity: UniformSpec('f'), -} +}; export type TextSchema = typeof TextSchema export type TextValues = Values<TextSchema> export function TextRenderable(ctx: WebGLContext, id: number, values: TextValues, state: RenderableState, materialId: number): Renderable<TextValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...TextSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...TextSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0) - } - const shaderCode = TextShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = TextShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId); return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/texture-mesh.ts b/src/mol-gl/renderable/texture-mesh.ts index c8ab401f072a30f79b8048d32c3d9cb7b8fab2b2..1aa193ab94a192074df10f6ce25a7aa16bdf22f5 100644 --- a/src/mol-gl/renderable/texture-mesh.ts +++ b/src/mol-gl/renderable/texture-mesh.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Renderable, RenderableState, createRenderable } from '../renderable' +import { Renderable, RenderableState, createRenderable } from '../renderable'; import { WebGLContext } from '../webgl/context'; import { createGraphicsRenderItem } from '../webgl/render-item'; import { GlobalUniformSchema, BaseSchema, DefineSpec, Values, InternalSchema, InternalValues, UniformSpec, TextureSpec } from './schema'; @@ -23,18 +23,18 @@ export const TextureMeshSchema = { dDoubleSided: DefineSpec('boolean'), dFlipSided: DefineSpec('boolean'), dGeoTexture: DefineSpec('boolean'), -} +}; export type TextureMeshSchema = typeof TextureMeshSchema export type TextureMeshValues = Values<TextureMeshSchema> export function TextureMeshRenderable(ctx: WebGLContext, id: number, values: TextureMeshValues, state: RenderableState, materialId: number): Renderable<TextureMeshValues> { - const schema = { ...GlobalUniformSchema, ...InternalSchema, ...TextureMeshSchema } + const schema = { ...GlobalUniformSchema, ...InternalSchema, ...TextureMeshSchema }; const internalValues: InternalValues = { uObjectId: ValueCell.create(id), uPickable: ValueCell.create(state.pickable ? 1 : 0) - } - const shaderCode = MeshShaderCode - const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId) + }; + const shaderCode = MeshShaderCode; + const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId); - return createRenderable(renderItem, values, state) + return createRenderable(renderItem, values, state); } \ No newline at end of file diff --git a/src/mol-gl/renderable/util.ts b/src/mol-gl/renderable/util.ts index 1e135671657688a07b1160c601c48cc711bdcde8..8a4781c01ad3ba248b5ee5cbc8eaaab0f134b02c 100644 --- a/src/mol-gl/renderable/util.ts +++ b/src/mol-gl/renderable/util.ts @@ -4,16 +4,16 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Sphere3D } from '../../mol-math/geometry' -import { Vec3 } from '../../mol-math/linear-algebra' +import { Sphere3D } from '../../mol-math/geometry'; +import { Vec3 } from '../../mol-math/linear-algebra'; import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper'; export function calculateTextureInfo (n: number, itemSize: number) { - const sqN = Math.sqrt(n) - let width = Math.ceil(sqN) - width = width + (itemSize - (width % itemSize)) % itemSize - const height = width > 0 ? Math.ceil(n / width) : 0 - return { width, height, length: width * height * itemSize } + const sqN = Math.sqrt(n); + let width = Math.ceil(sqN); + width = width + (itemSize - (width % itemSize)) % itemSize; + const height = width > 0 ? Math.ceil(n / width) : 0; + return { width, height, length: width * height * itemSize }; } export interface TextureImage<T extends Uint8Array | Float32Array> { @@ -30,132 +30,132 @@ export interface TextureVolume<T extends Uint8Array | Float32Array> { } export function createTextureImage<T extends Uint8Array | Float32Array>(n: number, itemSize: number, arrayCtor: new (length: number) => T, array?: T): TextureImage<T> { - const { length, width, height } = calculateTextureInfo(n, itemSize) - array = array && array.length >= length ? array : new arrayCtor(length) - return { array, width, height } + const { length, width, height } = calculateTextureInfo(n, itemSize); + array = array && array.length >= length ? array : new arrayCtor(length); + return { array, width, height }; } export function printTextureImage(textureImage: TextureImage<any>, scale = 1) { - const { array, width, height } = textureImage - const itemSize = array.length / (width * height) - const data = new Uint8ClampedArray(width * height * 4) + const { array, width, height } = textureImage; + const itemSize = array.length / (width * height); + const data = new Uint8ClampedArray(width * height * 4); if (itemSize === 1) { for (let y = 0; y < height; ++y) { for (let x = 0; x < width; ++x) { - data[(y * width + x) * 4 + 3] = array[y * width + x] + data[(y * width + x) * 4 + 3] = array[y * width + x]; } } } else if (itemSize === 4) { - data.set(array) + data.set(array); } else { - console.warn(`itemSize '${itemSize}' not supported`) + console.warn(`itemSize '${itemSize}' not supported`); } - return printImageData(new ImageData(data, width, height), scale) + return printImageData(new ImageData(data, width, height), scale); } export function printImageData(imageData: ImageData, scale = 1, pixelated = false) { - const canvas = document.createElement('canvas') - canvas.width = imageData.width - canvas.height = imageData.height - const ctx = canvas.getContext('2d') - if (!ctx) throw new Error('Could not create canvas 2d context') - ctx.putImageData(imageData, 0, 0) + const canvas = document.createElement('canvas'); + canvas.width = imageData.width; + canvas.height = imageData.height; + const ctx = canvas.getContext('2d'); + if (!ctx) throw new Error('Could not create canvas 2d context'); + ctx.putImageData(imageData, 0, 0); canvas.toBlob(imgBlob => { - const objectURL = window.URL.createObjectURL(imgBlob) - const img = document.createElement('img') - img.src = objectURL - img.style.width = imageData.width * scale + 'px' + const objectURL = window.URL.createObjectURL(imgBlob); + const img = document.createElement('img'); + img.src = objectURL; + img.style.width = imageData.width * scale + 'px'; img.style.height = imageData.height * scale + 'px'; if (pixelated) { // not supported in Firefox and IE - img.style.imageRendering = 'pixelated' + img.style.imageRendering = 'pixelated'; } - img.style.position = 'absolute' - img.style.top = '0px' - img.style.left = '0px' - img.style.border = 'solid grey' - document.body.appendChild(img) - }, 'image/png') + img.style.position = 'absolute'; + img.style.top = '0px'; + img.style.left = '0px'; + img.style.border = 'solid grey'; + document.body.appendChild(img); + }, 'image/png'); } // -const v = Vec3.zero() -const boundaryHelperCoarse = new BoundaryHelper('14') -const boundaryHelperFine = new BoundaryHelper('98') +const v = Vec3.zero(); +const boundaryHelperCoarse = new BoundaryHelper('14'); +const boundaryHelperFine = new BoundaryHelper('98'); function getHelper(count: number) { - return count > 500_000 ? boundaryHelperCoarse : boundaryHelperFine + return count > 500_000 ? boundaryHelperCoarse : boundaryHelperFine; } export function calculateInvariantBoundingSphere(position: Float32Array, positionCount: number, stepFactor: number): Sphere3D { - const step = stepFactor * 3 - const boundaryHelper = getHelper(positionCount) + const step = stepFactor * 3; + const boundaryHelper = getHelper(positionCount); - boundaryHelper.reset() + boundaryHelper.reset(); for (let i = 0, _i = positionCount * 3; i < _i; i += step) { - Vec3.fromArray(v, position, i) - boundaryHelper.includePosition(v) + Vec3.fromArray(v, position, i); + boundaryHelper.includePosition(v); } - boundaryHelper.finishedIncludeStep() + boundaryHelper.finishedIncludeStep(); for (let i = 0, _i = positionCount * 3; i < _i; i += step) { - Vec3.fromArray(v, position, i) - boundaryHelper.radiusPosition(v) + Vec3.fromArray(v, position, i); + boundaryHelper.radiusPosition(v); } - const sphere = boundaryHelper.getSphere() + const sphere = boundaryHelper.getSphere(); if (positionCount <= 98) { - const extrema: Vec3[] = [] + const extrema: Vec3[] = []; for (let i = 0, _i = positionCount * 3; i < _i; i += step) { extrema.push(Vec3.fromArray(Vec3(), position, i)); } - Sphere3D.setExtrema(sphere, extrema) + Sphere3D.setExtrema(sphere, extrema); } - return sphere + return sphere; } export function calculateTransformBoundingSphere(invariantBoundingSphere: Sphere3D, transform: Float32Array, transformCount: number): Sphere3D { - const boundaryHelper = getHelper(transformCount) - boundaryHelper.reset() + const boundaryHelper = getHelper(transformCount); + boundaryHelper.reset(); - const { center, radius, extrema } = invariantBoundingSphere + const { center, radius, extrema } = invariantBoundingSphere; // only use extrema if there are not too many transforms if (extrema && transformCount < 50) { for (let i = 0, _i = transformCount; i < _i; ++i) { for (const e of extrema) { - Vec3.transformMat4Offset(v, e, transform, 0, 0, i * 16) - boundaryHelper.includePosition(v) + Vec3.transformMat4Offset(v, e, transform, 0, 0, i * 16); + boundaryHelper.includePosition(v); } } - boundaryHelper.finishedIncludeStep() + boundaryHelper.finishedIncludeStep(); for (let i = 0, _i = transformCount; i < _i; ++i) { for (const e of extrema) { - Vec3.transformMat4Offset(v, e, transform, 0, 0, i * 16) - boundaryHelper.radiusPosition(v) + Vec3.transformMat4Offset(v, e, transform, 0, 0, i * 16); + boundaryHelper.radiusPosition(v); } } } else { for (let i = 0, _i = transformCount; i < _i; ++i) { - Vec3.transformMat4Offset(v, center, transform, 0, 0, i * 16) - boundaryHelper.includePositionRadius(v, radius) + Vec3.transformMat4Offset(v, center, transform, 0, 0, i * 16); + boundaryHelper.includePositionRadius(v, radius); } - boundaryHelper.finishedIncludeStep() + boundaryHelper.finishedIncludeStep(); for (let i = 0, _i = transformCount; i < _i; ++i) { - Vec3.transformMat4Offset(v, center, transform, 0, 0, i * 16) - boundaryHelper.radiusPositionRadius(v, radius) + Vec3.transformMat4Offset(v, center, transform, 0, 0, i * 16); + boundaryHelper.radiusPositionRadius(v, radius); } } - return boundaryHelper.getSphere() + return boundaryHelper.getSphere(); } export function calculateBoundingSphere(position: Float32Array, positionCount: number, transform: Float32Array, transformCount: number, padding = 0, stepFactor = 1): { boundingSphere: Sphere3D, invariantBoundingSphere: Sphere3D } { - const invariantBoundingSphere = calculateInvariantBoundingSphere(position, positionCount, stepFactor) - const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform, transformCount) - Sphere3D.expand(boundingSphere, boundingSphere, padding) - Sphere3D.expand(invariantBoundingSphere, invariantBoundingSphere, padding) - return { boundingSphere, invariantBoundingSphere } + const invariantBoundingSphere = calculateInvariantBoundingSphere(position, positionCount, stepFactor); + const boundingSphere = calculateTransformBoundingSphere(invariantBoundingSphere, transform, transformCount); + Sphere3D.expand(boundingSphere, boundingSphere, padding); + Sphere3D.expand(invariantBoundingSphere, invariantBoundingSphere, padding); + return { boundingSphere, invariantBoundingSphere }; } \ No newline at end of file diff --git a/src/mol-gl/renderer.ts b/src/mol-gl/renderer.ts index 6176d71bf232021207580d39b5021759edf6d1fe..334251f7f0ac4ef8bd33652b06d119a233deada6 100644 --- a/src/mol-gl/renderer.ts +++ b/src/mol-gl/renderer.ts @@ -71,59 +71,59 @@ export const RendererParams = { metallic: PD.Group({}), plastic: PD.Group({}), }, { label: 'Lighting', description: 'Style in which the 3D scene is rendered/lighted' }), -} +}; export type RendererProps = PD.Values<typeof RendererParams> function getStyle(props: RendererProps['style']) { switch (props.name) { case 'custom': - return props.params + return props.params; case 'flat': return { lightIntensity: 0, ambientIntensity: 1, metalness: 0, roughness: 0.4, reflectivity: 0.5 - } + }; case 'matte': return { lightIntensity: 0.6, ambientIntensity: 0.4, metalness: 0, roughness: 1, reflectivity: 0.5 - } + }; case 'glossy': return { lightIntensity: 0.6, ambientIntensity: 0.4, metalness: 0, roughness: 0.4, reflectivity: 0.5 - } + }; case 'metallic': return { lightIntensity: 0.6, ambientIntensity: 0.4, metalness: 0.4, roughness: 0.6, reflectivity: 0.5 - } + }; case 'plastic': return { lightIntensity: 0.6, ambientIntensity: 0.4, metalness: 0, roughness: 0.2, reflectivity: 0.5 - } + }; } } namespace Renderer { export function create(ctx: WebGLContext, props: Partial<RendererProps> = {}): Renderer { - const { gl, state, stats } = ctx - const p = PD.merge(RendererParams, PD.getDefaultValues(RendererParams), props) - const style = getStyle(p.style) + const { gl, state, stats } = ctx; + const p = PD.merge(RendererParams, PD.getDefaultValues(RendererParams), props); + const style = getStyle(p.style); - const viewport = Viewport() - const bgColor = Color.toVec3Normalized(Vec3(), p.backgroundColor) + const viewport = Viewport(); + const bgColor = Color.toVec3Normalized(Vec3(), p.backgroundColor); - const view = Mat4() - const invView = Mat4() - const modelView = Mat4() - const invModelView = Mat4() - const invProjection = Mat4() - const modelViewProjection = Mat4() - const invModelViewProjection = Mat4() + const view = Mat4(); + const invView = Mat4(); + const modelView = Mat4(); + const invModelView = Mat4(); + const invProjection = Mat4(); + const modelViewProjection = Mat4(); + const invModelViewProjection = Mat4(); - const viewOffset = Vec2() + const viewOffset = Vec2(); const globalUniforms: GlobalUniformValues = { uModel: ValueCell.create(Mat4.identity()), @@ -167,185 +167,185 @@ namespace Renderer { uHighlightColor: ValueCell.create(Color.toVec3Normalized(Vec3(), p.highlightColor)), uSelectColor: ValueCell.create(Color.toVec3Normalized(Vec3(), p.selectColor)), - } - const globalUniformList = Object.entries(globalUniforms) + }; + const globalUniformList = Object.entries(globalUniforms); - let globalUniformsNeedUpdate = true + let globalUniformsNeedUpdate = true; const renderObject = (r: Renderable<RenderableValues & BaseValues>, variant: GraphicsRenderVariant) => { - const program = r.getProgram(variant) + const program = r.getProgram(variant); if (r.state.visible) { if (state.currentProgramId !== program.id) { // console.log('new program') - globalUniformsNeedUpdate = true - program.use() + globalUniformsNeedUpdate = true; + program.use(); } if (globalUniformsNeedUpdate) { // console.log('globalUniformsNeedUpdate') - program.setUniforms(globalUniformList) - globalUniformsNeedUpdate = false + program.setUniforms(globalUniformList); + globalUniformsNeedUpdate = false; } if (r.values.dDoubleSided) { if (r.values.dDoubleSided.ref.value) { - state.disable(gl.CULL_FACE) + state.disable(gl.CULL_FACE); } else { - state.enable(gl.CULL_FACE) + state.enable(gl.CULL_FACE); } } else { // webgl default - state.disable(gl.CULL_FACE) + state.disable(gl.CULL_FACE); } if (r.values.dFlipSided) { if (r.values.dFlipSided.ref.value) { - state.frontFace(gl.CW) - state.cullFace(gl.FRONT) + state.frontFace(gl.CW); + state.cullFace(gl.FRONT); } else { - state.frontFace(gl.CCW) - state.cullFace(gl.BACK) + state.frontFace(gl.CCW); + state.cullFace(gl.BACK); } } else { // webgl default - state.frontFace(gl.CCW) - state.cullFace(gl.BACK) + state.frontFace(gl.CCW); + state.cullFace(gl.BACK); } - r.render(variant) + r.render(variant); } - } + }; const render = (scene: Scene, camera: Camera, variant: GraphicsRenderVariant, clear: boolean, transparentBackground: boolean) => { - ValueCell.update(globalUniforms.uModel, scene.view) - ValueCell.update(globalUniforms.uView, camera.view) - ValueCell.update(globalUniforms.uInvView, Mat4.invert(invView, camera.view)) - ValueCell.update(globalUniforms.uModelView, Mat4.mul(modelView, scene.view, camera.view)) - ValueCell.update(globalUniforms.uInvModelView, Mat4.invert(invModelView, modelView)) - ValueCell.update(globalUniforms.uProjection, camera.projection) - ValueCell.update(globalUniforms.uInvProjection, Mat4.invert(invProjection, camera.projection)) - ValueCell.update(globalUniforms.uModelViewProjection, Mat4.mul(modelViewProjection, modelView, camera.projection)) - ValueCell.update(globalUniforms.uInvModelViewProjection, Mat4.invert(invModelViewProjection, modelViewProjection)) - - ValueCell.update(globalUniforms.uIsOrtho, camera.state.mode === 'orthographic' ? 1 : 0) - ValueCell.update(globalUniforms.uViewOffset, camera.viewOffset.enabled ? Vec2.set(viewOffset, camera.viewOffset.offsetX * 16, camera.viewOffset.offsetY * 16) : Vec2.set(viewOffset, 0, 0)) - - ValueCell.update(globalUniforms.uCameraPosition, camera.state.position) - ValueCell.update(globalUniforms.uFar, camera.far) - ValueCell.update(globalUniforms.uNear, camera.near) - ValueCell.update(globalUniforms.uFogFar, camera.fogFar) - ValueCell.update(globalUniforms.uFogNear, camera.fogNear) - - ValueCell.update(globalUniforms.uTransparentBackground, transparentBackground ? 1 : 0) - - globalUniformsNeedUpdate = true - state.currentRenderItemId = -1 - - const { renderables } = scene - - state.disable(gl.SCISSOR_TEST) - state.disable(gl.BLEND) - state.depthMask(true) - state.colorMask(true, true, true, true) - state.enable(gl.DEPTH_TEST) + ValueCell.update(globalUniforms.uModel, scene.view); + ValueCell.update(globalUniforms.uView, camera.view); + ValueCell.update(globalUniforms.uInvView, Mat4.invert(invView, camera.view)); + ValueCell.update(globalUniforms.uModelView, Mat4.mul(modelView, scene.view, camera.view)); + ValueCell.update(globalUniforms.uInvModelView, Mat4.invert(invModelView, modelView)); + ValueCell.update(globalUniforms.uProjection, camera.projection); + ValueCell.update(globalUniforms.uInvProjection, Mat4.invert(invProjection, camera.projection)); + ValueCell.update(globalUniforms.uModelViewProjection, Mat4.mul(modelViewProjection, modelView, camera.projection)); + ValueCell.update(globalUniforms.uInvModelViewProjection, Mat4.invert(invModelViewProjection, modelViewProjection)); + + ValueCell.update(globalUniforms.uIsOrtho, camera.state.mode === 'orthographic' ? 1 : 0); + ValueCell.update(globalUniforms.uViewOffset, camera.viewOffset.enabled ? Vec2.set(viewOffset, camera.viewOffset.offsetX * 16, camera.viewOffset.offsetY * 16) : Vec2.set(viewOffset, 0, 0)); + + ValueCell.update(globalUniforms.uCameraPosition, camera.state.position); + ValueCell.update(globalUniforms.uFar, camera.far); + ValueCell.update(globalUniforms.uNear, camera.near); + ValueCell.update(globalUniforms.uFogFar, camera.fogFar); + ValueCell.update(globalUniforms.uFogNear, camera.fogNear); + + ValueCell.update(globalUniforms.uTransparentBackground, transparentBackground ? 1 : 0); + + globalUniformsNeedUpdate = true; + state.currentRenderItemId = -1; + + const { renderables } = scene; + + state.disable(gl.SCISSOR_TEST); + state.disable(gl.BLEND); + state.depthMask(true); + state.colorMask(true, true, true, true); + state.enable(gl.DEPTH_TEST); if (clear) { if (variant === 'color') { - state.clearColor(bgColor[0], bgColor[1], bgColor[2], transparentBackground ? 0 : 1) + state.clearColor(bgColor[0], bgColor[1], bgColor[2], transparentBackground ? 0 : 1); } else { - state.clearColor(1, 1, 1, 1) + state.clearColor(1, 1, 1, 1); } - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); } if (variant === 'color') { for (let i = 0, il = renderables.length; i < il; ++i) { - const r = renderables[i] - if (r.state.opaque) renderObject(r, variant) + const r = renderables[i]; + if (r.state.opaque) renderObject(r, variant); } - state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE) - state.enable(gl.BLEND) + state.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE); + state.enable(gl.BLEND); for (let i = 0, il = renderables.length; i < il; ++i) { - const r = renderables[i] + const r = renderables[i]; if (!r.state.opaque) { - state.depthMask(false) - renderObject(r, variant) + state.depthMask(false); + renderObject(r, variant); } } } else { // picking & depth for (let i = 0, il = renderables.length; i < il; ++i) { - renderObject(renderables[i], variant) + renderObject(renderables[i], variant); } } - gl.finish() - } + gl.finish(); + }; return { clear: (transparentBackground: boolean) => { - state.depthMask(true) - state.colorMask(true, true, true, true) - state.clearColor(bgColor[0], bgColor[1], bgColor[2], transparentBackground ? 0 : 1) - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + state.depthMask(true); + state.colorMask(true, true, true, true); + state.clearColor(bgColor[0], bgColor[1], bgColor[2], transparentBackground ? 0 : 1); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); }, render, setProps: (props: Partial<RendererProps>) => { if (props.backgroundColor !== undefined && props.backgroundColor !== p.backgroundColor) { - p.backgroundColor = props.backgroundColor - Color.toVec3Normalized(bgColor, p.backgroundColor) - ValueCell.update(globalUniforms.uFogColor, Vec3.copy(globalUniforms.uFogColor.ref.value, bgColor)) + p.backgroundColor = props.backgroundColor; + Color.toVec3Normalized(bgColor, p.backgroundColor); + ValueCell.update(globalUniforms.uFogColor, Vec3.copy(globalUniforms.uFogColor.ref.value, bgColor)); } if (props.pickingAlphaThreshold !== undefined && props.pickingAlphaThreshold !== p.pickingAlphaThreshold) { - p.pickingAlphaThreshold = props.pickingAlphaThreshold - ValueCell.update(globalUniforms.uPickingAlphaThreshold, p.pickingAlphaThreshold) + p.pickingAlphaThreshold = props.pickingAlphaThreshold; + ValueCell.update(globalUniforms.uPickingAlphaThreshold, p.pickingAlphaThreshold); } if (props.interiorDarkening !== undefined && props.interiorDarkening !== p.interiorDarkening) { - p.interiorDarkening = props.interiorDarkening - ValueCell.update(globalUniforms.uInteriorDarkening, p.interiorDarkening) + p.interiorDarkening = props.interiorDarkening; + ValueCell.update(globalUniforms.uInteriorDarkening, p.interiorDarkening); } if (props.interiorColorFlag !== undefined && props.interiorColorFlag !== p.interiorColorFlag) { - p.interiorColorFlag = props.interiorColorFlag - ValueCell.update(globalUniforms.uInteriorColorFlag, p.interiorColorFlag ? 1 : 0) + p.interiorColorFlag = props.interiorColorFlag; + ValueCell.update(globalUniforms.uInteriorColorFlag, p.interiorColorFlag ? 1 : 0); } if (props.interiorColor !== undefined && props.interiorColor !== p.interiorColor) { - p.interiorColor = props.interiorColor - ValueCell.update(globalUniforms.uInteriorColor, Color.toVec3Normalized(globalUniforms.uInteriorColor.ref.value, p.interiorColor)) + p.interiorColor = props.interiorColor; + ValueCell.update(globalUniforms.uInteriorColor, Color.toVec3Normalized(globalUniforms.uInteriorColor.ref.value, p.interiorColor)); } if (props.highlightColor !== undefined && props.highlightColor !== p.highlightColor) { - p.highlightColor = props.highlightColor - ValueCell.update(globalUniforms.uHighlightColor, Color.toVec3Normalized(globalUniforms.uHighlightColor.ref.value, p.highlightColor)) + p.highlightColor = props.highlightColor; + ValueCell.update(globalUniforms.uHighlightColor, Color.toVec3Normalized(globalUniforms.uHighlightColor.ref.value, p.highlightColor)); } if (props.selectColor !== undefined && props.selectColor !== p.selectColor) { - p.selectColor = props.selectColor - ValueCell.update(globalUniforms.uSelectColor, Color.toVec3Normalized(globalUniforms.uSelectColor.ref.value, p.selectColor)) + p.selectColor = props.selectColor; + ValueCell.update(globalUniforms.uSelectColor, Color.toVec3Normalized(globalUniforms.uSelectColor.ref.value, p.selectColor)); } if (props.style !== undefined) { - p.style = props.style - Object.assign(style, getStyle(props.style)) - ValueCell.updateIfChanged(globalUniforms.uLightIntensity, style.lightIntensity) - ValueCell.updateIfChanged(globalUniforms.uAmbientIntensity, style.ambientIntensity) - ValueCell.updateIfChanged(globalUniforms.uMetalness, style.metalness) - ValueCell.updateIfChanged(globalUniforms.uRoughness, style.roughness) - ValueCell.updateIfChanged(globalUniforms.uReflectivity, style.reflectivity) + p.style = props.style; + Object.assign(style, getStyle(props.style)); + ValueCell.updateIfChanged(globalUniforms.uLightIntensity, style.lightIntensity); + ValueCell.updateIfChanged(globalUniforms.uAmbientIntensity, style.ambientIntensity); + ValueCell.updateIfChanged(globalUniforms.uMetalness, style.metalness); + ValueCell.updateIfChanged(globalUniforms.uRoughness, style.roughness); + ValueCell.updateIfChanged(globalUniforms.uReflectivity, style.reflectivity); } }, setViewport: (x: number, y: number, width: number, height: number) => { - gl.viewport(x, y, width, height) + gl.viewport(x, y, width, height); if (x !== viewport.x || y !== viewport.y || width !== viewport.width || height !== viewport.height) { - Viewport.set(viewport, x, y, width, height) - ValueCell.update(globalUniforms.uViewportHeight, height) - ValueCell.update(globalUniforms.uViewport, Vec4.set(globalUniforms.uViewport.ref.value, x, y, width, height)) + Viewport.set(viewport, x, y, width, height); + ValueCell.update(globalUniforms.uViewportHeight, height); + ValueCell.update(globalUniforms.uViewport, Vec4.set(globalUniforms.uViewport.ref.value, x, y, width, height)); } }, get props() { - return p + return p; }, get stats(): RendererStats { return { @@ -362,13 +362,13 @@ namespace Renderer { drawCount: stats.drawCount, instanceCount: stats.instanceCount, instancedDrawCount: stats.instancedDrawCount, - } + }; }, dispose: () => { // TODO } - } + }; } } -export default Renderer \ No newline at end of file +export default Renderer; \ No newline at end of file diff --git a/src/mol-gl/scene.ts b/src/mol-gl/scene.ts index 2bed393392a409f6b0f5901b8c2d0a2a42539967..2aa4bec6abbaa15c66b3d8ae9f476fb903fa6e9a 100644 --- a/src/mol-gl/scene.ts +++ b/src/mol-gl/scene.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Renderable } from './renderable' +import { Renderable } from './renderable'; import { WebGLContext } from './webgl/context'; import { RenderableValues, BaseValues } from './renderable/schema'; import { GraphicsRenderObject, createRenderable } from './render-object'; @@ -17,7 +17,7 @@ import { arraySetRemove } from '../mol-util/array'; import { BoundaryHelper } from '../mol-math/geometry/boundary-helper'; import { hash1 } from '../mol-data/util'; -const boundaryHelper = new BoundaryHelper('98') +const boundaryHelper = new BoundaryHelper('98'); function calculateBoundingSphere(renderables: Renderable<RenderableValues & BaseValues>[], boundingSphere: Sphere3D, onlyVisible: boolean): Sphere3D { boundaryHelper.reset(); @@ -25,7 +25,7 @@ function calculateBoundingSphere(renderables: Renderable<RenderableValues & Base for (let i = 0, il = renderables.length; i < il; ++i) { if (onlyVisible && !renderables[i].state.visible) continue; - const boundingSphere = renderables[i].values.boundingSphere.ref.value + const boundingSphere = renderables[i].values.boundingSphere.ref.value; if (!boundingSphere.radius) continue; boundaryHelper.includeSphere(boundingSphere); @@ -34,7 +34,7 @@ function calculateBoundingSphere(renderables: Renderable<RenderableValues & Base for (let i = 0, il = renderables.length; i < il; ++i) { if (onlyVisible && !renderables[i].state.visible) continue; - const boundingSphere = renderables[i].values.boundingSphere.ref.value + const boundingSphere = renderables[i].values.boundingSphere.ref.value; if (!boundingSphere.radius) continue; boundaryHelper.radiusSphere(boundingSphere); @@ -44,15 +44,15 @@ function calculateBoundingSphere(renderables: Renderable<RenderableValues & Base } function renderableSort(a: Renderable<RenderableValues & BaseValues>, b: Renderable<RenderableValues & BaseValues>) { - const drawProgramIdA = a.getProgram('color').id - const drawProgramIdB = b.getProgram('color').id - const materialIdA = a.materialId - const materialIdB = b.materialId + const drawProgramIdA = a.getProgram('color').id; + const drawProgramIdB = b.getProgram('color').id; + const materialIdA = a.materialId; + const materialIdB = b.materialId; if (drawProgramIdA !== drawProgramIdB) { - return drawProgramIdA - drawProgramIdB // sort by program id to minimize gl state changes + return drawProgramIdA - drawProgramIdB; // sort by program id to minimize gl state changes } else if (materialIdA !== materialIdB) { - return materialIdA - materialIdB // sort by material id to minimize gl state changes + return materialIdA - materialIdB; // sort by material id to minimize gl state changes } else { return a.id - b.id; } @@ -78,38 +78,38 @@ interface Scene extends Object3D { namespace Scene { export function create(ctx: WebGLContext): Scene { - const renderableMap = new Map<GraphicsRenderObject, Renderable<RenderableValues & BaseValues>>() - const renderables: Renderable<RenderableValues & BaseValues>[] = [] - const boundingSphere = Sphere3D() - const boundingSphereVisible = Sphere3D() + const renderableMap = new Map<GraphicsRenderObject, Renderable<RenderableValues & BaseValues>>(); + const renderables: Renderable<RenderableValues & BaseValues>[] = []; + const boundingSphere = Sphere3D(); + const boundingSphereVisible = Sphere3D(); - let boundingSphereDirty = true - let boundingSphereVisibleDirty = true + let boundingSphereDirty = true; + let boundingSphereVisibleDirty = true; - const object3d = Object3D.create() + const object3d = Object3D.create(); function add(o: GraphicsRenderObject) { if (!renderableMap.has(o)) { - const renderable = createRenderable(ctx, o) - renderables.push(renderable) - renderableMap.set(o, renderable) - boundingSphereDirty = true - boundingSphereVisibleDirty = true + const renderable = createRenderable(ctx, o); + renderables.push(renderable); + renderableMap.set(o, renderable); + boundingSphereDirty = true; + boundingSphereVisibleDirty = true; return renderable; } else { - console.warn(`RenderObject with id '${o.id}' already present`) - return renderableMap.get(o)! + console.warn(`RenderObject with id '${o.id}' already present`); + return renderableMap.get(o)!; } } function remove(o: GraphicsRenderObject) { - const renderable = renderableMap.get(o) + const renderable = renderableMap.get(o); if (renderable) { - renderable.dispose() + renderable.dispose(); arraySetRemove(renderables, renderable); - renderableMap.delete(o) - boundingSphereDirty = true - boundingSphereVisibleDirty = true + renderableMap.delete(o); + boundingSphereDirty = true; + boundingSphereVisibleDirty = true; } } @@ -133,43 +133,43 @@ namespace Scene { if (++i % commitBulkSize === 0 && now() - start > maxTimeMs) return false; } - renderables.sort(renderableSort) + renderables.sort(renderableSort); return true; } const commitQueue = new CommitQueue(); - let visibleHash = -1 + let visibleHash = -1; function computeVisibleHash() { - let hash = 23 + let hash = 23; for (let i = 0, il = renderables.length; i < il; ++i) { if (!renderables[i].state.visible) continue; hash = (31 * hash + renderables[i].id) | 0; } hash = hash1(hash); if (hash === -1) hash = 0; - return hash + return hash; } function syncVisibility() { - const newVisibleHash = computeVisibleHash() + const newVisibleHash = computeVisibleHash(); if (newVisibleHash !== visibleHash) { - boundingSphereVisibleDirty = true - return true + boundingSphereVisibleDirty = true; + return true; } else { - return false + return false; } } return { - get view () { return object3d.view }, - get position () { return object3d.position }, - get direction () { return object3d.direction }, - get up () { return object3d.up }, + get view () { return object3d.view; }, + get position () { return object3d.position; }, + get direction () { return object3d.direction; }, + get up () { return object3d.up; }, syncVisibility, update(objects, keepBoundingSphere, isRemoving) { - Object3D.update(object3d) + Object3D.update(object3d); if (objects) { for (let i = 0, il = objects.length; i < il; ++i) { const o = renderableMap.get(objects[i]); @@ -178,14 +178,14 @@ namespace Scene { } } else if (!isRemoving) { for (let i = 0, il = renderables.length; i < il; ++i) { - renderables[i].update() + renderables[i].update(); } } if (!keepBoundingSphere) { - boundingSphereDirty = true - boundingSphereVisibleDirty = true + boundingSphereDirty = true; + boundingSphereVisibleDirty = true; } else { - syncVisibility() + syncVisibility(); } }, add: (o: GraphicsRenderObject) => commitQueue.add(o), @@ -193,41 +193,41 @@ namespace Scene { commit: (maxTime = Number.MAX_VALUE) => commit(maxTime), get needsCommit() { return !commitQueue.isEmpty; }, has: (o: GraphicsRenderObject) => { - return renderableMap.has(o) + return renderableMap.has(o); }, clear: () => { for (let i = 0, il = renderables.length; i < il; ++i) { - renderables[i].dispose() + renderables[i].dispose(); } - renderables.length = 0 - renderableMap.clear() - boundingSphereDirty = true - boundingSphereVisibleDirty = true + renderables.length = 0; + renderableMap.clear(); + boundingSphereDirty = true; + boundingSphereVisibleDirty = true; }, forEach: (callbackFn: (value: Renderable<any>, key: GraphicsRenderObject) => void) => { - renderableMap.forEach(callbackFn) + renderableMap.forEach(callbackFn); }, get count() { - return renderables.length + return renderables.length; }, renderables, get boundingSphere() { if (boundingSphereDirty) { - calculateBoundingSphere(renderables, boundingSphere, false) - boundingSphereDirty = false + calculateBoundingSphere(renderables, boundingSphere, false); + boundingSphereDirty = false; } - return boundingSphere + return boundingSphere; }, get boundingSphereVisible() { if (boundingSphereVisibleDirty) { - calculateBoundingSphere(renderables, boundingSphereVisible, true) - boundingSphereVisibleDirty = false - visibleHash = computeVisibleHash() + calculateBoundingSphere(renderables, boundingSphereVisible, true); + boundingSphereVisibleDirty = false; + visibleHash = computeVisibleHash(); } - return boundingSphereVisible + return boundingSphereVisible; } - } + }; } } -export default Scene \ No newline at end of file +export default Scene; \ No newline at end of file diff --git a/src/mol-gl/shader-code.ts b/src/mol-gl/shader-code.ts index 1bec4cace58284afcb10b9d6713e1d20cc661313..49d1c3e22941fdeaa64bee97f4512e53ca21f24c 100644 --- a/src/mol-gl/shader-code.ts +++ b/src/mol-gl/shader-code.ts @@ -13,7 +13,7 @@ export type DefineKind = 'boolean' | 'string' | 'number' export type DefineType = boolean | string export type DefineValues = { [k: string]: ValueCell<DefineType> } -const shaderCodeId = idFactory() +const shaderCodeId = idFactory(); export interface ShaderExtensions { readonly standardDerivatives?: boolean @@ -30,29 +30,29 @@ export interface ShaderCode { readonly extensions: ShaderExtensions } -import apply_fog from './shader/chunks/apply-fog.glsl' -import apply_interior_color from './shader/chunks/apply-interior-color.glsl' -import apply_light_color from './shader/chunks/apply-light-color.glsl' -import apply_marker_color from './shader/chunks/apply-marker-color.glsl' -import assign_color_varying from './shader/chunks/assign-color-varying.glsl' -import assign_group from './shader/chunks/assign-group.glsl' -import assign_marker_varying from './shader/chunks/assign-marker-varying.glsl' -import assign_material_color from './shader/chunks/assign-material-color.glsl' -import assign_position from './shader/chunks/assign-position.glsl' -import assign_size from './shader/chunks/assign-size.glsl' -import check_picking_alpha from './shader/chunks/check-picking-alpha.glsl' -import color_frag_params from './shader/chunks/color-frag-params.glsl' -import color_vert_params from './shader/chunks/color-vert-params.glsl' -import common_frag_params from './shader/chunks/common-frag-params.glsl' -import common_vert_params from './shader/chunks/common-vert-params.glsl' -import common from './shader/chunks/common.glsl' -import light_frag_params from './shader/chunks/light-frag-params.glsl' -import matrix_scale from './shader/chunks/matrix-scale.glsl' -import normal_frag_params from './shader/chunks/normal-frag-params.glsl' -import read_from_texture from './shader/chunks/read-from-texture.glsl' -import size_vert_params from './shader/chunks/size-vert-params.glsl' -import texture3d_from_2d_linear from './shader/chunks/texture3d-from-2d-nearest.glsl' -import texture3d_from_2d_nearest from './shader/chunks/texture3d-from-2d-nearest.glsl' +import apply_fog from './shader/chunks/apply-fog.glsl'; +import apply_interior_color from './shader/chunks/apply-interior-color.glsl'; +import apply_light_color from './shader/chunks/apply-light-color.glsl'; +import apply_marker_color from './shader/chunks/apply-marker-color.glsl'; +import assign_color_varying from './shader/chunks/assign-color-varying.glsl'; +import assign_group from './shader/chunks/assign-group.glsl'; +import assign_marker_varying from './shader/chunks/assign-marker-varying.glsl'; +import assign_material_color from './shader/chunks/assign-material-color.glsl'; +import assign_position from './shader/chunks/assign-position.glsl'; +import assign_size from './shader/chunks/assign-size.glsl'; +import check_picking_alpha from './shader/chunks/check-picking-alpha.glsl'; +import color_frag_params from './shader/chunks/color-frag-params.glsl'; +import color_vert_params from './shader/chunks/color-vert-params.glsl'; +import common_frag_params from './shader/chunks/common-frag-params.glsl'; +import common_vert_params from './shader/chunks/common-vert-params.glsl'; +import common from './shader/chunks/common.glsl'; +import light_frag_params from './shader/chunks/light-frag-params.glsl'; +import matrix_scale from './shader/chunks/matrix-scale.glsl'; +import normal_frag_params from './shader/chunks/normal-frag-params.glsl'; +import read_from_texture from './shader/chunks/read-from-texture.glsl'; +import size_vert_params from './shader/chunks/size-vert-params.glsl'; +import texture3d_from_2d_linear from './shader/chunks/texture3d-from-2d-nearest.glsl'; +import texture3d_from_2d_nearest from './shader/chunks/texture3d-from-2d-nearest.glsl'; const ShaderChunks: { [k: string]: string } = { apply_fog, @@ -78,53 +78,53 @@ const ShaderChunks: { [k: string]: string } = { size_vert_params, texture3d_from_2d_linear, texture3d_from_2d_nearest -} +}; -const reInclude = /^(?!\/\/)\s*#include\s+(\S+)/gmi -const reSingleLineComment = /[ \t]*\/\/.*\n/g -const reMultiLineComment = /[ \t]*\/\*[\s\S]*?\*\//g -const reMultipleLinebreaks = /\n{2,}/g +const reInclude = /^(?!\/\/)\s*#include\s+(\S+)/gmi; +const reSingleLineComment = /[ \t]*\/\/.*\n/g; +const reMultiLineComment = /[ \t]*\/\*[\s\S]*?\*\//g; +const reMultipleLinebreaks = /\n{2,}/g; function addIncludes(text: string) { return text .replace(reInclude, (_, p1) => { - const chunk = ShaderChunks[p1] - if (!chunk) throw new Error(`empty chunk, '${p1}'`) - return chunk + const chunk = ShaderChunks[p1]; + if (!chunk) throw new Error(`empty chunk, '${p1}'`); + return chunk; }) .trim() .replace(reSingleLineComment, '\n') .replace(reMultiLineComment, '\n') - .replace(reMultipleLinebreaks, '\n') + .replace(reMultipleLinebreaks, '\n'); } export function ShaderCode(name: string, vert: string, frag: string, extensions: ShaderExtensions = {}): ShaderCode { - return { id: shaderCodeId(), name, vert: addIncludes(vert), frag: addIncludes(frag), extensions } + return { id: shaderCodeId(), name, vert: addIncludes(vert), frag: addIncludes(frag), extensions }; } -import points_vert from './shader/points.vert' -import points_frag from './shader/points.frag' -export const PointsShaderCode = ShaderCode('points', points_vert, points_frag) +import points_vert from './shader/points.vert'; +import points_frag from './shader/points.frag'; +export const PointsShaderCode = ShaderCode('points', points_vert, points_frag); -import spheres_vert from './shader/spheres.vert' -import spheres_frag from './shader/spheres.frag' -export const SpheresShaderCode = ShaderCode('spheres', spheres_vert, spheres_frag, { fragDepth: true }) +import spheres_vert from './shader/spheres.vert'; +import spheres_frag from './shader/spheres.frag'; +export const SpheresShaderCode = ShaderCode('spheres', spheres_vert, spheres_frag, { fragDepth: true }); -import text_vert from './shader/text.vert' -import text_frag from './shader/text.frag' -export const TextShaderCode = ShaderCode('text', text_vert, text_frag, { standardDerivatives: true }) +import text_vert from './shader/text.vert'; +import text_frag from './shader/text.frag'; +export const TextShaderCode = ShaderCode('text', text_vert, text_frag, { standardDerivatives: true }); -import lines_vert from './shader/lines.vert' -import lines_frag from './shader/lines.frag' -export const LinesShaderCode = ShaderCode('lines', lines_vert, lines_frag) +import lines_vert from './shader/lines.vert'; +import lines_frag from './shader/lines.frag'; +export const LinesShaderCode = ShaderCode('lines', lines_vert, lines_frag); -import mesh_vert from './shader/mesh.vert' -import mesh_frag from './shader/mesh.frag' -export const MeshShaderCode = ShaderCode('mesh', mesh_vert, mesh_frag, { standardDerivatives: true }) +import mesh_vert from './shader/mesh.vert'; +import mesh_frag from './shader/mesh.frag'; +export const MeshShaderCode = ShaderCode('mesh', mesh_vert, mesh_frag, { standardDerivatives: true }); -import direct_volume_vert from './shader/direct-volume.vert' -import direct_volume_frag from './shader/direct-volume.frag' -export const DirectVolumeShaderCode = ShaderCode('direct-volume', direct_volume_vert, direct_volume_frag, { fragDepth: true }) +import direct_volume_vert from './shader/direct-volume.vert'; +import direct_volume_frag from './shader/direct-volume.frag'; +export const DirectVolumeShaderCode = ShaderCode('direct-volume', direct_volume_vert, direct_volume_frag, { fragDepth: true }); // @@ -133,64 +133,64 @@ export type ShaderDefines = { } function getDefinesCode (defines: ShaderDefines) { - if (defines === undefined) return '' - const lines = [] + if (defines === undefined) return ''; + const lines = []; for (const name in defines) { - const define = defines[name] - const v = define.ref.value + const define = defines[name]; + const v = define.ref.value; if (v !== undefined) { if (typeof v === 'string') { - lines.push(`#define ${name}_${v}`) + lines.push(`#define ${name}_${v}`); } else if (typeof v === 'number') { - lines.push(`#define ${name} ${v}`) + lines.push(`#define ${name} ${v}`); } else if (typeof v === 'boolean') { - if (v) lines.push(`#define ${name}`) + if (v) lines.push(`#define ${name}`); } else { - throw new Error('unknown define type') + throw new Error('unknown define type'); } } } - return lines.join('\n') + '\n' + return lines.join('\n') + '\n'; } function getGlsl100FragPrefix(extensions: WebGLExtensions, shaderExtensions: ShaderExtensions) { - const prefix: string[] = [] + const prefix: string[] = []; if (shaderExtensions.standardDerivatives) { - prefix.push('#extension GL_OES_standard_derivatives : enable') - prefix.push('#define enabledStandardDerivatives') + prefix.push('#extension GL_OES_standard_derivatives : enable'); + prefix.push('#define enabledStandardDerivatives'); } if (shaderExtensions.fragDepth) { if (extensions.fragDepth) { - prefix.push('#extension GL_EXT_frag_depth : enable') - prefix.push('#define enabledFragDepth') + prefix.push('#extension GL_EXT_frag_depth : enable'); + prefix.push('#define enabledFragDepth'); } else { - throw new Error(`requested 'GL_EXT_frag_depth' extension is unavailable`) + throw new Error(`requested 'GL_EXT_frag_depth' extension is unavailable`); } } if (shaderExtensions.drawBuffers) { if (extensions.drawBuffers) { - prefix.push('#extension GL_EXT_draw_buffers : require') - prefix.push('#define requiredDrawBuffers') + prefix.push('#extension GL_EXT_draw_buffers : require'); + prefix.push('#define requiredDrawBuffers'); } else { - throw new Error(`requested 'GL_EXT_draw_buffers' extension is unavailable`) + throw new Error(`requested 'GL_EXT_draw_buffers' extension is unavailable`); } } if (shaderExtensions.shaderTextureLod) { if (extensions.shaderTextureLod) { - prefix.push('#extension GL_EXT_shader_texture_lod : enable') - prefix.push('#define enabledShaderTextureLod') + prefix.push('#extension GL_EXT_shader_texture_lod : enable'); + prefix.push('#define enabledShaderTextureLod'); } else { - throw new Error(`requested 'GL_EXT_shader_texture_lod' extension is unavailable`) + throw new Error(`requested 'GL_EXT_shader_texture_lod' extension is unavailable`); } } - return prefix.join('\n') + '\n' + return prefix.join('\n') + '\n'; } const glsl300VertPrefix = `#version 300 es #define attribute in #define varying out #define texture2D texture -` +`; const glsl300FragPrefixCommon = ` #define varying in @@ -201,42 +201,42 @@ const glsl300FragPrefixCommon = ` #define gl_FragDepthEXT gl_FragDepth #define requiredDrawBuffers -` +`; function getGlsl300FragPrefix(gl: WebGL2RenderingContext, extensions: WebGLExtensions, shaderExtensions: ShaderExtensions) { - const prefix = [ '#version 300 es' ] + const prefix = [ '#version 300 es' ]; if (shaderExtensions.standardDerivatives) { - prefix.push('#define enabledStandardDerivatives') + prefix.push('#define enabledStandardDerivatives'); } if (shaderExtensions.fragDepth) { - prefix.push('#define enabledFragDepth') + prefix.push('#define enabledFragDepth'); } if (extensions.drawBuffers) { - const maxDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS) as number + const maxDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS) as number; for (let i = 0, il = maxDrawBuffers; i < il; ++i) { - prefix.push(`layout(location = ${i}) out highp vec4 out_FragData${i};`) + prefix.push(`layout(location = ${i}) out highp vec4 out_FragData${i};`); } } - prefix.push(glsl300FragPrefixCommon) - return prefix.join('\n') + '\n' + prefix.push(glsl300FragPrefixCommon); + return prefix.join('\n') + '\n'; } function transformGlsl300Frag(frag: string) { - return frag.replace(/gl_FragData\[([0-9]+)\]/g, 'out_FragData$1') + return frag.replace(/gl_FragData\[([0-9]+)\]/g, 'out_FragData$1'); } export function addShaderDefines(gl: GLRenderingContext, extensions: WebGLExtensions, defines: ShaderDefines, shaders: ShaderCode): ShaderCode { - const header = getDefinesCode(defines) - const vertPrefix = isWebGL2(gl) ? glsl300VertPrefix : '' + const header = getDefinesCode(defines); + const vertPrefix = isWebGL2(gl) ? glsl300VertPrefix : ''; const fragPrefix = isWebGL2(gl) ? getGlsl300FragPrefix(gl, extensions, shaders.extensions) - : getGlsl100FragPrefix(extensions, shaders.extensions) - const frag = isWebGL2(gl) ? transformGlsl300Frag(shaders.frag) : shaders.frag + : getGlsl100FragPrefix(extensions, shaders.extensions); + const frag = isWebGL2(gl) ? transformGlsl300Frag(shaders.frag) : shaders.frag; return { id: shaderCodeId(), name: shaders.name, vert: `${vertPrefix}${header}${shaders.vert}`, frag: `${fragPrefix}${header}${frag}`, extensions: shaders.extensions - } + }; } \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/apply-fog.glsl.ts b/src/mol-gl/shader/chunks/apply-fog.glsl.ts index 63ff5d82abfd0164036e5ef5bc4550518e55183a..7741a394643ce4058cf0169694342fc16aab7b41 100644 --- a/src/mol-gl/shader/chunks/apply-fog.glsl.ts +++ b/src/mol-gl/shader/chunks/apply-fog.glsl.ts @@ -7,4 +7,4 @@ if (uTransparentBackground == 0) { float fogAlpha = (1.0 - fogFactor) * gl_FragColor.a; gl_FragColor.a = fogAlpha; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/apply-interior-color.glsl.ts b/src/mol-gl/shader/chunks/apply-interior-color.glsl.ts index 40375bedb6cedf226aab2bb5fc590628cb052758..40b9a12e0e62e3c73605751e88c83cec97a1520f 100644 --- a/src/mol-gl/shader/chunks/apply-interior-color.glsl.ts +++ b/src/mol-gl/shader/chunks/apply-interior-color.glsl.ts @@ -6,4 +6,4 @@ if (interior) { gl_FragColor.rgb *= 1.0 - uInteriorDarkening; } } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/apply-light-color.glsl.ts b/src/mol-gl/shader/chunks/apply-light-color.glsl.ts index 54b00713f962bd11b7ac2b5a2703c30a9224b601..a126c7f079a780512643eb8d3da4ee53ce675bd5 100644 --- a/src/mol-gl/shader/chunks/apply-light-color.glsl.ts +++ b/src/mol-gl/shader/chunks/apply-light-color.glsl.ts @@ -47,4 +47,4 @@ RE_IndirectDiffuse_Physical(irradiance, geometry, physicalMaterial, reflectedLig vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular; gl_FragColor = vec4(outgoingLight, color.a); -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts b/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts index e37fbb5e26b77da10e7858d51d2aaa10807657b2..e276ef8c9d687f6d7a3799ea4bd54b9b716491d1 100644 --- a/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts +++ b/src/mol-gl/shader/chunks/apply-marker-color.glsl.ts @@ -10,4 +10,4 @@ if (gl_FragColor.a >= uPickingAlphaThreshold) { } } } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-color-varying.glsl.ts b/src/mol-gl/shader/chunks/assign-color-varying.glsl.ts index f7af2dc832375a712b145066bf0d200ed38a37d9..5a8de9e031f60b0863b48556230046cc01dff5fa 100644 --- a/src/mol-gl/shader/chunks/assign-color-varying.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-color-varying.glsl.ts @@ -23,4 +23,4 @@ export default ` vGroup = group; vTransparency = readFromTexture(tTransparency, aInstance * float(uGroupCount) + group, uTransparencyTexDim).a; #endif -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-group.glsl.ts b/src/mol-gl/shader/chunks/assign-group.glsl.ts index 0214cad5f6b22d9599b36e7b9f978559be5a9e98..9af3e1dbdd950c4fb4462de893b3ea3437074d8f 100644 --- a/src/mol-gl/shader/chunks/assign-group.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-group.glsl.ts @@ -5,4 +5,4 @@ export default ` #else float group = aGroup; #endif -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts b/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts index f2e5ff87e0c436e18c2c95bd02613701ec7b36f9..c314ee20fd903443f50adc5e90802a87dade0a9d 100644 --- a/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-marker-varying.glsl.ts @@ -1,3 +1,3 @@ export default ` vMarker = readFromTexture(tMarker, aInstance * float(uGroupCount) + group, uMarkerTexDim).a; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts index c4daf6f6108a8e0065c096fe2a040740d35ed191..91782a58ae60bddbccd9766fb9cba6c85e5acdf8 100644 --- a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts @@ -40,4 +40,4 @@ export default ` if (ta < 0.99 && (ta < 0.01 || ta < at)) discard; #endif -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-position.glsl.ts b/src/mol-gl/shader/chunks/assign-position.glsl.ts index d7a09fc8ae794d19cc4c1baa9085bd4cbda2a357..5631e47bd73cc7f34c4cb2c6904502a83a259e3b 100644 --- a/src/mol-gl/shader/chunks/assign-position.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-position.glsl.ts @@ -8,4 +8,4 @@ mat4 modelView = uView * uModel * aTransform; vec4 mvPosition = modelView * vec4(position, 1.0); vViewPosition = mvPosition.xyz; gl_Position = uProjection * mvPosition; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/assign-size.glsl.ts b/src/mol-gl/shader/chunks/assign-size.glsl.ts index 315643c742520e06da666a82a2ec8bffd9075e62..80492c3b93d8ed167d0395ffd6c63bc44c14c16b 100644 --- a/src/mol-gl/shader/chunks/assign-size.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-size.glsl.ts @@ -16,4 +16,4 @@ export default ` #endif size *= uSizeFactor; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/check-picking-alpha.glsl.ts b/src/mol-gl/shader/chunks/check-picking-alpha.glsl.ts index 7c047b6c7343cd9c64ec7dd8ec28fa96f8ada924..50c5c02e04f6566222e8bac5709ffd1ab2845d9b 100644 --- a/src/mol-gl/shader/chunks/check-picking-alpha.glsl.ts +++ b/src/mol-gl/shader/chunks/check-picking-alpha.glsl.ts @@ -4,4 +4,4 @@ float fogFactor = smoothstep(uFogNear, uFogFar, depth); float alpha = (1.0 - fogFactor) * uAlpha; if (uAlpha < uPickingAlphaThreshold || alpha < 0.1) discard; // ignore so the element below can be picked -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-frag-params.glsl.ts b/src/mol-gl/shader/chunks/color-frag-params.glsl.ts index 79caf3e48dc3edee0d13f6ac6ca3107f90ef2867..fd62778c784abaa963ada23636be38b9a8f565c4 100644 --- a/src/mol-gl/shader/chunks/color-frag-params.glsl.ts +++ b/src/mol-gl/shader/chunks/color-frag-params.glsl.ts @@ -19,4 +19,4 @@ export default ` varying float vGroup; varying float vTransparency; #endif -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/color-vert-params.glsl.ts b/src/mol-gl/shader/chunks/color-vert-params.glsl.ts index a9812d4e9e8bfdd7ac672ea293b1885bf0bb4bd7..7c5a4d233b454ade5ef3a741966cd518c37d0cb3 100644 --- a/src/mol-gl/shader/chunks/color-vert-params.glsl.ts +++ b/src/mol-gl/shader/chunks/color-vert-params.glsl.ts @@ -28,4 +28,4 @@ export default ` uniform vec2 uTransparencyTexDim; uniform sampler2D tTransparency; #endif -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts index 1525fce4da7faa2dacb4815172f91018d811d768..9addf2c14153af27d3dd2ba209c2221c044322fc 100644 --- a/src/mol-gl/shader/chunks/common-frag-params.glsl.ts +++ b/src/mol-gl/shader/chunks/common-frag-params.glsl.ts @@ -28,4 +28,4 @@ uniform float uInteriorDarkening; uniform int uInteriorColorFlag; uniform vec3 uInteriorColor; bool interior; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/common-vert-params.glsl.ts b/src/mol-gl/shader/chunks/common-vert-params.glsl.ts index 6354dc37db2529911b413422bfce27e7b0d46881..d5d018f8a3228e631b6bcc66632ad401c4409056 100644 --- a/src/mol-gl/shader/chunks/common-vert-params.glsl.ts +++ b/src/mol-gl/shader/chunks/common-vert-params.glsl.ts @@ -15,4 +15,4 @@ uniform sampler2D tMarker; #endif varying vec3 vViewPosition; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/common.glsl.ts b/src/mol-gl/shader/chunks/common.glsl.ts index 9800009644fcdb0df923b737ff5c2bbb2802cdb4..456f174d4778d040469d1b3d85d254648061ff73 100644 --- a/src/mol-gl/shader/chunks/common.glsl.ts +++ b/src/mol-gl/shader/chunks/common.glsl.ts @@ -151,4 +151,4 @@ float unpackRGBAToDepth(const in vec4 v) { #define inverse3(m) inverse(m) #define inverse4(m) inverse(m) #endif -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/light-frag-params.glsl.ts b/src/mol-gl/shader/chunks/light-frag-params.glsl.ts index b28b1e499338e60fd89891ebbafaaa69c8c03b79..7c0a731c744a75d766e7d717b1533b19febeb3fb 100644 --- a/src/mol-gl/shader/chunks/light-frag-params.glsl.ts +++ b/src/mol-gl/shader/chunks/light-frag-params.glsl.ts @@ -108,4 +108,4 @@ void RE_Direct_Physical(const in IncidentLight directLight, const in GeometricCo void RE_IndirectDiffuse_Physical(const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) { reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert(material.diffuseColor); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/matrix-scale.glsl.ts b/src/mol-gl/shader/chunks/matrix-scale.glsl.ts index 90ce37cd9834bd9ea2a97b4cc6f2405c4149d1cb..8b55d3d4db2390014d2f290864e2a2a5f1f18016 100644 --- a/src/mol-gl/shader/chunks/matrix-scale.glsl.ts +++ b/src/mol-gl/shader/chunks/matrix-scale.glsl.ts @@ -9,4 +9,4 @@ float matrixScale(in mat4 m){ vec4 r = m[0]; return sqrt(r[0] * r[0] + r[1] * r[1] + r[2] * r[2]); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/normal-frag-params.glsl.ts b/src/mol-gl/shader/chunks/normal-frag-params.glsl.ts index 2e61120ec3af5c9467d0450358df2e5319407c48..fe1dca389b1e64a80e77c72ba5ae67209bf3de8c 100644 --- a/src/mol-gl/shader/chunks/normal-frag-params.glsl.ts +++ b/src/mol-gl/shader/chunks/normal-frag-params.glsl.ts @@ -1,3 +1,3 @@ export default ` varying vec3 vNormal; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/read-from-texture.glsl.ts b/src/mol-gl/shader/chunks/read-from-texture.glsl.ts index 2994847938d53bc55b0ac358f262b198f5124b9c..4e97075a1c2bead711b00ac4c8db8d4733df65fd 100644 --- a/src/mol-gl/shader/chunks/read-from-texture.glsl.ts +++ b/src/mol-gl/shader/chunks/read-from-texture.glsl.ts @@ -11,4 +11,4 @@ vec4 readFromTexture (const in sampler2D tex, const in float i, const in vec2 di vec2 uv = (vec2(x, y) + 0.5) / dim; return texture2D(tex, uv); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/size-vert-params.glsl.ts b/src/mol-gl/shader/chunks/size-vert-params.glsl.ts index 8eae50508f2b94b7f336afbff867a444efcd30b7..fea3f121885f5aa4d4dae33f4e3bce3c90a725b5 100644 --- a/src/mol-gl/shader/chunks/size-vert-params.glsl.ts +++ b/src/mol-gl/shader/chunks/size-vert-params.glsl.ts @@ -9,4 +9,4 @@ export default ` #endif uniform float uSizeFactor; -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/texture3d-from-2d-linear.glsl.ts b/src/mol-gl/shader/chunks/texture3d-from-2d-linear.glsl.ts index 9a6a961fae047572916f08fd23e68b3f539c1ba2..4fbc39170835596f12baea9aa3041d0fee178040 100644 --- a/src/mol-gl/shader/chunks/texture3d-from-2d-linear.glsl.ts +++ b/src/mol-gl/shader/chunks/texture3d-from-2d-linear.glsl.ts @@ -22,4 +22,4 @@ vec4 texture3dFrom2dLinear(sampler2D tex, vec3 pos, vec3 gridDim, vec2 texDim) { float delta0 = abs((pos.z * gridDim.z) - zSlice0); return mix(color0, color1, delta0); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/chunks/texture3d-from-2d-nearest.glsl.ts b/src/mol-gl/shader/chunks/texture3d-from-2d-nearest.glsl.ts index d644900d15f2c192b2d1b45b45bac85b438cce7c..d4080cd605ae3e3610dd84a2f44da2407654a8bb 100644 --- a/src/mol-gl/shader/chunks/texture3d-from-2d-nearest.glsl.ts +++ b/src/mol-gl/shader/chunks/texture3d-from-2d-nearest.glsl.ts @@ -13,4 +13,4 @@ vec4 texture3dFrom2dNearest(sampler2D tex, vec3 pos, vec3 gridDim, vec2 texDim) vec2 coord = (vec2(column * gridDim.x, row * gridDim.y) + (pos.xy * gridDim.xy)) / texDim; return texture2D(tex, coord); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/compose.frag.ts b/src/mol-gl/shader/compose.frag.ts index ccd906b259ec809ed930919cc3d26e8f24585a6c..172330fded2b7030fa5bd855b6e15a36c4aeeb5e 100644 --- a/src/mol-gl/shader/compose.frag.ts +++ b/src/mol-gl/shader/compose.frag.ts @@ -10,4 +10,4 @@ void main() { vec2 coords = gl_FragCoord.xy / uTexSize; gl_FragColor = texture2D(tColor, coords) * uWeight; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/direct-volume.frag.ts b/src/mol-gl/shader/direct-volume.frag.ts index a96070e5e2946a53615a3f421b9a939f986addbd..eb7a9927e7cf0202c4a98929366dd55f3ca7c537 100644 --- a/src/mol-gl/shader/direct-volume.frag.ts +++ b/src/mol-gl/shader/direct-volume.frag.ts @@ -193,4 +193,4 @@ void main () { gl_FragColor.a *= uAlpha; #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/direct-volume.vert.ts b/src/mol-gl/shader/direct-volume.vert.ts index 15a8deff8862fb954fe3d24bc3a8424396644fae..bf2361a6b99fbc7a7d3be8310f86de3f82b4d9b5 100644 --- a/src/mol-gl/shader/direct-volume.vert.ts +++ b/src/mol-gl/shader/direct-volume.vert.ts @@ -39,4 +39,4 @@ void main() { gl_Position.z = -gl_Position.w + 0.0001; } } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/gaussian-density.frag.ts b/src/mol-gl/shader/gaussian-density.frag.ts index 216d1aa540ce1ed744479398241eeede0c599823..6f9d31b866d18c26049a9036f22ea4b5a923f6fb 100644 --- a/src/mol-gl/shader/gaussian-density.frag.ts +++ b/src/mol-gl/shader/gaussian-density.frag.ts @@ -44,4 +44,4 @@ void main() { gl_FragColor.rgb = encodeFloatRGB(vGroup); #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/gaussian-density.vert.ts b/src/mol-gl/shader/gaussian-density.vert.ts index 748d1ff73746c0866f40e8cb4b9e8a71eda0ec5c..750cd4ebd1b7bc319da2d79c9ff2760b5e5e972e 100644 --- a/src/mol-gl/shader/gaussian-density.vert.ts +++ b/src/mol-gl/shader/gaussian-density.vert.ts @@ -33,4 +33,4 @@ void main() { vPosition = (aPosition - uBboxMin) / uResolution; gl_Position = vec4(((aPosition - uBboxMin) / uBboxSize) * 2.0 - 1.0, 1.0); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/histogram-pyramid/reduction.frag.ts b/src/mol-gl/shader/histogram-pyramid/reduction.frag.ts index 9e3241ce5df1e9d8f3f1cee52ced1562f9a045a7..0168e1aa512f42ab7c7c5c2bb5023f8f425e8745 100644 --- a/src/mol-gl/shader/histogram-pyramid/reduction.frag.ts +++ b/src/mol-gl/shader/histogram-pyramid/reduction.frag.ts @@ -21,4 +21,4 @@ void main(void) { gl_FragColor.g = gl_FragColor.b + c; gl_FragColor.r = gl_FragColor.g + d; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/histogram-pyramid/sum.frag.ts b/src/mol-gl/shader/histogram-pyramid/sum.frag.ts index b4022f4ae467f3d2519d46a5252a49da6767c180..fbe31eccc5d9d083c1d4ff0a7cbba15e6286195d 100644 --- a/src/mol-gl/shader/histogram-pyramid/sum.frag.ts +++ b/src/mol-gl/shader/histogram-pyramid/sum.frag.ts @@ -15,4 +15,4 @@ uniform sampler2D tTexture; void main(void) { gl_FragColor = vec4(encodeFloatRGB(texture2D(tTexture, vec2(0.5)).r), 1.0); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/lines.frag.ts b/src/mol-gl/shader/lines.frag.ts index 16a5b6248ad525bea01cb54e19e4998446d7e611..7c90ee9368f8e2c3e73d4a86d3dec4d5ea7fa016 100644 --- a/src/mol-gl/shader/lines.frag.ts +++ b/src/mol-gl/shader/lines.frag.ts @@ -27,4 +27,4 @@ void main(){ #include apply_fog #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/lines.vert.ts b/src/mol-gl/shader/lines.vert.ts index 8a576f2aea611fafdc4529ac14c22aa76d2edd62..7e0a9228f50843cfdacdba0e163826555f354261 100644 --- a/src/mol-gl/shader/lines.vert.ts +++ b/src/mol-gl/shader/lines.vert.ts @@ -115,4 +115,4 @@ void main(){ clip.xy += offset; gl_Position = clip; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/marching-cubes/active-voxels.frag.ts b/src/mol-gl/shader/marching-cubes/active-voxels.frag.ts index f8115e2dcb7a65c71990f4fc7833f1c8941d9954..4b7d86b4c82645c343c7264547a22591e40b1e7a 100644 --- a/src/mol-gl/shader/marching-cubes/active-voxels.frag.ts +++ b/src/mol-gl/shader/marching-cubes/active-voxels.frag.ts @@ -74,4 +74,4 @@ void main(void) { // gl_FragColor = vec4(vCoordinate * 255.0, 0.0, 255.0); // gl_FragColor = vec4(250.0, 0.0, 0.0, 255.0); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/marching-cubes/isosurface.frag.ts b/src/mol-gl/shader/marching-cubes/isosurface.frag.ts index d8cb57a87a913fa3885c962adab37659af509a53..6c558ef4eea6e0dfba48915590c4a0827624041c 100644 --- a/src/mol-gl/shader/marching-cubes/isosurface.frag.ts +++ b/src/mol-gl/shader/marching-cubes/isosurface.frag.ts @@ -207,4 +207,4 @@ void main(void) { mat3 normalMatrix = transpose3(inverse3(mat3(uGridTransform))); gl_FragData[1].xyz = normalMatrix * gl_FragData[1].xyz; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.frag.ts b/src/mol-gl/shader/mesh.frag.ts index d2c65dcf51a4bd19391ac66915432968d9f3e8d6..fa1a241a728a105cb4270ef1e3a4fc5f9264ea1a 100644 --- a/src/mol-gl/shader/mesh.frag.ts +++ b/src/mol-gl/shader/mesh.frag.ts @@ -58,4 +58,4 @@ void main() { #include apply_fog #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/mesh.vert.ts b/src/mol-gl/shader/mesh.vert.ts index bffb98b2a71571456aa09f10f3be85fa92728146..e00073548c71d2749d4e32de79ada8531f3a43d4 100644 --- a/src/mol-gl/shader/mesh.vert.ts +++ b/src/mol-gl/shader/mesh.vert.ts @@ -48,4 +48,4 @@ void main(){ #endif vNormal = transformedNormal; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/points.frag.ts b/src/mol-gl/shader/points.frag.ts index 4affb371abe7741a88acf322e6cb0db0bbe48ffb..3a33247b77fd4a0fab004a4ab4b696bf3d2d6f85 100644 --- a/src/mol-gl/shader/points.frag.ts +++ b/src/mol-gl/shader/points.frag.ts @@ -41,4 +41,4 @@ void main(){ #include apply_fog #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/points.vert.ts b/src/mol-gl/shader/points.vert.ts index abfc9398ce42b9f96eaa1c8e2f60775065156258..e9fd184ae54379905b9d9dfa63efdeee0da09c5a 100644 --- a/src/mol-gl/shader/points.vert.ts +++ b/src/mol-gl/shader/points.vert.ts @@ -37,4 +37,4 @@ void main(){ gl_Position = uProjection * mvPosition; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/postprocessing.frag.ts b/src/mol-gl/shader/postprocessing.frag.ts index 86ccf4eac715cc51516c18aa495db7b5306416da..a75180878859fe7f1a9ef153b530cd96191b5b37 100644 --- a/src/mol-gl/shader/postprocessing.frag.ts +++ b/src/mol-gl/shader/postprocessing.frag.ts @@ -122,4 +122,4 @@ void main(void) { gl_FragColor = color; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/quad.vert.ts b/src/mol-gl/shader/quad.vert.ts index 239ef7e5ae2c302f43b77e54a5b3124b9f4926d4..c407fecaba8e1f09975e3052e00ae1391d260bb0 100644 --- a/src/mol-gl/shader/quad.vert.ts +++ b/src/mol-gl/shader/quad.vert.ts @@ -14,4 +14,4 @@ void main(void) { vec2 position = aPosition * uQuadScale - vec2(1.0, 1.0) + uQuadScale; gl_Position = vec4(position, 0.0, 1.0); } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/spheres.frag.ts b/src/mol-gl/shader/spheres.frag.ts index 426ae9fd131a5387b76dd25612ace3be7fee0e9e..f9c52c7c3267e6482855db2cd816bab8c0a1a2f6 100644 --- a/src/mol-gl/shader/spheres.frag.ts +++ b/src/mol-gl/shader/spheres.frag.ts @@ -113,4 +113,4 @@ void main(void){ #include apply_fog #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/spheres.vert.ts b/src/mol-gl/shader/spheres.vert.ts index fabd271ada90f7495d60e0ffec4830e4041ae0ff..0391f8c8b1bf6d992b5c8631609d7fc40b5d09c4 100644 --- a/src/mol-gl/shader/spheres.vert.ts +++ b/src/mol-gl/shader/spheres.vert.ts @@ -92,4 +92,4 @@ void main(void){ vPoint = vPoint4.xyz / vPoint4.w; vPointViewPosition = -mvPosition.xyz / mvPosition.w; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/text.frag.ts b/src/mol-gl/shader/text.frag.ts index 5bf2559896d4b0ba6f394300481863e8f4e64aed..69cf6aa0b5e67d024aeb6278d0cf4da137a3b677 100644 --- a/src/mol-gl/shader/text.frag.ts +++ b/src/mol-gl/shader/text.frag.ts @@ -65,4 +65,4 @@ void main(){ #include apply_fog #endif } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/shader/text.vert.ts b/src/mol-gl/shader/text.vert.ts index 79b0bc61907c28c6fa6feda31987ecbabec9350d..053815bd194600340999bc9ee8cced723244cac2 100644 --- a/src/mol-gl/shader/text.vert.ts +++ b/src/mol-gl/shader/text.vert.ts @@ -84,4 +84,4 @@ void main(void){ vViewPosition = -mvCorner.xyz; } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-gl/webgl/buffer.ts b/src/mol-gl/webgl/buffer.ts index d734027cd40a99982adafbb823c971ec971e60e8..1bcc13f647dda46d42f55be96c4918d20548d0df 100644 --- a/src/mol-gl/webgl/buffer.ts +++ b/src/mol-gl/webgl/buffer.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { WebGLContext } from './context' +import { WebGLContext } from './context'; import { ValueCell } from '../../mol-util'; import { RenderableSchema } from '../renderable/schema'; import { idFactory } from '../../mol-util/id-factory'; @@ -12,7 +12,7 @@ import { ValueOf } from '../../mol-util/type-helpers'; import { GLRenderingContext } from './compat'; import { WebGLExtensions } from './extensions'; -const getNextBufferId = idFactory() +const getNextBufferId = idFactory(); export type UsageHint = 'static' | 'dynamic' | 'stream' export type DataType = 'uint8' | 'int8' | 'uint16' | 'int16' | 'uint32' | 'int32' | 'float32' @@ -32,49 +32,49 @@ export type ArrayKind = keyof DataTypeArrayType export function getUsageHint(gl: GLRenderingContext, usageHint: UsageHint) { switch (usageHint) { - case 'static': return gl.STATIC_DRAW - case 'dynamic': return gl.DYNAMIC_DRAW - case 'stream': return gl.STREAM_DRAW + case 'static': return gl.STATIC_DRAW; + case 'dynamic': return gl.DYNAMIC_DRAW; + case 'stream': return gl.STREAM_DRAW; } } export function getDataType(gl: GLRenderingContext, dataType: DataType) { switch (dataType) { - case 'uint8': return gl.UNSIGNED_BYTE - case 'int8': return gl.BYTE - case 'uint16': return gl.UNSIGNED_SHORT - case 'int16': return gl.SHORT - case 'uint32': return gl.UNSIGNED_INT - case 'int32': return gl.INT - case 'float32': return gl.FLOAT + case 'uint8': return gl.UNSIGNED_BYTE; + case 'int8': return gl.BYTE; + case 'uint16': return gl.UNSIGNED_SHORT; + case 'int16': return gl.SHORT; + case 'uint32': return gl.UNSIGNED_INT; + case 'int32': return gl.INT; + case 'float32': return gl.FLOAT; } } function dataTypeFromArray(gl: GLRenderingContext, array: ArrayType) { if (array instanceof Uint8Array) { - return gl.UNSIGNED_BYTE + return gl.UNSIGNED_BYTE; } else if (array instanceof Int8Array) { - return gl.BYTE + return gl.BYTE; } else if (array instanceof Uint16Array) { - return gl.UNSIGNED_SHORT + return gl.UNSIGNED_SHORT; } else if (array instanceof Int16Array) { - return gl.SHORT + return gl.SHORT; } else if (array instanceof Uint32Array) { - return gl.UNSIGNED_INT + return gl.UNSIGNED_INT; } else if (array instanceof Int32Array) { - return gl.INT + return gl.INT; } else if (array instanceof Float32Array) { - return gl.FLOAT + return gl.FLOAT; } else { - throw new Error('Should nevver happen') + throw new Error('Should nevver happen'); } } export function getBufferType(gl: GLRenderingContext, bufferType: BufferType) { switch (bufferType) { - case 'attribute': return gl.ARRAY_BUFFER - case 'elements': return gl.ELEMENT_ARRAY_BUFFER - case 'uniform': return (gl as WebGL2RenderingContext).UNIFORM_BUFFER + case 'attribute': return gl.ARRAY_BUFFER; + case 'elements': return gl.ELEMENT_ARRAY_BUFFER; + case 'uniform': return (gl as WebGL2RenderingContext).UNIFORM_BUFFER; } } @@ -97,29 +97,29 @@ export interface Buffer { } function getBuffer(gl: GLRenderingContext) { - const buffer = gl.createBuffer() + const buffer = gl.createBuffer(); if (buffer === null) { - throw new Error('Could not create WebGL buffer') + throw new Error('Could not create WebGL buffer'); } - return buffer + return buffer; } function createBuffer(gl: GLRenderingContext, array: ArrayType, usageHint: UsageHint, bufferType: BufferType): Buffer { - let _buffer = getBuffer(gl) + let _buffer = getBuffer(gl); - const _usageHint = getUsageHint(gl, usageHint) - const _bufferType = getBufferType(gl, bufferType) - const _dataType = dataTypeFromArray(gl, array) - const _bpe = array.BYTES_PER_ELEMENT - const _length = array.length + const _usageHint = getUsageHint(gl, usageHint); + const _bufferType = getBufferType(gl, bufferType); + const _dataType = dataTypeFromArray(gl, array); + const _bpe = array.BYTES_PER_ELEMENT; + const _length = array.length; function updateData(array: ArrayType) { gl.bindBuffer(_bufferType, _buffer); - gl.bufferData(_bufferType, array, _usageHint) + gl.bufferData(_bufferType, array, _usageHint); } - updateData(array) + updateData(array); - let destroyed = false + let destroyed = false; return { id: getNextBufferId(), @@ -135,19 +135,19 @@ function createBuffer(gl: GLRenderingContext, array: ArrayType, usageHint: Usage updateData, updateSubData: (array: ArrayType, offset: number, count: number) => { gl.bindBuffer(_bufferType, _buffer); - gl.bufferSubData(_bufferType, offset * _bpe, array.subarray(offset, offset + count)) + gl.bufferSubData(_bufferType, offset * _bpe, array.subarray(offset, offset + count)); }, reset: () => { - _buffer = getBuffer(gl) - updateData(array) + _buffer = getBuffer(gl); + updateData(array); }, destroy: () => { - if (destroyed) return - gl.deleteBuffer(_buffer) - destroyed = true + if (destroyed) return; + gl.deleteBuffer(_buffer); + destroyed = true; } - } + }; } // @@ -159,23 +159,23 @@ export function getAttribType(gl: GLRenderingContext, kind: AttributeKind, itemS switch (kind) { case 'int32': switch (itemSize) { - case 1: return gl.INT - case 2: return gl.INT_VEC2 - case 3: return gl.INT_VEC3 - case 4: return gl.INT_VEC4 + case 1: return gl.INT; + case 2: return gl.INT_VEC2; + case 3: return gl.INT_VEC3; + case 4: return gl.INT_VEC4; } - break + break; case 'float32': switch (itemSize) { - case 1: return gl.FLOAT - case 2: return gl.FLOAT_VEC2 - case 3: return gl.FLOAT_VEC3 - case 4: return gl.FLOAT_VEC4 - case 16: return gl.FLOAT_MAT4 + case 1: return gl.FLOAT; + case 2: return gl.FLOAT_VEC2; + case 3: return gl.FLOAT_VEC3; + case 4: return gl.FLOAT_VEC4; + case 16: return gl.FLOAT_MAT4; } - break + break; } - throw new Error(`unknown attribute type for kind '${kind}' and itemSize '${itemSize}'`) + throw new Error(`unknown attribute type for kind '${kind}' and itemSize '${itemSize}'`); } export type AttributeDefs = { @@ -189,39 +189,39 @@ export interface AttributeBuffer extends Buffer { } export function createAttributeBuffer<T extends ArrayType, S extends AttributeItemSize>(gl: GLRenderingContext, extensions: WebGLExtensions, array: T, itemSize: S, divisor: number, usageHint: UsageHint = 'dynamic'): AttributeBuffer { - const { instancedArrays } = extensions + const { instancedArrays } = extensions; - const buffer = createBuffer(gl, array, usageHint, 'attribute') - const { _bufferType, _dataType, _bpe } = buffer + const buffer = createBuffer(gl, array, usageHint, 'attribute'); + const { _bufferType, _dataType, _bpe } = buffer; return { ...buffer, bind: (location: number) => { - gl.bindBuffer(_bufferType, buffer.getBuffer()) + gl.bindBuffer(_bufferType, buffer.getBuffer()); if (itemSize === 16) { for (let i = 0; i < 4; ++i) { - gl.enableVertexAttribArray(location + i) - gl.vertexAttribPointer(location + i, 4, _dataType, false, 4 * 4 * _bpe, i * 4 * _bpe) - instancedArrays.vertexAttribDivisor(location + i, divisor) + gl.enableVertexAttribArray(location + i); + gl.vertexAttribPointer(location + i, 4, _dataType, false, 4 * 4 * _bpe, i * 4 * _bpe); + instancedArrays.vertexAttribDivisor(location + i, divisor); } } else { - gl.enableVertexAttribArray(location) - gl.vertexAttribPointer(location, itemSize, _dataType, false, 0, 0) - instancedArrays.vertexAttribDivisor(location, divisor) + gl.enableVertexAttribArray(location); + gl.vertexAttribPointer(location, itemSize, _dataType, false, 0, 0); + instancedArrays.vertexAttribDivisor(location, divisor); } } - } + }; } export function createAttributeBuffers(ctx: WebGLContext, schema: RenderableSchema, values: AttributeValues) { - const buffers: AttributeBuffers = [] + const buffers: AttributeBuffers = []; Object.keys(schema).forEach(k => { - const spec = schema[k] + const spec = schema[k]; if (spec.type === 'attribute') { - buffers[buffers.length] = [k, ctx.resources.attribute(values[k].ref.value, spec.itemSize, spec.divisor)] + buffers[buffers.length] = [k, ctx.resources.attribute(values[k].ref.value, spec.itemSize, spec.divisor)]; } - }) - return buffers + }); + return buffers; } // @@ -234,12 +234,12 @@ export interface ElementsBuffer extends Buffer { } export function createElementsBuffer(gl: GLRenderingContext, array: ElementsType, usageHint: UsageHint = 'static'): ElementsBuffer { - const buffer = createBuffer(gl, array, usageHint, 'elements') + const buffer = createBuffer(gl, array, usageHint, 'elements'); return { ...buffer, bind: () => { gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.getBuffer()); } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/compat.ts b/src/mol-gl/webgl/compat.ts index 60a7e1cad3bca5cf6e3231fd576a924629889cef..34b8137c25e3889d8ecef9413c98a9d09fbd9aa0 100644 --- a/src/mol-gl/webgl/compat.ts +++ b/src/mol-gl/webgl/compat.ts @@ -7,11 +7,11 @@ export type GLRenderingContext = WebGLRenderingContext | WebGL2RenderingContext export function isWebGL(gl: any): gl is WebGLRenderingContext { - return typeof WebGLRenderingContext !== 'undefined' && gl instanceof WebGLRenderingContext + return typeof WebGLRenderingContext !== 'undefined' && gl instanceof WebGLRenderingContext; } export function isWebGL2(gl: any): gl is WebGL2RenderingContext { - return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext + return typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext; } export interface COMPAT_instanced_arrays { @@ -28,16 +28,16 @@ export function getInstancedArrays(gl: GLRenderingContext): COMPAT_instanced_arr drawElementsInstanced: gl.drawElementsInstanced.bind(gl), vertexAttribDivisor: gl.vertexAttribDivisor.bind(gl), VERTEX_ATTRIB_ARRAY_DIVISOR: gl.VERTEX_ATTRIB_ARRAY_DIVISOR - } + }; } else { - const ext = gl.getExtension('ANGLE_instanced_arrays') - if (ext === null) return null + const ext = gl.getExtension('ANGLE_instanced_arrays'); + if (ext === null) return null; return { drawArraysInstanced: ext.drawArraysInstancedANGLE.bind(ext), drawElementsInstanced: ext.drawElementsInstancedANGLE.bind(ext), vertexAttribDivisor: ext.vertexAttribDivisorANGLE.bind(ext), VERTEX_ATTRIB_ARRAY_DIVISOR: ext.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE - } + }; } } @@ -47,11 +47,11 @@ export interface COMPAT_standard_derivatives { export function getStandardDerivatives(gl: GLRenderingContext): COMPAT_standard_derivatives | null { if (isWebGL2(gl)) { - return { FRAGMENT_SHADER_DERIVATIVE_HINT: gl.FRAGMENT_SHADER_DERIVATIVE_HINT } + return { FRAGMENT_SHADER_DERIVATIVE_HINT: gl.FRAGMENT_SHADER_DERIVATIVE_HINT }; } else { - const ext = gl.getExtension('OES_standard_derivatives') - if (ext === null) return null - return { FRAGMENT_SHADER_DERIVATIVE_HINT: ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES } + const ext = gl.getExtension('OES_standard_derivatives'); + if (ext === null) return null; + return { FRAGMENT_SHADER_DERIVATIVE_HINT: ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES }; } } @@ -59,7 +59,7 @@ export interface COMPAT_element_index_uint { } export function getElementIndexUint(gl: GLRenderingContext): COMPAT_element_index_uint | null { - return isWebGL2(gl) ? {} : gl.getExtension('OES_element_index_uint') + return isWebGL2(gl) ? {} : gl.getExtension('OES_element_index_uint'); } export interface COMPAT_vertex_array_object { @@ -78,17 +78,17 @@ export function getVertexArrayObject(gl: GLRenderingContext): COMPAT_vertex_arra createVertexArray: gl.createVertexArray.bind(gl), deleteVertexArray: gl.deleteVertexArray.bind(gl), isVertexArray: gl.isVertexArray.bind(gl) - } + }; } else { - const ext = gl.getExtension('OES_vertex_array_object') - if (ext === null) return null + const ext = gl.getExtension('OES_vertex_array_object'); + if (ext === null) return null; return { VERTEX_ARRAY_BINDING: ext.VERTEX_ARRAY_BINDING_OES, bindVertexArray: ext.bindVertexArrayOES.bind(ext), createVertexArray: ext.createVertexArrayOES.bind(ext), deleteVertexArray: ext.deleteVertexArrayOES.bind(ext), isVertexArray: ext.isVertexArrayOES.bind(ext) - } + }; } } @@ -96,14 +96,14 @@ export interface COMPAT_texture_float { } export function getTextureFloat(gl: GLRenderingContext): COMPAT_texture_float | null { - return isWebGL2(gl) ? {} : gl.getExtension('OES_texture_float') + return isWebGL2(gl) ? {} : gl.getExtension('OES_texture_float'); } export interface COMPAT_texture_float_linear { } export function getTextureFloatLinear(gl: GLRenderingContext): COMPAT_texture_float_linear | null { - return gl.getExtension('OES_texture_float_linear') + return gl.getExtension('OES_texture_float_linear'); } export interface COMPAT_blend_minmax { @@ -113,11 +113,11 @@ export interface COMPAT_blend_minmax { export function getBlendMinMax(gl: GLRenderingContext): COMPAT_blend_minmax | null { if (isWebGL2(gl)) { - return { MIN: gl.MIN, MAX: gl.MAX } + return { MIN: gl.MIN, MAX: gl.MAX }; } else { - const ext = gl.getExtension('EXT_blend_minmax') - if (ext === null) return null - return { MIN: ext.MIN_EXT, MAX: ext.MAX_EXT } + const ext = gl.getExtension('EXT_blend_minmax'); + if (ext === null) return null; + return { MIN: ext.MIN_EXT, MAX: ext.MAX_EXT }; } } @@ -125,7 +125,7 @@ export interface COMPAT_frag_depth { } export function getFragDepth(gl: GLRenderingContext): COMPAT_frag_depth | null { - return isWebGL2(gl) ? {} : gl.getExtension('EXT_frag_depth') + return isWebGL2(gl) ? {} : gl.getExtension('EXT_frag_depth'); } export interface COMPAT_color_buffer_float { @@ -134,12 +134,12 @@ export interface COMPAT_color_buffer_float { export function getColorBufferFloat(gl: GLRenderingContext): COMPAT_color_buffer_float | null { if (isWebGL2(gl)) { - if (gl.getExtension('EXT_color_buffer_float') === null) return null - return { RGBA32F: gl.RGBA32F } + if (gl.getExtension('EXT_color_buffer_float') === null) return null; + return { RGBA32F: gl.RGBA32F }; } else { - const ext = gl.getExtension('WEBGL_color_buffer_float') - if (ext === null) return null - return { RGBA32F: ext.RGBA32F_EXT } + const ext = gl.getExtension('WEBGL_color_buffer_float'); + if (ext === null) return null; + return { RGBA32F: ext.RGBA32F_EXT }; } } @@ -187,10 +187,10 @@ export function getDrawBuffers(gl: GLRenderingContext): COMPAT_draw_buffers | nu DRAW_BUFFER7: gl.DRAW_BUFFER7, MAX_COLOR_ATTACHMENTS: gl.MAX_COLOR_ATTACHMENTS, MAX_DRAW_BUFFERS: gl.MAX_DRAW_BUFFERS, - } + }; } else { - const ext = gl.getExtension('WEBGL_draw_buffers') - if (ext === null) return null + const ext = gl.getExtension('WEBGL_draw_buffers'); + if (ext === null) return null; return { drawBuffers: ext.drawBuffersWEBGL.bind(ext), COLOR_ATTACHMENT0: ext.COLOR_ATTACHMENT0_WEBGL, @@ -211,7 +211,7 @@ export function getDrawBuffers(gl: GLRenderingContext): COMPAT_draw_buffers | nu DRAW_BUFFER7: ext.DRAW_BUFFER7_WEBGL, MAX_COLOR_ATTACHMENTS: ext.MAX_COLOR_ATTACHMENTS_WEBGL, MAX_DRAW_BUFFERS: ext.MAX_DRAW_BUFFERS_WEBGL, - } + }; } } @@ -219,7 +219,7 @@ export interface COMPAT_shader_texture_lod { } export function getShaderTextureLod(gl: GLRenderingContext): COMPAT_shader_texture_lod | null { - return isWebGL2(gl) ? {} : gl.getExtension('EXT_shader_texture_lod') + return isWebGL2(gl) ? {} : gl.getExtension('EXT_shader_texture_lod'); } export interface COMPAT_depth_texture { @@ -230,12 +230,12 @@ export function getDepthTexture(gl: GLRenderingContext): COMPAT_depth_texture | if (isWebGL2(gl)) { return { UNSIGNED_INT_24_8: gl.UNSIGNED_INT_24_8 - } + }; } else { - const ext = gl.getExtension('WEBGL_depth_texture') - if (ext === null) return null + const ext = gl.getExtension('WEBGL_depth_texture'); + if (ext === null) return null; return { UNSIGNED_INT_24_8: ext.UNSIGNED_INT_24_8_WEBGL - } + }; } } \ No newline at end of file diff --git a/src/mol-gl/webgl/context.ts b/src/mol-gl/webgl/context.ts index 0008ebf05eb0521206f696906450ebc527260239..cfc6a8720cf8b4b535af5ce9969df7fce997fd42 100644 --- a/src/mol-gl/webgl/context.ts +++ b/src/mol-gl/webgl/context.ts @@ -19,48 +19,48 @@ import { now } from '../../mol-util/now'; export function getGLContext(canvas: HTMLCanvasElement, contextAttributes?: WebGLContextAttributes): GLRenderingContext | null { function getContext(contextId: 'webgl' | 'experimental-webgl' | 'webgl2') { try { - return canvas.getContext(contextId, contextAttributes) as GLRenderingContext | null + return canvas.getContext(contextId, contextAttributes) as GLRenderingContext | null; } catch (e) { - return null + return null; } } - return getContext('webgl2') || getContext('webgl') || getContext('experimental-webgl') + return getContext('webgl2') || getContext('webgl') || getContext('experimental-webgl'); } function getPixelRatio() { - return (typeof window !== 'undefined') ? window.devicePixelRatio : 1 + return (typeof window !== 'undefined') ? window.devicePixelRatio : 1; } function getErrorDescription(gl: GLRenderingContext, error: number) { switch (error) { - case gl.NO_ERROR: return 'no error' - case gl.INVALID_ENUM: return 'invalid enum' - case gl.INVALID_VALUE: return 'invalid value' - case gl.INVALID_OPERATION: return 'invalid operation' - case gl.INVALID_FRAMEBUFFER_OPERATION: return 'invalid framebuffer operation' - case gl.OUT_OF_MEMORY: return 'out of memory' - case gl.CONTEXT_LOST_WEBGL: return 'context lost' + case gl.NO_ERROR: return 'no error'; + case gl.INVALID_ENUM: return 'invalid enum'; + case gl.INVALID_VALUE: return 'invalid value'; + case gl.INVALID_OPERATION: return 'invalid operation'; + case gl.INVALID_FRAMEBUFFER_OPERATION: return 'invalid framebuffer operation'; + case gl.OUT_OF_MEMORY: return 'out of memory'; + case gl.CONTEXT_LOST_WEBGL: return 'context lost'; } - return 'unknown error' + return 'unknown error'; } export function checkError(gl: GLRenderingContext) { - const error = gl.getError() + const error = gl.getError(); if (error !== gl.NO_ERROR) { - throw new Error(`WebGL error: '${getErrorDescription(gl, error)}'`) + throw new Error(`WebGL error: '${getErrorDescription(gl, error)}'`); } } function unbindResources (gl: GLRenderingContext) { // bind null to all texture units - const maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) + const maxTextureImageUnits = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS); for (let i = 0; i < maxTextureImageUnits; ++i) { - gl.activeTexture(gl.TEXTURE0 + i) - gl.bindTexture(gl.TEXTURE_2D, null) - gl.bindTexture(gl.TEXTURE_CUBE_MAP, null) + gl.activeTexture(gl.TEXTURE0 + i); + gl.bindTexture(gl.TEXTURE_2D, null); + gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); if (isWebGL2(gl)) { - gl.bindTexture(gl.TEXTURE_2D_ARRAY, null) - gl.bindTexture(gl.TEXTURE_3D, null) + gl.bindTexture(gl.TEXTURE_2D_ARRAY, null); + gl.bindTexture(gl.TEXTURE_3D, null); } } @@ -73,80 +73,80 @@ function unbindResources (gl: GLRenderingContext) { } // bind null to all buffers - gl.bindBuffer(gl.ARRAY_BUFFER, null) - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null) - gl.bindRenderbuffer(gl.RENDERBUFFER, null) - unbindFramebuffer(gl) + gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); + gl.bindRenderbuffer(gl.RENDERBUFFER, null); + unbindFramebuffer(gl); } function unbindFramebuffer(gl: GLRenderingContext) { - gl.bindFramebuffer(gl.FRAMEBUFFER, null) + gl.bindFramebuffer(gl.FRAMEBUFFER, null); } const tmpPixel = new Uint8Array(1 * 4); function checkSync(gl: WebGL2RenderingContext, sync: WebGLSync, resolve: () => void) { if (gl.getSyncParameter(sync, gl.SYNC_STATUS) === gl.SIGNALED) { - gl.deleteSync(sync) - resolve() + gl.deleteSync(sync); + resolve(); } else { - Scheduler.setImmediate(checkSync, gl, sync, resolve) + Scheduler.setImmediate(checkSync, gl, sync, resolve); } } function fence(gl: WebGL2RenderingContext, resolve: () => void) { - const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0) + const sync = gl.fenceSync(gl.SYNC_GPU_COMMANDS_COMPLETE, 0); if (!sync) { - console.warn('Could not create a WebGLSync object') - gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, tmpPixel) - resolve() + console.warn('Could not create a WebGLSync object'); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, tmpPixel); + resolve(); } else { - Scheduler.setImmediate(checkSync, gl, sync, resolve) + Scheduler.setImmediate(checkSync, gl, sync, resolve); } } -let SentWebglSyncObjectNotSupportedInWebglMessage = false +let SentWebglSyncObjectNotSupportedInWebglMessage = false; function waitForGpuCommandsComplete(gl: GLRenderingContext): Promise<void> { return new Promise(resolve => { if (isWebGL2(gl)) { // TODO seems quite slow - fence(gl, resolve) + fence(gl, resolve); } else { if (!SentWebglSyncObjectNotSupportedInWebglMessage) { - console.info('Sync object not supported in WebGL') - SentWebglSyncObjectNotSupportedInWebglMessage = true + console.info('Sync object not supported in WebGL'); + SentWebglSyncObjectNotSupportedInWebglMessage = true; } - waitForGpuCommandsCompleteSync(gl) - resolve() + waitForGpuCommandsCompleteSync(gl); + resolve(); } - }) + }); } function waitForGpuCommandsCompleteSync(gl: GLRenderingContext): void { - gl.bindFramebuffer(gl.FRAMEBUFFER, null) - gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, tmpPixel) + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, tmpPixel); } export function readPixels(gl: GLRenderingContext, x: number, y: number, width: number, height: number, buffer: Uint8Array | Float32Array) { - if (isDebugMode) checkFramebufferStatus(gl) + if (isDebugMode) checkFramebufferStatus(gl); if (buffer instanceof Uint8Array) { - gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer) + gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buffer); } else if (buffer instanceof Float32Array) { - gl.readPixels(x, y, width, height, gl.RGBA, gl.FLOAT, buffer) + gl.readPixels(x, y, width, height, gl.RGBA, gl.FLOAT, buffer); } else { - throw new Error('unsupported readPixels buffer type') + throw new Error('unsupported readPixels buffer type'); } - if (isDebugMode) checkError(gl) + if (isDebugMode) checkError(gl); } function getDrawingBufferPixelData(gl: GLRenderingContext) { - const w = gl.drawingBufferWidth - const h = gl.drawingBufferHeight - const buffer = new Uint8Array(w * h * 4) - unbindFramebuffer(gl) - gl.viewport(0, 0, w, h) - readPixels(gl, 0, 0, w, h, buffer) - return PixelData.flipY(PixelData.create(buffer, w, h)) + const w = gl.drawingBufferWidth; + const h = gl.drawingBufferHeight; + const buffer = new Uint8Array(w * h * 4); + unbindFramebuffer(gl); + gl.viewport(0, 0, w, h); + readPixels(gl, 0, 0, w, h, buffer); + return PixelData.flipY(PixelData.create(buffer, w, h)); } // @@ -167,7 +167,7 @@ function createStats() { drawCount: 0, instanceCount: 0, instancedDrawCount: 0, - } + }; } export type WebGLStats = ReturnType<typeof createStats> @@ -205,70 +205,70 @@ export interface WebGLContext { } export function createContext(gl: GLRenderingContext): WebGLContext { - const extensions = createExtensions(gl) - const state = createState(gl) - const stats = createStats() - const resources = createResources(gl, state, stats, extensions) + const extensions = createExtensions(gl); + const state = createState(gl); + const stats = createStats(); + const resources = createResources(gl, state, stats, extensions); const parameters = { maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE) as number, maxRenderbufferSize: gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) as number, maxDrawBuffers: isWebGL2(gl) ? gl.getParameter(gl.MAX_DRAW_BUFFERS) as number : 0, maxVertexTextureImageUnits: gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) as number, - } + }; if (parameters.maxVertexTextureImageUnits < 8) { - throw new Error('Need "MAX_VERTEX_TEXTURE_IMAGE_UNITS" >= 8') + throw new Error('Need "MAX_VERTEX_TEXTURE_IMAGE_UNITS" >= 8'); } - let isContextLost = false - let contextRestored = new BehaviorSubject<now.Timestamp>(0 as now.Timestamp) + let isContextLost = false; + let contextRestored = new BehaviorSubject<now.Timestamp>(0 as now.Timestamp); - let readPixelsAsync: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => Promise<void> + let readPixelsAsync: (x: number, y: number, width: number, height: number, buffer: Uint8Array) => Promise<void>; if (isWebGL2(gl)) { - const pbo = gl.createBuffer() - let _buffer: Uint8Array | undefined = void 0 - let _resolve: (() => void) | undefined = void 0 - let _reading = false + const pbo = gl.createBuffer(); + let _buffer: Uint8Array | undefined = void 0; + let _resolve: (() => void) | undefined = void 0; + let _reading = false; const bindPBO = () => { - gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo) - gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, _buffer!) - gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null) - _reading = false - _resolve!() - _resolve = void 0 - _buffer = void 0 - } + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo); + gl.getBufferSubData(gl.PIXEL_PACK_BUFFER, 0, _buffer!); + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null); + _reading = false; + _resolve!(); + _resolve = void 0; + _buffer = void 0; + }; readPixelsAsync = (x: number, y: number, width: number, height: number, buffer: Uint8Array): Promise<void> => new Promise<void>((resolve, reject) => { if (_reading) { - reject('Can not call multiple readPixelsAsync at the same time') - return + reject('Can not call multiple readPixelsAsync at the same time'); + return; } _reading = true; - gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo) - gl.bufferData(gl.PIXEL_PACK_BUFFER, width * height * 4, gl.STREAM_READ) - gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0) - gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null) + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, pbo); + gl.bufferData(gl.PIXEL_PACK_BUFFER, width * height * 4, gl.STREAM_READ); + gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, 0); + gl.bindBuffer(gl.PIXEL_PACK_BUFFER, null); // need to unbind/bind PBO before/after async awaiting the fence - _resolve = resolve - _buffer = buffer - fence(gl, bindPBO) - }) + _resolve = resolve; + _buffer = buffer; + fence(gl, bindPBO); + }); } else { readPixelsAsync = async (x: number, y: number, width: number, height: number, buffer: Uint8Array) => { - readPixels(gl, x, y, width, height, buffer) - } + readPixels(gl, x, y, width, height, buffer); + }; } - const renderTargets = new Set<RenderTarget>() + const renderTargets = new Set<RenderTarget>(); return { gl, isWebGL2: isWebGL2(gl), get pixelRatio () { // this can change during the lifetime of a rendering context, so need to re-obtain on access - return getPixelRatio() + return getPixelRatio(); }, extensions, @@ -276,46 +276,46 @@ export function createContext(gl: GLRenderingContext): WebGLContext { stats, resources, - get maxTextureSize () { return parameters.maxTextureSize }, - get maxRenderbufferSize () { return parameters.maxRenderbufferSize }, - get maxDrawBuffers () { return parameters.maxDrawBuffers }, + get maxTextureSize () { return parameters.maxTextureSize; }, + get maxRenderbufferSize () { return parameters.maxRenderbufferSize; }, + get maxDrawBuffers () { return parameters.maxDrawBuffers; }, get isContextLost () { - return isContextLost || gl.isContextLost() + return isContextLost || gl.isContextLost(); }, contextRestored, setContextLost: () => { - isContextLost = true + isContextLost = true; }, handleContextRestored: () => { - Object.assign(extensions, createExtensions(gl)) + Object.assign(extensions, createExtensions(gl)); - state.reset() - state.currentMaterialId = -1 - state.currentProgramId = -1 - state.currentRenderItemId = -1 + state.reset(); + state.currentMaterialId = -1; + state.currentProgramId = -1; + state.currentRenderItemId = -1; - resources.reset() - renderTargets.forEach(rt => rt.reset()) + resources.reset(); + renderTargets.forEach(rt => rt.reset()); - isContextLost = false - contextRestored.next(now()) + isContextLost = false; + contextRestored.next(now()); }, createRenderTarget: (width: number, height: number) => { - const renderTarget = createRenderTarget(gl, resources, width, height) - renderTargets.add(renderTarget) + const renderTarget = createRenderTarget(gl, resources, width, height); + renderTargets.add(renderTarget); return { ...renderTarget, destroy: () => { - renderTarget.destroy() - renderTargets.delete(renderTarget) + renderTarget.destroy(); + renderTargets.delete(renderTarget); } - } + }; }, unbindFramebuffer: () => unbindFramebuffer(gl), readPixels: (x: number, y: number, width: number, height: number, buffer: Uint8Array | Float32Array) => { - readPixels(gl, x, y, width, height, buffer) + readPixels(gl, x, y, width, height, buffer); }, readPixelsAsync, waitForGpuCommandsComplete: () => waitForGpuCommandsComplete(gl), @@ -323,8 +323,8 @@ export function createContext(gl: GLRenderingContext): WebGLContext { getDrawingBufferPixelData: () => getDrawingBufferPixelData(gl), destroy: () => { - resources.destroy() - unbindResources(gl) + resources.destroy(); + unbindResources(gl); } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/extensions.ts b/src/mol-gl/webgl/extensions.ts index bc54182ba3d325efe613c9da918d312691cfa2d5..76462e8c54eca776742aec13148d4bd641e54b19 100644 --- a/src/mol-gl/webgl/extensions.ts +++ b/src/mol-gl/webgl/extensions.ts @@ -24,60 +24,60 @@ export type WebGLExtensions = { } export function createExtensions(gl: GLRenderingContext): WebGLExtensions { - const instancedArrays = getInstancedArrays(gl) + const instancedArrays = getInstancedArrays(gl); if (instancedArrays === null) { - throw new Error('Could not find support for "instanced_arrays"') + throw new Error('Could not find support for "instanced_arrays"'); } - const textureFloat = getTextureFloat(gl) + const textureFloat = getTextureFloat(gl); if (textureFloat === null) { - throw new Error('Could not find support for "texture_float"') + throw new Error('Could not find support for "texture_float"'); } - const elementIndexUint = getElementIndexUint(gl) + const elementIndexUint = getElementIndexUint(gl); if (elementIndexUint === null) { - throw new Error('Could not find support for "element_index_uint"') + throw new Error('Could not find support for "element_index_uint"'); } - const standardDerivatives = getStandardDerivatives(gl) + const standardDerivatives = getStandardDerivatives(gl); if (isDebugMode && standardDerivatives === null) { // - non-support handled downstream (flat shading option is ignored) // - can't be a required extension because it is not supported by `headless-gl` - console.log('Could not find support for "standard_derivatives"') + console.log('Could not find support for "standard_derivatives"'); } - const textureFloatLinear = getTextureFloatLinear(gl) + const textureFloatLinear = getTextureFloatLinear(gl); if (isDebugMode && textureFloatLinear === null) { // TODO handle non-support downstream (no gpu gaussian calc, no gpu mc???) // - can't be a required extension because it is not supported by `headless-gl` - console.log('Could not find support for "texture_float_linear"') + console.log('Could not find support for "texture_float_linear"'); } - const depthTexture = getDepthTexture(gl) + const depthTexture = getDepthTexture(gl); if (isDebugMode && depthTexture === null) { - console.log('Could not find support for "depth_texture"') + console.log('Could not find support for "depth_texture"'); } - const blendMinMax = getBlendMinMax(gl) + const blendMinMax = getBlendMinMax(gl); if (isDebugMode && blendMinMax === null) { // TODO handle non-support downstream (e.g. no gpu gaussian calc) // - can't be a required extension because it is not supported by `headless-gl` - console.log('Could not find support for "blend_minmax"') + console.log('Could not find support for "blend_minmax"'); } - const vertexArrayObject = getVertexArrayObject(gl) + const vertexArrayObject = getVertexArrayObject(gl); if (isDebugMode && vertexArrayObject === null) { - console.log('Could not find support for "vertex_array_object"') + console.log('Could not find support for "vertex_array_object"'); } - const fragDepth = getFragDepth(gl) + const fragDepth = getFragDepth(gl); if (isDebugMode && fragDepth === null) { - console.log('Could not find support for "frag_depth"') + console.log('Could not find support for "frag_depth"'); } - const colorBufferFloat = getColorBufferFloat(gl) + const colorBufferFloat = getColorBufferFloat(gl); if (isDebugMode && colorBufferFloat === null) { - console.log('Could not find support for "color_buffer_float"') + console.log('Could not find support for "color_buffer_float"'); } - const drawBuffers = getDrawBuffers(gl) + const drawBuffers = getDrawBuffers(gl); if (isDebugMode && drawBuffers === null) { - console.log('Could not find support for "draw_buffers"') + console.log('Could not find support for "draw_buffers"'); } - const shaderTextureLod = getShaderTextureLod(gl) + const shaderTextureLod = getShaderTextureLod(gl); if (isDebugMode && shaderTextureLod === null) { - console.log('Could not find support for "shader_texture_lod"') + console.log('Could not find support for "shader_texture_lod"'); } return { @@ -94,5 +94,5 @@ export function createExtensions(gl: GLRenderingContext): WebGLExtensions { colorBufferFloat, drawBuffers, shaderTextureLod, - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/framebuffer.ts b/src/mol-gl/webgl/framebuffer.ts index 7ff899d8eb30ba065431ede5253d03849b96704d..3f982cfa37d9917af86de6fe61da26c060a7398b 100644 --- a/src/mol-gl/webgl/framebuffer.ts +++ b/src/mol-gl/webgl/framebuffer.ts @@ -7,30 +7,30 @@ import { idFactory } from '../../mol-util/id-factory'; import { GLRenderingContext, isWebGL2 } from './compat'; -const getNextFramebufferId = idFactory() +const getNextFramebufferId = idFactory(); function getFramebufferStatusDescription(gl: GLRenderingContext, status: number) { switch (status) { - case gl.FRAMEBUFFER_COMPLETE: return 'complete' - case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return 'incomplete attachment' - case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return 'incomplete missing attachment' - case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return 'incomplete dimensions' - case gl.FRAMEBUFFER_UNSUPPORTED: return 'unsupported' + case gl.FRAMEBUFFER_COMPLETE: return 'complete'; + case gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return 'incomplete attachment'; + case gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return 'incomplete missing attachment'; + case gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return 'incomplete dimensions'; + case gl.FRAMEBUFFER_UNSUPPORTED: return 'unsupported'; } if (isWebGL2(gl)) { switch (status) { - case gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return 'incomplete multisample' - case gl.RENDERBUFFER_SAMPLES: return 'renderbuffer samples' + case gl.FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return 'incomplete multisample'; + case gl.RENDERBUFFER_SAMPLES: return 'renderbuffer samples'; } } - return 'unknown error' + return 'unknown error'; } export function checkFramebufferStatus(gl: GLRenderingContext) { - const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER) + const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); if (status !== gl.FRAMEBUFFER_COMPLETE) { - const description = getFramebufferStatusDescription(gl, status) - throw new Error(`Framebuffer status: ${description}`) + const description = getFramebufferStatusDescription(gl, status); + throw new Error(`Framebuffer status: ${description}`); } } @@ -43,29 +43,29 @@ export interface Framebuffer { } function getFramebuffer(gl: GLRenderingContext) { - const framebuffer = gl.createFramebuffer() + const framebuffer = gl.createFramebuffer(); if (framebuffer === null) { - throw new Error('Could not create WebGL framebuffer') + throw new Error('Could not create WebGL framebuffer'); } - return framebuffer + return framebuffer; } export function createFramebuffer (gl: GLRenderingContext): Framebuffer { - let _framebuffer = getFramebuffer(gl) + let _framebuffer = getFramebuffer(gl); - let destroyed = false + let destroyed = false; return { id: getNextFramebufferId(), bind: () => gl.bindFramebuffer(gl.FRAMEBUFFER, _framebuffer), reset: () => { - _framebuffer = getFramebuffer(gl) + _framebuffer = getFramebuffer(gl); }, destroy: () => { - if (destroyed) return - gl.deleteFramebuffer(_framebuffer) - destroyed = true + if (destroyed) return; + gl.deleteFramebuffer(_framebuffer); + destroyed = true; } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/program.ts b/src/mol-gl/webgl/program.ts index bd13ec3542e6d058e0fded9fe3402781aa9ee436..a36d4c8dc45d90b39b05e9c4d0bac3843219d80c 100644 --- a/src/mol-gl/webgl/program.ts +++ b/src/mol-gl/webgl/program.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code' +import { ShaderCode, DefineValues, addShaderDefines } from '../shader-code'; import { WebGLState } from './state'; import { WebGLExtensions } from './extensions'; import { getUniformSetters, UniformsList, getUniformType, UniformSetters } from './uniform'; @@ -16,7 +16,7 @@ import { isDebugMode } from '../../mol-util/debug'; import { GLRenderingContext } from './compat'; import { ShaderType, Shader } from './shader'; -const getNextProgramId = idFactory() +const getNextProgramId = idFactory(); export interface Program { readonly id: number @@ -33,22 +33,22 @@ export interface Program { type Locations = { [k: string]: number } function getLocations(gl: GLRenderingContext, program: WebGLProgram, schema: RenderableSchema) { - const locations: Locations = {} + const locations: Locations = {}; Object.keys(schema).forEach(k => { - const spec = schema[k] + const spec = schema[k]; if (spec.type === 'attribute') { - const loc = gl.getAttribLocation(program, k) + const loc = gl.getAttribLocation(program, k); // unused attributes will result in a `-1` location which is usually fine // if (loc === -1) console.info(`Could not get attribute location for '${k}'`) - locations[k] = loc + locations[k] = loc; } else if (spec.type === 'uniform' || spec.type === 'texture') { - const loc = gl.getUniformLocation(program, k) + const loc = gl.getUniformLocation(program, k); // unused uniforms will result in a `null` location which is usually fine // if (loc === null) console.info(`Could not get uniform location for '${k}'`) - locations[k] = loc as number + locations[k] = loc as number; } - }) - return locations + }); + return locations; } function checkActiveAttributes(gl: GLRenderingContext, program: WebGLProgram, schema: RenderableSchema) { @@ -56,21 +56,21 @@ function checkActiveAttributes(gl: GLRenderingContext, program: WebGLProgram, sc for (let i = 0; i < attribCount; ++i) { const info = gl.getActiveAttrib(program, i); if (info) { - const { name, type } = info + const { name, type } = info; if (name.startsWith('__activeAttribute')) { // name assigned by `gl.shim.ts`, ignore for checks - continue + continue; } - const spec = schema[name] + const spec = schema[name]; if (spec === undefined) { - throw new Error(`missing 'uniform' or 'texture' with name '${name}' in schema`) + throw new Error(`missing 'uniform' or 'texture' with name '${name}' in schema`); } if (spec.type !== 'attribute') { - throw new Error(`'${name}' must be of type 'attribute' but is '${spec.type}'`) + throw new Error(`'${name}' must be of type 'attribute' but is '${spec.type}'`); } - const attribType = getAttribType(gl, spec.kind, spec.itemSize) + const attribType = getAttribType(gl, spec.kind, spec.itemSize); if (attribType !== type) { - throw new Error(`unexpected attribute type for ${name}`) + throw new Error(`unexpected attribute type for ${name}`); } } } @@ -81,34 +81,34 @@ function checkActiveUniforms(gl: GLRenderingContext, program: WebGLProgram, sche for (let i = 0; i < attribCount; ++i) { const info = gl.getActiveUniform(program, i); if (info) { - const { name, type } = info + const { name, type } = info; if (name.startsWith('__activeUniform')) { // name assigned by `gl.shim.ts`, ignore for checks - continue + continue; } - const spec = schema[name] + const spec = schema[name]; if (spec === undefined) { - throw new Error(`missing 'uniform' or 'texture' with name '${name}' in schema`) + throw new Error(`missing 'uniform' or 'texture' with name '${name}' in schema`); } if (spec.type === 'uniform') { - const uniformType = getUniformType(gl, spec.kind) + const uniformType = getUniformType(gl, spec.kind); if (uniformType !== type) { - throw new Error(`unexpected uniform type for ${name}`) + throw new Error(`unexpected uniform type for ${name}`); } } else if (spec.type === 'texture') { if (spec.kind === 'image-float32' || spec.kind === 'image-uint8') { if (type !== gl.SAMPLER_2D) { - throw new Error(`unexpected sampler type for '${name}'`) + throw new Error(`unexpected sampler type for '${name}'`); } } else if (spec.kind === 'volume-float32' || spec.kind === 'volume-uint8') { if (type !== (gl as WebGL2RenderingContext).SAMPLER_3D) { - throw new Error(`unexpected sampler type for '${name}'`) + throw new Error(`unexpected sampler type for '${name}'`); } } else { // TODO } } else { - throw new Error(`'${name}' must be of type 'uniform' or 'texture' but is '${spec.type}'`) + throw new Error(`'${name}' must be of type 'uniform' or 'texture' but is '${spec.type}'`); } } } @@ -129,95 +129,95 @@ export interface ProgramProps { } function getProgram(gl: GLRenderingContext) { - const program = gl.createProgram() + const program = gl.createProgram(); if (program === null) { - throw new Error('Could not create WebGL program') + throw new Error('Could not create WebGL program'); } - return program + return program; } type ShaderGetter = (type: ShaderType, source: string) => Shader export function createProgram(gl: GLRenderingContext, state: WebGLState, extensions: WebGLExtensions, getShader: ShaderGetter, props: ProgramProps): Program { - const { defineValues, shaderCode: _shaderCode, schema } = props + const { defineValues, shaderCode: _shaderCode, schema } = props; - let program = getProgram(gl) - const programId = getNextProgramId() + let program = getProgram(gl); + const programId = getNextProgramId(); - const shaderCode = addShaderDefines(gl, extensions, defineValues, _shaderCode) - const vertShader = getShader('vert', shaderCode.vert) - const fragShader = getShader('frag', shaderCode.frag) + const shaderCode = addShaderDefines(gl, extensions, defineValues, _shaderCode); + const vertShader = getShader('vert', shaderCode.vert); + const fragShader = getShader('frag', shaderCode.frag); - let locations: Locations - let uniformSetters: UniformSetters + let locations: Locations; + let uniformSetters: UniformSetters; function init() { - vertShader.attach(program) - fragShader.attach(program) - gl.linkProgram(program) + vertShader.attach(program); + fragShader.attach(program); + gl.linkProgram(program); if (isDebugMode) { - checkProgram(gl, program) + checkProgram(gl, program); } - locations = getLocations(gl, program, schema) - uniformSetters = getUniformSetters(schema) + locations = getLocations(gl, program, schema); + uniformSetters = getUniformSetters(schema); if (isDebugMode) { - checkActiveAttributes(gl, program, schema) - checkActiveUniforms(gl, program, schema) + checkActiveAttributes(gl, program, schema); + checkActiveUniforms(gl, program, schema); } } - init() + init(); - let destroyed = false + let destroyed = false; return { id: programId, use: () => { // console.log('use', programId) - state.currentProgramId = programId - gl.useProgram(program) + state.currentProgramId = programId; + gl.useProgram(program); }, setUniforms: (uniformValues: UniformsList) => { for (let i = 0, il = uniformValues.length; i < il; ++i) { - const [k, v] = uniformValues[i] + const [k, v] = uniformValues[i]; if (v) { - const l = locations[k] - if (l !== null) uniformSetters[k](gl, l, v.ref.value) + const l = locations[k]; + if (l !== null) uniformSetters[k](gl, l, v.ref.value); } } }, bindAttributes: (attributeBuffers: AttributeBuffers) => { for (let i = 0, il = attributeBuffers.length; i < il; ++i) { - const [k, buffer] = attributeBuffers[i] - const l = locations[k] - if (l !== -1) buffer.bind(l) + const [k, buffer] = attributeBuffers[i]; + const l = locations[k]; + if (l !== -1) buffer.bind(l); } }, bindTextures: (textures: Textures) => { for (let i = 0, il = textures.length; i < il; ++i) { - const [k, texture] = textures[i] - const l = locations[k] + const [k, texture] = textures[i]; + const l = locations[k]; if (l !== null) { // TODO if the order and count of textures in a material can be made invariant // bind needs to be called only when the material changes - texture.bind(i as TextureId) - uniformSetters[k](gl, l, i as TextureId) + texture.bind(i as TextureId); + uniformSetters[k](gl, l, i as TextureId); } } }, reset: () => { - program = getProgram(gl) - init() + program = getProgram(gl); + init(); }, destroy: () => { - if (destroyed) return - vertShader.destroy() - fragShader.destroy() - gl.deleteProgram(program) - destroyed = true + if (destroyed) return; + vertShader.destroy(); + fragShader.destroy(); + gl.deleteProgram(program); + destroyed = true; } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/render-item.ts b/src/mol-gl/webgl/render-item.ts index 1cc9ee17db1169144b6cefc1c0115da34a27ed8b..1dd18e46887dd58277b22f1d2cca367fb5c0cd95 100644 --- a/src/mol-gl/webgl/render-item.ts +++ b/src/mol-gl/webgl/render-item.ts @@ -17,20 +17,20 @@ import { checkFramebufferStatus } from './framebuffer'; import { isDebugMode } from '../../mol-util/debug'; import { VertexArray } from './vertex-array'; -const getNextRenderItemId = idFactory() +const getNextRenderItemId = idFactory(); export type DrawMode = 'points' | 'lines' | 'line-strip' | 'line-loop' | 'triangles' | 'triangle-strip' | 'triangle-fan' export function getDrawMode(ctx: WebGLContext, drawMode: DrawMode) { - const { gl } = ctx + const { gl } = ctx; switch (drawMode) { - case 'points': return gl.POINTS - case 'lines': return gl.LINES - case 'line-strip': return gl.LINE_STRIP - case 'line-loop': return gl.LINE_LOOP - case 'triangles': return gl.TRIANGLES - case 'triangle-strip': return gl.TRIANGLE_STRIP - case 'triangle-fan': return gl.TRIANGLE_FAN + case 'points': return gl.POINTS; + case 'lines': return gl.LINES; + case 'line-strip': return gl.LINE_STRIP; + case 'line-loop': return gl.LINE_LOOP; + case 'triangles': return gl.TRIANGLES; + case 'triangle-strip': return gl.TRIANGLE_STRIP; + case 'triangle-fan': return gl.TRIANGLE_FAN; } } @@ -52,12 +52,12 @@ const GraphicsRenderVariantDefines = { 'pickInstance': { dColorType: ValueCell.create('instancePicking') }, 'pickGroup': { dColorType: ValueCell.create('groupPicking') }, 'depth': { dColorType: ValueCell.create('depth') } -} +}; export type GraphicsRenderVariant = keyof typeof GraphicsRenderVariantDefines const ComputeRenderVariantDefines = { 'compute': {}, -} +}; export type ComputeRenderVariant = keyof typeof ComputeRenderVariantDefines type RenderVariantDefines = typeof GraphicsRenderVariantDefines | typeof ComputeRenderVariantDefines @@ -79,25 +79,25 @@ function createValueChanges() { defines: false, elements: false, textures: false, - } + }; } function resetValueChanges(valueChanges: ValueChanges) { - valueChanges.attributes = false - valueChanges.defines = false - valueChanges.elements = false - valueChanges.textures = false + valueChanges.attributes = false; + valueChanges.defines = false; + valueChanges.elements = false; + valueChanges.textures = false; } // export type GraphicsRenderItem = RenderItem<keyof typeof GraphicsRenderVariantDefines & string> export function createGraphicsRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number) { - return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, GraphicsRenderVariantDefines) + return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, GraphicsRenderVariantDefines); } export type ComputeRenderItem = RenderItem<keyof typeof ComputeRenderVariantDefines & string> export function createComputeRenderItem(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId = -1) { - return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, ComputeRenderVariantDefines) + return createRenderItem(ctx, drawMode, shaderCode, schema, values, materialId, ComputeRenderVariantDefines); } /** @@ -106,51 +106,51 @@ export function createComputeRenderItem(ctx: WebGLContext, drawMode: DrawMode, s * - assumes that `values.drawCount` and `values.instanceCount` exist */ export function createRenderItem<T extends RenderVariantDefines, S extends keyof T & string>(ctx: WebGLContext, drawMode: DrawMode, shaderCode: ShaderCode, schema: RenderableSchema, values: RenderableValues, materialId: number, renderVariantDefines: T): RenderItem<S> { - const id = getNextRenderItemId() - const { stats, state, resources } = ctx - const { instancedArrays, vertexArrayObject } = ctx.extensions + const id = getNextRenderItemId(); + const { stats, state, resources } = ctx; + const { instancedArrays, vertexArrayObject } = ctx.extensions; - const { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues } = splitValues(schema, values) + const { attributeValues, defineValues, textureValues, uniformValues, materialUniformValues } = splitValues(schema, values); - const uniformValueEntries = Object.entries(uniformValues) - const materialUniformValueEntries = Object.entries(materialUniformValues) - const defineValueEntries = Object.entries(defineValues) + const uniformValueEntries = Object.entries(uniformValues); + const materialUniformValueEntries = Object.entries(materialUniformValues); + const defineValueEntries = Object.entries(defineValues); - const versions = getValueVersions(values) + const versions = getValueVersions(values); - const glDrawMode = getDrawMode(ctx, drawMode) + const glDrawMode = getDrawMode(ctx, drawMode); - const programs: ProgramVariants = {} + const programs: ProgramVariants = {}; Object.keys(renderVariantDefines).forEach(k => { - const variantDefineValues: Values<RenderableSchema> = (renderVariantDefines as any)[k] - programs[k] = resources.program({ ...defineValues, ...variantDefineValues }, shaderCode, schema) - }) + const variantDefineValues: Values<RenderableSchema> = (renderVariantDefines as any)[k]; + programs[k] = resources.program({ ...defineValues, ...variantDefineValues }, shaderCode, schema); + }); - const textures = createTextures(ctx, schema, textureValues) - const attributeBuffers = createAttributeBuffers(ctx, schema, attributeValues) + const textures = createTextures(ctx, schema, textureValues); + const attributeBuffers = createAttributeBuffers(ctx, schema, attributeValues); - let elementsBuffer: ElementsBuffer | undefined - const elements = values.elements + let elementsBuffer: ElementsBuffer | undefined; + const elements = values.elements; if (elements && elements.ref.value) { - elementsBuffer = resources.elements(elements.ref.value) + elementsBuffer = resources.elements(elements.ref.value); } - const vertexArrays: VertexArrayVariants = {} + const vertexArrays: VertexArrayVariants = {}; Object.keys(renderVariantDefines).forEach(k => { - vertexArrays[k] = vertexArrayObject ? resources.vertexArray(programs[k], attributeBuffers, elementsBuffer) : null - }) + vertexArrays[k] = vertexArrayObject ? resources.vertexArray(programs[k], attributeBuffers, elementsBuffer) : null; + }); - let drawCount = values.drawCount.ref.value - let instanceCount = values.instanceCount.ref.value + let drawCount = values.drawCount.ref.value; + let instanceCount = values.instanceCount.ref.value; - stats.drawCount += drawCount - stats.instanceCount += instanceCount - stats.instancedDrawCount += instanceCount * drawCount + stats.drawCount += drawCount; + stats.instanceCount += instanceCount; + stats.instancedDrawCount += instanceCount * drawCount; - const valueChanges = createValueChanges() + const valueChanges = createValueChanges(); - let destroyed = false - let currentProgramId = -1 + let destroyed = false; + let currentProgramId = -1; return { id, @@ -158,161 +158,161 @@ export function createRenderItem<T extends RenderVariantDefines, S extends keyof getProgram: (variant: S) => programs[variant], render: (variant: S) => { - if (drawCount === 0 || instanceCount === 0 || ctx.isContextLost) return - const program = programs[variant] + if (drawCount === 0 || instanceCount === 0 || ctx.isContextLost) return; + const program = programs[variant]; if (program.id === currentProgramId && state.currentRenderItemId === id) { - program.setUniforms(uniformValueEntries) - program.bindTextures(textures) + program.setUniforms(uniformValueEntries); + program.bindTextures(textures); } else { - const vertexArray = vertexArrays[variant] + const vertexArray = vertexArrays[variant]; if (program.id !== state.currentProgramId || program.id !== currentProgramId || materialId === -1 || materialId !== state.currentMaterialId ) { // console.log('program.id changed or materialId changed/-1', materialId) - if (program.id !== state.currentProgramId) program.use() - program.setUniforms(materialUniformValueEntries) - state.currentMaterialId = materialId - currentProgramId = program.id + if (program.id !== state.currentProgramId) program.use(); + program.setUniforms(materialUniformValueEntries); + state.currentMaterialId = materialId; + currentProgramId = program.id; } - program.setUniforms(uniformValueEntries) - program.bindTextures(textures) + program.setUniforms(uniformValueEntries); + program.bindTextures(textures); if (vertexArray) { - vertexArray.bind() + vertexArray.bind(); // need to bind elements buffer explicitly since it is not always recorded in the VAO - if (elementsBuffer) elementsBuffer.bind() + if (elementsBuffer) elementsBuffer.bind(); } else { - if (elementsBuffer) elementsBuffer.bind() - program.bindAttributes(attributeBuffers) + if (elementsBuffer) elementsBuffer.bind(); + program.bindAttributes(attributeBuffers); } - state.currentRenderItemId = id + state.currentRenderItemId = id; } if (isDebugMode) { - checkFramebufferStatus(ctx.gl) + checkFramebufferStatus(ctx.gl); } if (elementsBuffer) { instancedArrays.drawElementsInstanced(glDrawMode, drawCount, elementsBuffer._dataType, 0, instanceCount); } else { - instancedArrays.drawArraysInstanced(glDrawMode, 0, drawCount, instanceCount) + instancedArrays.drawArraysInstanced(glDrawMode, 0, drawCount, instanceCount); } if (isDebugMode) { try { - checkError(ctx.gl) + checkError(ctx.gl); } catch (e) { - throw new Error(`Error rendering item id ${id}: '${e}'`) + throw new Error(`Error rendering item id ${id}: '${e}'`); } } }, update: () => { - resetValueChanges(valueChanges) + resetValueChanges(valueChanges); for (let i = 0, il = defineValueEntries.length; i < il; ++i) { - const [k, value] = defineValueEntries[i] + const [k, value] = defineValueEntries[i]; if (value.ref.version !== versions[k]) { // console.log('define version changed', k) - valueChanges.defines = true - versions[k] = value.ref.version + valueChanges.defines = true; + versions[k] = value.ref.version; } } if (valueChanges.defines) { // console.log('some defines changed, need to rebuild programs') Object.keys(renderVariantDefines).forEach(k => { - const variantDefineValues: Values<RenderableSchema> = (renderVariantDefines as any)[k] - programs[k].destroy() - programs[k] = resources.program({ ...defineValues, ...variantDefineValues }, shaderCode, schema) - }) + const variantDefineValues: Values<RenderableSchema> = (renderVariantDefines as any)[k]; + programs[k].destroy(); + programs[k] = resources.program({ ...defineValues, ...variantDefineValues }, shaderCode, schema); + }); } if (values.drawCount.ref.version !== versions.drawCount) { // console.log('drawCount version changed') - stats.drawCount += values.drawCount.ref.value - drawCount - stats.instancedDrawCount += instanceCount * values.drawCount.ref.value - instanceCount * drawCount - drawCount = values.drawCount.ref.value - versions.drawCount = values.drawCount.ref.version + stats.drawCount += values.drawCount.ref.value - drawCount; + stats.instancedDrawCount += instanceCount * values.drawCount.ref.value - instanceCount * drawCount; + drawCount = values.drawCount.ref.value; + versions.drawCount = values.drawCount.ref.version; } if (values.instanceCount.ref.version !== versions.instanceCount) { // console.log('instanceCount version changed') - stats.instanceCount += values.instanceCount.ref.value - instanceCount - stats.instancedDrawCount += values.instanceCount.ref.value * drawCount - instanceCount * drawCount - instanceCount = values.instanceCount.ref.value - versions.instanceCount = values.instanceCount.ref.version + stats.instanceCount += values.instanceCount.ref.value - instanceCount; + stats.instancedDrawCount += values.instanceCount.ref.value * drawCount - instanceCount * drawCount; + instanceCount = values.instanceCount.ref.value; + versions.instanceCount = values.instanceCount.ref.version; } for (let i = 0, il = attributeBuffers.length; i < il; ++i) { - const [k, buffer] = attributeBuffers[i] - const value = attributeValues[k] + const [k, buffer] = attributeBuffers[i]; + const value = attributeValues[k]; if (value.ref.version !== versions[k]) { if (buffer.length >= value.ref.value.length) { // console.log('attribute array large enough to update', buffer.id, k, value.ref.id, value.ref.version) - buffer.updateData(value.ref.value) + buffer.updateData(value.ref.value); } else { // console.log('attribute array too small, need to create new attribute', buffer.id, k, value.ref.id, value.ref.version) - buffer.destroy() - const { itemSize, divisor } = schema[k] as AttributeSpec<AttributeKind> - attributeBuffers[i][1] = resources.attribute(value.ref.value, itemSize, divisor) - valueChanges.attributes = true + buffer.destroy(); + const { itemSize, divisor } = schema[k] as AttributeSpec<AttributeKind>; + attributeBuffers[i][1] = resources.attribute(value.ref.value, itemSize, divisor); + valueChanges.attributes = true; } - versions[k] = value.ref.version + versions[k] = value.ref.version; } } if (elementsBuffer && values.elements.ref.version !== versions.elements) { if (elementsBuffer.length >= values.elements.ref.value.length) { // console.log('elements array large enough to update', values.elements.ref.id, values.elements.ref.version) - elementsBuffer.updateData(values.elements.ref.value) + elementsBuffer.updateData(values.elements.ref.value); } else { // console.log('elements array to small, need to create new elements', values.elements.ref.id, values.elements.ref.version) - elementsBuffer.destroy() - elementsBuffer = resources.elements(values.elements.ref.value) - valueChanges.elements = true + elementsBuffer.destroy(); + elementsBuffer = resources.elements(values.elements.ref.value); + valueChanges.elements = true; } - versions.elements = values.elements.ref.version + versions.elements = values.elements.ref.version; } if (valueChanges.attributes || valueChanges.defines || valueChanges.elements) { // console.log('program/defines or buffers changed, update vaos') Object.keys(renderVariantDefines).forEach(k => { - const vertexArray = vertexArrays[k] - if (vertexArray) vertexArray.destroy() - vertexArrays[k] = vertexArrayObject ? resources.vertexArray(programs[k], attributeBuffers, elementsBuffer) : null - }) + const vertexArray = vertexArrays[k]; + if (vertexArray) vertexArray.destroy(); + vertexArrays[k] = vertexArrayObject ? resources.vertexArray(programs[k], attributeBuffers, elementsBuffer) : null; + }); } for (let i = 0, il = textures.length; i < il; ++i) { - const [k, texture] = textures[i] - const value = textureValues[k] + const [k, texture] = textures[i]; + const value = textureValues[k]; if (value.ref.version !== versions[k]) { // update of textures with kind 'texture' is done externally if (schema[k].kind !== 'texture') { // console.log('texture version changed, uploading image', k) - texture.load(value.ref.value as TextureImage<any> | TextureVolume<any>) - versions[k] = value.ref.version - valueChanges.textures = true + texture.load(value.ref.value as TextureImage<any> | TextureVolume<any>); + versions[k] = value.ref.version; + valueChanges.textures = true; } else { - textures[i][1] = value.ref.value as Texture + textures[i][1] = value.ref.value as Texture; } } } - return valueChanges + return valueChanges; }, destroy: () => { if (!destroyed) { Object.keys(renderVariantDefines).forEach(k => { - programs[k].destroy() - const vertexArray = vertexArrays[k] - if (vertexArray) vertexArray.destroy() - }) + programs[k].destroy(); + const vertexArray = vertexArrays[k]; + if (vertexArray) vertexArray.destroy(); + }); textures.forEach(([k, texture]) => { // lifetime of textures with kind 'texture' is defined externally if (schema[k].kind !== 'texture') { - texture.destroy() + texture.destroy(); } - }) - attributeBuffers.forEach(([_, buffer]) => buffer.destroy()) - if (elementsBuffer) elementsBuffer.destroy() - destroyed = true + }); + attributeBuffers.forEach(([_, buffer]) => buffer.destroy()); + if (elementsBuffer) elementsBuffer.destroy(); + destroyed = true; } } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/render-target.ts b/src/mol-gl/webgl/render-target.ts index 36b1842d281059b96d432303afb434e6de8b5621..7860728ad012909d78caa9471a1c20e345db10b7 100644 --- a/src/mol-gl/webgl/render-target.ts +++ b/src/mol-gl/webgl/render-target.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { readPixels } from './context' +import { readPixels } from './context'; import { idFactory } from '../../mol-util/id-factory'; import { Texture } from './texture'; import { Framebuffer } from './framebuffer'; @@ -14,7 +14,7 @@ import { PixelData } from '../../mol-util/image'; import { WebGLResources } from './resources'; import { GLRenderingContext } from './compat'; -const getNextRenderTargetId = idFactory() +const getNextRenderTargetId = idFactory(); export interface RenderTarget { readonly id: number @@ -39,31 +39,31 @@ export function createRenderTarget(gl: GLRenderingContext, resources: WebGLResou array: new Uint8Array(_width * _height * 4), width: _width, height: _height - } + }; - const framebuffer = resources.framebuffer() - const targetTexture = resources.texture('image-uint8', 'rgba', 'ubyte', 'linear') + const framebuffer = resources.framebuffer(); + const targetTexture = resources.texture('image-uint8', 'rgba', 'ubyte', 'linear'); // make a depth renderbuffer of the same size as the targetTexture - const depthRenderbuffer = resources.renderbuffer('depth16', 'depth', _width, _height) + const depthRenderbuffer = resources.renderbuffer('depth16', 'depth', _width, _height); function init() { - targetTexture.load(image) - targetTexture.attachFramebuffer(framebuffer, 'color0') - depthRenderbuffer.attachFramebuffer(framebuffer) + targetTexture.load(image); + targetTexture.attachFramebuffer(framebuffer, 'color0'); + depthRenderbuffer.attachFramebuffer(framebuffer); } - init() + init(); - let destroyed = false + let destroyed = false; function readBuffer(x: number, y: number, width: number, height: number, dst: Uint8Array) { - framebuffer.bind() - gl.viewport(0, 0, _width, _height) - readPixels(gl, x, y, width, height, dst) + framebuffer.bind(); + gl.viewport(0, 0, _width, _height); + readPixels(gl, x, y, width, height, dst); } function getBuffer() { - readBuffer(0, 0, _width, _height, image.array) - return image.array + readBuffer(0, 0, _width, _height, image.array); + return image.array; } return { @@ -75,30 +75,30 @@ export function createRenderTarget(gl: GLRenderingContext, resources: WebGLResou getWidth: () => _width, getHeight: () => _height, bind: () => { - framebuffer.bind() - gl.viewport(0, 0, _width, _height) + framebuffer.bind(); + gl.viewport(0, 0, _width, _height); }, setSize: (width: number, height: number) => { - _width = width - _height = height - image.array = new Uint8Array(_width * _height * 4) - image.width = _width - image.height = _height - targetTexture.load(image) - depthRenderbuffer.setSize(_width, _height) + _width = width; + _height = height; + image.array = new Uint8Array(_width * _height * 4); + image.width = _width; + image.height = _height; + targetTexture.load(image); + depthRenderbuffer.setSize(_width, _height); }, readBuffer, getBuffer, getPixelData: () => PixelData.flipY(PixelData.create(getBuffer(), _width, _height)), reset: () => { - init() + init(); }, destroy: () => { - if (destroyed) return - targetTexture.destroy() - framebuffer.destroy() - depthRenderbuffer.destroy() - destroyed = true + if (destroyed) return; + targetTexture.destroy(); + framebuffer.destroy(); + depthRenderbuffer.destroy(); + destroyed = true; } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/renderbuffer.ts b/src/mol-gl/webgl/renderbuffer.ts index 72cc06d6864562abc59366ef968ba4b68b1082ba..0fd6a1095965d36fde7ce8dbeca8e39476b8e9fb 100644 --- a/src/mol-gl/webgl/renderbuffer.ts +++ b/src/mol-gl/webgl/renderbuffer.ts @@ -9,26 +9,26 @@ import { GLRenderingContext } from './compat'; import { Framebuffer, checkFramebufferStatus } from './framebuffer'; import { isDebugMode } from '../../mol-util/debug'; -const getNextRenderbufferId = idFactory() +const getNextRenderbufferId = idFactory(); export type RenderbufferFormat = 'depth16' | 'stencil8' | 'rgba4' | 'depth-stencil' export type RenderbufferAttachment = 'depth' | 'stencil' | 'depth-stencil' | 'color0' export function getFormat(gl: GLRenderingContext, format: RenderbufferFormat) { switch (format) { - case 'depth16': return gl.DEPTH_COMPONENT16 - case 'stencil8': return gl.STENCIL_INDEX8 - case 'rgba4': return gl.RGBA4 - case 'depth-stencil': return gl.DEPTH_STENCIL + case 'depth16': return gl.DEPTH_COMPONENT16; + case 'stencil8': return gl.STENCIL_INDEX8; + case 'rgba4': return gl.RGBA4; + case 'depth-stencil': return gl.DEPTH_STENCIL; } } export function getAttachment(gl: GLRenderingContext, attachment: RenderbufferAttachment) { switch (attachment) { - case 'depth': return gl.DEPTH_ATTACHMENT - case 'stencil': return gl.STENCIL_ATTACHMENT - case 'depth-stencil': return gl.DEPTH_STENCIL_ATTACHMENT - case 'color0': return gl.COLOR_ATTACHMENT0 + case 'depth': return gl.DEPTH_ATTACHMENT; + case 'stencil': return gl.STENCIL_ATTACHMENT; + case 'depth-stencil': return gl.DEPTH_STENCIL_ATTACHMENT; + case 'color0': return gl.COLOR_ATTACHMENT0; } } @@ -43,51 +43,51 @@ export interface Renderbuffer { } function getRenderbuffer(gl: GLRenderingContext) { - const renderbuffer = gl.createRenderbuffer() + const renderbuffer = gl.createRenderbuffer(); if (renderbuffer === null) { - throw new Error('Could not create WebGL renderbuffer') + throw new Error('Could not create WebGL renderbuffer'); } - return renderbuffer + return renderbuffer; } export function createRenderbuffer (gl: GLRenderingContext, format: RenderbufferFormat, attachment: RenderbufferAttachment, _width: number, _height: number): Renderbuffer { - let _renderbuffer = getRenderbuffer(gl) + let _renderbuffer = getRenderbuffer(gl); - const bind = () => gl.bindRenderbuffer(gl.RENDERBUFFER, _renderbuffer) - const _format = getFormat(gl, format) - const _attachment = getAttachment(gl, attachment) + const bind = () => gl.bindRenderbuffer(gl.RENDERBUFFER, _renderbuffer); + const _format = getFormat(gl, format); + const _attachment = getAttachment(gl, attachment); function init() { - bind() - gl.renderbufferStorage(gl.RENDERBUFFER, _format, _width, _height) + bind(); + gl.renderbufferStorage(gl.RENDERBUFFER, _format, _width, _height); } - init() + init(); - let destroyed = false + let destroyed = false; return { id: getNextRenderbufferId(), bind, attachFramebuffer: (framebuffer: Framebuffer) => { - framebuffer.bind() - bind() - gl.framebufferRenderbuffer(gl.FRAMEBUFFER, _attachment, gl.RENDERBUFFER, _renderbuffer) - if (isDebugMode) checkFramebufferStatus(gl) + framebuffer.bind(); + bind(); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, _attachment, gl.RENDERBUFFER, _renderbuffer); + if (isDebugMode) checkFramebufferStatus(gl); }, setSize: (width: number, height: number) => { - _width = width - _height = height - init() + _width = width; + _height = height; + init(); }, reset: () => { - _renderbuffer = getRenderbuffer(gl) - init() + _renderbuffer = getRenderbuffer(gl); + init(); }, destroy: () => { - if (destroyed) return - gl.deleteRenderbuffer(_renderbuffer) - destroyed = true + if (destroyed) return; + gl.deleteRenderbuffer(_renderbuffer); + destroyed = true; } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/resources.ts b/src/mol-gl/webgl/resources.ts index e96ab597dc06fb5f59716965de3e3a15a279efb9..53ae77951a2430b02a04b39dc41ec6c807a43870 100644 --- a/src/mol-gl/webgl/resources.ts +++ b/src/mol-gl/webgl/resources.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ProgramProps, createProgram, Program } from './program' -import { ShaderType, createShader, Shader, ShaderProps } from './shader' +import { ProgramProps, createProgram, Program } from './program'; +import { ShaderType, createShader, Shader, ShaderProps } from './shader'; import { GLRenderingContext } from './compat'; import { Framebuffer, createFramebuffer } from './framebuffer'; import { WebGLExtensions } from './extensions'; @@ -22,18 +22,18 @@ import { VertexArray, createVertexArray } from './vertex-array'; function defineValueHash(v: boolean | number | string): number { return typeof v === 'boolean' ? (v ? 1 : 0) : - typeof v === 'number' ? v : hashString(v) + typeof v === 'number' ? v : hashString(v); } function wrapCached<T extends Resource>(resourceItem: ReferenceItem<T>) { const wrapped = { ...resourceItem.value, destroy: () => { - resourceItem.free() + resourceItem.free(); } - } + }; - return wrapped + return wrapped; } // @@ -69,87 +69,87 @@ export function createResources(gl: GLRenderingContext, state: WebGLState, stats shader: new Set<Resource>(), texture: new Set<Resource>(), vertexArray: new Set<Resource>(), - } + }; function wrap<T extends Resource>(name: ResourceName, resource: T) { - sets[name].add(resource) - stats.resourceCounts[name] += 1 + sets[name].add(resource); + stats.resourceCounts[name] += 1; return { ...resource, destroy: () => { - resource.destroy() - sets[name].delete(resource) - stats.resourceCounts[name] -= 1 + resource.destroy(); + sets[name].delete(resource); + stats.resourceCounts[name] -= 1; } - } + }; } const shaderCache = createReferenceCache( (props: ShaderProps) => JSON.stringify(props), (props: ShaderProps) => wrap('shader', createShader(gl, props)), - (shader: Shader) => { shader.destroy() } - ) + (shader: Shader) => { shader.destroy(); } + ); function getShader(type: ShaderType, source: string) { - return wrapCached(shaderCache.get({ type, source })) + return wrapCached(shaderCache.get({ type, source })); } const programCache = createReferenceCache( (props: ProgramProps) => { - const array = [ props.shaderCode.id ] - Object.keys(props.defineValues).forEach(k => array.push(hashString(k), defineValueHash(props.defineValues[k].ref.value))) - return hashFnv32a(array).toString() + const array = [ props.shaderCode.id ]; + Object.keys(props.defineValues).forEach(k => array.push(hashString(k), defineValueHash(props.defineValues[k].ref.value))); + return hashFnv32a(array).toString(); }, (props: ProgramProps) => wrap('program', createProgram(gl, state, extensions, getShader, props)), - (program: Program) => { program.destroy() } - ) + (program: Program) => { program.destroy(); } + ); return { attribute: (array: ArrayType, itemSize: AttributeItemSize, divisor: number, usageHint?: UsageHint) => { - return wrap('attribute', createAttributeBuffer(gl, extensions, array, itemSize, divisor, usageHint)) + return wrap('attribute', createAttributeBuffer(gl, extensions, array, itemSize, divisor, usageHint)); }, elements: (array: ElementsType, usageHint?: UsageHint) => { - return wrap('elements', createElementsBuffer(gl, array, usageHint)) + return wrap('elements', createElementsBuffer(gl, array, usageHint)); }, framebuffer: () => { - return wrap('framebuffer', createFramebuffer(gl)) + return wrap('framebuffer', createFramebuffer(gl)); }, program: (defineValues: DefineValues, shaderCode: ShaderCode, schema: RenderableSchema) => { - return wrapCached(programCache.get({ defineValues, shaderCode, schema })) + return wrapCached(programCache.get({ defineValues, shaderCode, schema })); }, renderbuffer: (format: RenderbufferFormat, attachment: RenderbufferAttachment, width: number, height: number) => { - return wrap('renderbuffer', createRenderbuffer(gl, format, attachment, width, height)) + return wrap('renderbuffer', createRenderbuffer(gl, format, attachment, width, height)); }, shader: getShader, texture: (kind: TextureKind, format: TextureFormat, type: TextureType, filter: TextureFilter) => { - return wrap('texture', createTexture(gl, extensions, kind, format, type, filter)) + return wrap('texture', createTexture(gl, extensions, kind, format, type, filter)); }, vertexArray: (program: Program, attributeBuffers: AttributeBuffers, elementsBuffer?: ElementsBuffer) => { - return wrap('vertexArray', createVertexArray(extensions, program, attributeBuffers, elementsBuffer)) + return wrap('vertexArray', createVertexArray(extensions, program, attributeBuffers, elementsBuffer)); }, reset: () => { - sets.attribute.forEach(r => r.reset()) - sets.elements.forEach(r => r.reset()) - sets.framebuffer.forEach(r => r.reset()) - sets.renderbuffer.forEach(r => r.reset()) - sets.shader.forEach(r => r.reset()) - sets.program.forEach(r => r.reset()) - sets.vertexArray.forEach(r => r.reset()) - sets.texture.forEach(r => r.reset()) + sets.attribute.forEach(r => r.reset()); + sets.elements.forEach(r => r.reset()); + sets.framebuffer.forEach(r => r.reset()); + sets.renderbuffer.forEach(r => r.reset()); + sets.shader.forEach(r => r.reset()); + sets.program.forEach(r => r.reset()); + sets.vertexArray.forEach(r => r.reset()); + sets.texture.forEach(r => r.reset()); }, destroy: () => { - sets.attribute.forEach(r => r.destroy()) - sets.elements.forEach(r => r.destroy()) - sets.framebuffer.forEach(r => r.destroy()) - sets.renderbuffer.forEach(r => r.destroy()) - sets.shader.forEach(r => r.destroy()) - sets.program.forEach(r => r.destroy()) - sets.vertexArray.forEach(r => r.destroy()) - sets.texture.forEach(r => r.destroy()) - - shaderCache.clear() - programCache.clear() + sets.attribute.forEach(r => r.destroy()); + sets.elements.forEach(r => r.destroy()); + sets.framebuffer.forEach(r => r.destroy()); + sets.renderbuffer.forEach(r => r.destroy()); + sets.shader.forEach(r => r.destroy()); + sets.program.forEach(r => r.destroy()); + sets.vertexArray.forEach(r => r.destroy()); + sets.texture.forEach(r => r.destroy()); + + shaderCache.clear(); + programCache.clear(); } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/shader.ts b/src/mol-gl/webgl/shader.ts index 7fc9e354dc64c9fddf6f0b79d599b743a2ac9a53..87f719b9d62c40bd2570448d908a258d5b34c29d 100644 --- a/src/mol-gl/webgl/shader.ts +++ b/src/mol-gl/webgl/shader.ts @@ -8,14 +8,14 @@ import { idFactory } from '../../mol-util/id-factory'; import { GLRenderingContext } from './compat'; import { isDebugMode } from '../../mol-util/debug'; -const getNextShaderId = idFactory() +const getNextShaderId = idFactory(); function addLineNumbers(source: string) { - const lines = source.split('\n') + const lines = source.split('\n'); for (let i = 0; i < lines.length; ++i) { - lines[i] = (i + 1) + ': ' + lines[i] + lines[i] = (i + 1) + ': ' + lines[i]; } - return lines.join('\n') + return lines.join('\n'); } export type ShaderType = 'vert' | 'frag' @@ -28,37 +28,37 @@ export interface Shader { } function getShader(gl: GLRenderingContext, props: ShaderProps) { - const { type, source } = props - const shader = gl.createShader(type === 'vert' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER) + const { type, source } = props; + const shader = gl.createShader(type === 'vert' ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER); if (shader === null) { - throw new Error(`Error creating ${type} shader`) + throw new Error(`Error creating ${type} shader`); } - gl.shaderSource(shader, source) - gl.compileShader(shader) + gl.shaderSource(shader, source); + gl.compileShader(shader); if (isDebugMode && gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) { - console.warn(`'${type}' shader info log '${gl.getShaderInfoLog(shader)}'\n${addLineNumbers(source)}`) - throw new Error(`Error compiling ${type} shader`) + console.warn(`'${type}' shader info log '${gl.getShaderInfoLog(shader)}'\n${addLineNumbers(source)}`); + throw new Error(`Error compiling ${type} shader`); } - return shader + return shader; } export function createShader(gl: GLRenderingContext, props: ShaderProps): Shader { - let shader = getShader(gl, props) + let shader = getShader(gl, props); return { id: getNextShaderId(), attach: (program: WebGLProgram) => { - gl.attachShader(program, shader) + gl.attachShader(program, shader); }, reset: () => { - shader = getShader(gl, props) + shader = getShader(gl, props); }, destroy: () => { - gl.deleteShader(shader) + gl.deleteShader(shader); } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/state.ts b/src/mol-gl/webgl/state.ts index 7f3f70059eef8a5b4cf74e7b01251cfed2896724..4e9c188362a85700fc60c2d33c13ee0220b25901 100644 --- a/src/mol-gl/webgl/state.ts +++ b/src/mol-gl/webgl/state.ts @@ -63,21 +63,21 @@ export type WebGLState = { } export function createState(gl: GLRenderingContext): WebGLState { - let enabledCapabilities: { [k: number]: boolean } = {} + let enabledCapabilities: { [k: number]: boolean } = {}; - let currentFrontFace = gl.getParameter(gl.FRONT_FACE) - let currentCullFace = gl.getParameter(gl.CULL_FACE_MODE) - let currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK) - let currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK) - let currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE) + let currentFrontFace = gl.getParameter(gl.FRONT_FACE); + let currentCullFace = gl.getParameter(gl.CULL_FACE_MODE); + let currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK); + let currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK); + let currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); - let currentBlendSrcRGB = gl.getParameter(gl.BLEND_SRC_RGB) - let currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB) - let currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA) - let currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA) + let currentBlendSrcRGB = gl.getParameter(gl.BLEND_SRC_RGB); + let currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB); + let currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA); + let currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA); - let currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB) - let currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA) + let currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB); + let currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA); return { currentProgramId: -1, @@ -86,104 +86,104 @@ export function createState(gl: GLRenderingContext): WebGLState { enable: (cap: number) => { if (enabledCapabilities[cap] !== true ) { - gl.enable(cap) - enabledCapabilities[cap] = true + gl.enable(cap); + enabledCapabilities[cap] = true; } }, disable: (cap: number) => { if (enabledCapabilities[cap] !== false) { - gl.disable(cap) - enabledCapabilities[cap] = false + gl.disable(cap); + enabledCapabilities[cap] = false; } }, frontFace: (mode: number) => { if (mode !== currentFrontFace) { - gl.frontFace(mode) - currentFrontFace = mode + gl.frontFace(mode); + currentFrontFace = mode; } }, cullFace: (mode: number) => { if (mode !== currentCullFace) { - gl.cullFace(mode) - currentCullFace = mode + gl.cullFace(mode); + currentCullFace = mode; } }, depthMask: (flag: boolean) => { if (flag !== currentDepthMask) { - gl.depthMask(flag) - currentDepthMask = flag + gl.depthMask(flag); + currentDepthMask = flag; } }, colorMask: (red: boolean, green: boolean, blue: boolean, alpha: boolean) => { if (red !== currentColorMask[0] || green !== currentColorMask[1] || blue !== currentColorMask[2] || alpha !== currentColorMask[3]) { - gl.colorMask(red, green, blue, alpha) - currentColorMask[0] = red - currentColorMask[1] = green - currentColorMask[2] = blue - currentColorMask[3] = alpha + gl.colorMask(red, green, blue, alpha); + currentColorMask[0] = red; + currentColorMask[1] = green; + currentColorMask[2] = blue; + currentColorMask[3] = alpha; } }, clearColor: (red: number, green: number, blue: number, alpha: number) => { if (red !== currentClearColor[0] || green !== currentClearColor[1] || blue !== currentClearColor[2] || alpha !== currentClearColor[3]) { - gl.clearColor(red, green, blue, alpha) - currentClearColor[0] = red - currentClearColor[1] = green - currentClearColor[2] = blue - currentClearColor[3] = alpha + gl.clearColor(red, green, blue, alpha); + currentClearColor[0] = red; + currentClearColor[1] = green; + currentClearColor[2] = blue; + currentClearColor[3] = alpha; } }, blendFunc: (src: number, dst: number) => { if (src !== currentBlendSrcRGB || dst !== currentBlendDstRGB || src !== currentBlendSrcAlpha || dst !== currentBlendDstAlpha) { - gl.blendFunc(src, dst) - currentBlendSrcRGB = src - currentBlendDstRGB = dst - currentBlendSrcAlpha = src - currentBlendDstAlpha = dst + gl.blendFunc(src, dst); + currentBlendSrcRGB = src; + currentBlendDstRGB = dst; + currentBlendSrcAlpha = src; + currentBlendDstAlpha = dst; } }, blendFuncSeparate: (srcRGB: number, dstRGB: number, srcAlpha: number, dstAlpha: number) => { if (srcRGB !== currentBlendSrcRGB || dstRGB !== currentBlendDstRGB || srcAlpha !== currentBlendSrcAlpha || dstAlpha !== currentBlendDstAlpha) { - gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha) - currentBlendSrcRGB = srcRGB - currentBlendDstRGB = dstRGB - currentBlendSrcAlpha = srcAlpha - currentBlendDstAlpha = dstAlpha + gl.blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); + currentBlendSrcRGB = srcRGB; + currentBlendDstRGB = dstRGB; + currentBlendSrcAlpha = srcAlpha; + currentBlendDstAlpha = dstAlpha; } }, blendEquation: (mode: number) => { if (mode !== currentBlendEqRGB || mode !== currentBlendEqAlpha) { - gl.blendEquation(mode) - currentBlendEqRGB = mode - currentBlendEqAlpha = mode + gl.blendEquation(mode); + currentBlendEqRGB = mode; + currentBlendEqAlpha = mode; } }, blendEquationSeparate: (modeRGB: number, modeAlpha: number) => { if (modeRGB !== currentBlendEqRGB || modeAlpha !== currentBlendEqAlpha) { - gl.blendEquationSeparate(modeRGB, modeAlpha) - currentBlendEqRGB = modeRGB - currentBlendEqAlpha = modeAlpha + gl.blendEquationSeparate(modeRGB, modeAlpha); + currentBlendEqRGB = modeRGB; + currentBlendEqAlpha = modeAlpha; } }, reset: () => { - enabledCapabilities = {} + enabledCapabilities = {}; - currentFrontFace = gl.getParameter(gl.FRONT_FACE) - currentCullFace = gl.getParameter(gl.CULL_FACE_MODE) - currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK) - currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK) - currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE) + currentFrontFace = gl.getParameter(gl.FRONT_FACE); + currentCullFace = gl.getParameter(gl.CULL_FACE_MODE); + currentDepthMask = gl.getParameter(gl.DEPTH_WRITEMASK); + currentColorMask = gl.getParameter(gl.COLOR_WRITEMASK); + currentClearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); - currentBlendSrcRGB = gl.getParameter(gl.BLEND_SRC_RGB) - currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB) - currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA) - currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA) + currentBlendSrcRGB = gl.getParameter(gl.BLEND_SRC_RGB); + currentBlendDstRGB = gl.getParameter(gl.BLEND_DST_RGB); + currentBlendSrcAlpha = gl.getParameter(gl.BLEND_SRC_ALPHA); + currentBlendDstAlpha = gl.getParameter(gl.BLEND_DST_ALPHA); - currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB) - currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA) + currentBlendEqRGB = gl.getParameter(gl.BLEND_EQUATION_RGB); + currentBlendEqAlpha = gl.getParameter(gl.BLEND_EQUATION_ALPHA); } - } + }; } \ No newline at end of file diff --git a/src/mol-gl/webgl/texture.ts b/src/mol-gl/webgl/texture.ts index d09cff792c024de1d43cda1a5598011aa73560eb..4702362ed02e5a0b0a3a17c7727ca9962212512a 100644 --- a/src/mol-gl/webgl/texture.ts +++ b/src/mol-gl/webgl/texture.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { WebGLContext } from './context' +import { WebGLContext } from './context'; import { TextureImage, TextureVolume } from '../renderable/util'; import { ValueCell } from '../../mol-util'; import { RenderableSchema } from '../renderable/schema'; @@ -14,7 +14,7 @@ import { isWebGL2, GLRenderingContext } from './compat'; import { ValueOf } from '../../mol-util/type-helpers'; import { WebGLExtensions } from './extensions'; -const getNextTextureId = idFactory() +const getNextTextureId = idFactory(); export type TextureKindValue = { 'image-uint8': TextureImage<Uint8Array> @@ -34,27 +34,27 @@ export type TextureFilter = 'nearest' | 'linear' export function getTarget(gl: GLRenderingContext, kind: TextureKind): number { switch (kind) { - case 'image-uint8': return gl.TEXTURE_2D - case 'image-float32': return gl.TEXTURE_2D - case 'image-depth': return gl.TEXTURE_2D + case 'image-uint8': return gl.TEXTURE_2D; + case 'image-float32': return gl.TEXTURE_2D; + case 'image-depth': return gl.TEXTURE_2D; } if (isWebGL2(gl)) { switch (kind) { - case 'volume-uint8': return gl.TEXTURE_3D - case 'volume-float32': return gl.TEXTURE_3D + case 'volume-uint8': return gl.TEXTURE_3D; + case 'volume-float32': return gl.TEXTURE_3D; } } - throw new Error(`unknown texture kind '${kind}'`) + throw new Error(`unknown texture kind '${kind}'`); } export function getFormat(gl: GLRenderingContext, format: TextureFormat, type: TextureType): number { switch (format) { case 'alpha': - if (isWebGL2(gl) && type === 'float') return gl.RED - else return gl.ALPHA - case 'rgb': return gl.RGB - case 'rgba': return gl.RGBA - case 'depth': return gl.DEPTH_COMPONENT + if (isWebGL2(gl) && type === 'float') return gl.RED; + else return gl.ALPHA; + case 'rgb': return gl.RGB; + case 'rgba': return gl.RGBA; + case 'depth': return gl.DEPTH_COMPONENT; } } @@ -63,59 +63,59 @@ export function getInternalFormat(gl: GLRenderingContext, format: TextureFormat, switch (format) { case 'alpha': switch (type) { - case 'ubyte': return gl.ALPHA - case 'float': return gl.R32F + case 'ubyte': return gl.ALPHA; + case 'float': return gl.R32F; } case 'rgb': switch (type) { - case 'ubyte': return gl.RGB - case 'float': return gl.RGB32F + case 'ubyte': return gl.RGB; + case 'float': return gl.RGB32F; } case 'rgba': switch (type) { - case 'ubyte': return gl.RGBA - case 'float': return gl.RGBA32F + case 'ubyte': return gl.RGBA; + case 'float': return gl.RGBA32F; } case 'depth': - return gl.DEPTH_COMPONENT16 + return gl.DEPTH_COMPONENT16; } } - return getFormat(gl, format, type) + return getFormat(gl, format, type); } export function getType(gl: GLRenderingContext, type: TextureType): number { switch (type) { - case 'ubyte': return gl.UNSIGNED_BYTE - case 'ushort': return gl.UNSIGNED_SHORT - case 'float': return gl.FLOAT + case 'ubyte': return gl.UNSIGNED_BYTE; + case 'ushort': return gl.UNSIGNED_SHORT; + case 'float': return gl.FLOAT; } } export function getFilter(gl: GLRenderingContext, type: TextureFilter): number { switch (type) { - case 'nearest': return gl.NEAREST - case 'linear': return gl.LINEAR + case 'nearest': return gl.NEAREST; + case 'linear': return gl.LINEAR; } } export function getAttachment(gl: GLRenderingContext, extensions: WebGLExtensions, attachment: TextureAttachment): number { switch (attachment) { - case 'depth': return gl.DEPTH_ATTACHMENT - case 'stencil': return gl.STENCIL_ATTACHMENT - case 'color0': case 0: return gl.COLOR_ATTACHMENT0 + case 'depth': return gl.DEPTH_ATTACHMENT; + case 'stencil': return gl.STENCIL_ATTACHMENT; + case 'color0': case 0: return gl.COLOR_ATTACHMENT0; } if (extensions.drawBuffers) { switch (attachment) { - case 'color1': case 1: return extensions.drawBuffers.COLOR_ATTACHMENT1 - case 'color2': case 2: return extensions.drawBuffers.COLOR_ATTACHMENT2 - case 'color3': case 3: return extensions.drawBuffers.COLOR_ATTACHMENT3 - case 'color4': case 4: return extensions.drawBuffers.COLOR_ATTACHMENT4 - case 'color5': case 5: return extensions.drawBuffers.COLOR_ATTACHMENT5 - case 'color6': case 6: return extensions.drawBuffers.COLOR_ATTACHMENT6 - case 'color7': case 7: return extensions.drawBuffers.COLOR_ATTACHMENT7 + case 'color1': case 1: return extensions.drawBuffers.COLOR_ATTACHMENT1; + case 'color2': case 2: return extensions.drawBuffers.COLOR_ATTACHMENT2; + case 'color3': case 3: return extensions.drawBuffers.COLOR_ATTACHMENT3; + case 'color4': case 4: return extensions.drawBuffers.COLOR_ATTACHMENT4; + case 'color5': case 5: return extensions.drawBuffers.COLOR_ATTACHMENT5; + case 'color6': case 6: return extensions.drawBuffers.COLOR_ATTACHMENT6; + case 'color7': case 7: return extensions.drawBuffers.COLOR_ATTACHMENT7; } } - throw new Error('unknown texture attachment') + throw new Error('unknown texture attachment'); } export interface Texture { @@ -153,16 +153,16 @@ type FramebufferAttachment = { } function getTexture(gl: GLRenderingContext) { - const texture = gl.createTexture() + const texture = gl.createTexture(); if (texture === null) { - throw new Error('Could not create WebGL texture') + throw new Error('Could not create WebGL texture'); } - return texture + return texture; } // export type TextureProps = { kind: TextureKind, format: TextureFormat, type: TextureType, filter: TextureFilter } export function createTexture(gl: GLRenderingContext, extensions: WebGLExtensions, kind: TextureKind, _format: TextureFormat, _type: TextureType, _filter: TextureFilter): Texture { - const id = getNextTextureId() - let texture = getTexture(gl) + const id = getNextTextureId(); + let texture = getTexture(gl); // check texture kind and type compatability if ( @@ -170,79 +170,79 @@ export function createTexture(gl: GLRenderingContext, extensions: WebGLExtension (kind.endsWith('uint8') && _type !== 'ubyte') || (kind.endsWith('depth') && _type !== 'ushort') ) { - throw new Error(`texture kind '${kind}' and type '${_type}' are incompatible`) + throw new Error(`texture kind '${kind}' and type '${_type}' are incompatible`); } - const target = getTarget(gl, kind) - const filter = getFilter(gl, _filter) - const format = getFormat(gl, _format, _type) - const internalFormat = getInternalFormat(gl, _format, _type) - const type = getType(gl, _type) + const target = getTarget(gl, kind); + const filter = getFilter(gl, _filter); + const format = getFormat(gl, _format, _type); + const internalFormat = getInternalFormat(gl, _format, _type); + const type = getType(gl, _type); function init() { - gl.bindTexture(target, texture) - gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, filter) - gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, filter) + gl.bindTexture(target, texture); + gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, filter); + gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, filter); // clamp-to-edge needed for non-power-of-two textures in webgl gl.texParameteri(target, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(target, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - gl.bindTexture(target, null) + gl.bindTexture(target, null); } - init() + init(); - let fba: undefined | FramebufferAttachment = undefined + let fba: undefined | FramebufferAttachment = undefined; - let width = 0, height = 0, depth = 0 - let loadedData: undefined | TextureImage<any> | TextureVolume<any> - let destroyed = false + let width = 0, height = 0, depth = 0; + let loadedData: undefined | TextureImage<any> | TextureVolume<any>; + let destroyed = false; function define(_width: number, _height: number, _depth?: number) { - width = _width, height = _height, depth = _depth || 0 - gl.bindTexture(target, texture) + width = _width, height = _height, depth = _depth || 0; + gl.bindTexture(target, texture); if (target === gl.TEXTURE_2D) { - gl.texImage2D(target, 0, internalFormat, width, height, 0, format, type, null) + gl.texImage2D(target, 0, internalFormat, width, height, 0, format, type, null); } else if (isWebGL2(gl) && target === gl.TEXTURE_3D && depth !== undefined) { - gl.texImage3D(target, 0, internalFormat, width, height, depth, 0, format, type, null) + gl.texImage3D(target, 0, internalFormat, width, height, depth, 0, format, type, null); } else { - throw new Error('unknown texture target') + throw new Error('unknown texture target'); } } function load(data: TextureImage<any> | TextureVolume<any>) { - gl.bindTexture(target, texture) + gl.bindTexture(target, texture); // unpack alignment of 1 since we use textures only for data gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 0); if (target === gl.TEXTURE_2D) { - const { array, width: _width, height: _height } = data as TextureImage<any> + const { array, width: _width, height: _height } = data as TextureImage<any>; width = _width, height = _height; - gl.texImage2D(target, 0, internalFormat, width, height, 0, format, type, array) + gl.texImage2D(target, 0, internalFormat, width, height, 0, format, type, array); } else if (isWebGL2(gl) && target === gl.TEXTURE_3D) { - const { array, width: _width, height: _height, depth: _depth } = data as TextureVolume<any> - width = _width, height = _height, depth = _depth - gl.texImage3D(target, 0, internalFormat, width, height, depth, 0, format, type, array) + const { array, width: _width, height: _height, depth: _depth } = data as TextureVolume<any>; + width = _width, height = _height, depth = _depth; + gl.texImage3D(target, 0, internalFormat, width, height, depth, 0, format, type, array); } else { - throw new Error('unknown texture target') + throw new Error('unknown texture target'); } - gl.bindTexture(target, null) - loadedData = data + gl.bindTexture(target, null); + loadedData = data; } function attachFramebuffer(framebuffer: Framebuffer, attachment: TextureAttachment, layer?: number) { if (fba && fba.framebuffer === framebuffer && fba.attachment === attachment && fba.layer === layer) { - return + return; } - framebuffer.bind() + framebuffer.bind(); if (target === gl.TEXTURE_2D) { - gl.framebufferTexture2D(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), gl.TEXTURE_2D, texture, 0) + gl.framebufferTexture2D(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), gl.TEXTURE_2D, texture, 0); } else if (isWebGL2(gl) && target === gl.TEXTURE_3D) { - if (layer === undefined) throw new Error('need `layer` to attach 3D texture') - gl.framebufferTextureLayer(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), texture, 0, layer) + if (layer === undefined) throw new Error('need `layer` to attach 3D texture'); + gl.framebufferTextureLayer(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), texture, 0, layer); } else { - throw new Error('unknown texture target') + throw new Error('unknown texture target'); } - fba = { framebuffer, attachment, layer } + fba = { framebuffer, attachment, layer }; } return { @@ -259,63 +259,63 @@ export function createTexture(gl: GLRenderingContext, extensions: WebGLExtension define, load, bind: (id: TextureId) => { - gl.activeTexture(gl.TEXTURE0 + id) - gl.bindTexture(target, texture) + gl.activeTexture(gl.TEXTURE0 + id); + gl.bindTexture(target, texture); }, unbind: (id: TextureId) => { - gl.activeTexture(gl.TEXTURE0 + id) - gl.bindTexture(target, null) + gl.activeTexture(gl.TEXTURE0 + id); + gl.bindTexture(target, null); }, attachFramebuffer, detachFramebuffer: (framebuffer: Framebuffer, attachment: TextureAttachment) => { - framebuffer.bind() + framebuffer.bind(); if (target === gl.TEXTURE_2D) { - gl.framebufferTexture2D(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), gl.TEXTURE_2D, null, 0) + gl.framebufferTexture2D(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), gl.TEXTURE_2D, null, 0); } else if (isWebGL2(gl) && target === gl.TEXTURE_3D) { - gl.framebufferTextureLayer(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), null, 0, 0) + gl.framebufferTextureLayer(gl.FRAMEBUFFER, getAttachment(gl, extensions, attachment), null, 0, 0); } else { - throw new Error('unknown texture target') + throw new Error('unknown texture target'); } - fba = undefined + fba = undefined; }, reset: () => { - texture = getTexture(gl) - init() + texture = getTexture(gl); + init(); if (loadedData) { - load(loadedData) + load(loadedData); } else { - define(width, height, depth) + define(width, height, depth); } if (fba) { // TODO unclear why calling `attachFramebuffer` here does not work reliably after context loss // e.g. it still needs to be called in `DrawPass` to work - fba = undefined + fba = undefined; } }, destroy: () => { - if (destroyed) return - gl.deleteTexture(texture) - destroyed = true + if (destroyed) return; + gl.deleteTexture(texture); + destroyed = true; } - } + }; } export function createTextures(ctx: WebGLContext, schema: RenderableSchema, values: TextureValues) { - const { resources } = ctx - const textures: Textures = [] + const { resources } = ctx; + const textures: Textures = []; Object.keys(schema).forEach(k => { - const spec = schema[k] + const spec = schema[k]; if (spec.type === 'texture') { if (spec.kind === 'texture') { - textures[textures.length] = [k, values[k].ref.value as Texture] + textures[textures.length] = [k, values[k].ref.value as Texture]; } else { - const texture = resources.texture(spec.kind, spec.format, spec.dataType, spec.filter) - texture.load(values[k].ref.value as TextureImage<any> | TextureVolume<any>) - textures[textures.length] = [k, texture] + const texture = resources.texture(spec.kind, spec.format, spec.dataType, spec.filter); + texture.load(values[k].ref.value as TextureImage<any> | TextureVolume<any>); + textures[textures.length] = [k, texture]; } } - }) - return textures + }); + return textures; } \ No newline at end of file diff --git a/src/mol-gl/webgl/uniform.ts b/src/mol-gl/webgl/uniform.ts index 136c54c3200edd7244cd4ee18cb3066fb09f0a6f..8fa7d51e09606660f6a37f7fa6b2bf516dfd79a0 100644 --- a/src/mol-gl/webgl/uniform.ts +++ b/src/mol-gl/webgl/uniform.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Mat3, Mat4, Vec2, Vec3, Vec4 } from '../../mol-math/linear-algebra' +import { Mat3, Mat4, Vec2, Vec3, Vec4 } from '../../mol-math/linear-algebra'; import { ValueCell } from '../../mol-util'; import { GLRenderingContext } from './compat'; import { RenderableSchema } from '../../mol-gl/renderable/schema'; @@ -27,63 +27,63 @@ export type UniformsList = [string, ValueCell<UniformType>][] export function getUniformType(gl: GLRenderingContext, kind: UniformKind) { switch (kind) { - case 'f': return gl.FLOAT - case 'i': return gl.INT - case 'v2': return gl.FLOAT_VEC2 - case 'v3': return gl.FLOAT_VEC3 - case 'v4': return gl.FLOAT_VEC4 - case 'm3': return gl.FLOAT_MAT3 - case 'm4': return gl.FLOAT_MAT4 - default: console.error(`unknown uniform kind '${kind}'`) + case 'f': return gl.FLOAT; + case 'i': return gl.INT; + case 'v2': return gl.FLOAT_VEC2; + case 'v3': return gl.FLOAT_VEC3; + case 'v4': return gl.FLOAT_VEC4; + case 'm3': return gl.FLOAT_MAT3; + case 'm4': return gl.FLOAT_MAT4; + default: console.error(`unknown uniform kind '${kind}'`); } } export function setUniform(gl: GLRenderingContext, location: WebGLUniformLocation | null, kind: UniformKind, value: any) { switch (kind) { - case 'f': gl.uniform1f(location, value); break - case 'i': case 't': gl.uniform1i(location, value); break - case 'v2': gl.uniform2fv(location, value); break - case 'v3': gl.uniform3fv(location, value); break - case 'v4': gl.uniform4fv(location, value); break - case 'm3': gl.uniformMatrix3fv(location, false, value); break - case 'm4': gl.uniformMatrix4fv(location, false, value); break - default: console.error(`unknown uniform kind '${kind}'`) + case 'f': gl.uniform1f(location, value); break; + case 'i': case 't': gl.uniform1i(location, value); break; + case 'v2': gl.uniform2fv(location, value); break; + case 'v3': gl.uniform3fv(location, value); break; + case 'v4': gl.uniform4fv(location, value); break; + case 'm3': gl.uniformMatrix3fv(location, false, value); break; + case 'm4': gl.uniformMatrix4fv(location, false, value); break; + default: console.error(`unknown uniform kind '${kind}'`); } } export type UniformSetter = (gl: GLRenderingContext, location: number, value: any) => void export type UniformSetters = { [k: string]: UniformSetter } -function uniform1f (gl: GLRenderingContext, location: number, value: any) { gl.uniform1f(location, value) } -function uniform1i (gl: GLRenderingContext, location: number, value: any) { gl.uniform1i(location, value) } -function uniform2fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform2fv(location, value) } -function uniform3fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform3fv(location, value) } -function uniform4fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform4fv(location, value) } -function uniformMatrix3fv (gl: GLRenderingContext, location: number, value: any) { gl.uniformMatrix3fv(location, false, value) } -function uniformMatrix4fv (gl: GLRenderingContext, location: number, value: any) { gl.uniformMatrix4fv(location, false, value) } +function uniform1f (gl: GLRenderingContext, location: number, value: any) { gl.uniform1f(location, value); } +function uniform1i (gl: GLRenderingContext, location: number, value: any) { gl.uniform1i(location, value); } +function uniform2fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform2fv(location, value); } +function uniform3fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform3fv(location, value); } +function uniform4fv (gl: GLRenderingContext, location: number, value: any) { gl.uniform4fv(location, value); } +function uniformMatrix3fv (gl: GLRenderingContext, location: number, value: any) { gl.uniformMatrix3fv(location, false, value); } +function uniformMatrix4fv (gl: GLRenderingContext, location: number, value: any) { gl.uniformMatrix4fv(location, false, value); } function getUniformSetter(kind: UniformKind) { switch (kind) { - case 'f': return uniform1f - case 'i': case 't': return uniform1i - case 'v2': return uniform2fv - case 'v3': return uniform3fv - case 'v4': return uniform4fv - case 'm3': return uniformMatrix3fv - case 'm4': return uniformMatrix4fv + case 'f': return uniform1f; + case 'i': case 't': return uniform1i; + case 'v2': return uniform2fv; + case 'v3': return uniform3fv; + case 'v4': return uniform4fv; + case 'm3': return uniformMatrix3fv; + case 'm4': return uniformMatrix4fv; } - throw new Error(`unknown uniform kind '${kind}'`) + throw new Error(`unknown uniform kind '${kind}'`); } export function getUniformSetters(schema: RenderableSchema) { - const setters: UniformSetters = {} + const setters: UniformSetters = {}; Object.keys(schema).forEach(k => { - const spec = schema[k] + const spec = schema[k]; if (spec.type === 'uniform') { - setters[k] = getUniformSetter(spec.kind as UniformKind) + setters[k] = getUniformSetter(spec.kind as UniformKind); } else if (spec.type === 'texture') { - setters[k] = getUniformSetter('t') + setters[k] = getUniformSetter('t'); } - }) - return setters + }); + return setters; } \ No newline at end of file diff --git a/src/mol-gl/webgl/vertex-array.ts b/src/mol-gl/webgl/vertex-array.ts index 7f12703e21b220e7c92147c462932a666b0dbc39..fda7c96e0b965679ab4d95e3d1c49079d58144d0 100644 --- a/src/mol-gl/webgl/vertex-array.ts +++ b/src/mol-gl/webgl/vertex-array.ts @@ -9,26 +9,26 @@ import { ElementsBuffer, AttributeBuffers } from './buffer'; import { WebGLExtensions } from './extensions'; import { idFactory } from '../../mol-util/id-factory'; -const getNextVertexArrayId = idFactory() +const getNextVertexArrayId = idFactory(); function getVertexArray(extensions: WebGLExtensions): WebGLVertexArrayObject { - const { vertexArrayObject } = extensions + const { vertexArrayObject } = extensions; if (!vertexArrayObject) { - throw new Error('VertexArrayObject not supported') + throw new Error('VertexArrayObject not supported'); } - const vertexArray = vertexArrayObject.createVertexArray() + const vertexArray = vertexArrayObject.createVertexArray(); if (!vertexArray) { - throw new Error('Could not create WebGL vertex array') + throw new Error('Could not create WebGL vertex array'); } - return vertexArray + return vertexArray; } function getVertexArrayObject(extensions: WebGLExtensions) { - const { vertexArrayObject } = extensions + const { vertexArrayObject } = extensions; if (vertexArrayObject === null) { - throw new Error('VertexArrayObject not supported') + throw new Error('VertexArrayObject not supported'); } - return vertexArrayObject + return vertexArrayObject; } export interface VertexArray { @@ -41,35 +41,35 @@ export interface VertexArray { } export function createVertexArray(extensions: WebGLExtensions, program: Program, attributeBuffers: AttributeBuffers, elementsBuffer?: ElementsBuffer): VertexArray { - const id = getNextVertexArrayId() - let vertexArray = getVertexArray(extensions) - let vertexArrayObject = getVertexArrayObject(extensions) + const id = getNextVertexArrayId(); + let vertexArray = getVertexArray(extensions); + let vertexArrayObject = getVertexArrayObject(extensions); function update() { - vertexArrayObject.bindVertexArray(vertexArray) - if (elementsBuffer) elementsBuffer.bind() - program.bindAttributes(attributeBuffers) - vertexArrayObject.bindVertexArray(null) + vertexArrayObject.bindVertexArray(vertexArray); + if (elementsBuffer) elementsBuffer.bind(); + program.bindAttributes(attributeBuffers); + vertexArrayObject.bindVertexArray(null); } - update() - let destroyed = false + update(); + let destroyed = false; return { id, bind: () => { - vertexArrayObject.bindVertexArray(vertexArray) + vertexArrayObject.bindVertexArray(vertexArray); }, update, reset: () => { - vertexArray = getVertexArray(extensions) - vertexArrayObject = getVertexArrayObject(extensions) - update() + vertexArray = getVertexArray(extensions); + vertexArrayObject = getVertexArrayObject(extensions); + update(); }, destroy: () => { - if (destroyed) return - vertexArrayObject.deleteVertexArray(vertexArray) - destroyed = true + if (destroyed) return; + vertexArrayObject.deleteVertexArray(vertexArray); + destroyed = true; } - } + }; } \ No newline at end of file diff --git a/src/mol-io/common/binary-cif.ts b/src/mol-io/common/binary-cif.ts index 37d43e536be58a278b4fcad798bc5d26e66b530b..6ee46cbf154c270d43d72b41a337c8d913756215 100644 --- a/src/mol-io/common/binary-cif.ts +++ b/src/mol-io/common/binary-cif.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import decode from './binary-cif/decoder' +import decode from './binary-cif/decoder'; -export * from './binary-cif/encoding' -export * from './binary-cif/array-encoder' -export * from './binary-cif/classifier' -export { decode } \ No newline at end of file +export * from './binary-cif/encoding'; +export * from './binary-cif/array-encoder'; +export * from './binary-cif/classifier'; +export { decode }; \ No newline at end of file diff --git a/src/mol-io/common/binary-cif/array-encoder.ts b/src/mol-io/common/binary-cif/array-encoder.ts index 60affaf1efd0ff2a79a9a2152b04aee7fc6ecb0c..08dfee8f6d315a0c995cdc0939f7d76648714365 100644 --- a/src/mol-io/common/binary-cif/array-encoder.ts +++ b/src/mol-io/common/binary-cif/array-encoder.ts @@ -7,8 +7,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ChunkedArray } from '../../../mol-data/util' -import { Encoding, EncodedData } from './encoding' +import { ChunkedArray } from '../../../mol-data/util'; +import { Encoding, EncodedData } from './encoding'; import { classifyIntArray } from './classifier'; import { TypedIntArray, TypedFloatArray } from '../../../mol-util/type-helpers'; @@ -42,7 +42,7 @@ export class ArrayEncoderImpl implements ArrayEncoder { return { encoding, data - } + }; } constructor(private providers: ArrayEncoding.Provider[]) { @@ -103,13 +103,13 @@ export namespace ArrayEncoding { } const writers = { - [Encoding.IntDataType.Int16]: function (v: DataView, i: number, a: number) { v.setInt16(2 * i, a, true) }, - [Encoding.IntDataType.Uint16]: function (v: DataView, i: number, a: number) { v.setUint16(2 * i, a, true) }, - [Encoding.IntDataType.Int32]: function (v: DataView, i: number, a: number) { v.setInt32(4 * i, a, true) }, - [Encoding.IntDataType.Uint32]: function (v: DataView, i: number, a: number) { v.setUint32(4 * i, a, true) }, - [Encoding.FloatDataType.Float32]: function (v: DataView, i: number, a: number) { v.setFloat32(4 * i, a, true) }, - [Encoding.FloatDataType.Float64]: function (v: DataView, i: number, a: number) { v.setFloat64(8 * i, a, true) } - } + [Encoding.IntDataType.Int16]: function (v: DataView, i: number, a: number) { v.setInt16(2 * i, a, true); }, + [Encoding.IntDataType.Uint16]: function (v: DataView, i: number, a: number) { v.setUint16(2 * i, a, true); }, + [Encoding.IntDataType.Int32]: function (v: DataView, i: number, a: number) { v.setInt32(4 * i, a, true); }, + [Encoding.IntDataType.Uint32]: function (v: DataView, i: number, a: number) { v.setUint32(4 * i, a, true); }, + [Encoding.FloatDataType.Float32]: function (v: DataView, i: number, a: number) { v.setFloat32(4 * i, a, true); }, + [Encoding.FloatDataType.Float64]: function (v: DataView, i: number, a: number) { v.setFloat64(8 * i, a, true); } + }; const byteSizes = { [Encoding.IntDataType.Int16]: 2, @@ -118,7 +118,7 @@ export namespace ArrayEncoding { [Encoding.IntDataType.Uint32]: 4, [Encoding.FloatDataType.Float32]: 4, [Encoding.FloatDataType.Float64]: 8 - } + }; export function byteArray(data: TypedFloatArray | TypedIntArray) { const type = Encoding.getDataType(data); @@ -300,14 +300,14 @@ export namespace ArrayEncoding { isSigned: signed, size: size16, bytesPerElement: 2 - } + }; } else { // 1 byte packing is the most effective return { isSigned: signed, size: size8, bytesPerElement: 1 - } + }; }; } diff --git a/src/mol-io/common/binary-cif/classifier.ts b/src/mol-io/common/binary-cif/classifier.ts index 2ffcd21b741324227f222288c90e4963033cf43a..2c94fbc896d121c463560755c9b39b5a0cfc7887 100644 --- a/src/mol-io/common/binary-cif/classifier.ts +++ b/src/mol-io/common/binary-cif/classifier.ts @@ -37,7 +37,7 @@ namespace IntClassifier { } type SizeInfo = { pack8: number, pack16: number, count: number } - function SizeInfo(): SizeInfo { return { pack8: 0, pack16: 0, count: 0 } }; + function SizeInfo(): SizeInfo { return { pack8: 0, pack16: 0, count: 0 }; }; function incSize({ limit8, limit16 }: IntColumnInfo, info: SizeInfo, value: number) { info.pack8 += packSize(value, limit8); diff --git a/src/mol-io/common/binary-cif/decoder.ts b/src/mol-io/common/binary-cif/decoder.ts index 21845329952d64bad0fff4c2f8a72e65a4401fac..539bdcebad864af2d222959f963d0686ab3b0f0e 100644 --- a/src/mol-io/common/binary-cif/decoder.ts +++ b/src/mol-io/common/binary-cif/decoder.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Encoding, EncodedData } from './encoding' +import { Encoding, EncodedData } from './encoding'; import { IsNativeEndianLittle, flipByteOrder } from '../binary'; /** @@ -33,7 +33,7 @@ function decodeStep(data: any, encoding: Encoding): any { case Encoding.IntDataType.Uint32: return uint32(data); case Encoding.FloatDataType.Float32: return float32(data); case Encoding.FloatDataType.Float64: return float64(data); - default: throw new Error('Unsupported ByteArray type.') + default: throw new Error('Unsupported ByteArray type.'); } } case 'FixedPoint': return fixedPoint(data, encoding); @@ -92,7 +92,7 @@ function fixedPoint(data: Int32Array, encoding: Encoding.FixedPoint) { function intervalQuantization(data: Int32Array, encoding: Encoding.IntervalQuantization) { let n = data.length; let output = getFloatArray(encoding.srcType, n); - let delta = (encoding.max - encoding.min) / (encoding.numSteps - 1) + let delta = (encoding.max - encoding.min) / (encoding.numSteps - 1); let min = encoding.min; for (let i = 0; i < n; i++) { output[i] = min + delta * data[i]; diff --git a/src/mol-io/common/binary.ts b/src/mol-io/common/binary.ts index cd60acbab1cb875bbc2cea17870123a97958138d..ef50b7fc5c1d8c14bf11619fb65c92bba492a23d 100644 --- a/src/mol-io/common/binary.ts +++ b/src/mol-io/common/binary.ts @@ -18,15 +18,15 @@ export function flipByteOrder(data: Uint8Array, bytes: number) { return buffer; } -const ChunkSize = 0x7000 +const ChunkSize = 0x7000; export function uint8ToString(array: Uint8Array) { if (array.length > ChunkSize) { - const c = [] + const c = []; for (let i = 0; i < array.length; i += ChunkSize) { - c.push(String.fromCharCode.apply(null, array.subarray(i, i + ChunkSize))) + c.push(String.fromCharCode.apply(null, array.subarray(i, i + ChunkSize))); } - return c.join('') + return c.join(''); } else { - return String.fromCharCode.apply(null, array) + return String.fromCharCode.apply(null, array); } } \ No newline at end of file diff --git a/src/mol-io/common/file-handle.ts b/src/mol-io/common/file-handle.ts index cc2470e1f0a2dedd4918d678e9bc931eab241092..e0c6e81f85e035740a2f8614434e3495b9f810c0 100644 --- a/src/mol-io/common/file-handle.ts +++ b/src/mol-io/common/file-handle.ts @@ -47,55 +47,55 @@ export namespace FileHandle { export function fromBuffer(buffer: SimpleBuffer): FileHandle { return { readBuffer: (position: number, sizeOrBuffer: SimpleBuffer | number, size?: number, byteOffset?: number) => { - let bytesRead: number - let outBuffer: SimpleBuffer + let bytesRead: number; + let outBuffer: SimpleBuffer; if (typeof sizeOrBuffer === 'number') { - size = defaults(size, sizeOrBuffer) - const start = position - const end = Math.min(buffer.length, start + size) - bytesRead = end - start - outBuffer = SimpleBuffer.fromUint8Array(new Uint8Array(buffer.buffer, start, end - start)) + size = defaults(size, sizeOrBuffer); + const start = position; + const end = Math.min(buffer.length, start + size); + bytesRead = end - start; + outBuffer = SimpleBuffer.fromUint8Array(new Uint8Array(buffer.buffer, start, end - start)); } else { - size = defaults(size, sizeOrBuffer.length) - const start = position - const end = Math.min(buffer.length, start + size) - sizeOrBuffer.set(buffer.subarray(start, end), byteOffset) - bytesRead = end - start - outBuffer = sizeOrBuffer + size = defaults(size, sizeOrBuffer.length); + const start = position; + const end = Math.min(buffer.length, start + size); + sizeOrBuffer.set(buffer.subarray(start, end), byteOffset); + bytesRead = end - start; + outBuffer = sizeOrBuffer; } if (size !== bytesRead) { - console.warn(`byteCount ${size} and bytesRead ${bytesRead} differ`) + console.warn(`byteCount ${size} and bytesRead ${bytesRead} differ`); } - return Promise.resolve({ bytesRead, buffer: outBuffer }) + return Promise.resolve({ bytesRead, buffer: outBuffer }); }, writeBuffer: (position: number, buffer: SimpleBuffer, length?: number) => { - length = defaults(length, buffer.length) - console.error('.writeBuffer not implemented for FileHandle.fromBuffer') - return Promise.resolve(0) + length = defaults(length, buffer.length); + console.error('.writeBuffer not implemented for FileHandle.fromBuffer'); + return Promise.resolve(0); }, writeBufferSync: (position: number, buffer: SimpleBuffer, length?: number, ) => { - length = defaults(length, buffer.length) - console.error('.writeSync not implemented for FileHandle.fromBuffer') - return 0 + length = defaults(length, buffer.length); + console.error('.writeSync not implemented for FileHandle.fromBuffer'); + return 0; }, close: noop - } + }; } export function fromDescriptor(file: number): FileHandle { - if (fs === undefined) throw new Error('fs module not available') + if (fs === undefined) throw new Error('fs module not available'); return { readBuffer: (position: number, sizeOrBuffer: SimpleBuffer | number, length?: number, byteOffset?: number) => { return new Promise((res, rej) => { - let outBuffer: SimpleBuffer + let outBuffer: SimpleBuffer; if (typeof sizeOrBuffer === 'number') { - byteOffset = defaults(byteOffset, 0) - length = defaults(length, sizeOrBuffer) + byteOffset = defaults(byteOffset, 0); + length = defaults(length, sizeOrBuffer); outBuffer = SimpleBuffer.fromArrayBuffer(new ArrayBuffer(sizeOrBuffer)); } else { - byteOffset = defaults(byteOffset, 0) - length = defaults(length, sizeOrBuffer.length) - outBuffer = sizeOrBuffer + byteOffset = defaults(byteOffset, 0); + length = defaults(length, sizeOrBuffer.length); + outBuffer = sizeOrBuffer; } fs.read(file, outBuffer, byteOffset, length, position, (err, bytesRead, buffer) => { if (err) { @@ -103,23 +103,23 @@ export namespace FileHandle { return; } if (length !== bytesRead) { - console.warn(`byteCount ${length} and bytesRead ${bytesRead} differ`) + console.warn(`byteCount ${length} and bytesRead ${bytesRead} differ`); } res({ bytesRead, buffer }); }); - }) + }); }, writeBuffer: (position: number, buffer: SimpleBuffer, length?: number) => { - length = defaults(length, buffer.length) + length = defaults(length, buffer.length); return new Promise<number>((res, rej) => { fs.write(file, buffer, 0, length, position, (err, written) => { if (err) rej(err); else res(written); - }) - }) + }); + }); }, writeBufferSync: (position: number, buffer: Uint8Array, length?: number) => { - length = defaults(length, buffer.length) + length = defaults(length, buffer.length); return fs.writeSync(file, buffer, 0, length, position); }, close: () => { @@ -129,6 +129,6 @@ export namespace FileHandle { } } - } + }; } } \ No newline at end of file diff --git a/src/mol-io/common/msgpack/decode.ts b/src/mol-io/common/msgpack/decode.ts index 9d6e1aa85b11443612730d43383879e063e3c4af..ba7faba5d7218c5dfb048fb31a41b70b289058e8 100644 --- a/src/mol-io/common/msgpack/decode.ts +++ b/src/mol-io/common/msgpack/decode.ts @@ -6,7 +6,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { utf8Read } from '../utf8' +import { utf8Read } from '../utf8'; export default function decode(buffer: Uint8Array) { return parse({ buffer, offset: 0, dataView: new DataView(buffer.buffer) }); diff --git a/src/mol-io/common/msgpack/encode.ts b/src/mol-io/common/msgpack/encode.ts index 9fa997674258233b3d1b089c4469fcc179e8f6ef..d8915da8d16390a7ea2040d964d7f8c202e3f8cb 100644 --- a/src/mol-io/common/msgpack/encode.ts +++ b/src/mol-io/common/msgpack/encode.ts @@ -6,7 +6,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { utf8ByteCount, utf8Write } from '../utf8' +import { utf8ByteCount, utf8Write } from '../utf8'; export default function encode(value: any) { const buffer = new ArrayBuffer(encodedSize(value)); diff --git a/src/mol-io/common/simple-buffer.ts b/src/mol-io/common/simple-buffer.ts index b5666a0c630a30b707995b87d4a5dc69470d8b23..e6a8a79b62ffa1afc873da42af835a13291bd41c 100644 --- a/src/mol-io/common/simple-buffer.ts +++ b/src/mol-io/common/simple-buffer.ts @@ -47,7 +47,7 @@ export interface SimpleBuffer extends Uint8Array { export namespace SimpleBuffer { export function fromUint8Array(array: Uint8Array): SimpleBuffer { - const dv = new DataView(array.buffer) + const dv = new DataView(array.buffer); return Object.assign(array.subarray(0), { readInt8: (offset: number) => dv.getInt8(offset), readUInt8: (offset: number) => dv.getUint8(offset), @@ -83,21 +83,21 @@ export namespace SimpleBuffer { writeDoubleBE: (value: number, offset: number) => dv.setFloat64(offset, value, false), copy: (targetBuffer: Uint8Array, targetStart?: number, sourceStart?: number, sourceEnd?: number) => { - targetStart = defaults(targetStart, 0) - sourceStart = defaults(sourceStart, 0) - sourceEnd = defaults(sourceEnd, array.length) - targetBuffer.set(array.subarray(sourceStart, sourceEnd), targetStart) - return sourceEnd - sourceStart + targetStart = defaults(targetStart, 0); + sourceStart = defaults(sourceStart, 0); + sourceEnd = defaults(sourceEnd, array.length); + targetBuffer.set(array.subarray(sourceStart, sourceEnd), targetStart); + return sourceEnd - sourceStart; } - }) + }); } export function fromArrayBuffer(arrayBuffer: ArrayBuffer): SimpleBuffer { - return fromUint8Array(new Uint8Array(arrayBuffer)) + return fromUint8Array(new Uint8Array(arrayBuffer)); } export function fromBuffer(buffer: Buffer): SimpleBuffer { - return buffer + return buffer; } export const IsNativeEndianLittle = new Uint16Array(new Uint8Array([0x12, 0x34]).buffer)[0] === 0x3412; @@ -112,10 +112,10 @@ export namespace SimpleBuffer { } export function flipByteOrderInPlace2(buffer: ArrayBuffer, byteOffset = 0, length?: number) { - const intView = new Int16Array(buffer, byteOffset, length) + const intView = new Int16Array(buffer, byteOffset, length); for (let i = 0, n = intView.length; i < n; ++i) { - const val = intView[i] - intView[i] = ((val & 0xff) << 8) | ((val >> 8) & 0xff) + const val = intView[i]; + intView[i] = ((val & 0xff) << 8) | ((val >> 8) & 0xff); } } diff --git a/src/mol-io/common/utf8.ts b/src/mol-io/common/utf8.ts index 706fe90db5492faf6f8980958504c5a5aa29ae15..660f08ce9be6f03520da65b82d7542978fd3393c 100644 --- a/src/mol-io/common/utf8.ts +++ b/src/mol-io/common/utf8.ts @@ -95,13 +95,13 @@ function _utf8Read(data: Uint8Array, offset: number, length: number) { return str.join(''); } -const utf8Decoder = (typeof TextDecoder !== 'undefined') ? new TextDecoder() : undefined +const utf8Decoder = (typeof TextDecoder !== 'undefined') ? new TextDecoder() : undefined; export function utf8Read(data: Uint8Array, offset: number, length: number) { if (utf8Decoder) { - const input = (offset || length !== data.length) ? data.subarray(offset, offset + length) : data - return utf8Decoder.decode(input) + const input = (offset || length !== data.length) ? data.subarray(offset, offset + length) : data; + return utf8Decoder.decode(input); } else { - return _utf8Read(data, offset, length) + return _utf8Read(data, offset, length); } } diff --git a/src/mol-io/reader/3dg/parser.ts b/src/mol-io/reader/3dg/parser.ts index bc632a7144b305c656153c6c3202a731e0e46eea..1fc7b6a36b2aa1eb428a38015fcab3f48ad723ce 100644 --- a/src/mol-io/reader/3dg/parser.ts +++ b/src/mol-io/reader/3dg/parser.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ReaderResult as Result } from '../result' -import { Task } from '../../../mol-task' +import { ReaderResult as Result } from '../result'; +import { Task } from '../../../mol-task'; import { parseCsv } from '../csv/parser'; import { Column, Table } from '../../../mol-data/db'; import { toTable } from '../cif/schema'; @@ -25,14 +25,14 @@ export const Schema3DG = { y: Schema.float, /** Z coordinate */ z: Schema.float, -} +}; export type Schema3DG = typeof Schema3DG export interface File3DG { table: Table<Schema3DG> } -const FieldNames = [ 'chromosome', 'position', 'x', 'y', 'z' ] +const FieldNames = [ 'chromosome', 'position', 'x', 'y', 'z' ]; function categoryFromTable(name: string, table: CsvTable) { return { @@ -40,18 +40,18 @@ function categoryFromTable(name: string, table: CsvTable) { rowCount: table.rowCount, fieldNames: FieldNames, getField: (name: string) => { - return table.getColumn(FieldNames.indexOf(name).toString()) + return table.getColumn(FieldNames.indexOf(name).toString()); } - } + }; } export function parse3DG(data: string) { return Task.create<Result<File3DG>>('Parse 3DG', async ctx => { - const opts = { quote: '', comment: '#', delimiter: '\t', noColumnNames: true } - const csvFile = await parseCsv(data, opts).runInContext(ctx) - if (csvFile.isError) return Result.error(csvFile.message, csvFile.line) - const category = categoryFromTable('3dg', csvFile.result.table) - const table = toTable(Schema3DG, category) - return Result.success({ table }) + const opts = { quote: '', comment: '#', delimiter: '\t', noColumnNames: true }; + const csvFile = await parseCsv(data, opts).runInContext(ctx); + if (csvFile.isError) return Result.error(csvFile.message, csvFile.line); + const category = categoryFromTable('3dg', csvFile.result.table); + const table = toTable(Schema3DG, category); + return Result.success({ table }); }); } \ No newline at end of file diff --git a/src/mol-io/reader/_spec/3dg.spec.ts b/src/mol-io/reader/_spec/3dg.spec.ts index 2a44987e991f93f462358c4d924d9d14b2307cad..25f4dd4d6bd72261d34f018bdf53c8de8ff9773a 100644 --- a/src/mol-io/reader/_spec/3dg.spec.ts +++ b/src/mol-io/reader/_spec/3dg.spec.ts @@ -15,19 +15,19 @@ const basic3dgString = `1(mat) 1420000 0.791377837067 10.9947291355 -13.18828976 1(mat) 1540000 -0.458643807046 12.5985791771 -13.4701149287 1(mat) 1560000 -0.810322906201 12.2461643989 -12.3172933413 1(mat) 1580000 -2.08211172035 12.8886838656 -12.8742007778 -1(mat) 1600000 -3.52093948201 13.1850935438 -12.4118684428` +1(mat) 1600000 -3.52093948201 13.1850935438 -12.4118684428`; describe('3dg reader', () => { it('basic', async () => { const parsed = await parse3DG(basic3dgString).run(); - expect(parsed.isError).toBe(false) + expect(parsed.isError).toBe(false); if (parsed.isError) return; const { chromosome, position, x, y, z } = parsed.result.table; - expect(chromosome.value(0)).toBe('1(mat)') - expect(position.value(1)).toBe(1440000) - expect(x.value(5)).toBe(-0.0848245107875) - expect(y.value(5)).toBe(12.2624690808) - expect(z.value(5)).toBe(-14.354289628) + expect(chromosome.value(0)).toBe('1(mat)'); + expect(position.value(1)).toBe(1440000); + expect(x.value(5)).toBe(-0.0848245107875); + expect(y.value(5)).toBe(12.2624690808); + expect(z.value(5)).toBe(-14.354289628); }); }); \ No newline at end of file diff --git a/src/mol-io/reader/_spec/ccp4.spec.ts b/src/mol-io/reader/_spec/ccp4.spec.ts index 87c1acbf34811fc434c6c9abecf2d87efbb71a13..96cfe71690171ed62c607ef923946aa59d84cb43 100644 --- a/src/mol-io/reader/_spec/ccp4.spec.ts +++ b/src/mol-io/reader/_spec/ccp4.spec.ts @@ -4,44 +4,44 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as CCP4 from '../ccp4/parser' +import * as CCP4 from '../ccp4/parser'; function createCcp4Data() { - const data = new Uint8Array(4 * 256 + 6) + const data = new Uint8Array(4 * 256 + 6); - const dv = new DataView(data.buffer) + const dv = new DataView(data.buffer); - dv.setInt8(52 * 4, 'M'.charCodeAt(0)) - dv.setInt8(52 * 4 + 1, 'A'.charCodeAt(0)) - dv.setInt8(52 * 4 + 2, 'P'.charCodeAt(0)) - dv.setInt8(52 * 4 + 3, ' '.charCodeAt(0)) + dv.setInt8(52 * 4, 'M'.charCodeAt(0)); + dv.setInt8(52 * 4 + 1, 'A'.charCodeAt(0)); + dv.setInt8(52 * 4 + 2, 'P'.charCodeAt(0)); + dv.setInt8(52 * 4 + 3, ' '.charCodeAt(0)); - dv.setUint8(53 * 4, 17) - dv.setUint8(53 * 4 + 1, 17) + dv.setUint8(53 * 4, 17); + dv.setUint8(53 * 4 + 1, 17); - dv.setInt32(0 * 4, 1) // NC - dv.setInt32(1 * 4, 2) // NR - dv.setInt32(2 * 4, 3) // NS + dv.setInt32(0 * 4, 1); // NC + dv.setInt32(1 * 4, 2); // NR + dv.setInt32(2 * 4, 3); // NS - dv.setInt32(3 * 4, 0) // MODE + dv.setInt32(3 * 4, 0); // MODE - return data + return data; } describe('ccp4 reader', () => { it('basic', async () => { - const data = createCcp4Data() + const data = createCcp4Data(); const parsed = await CCP4.parse(data).run(); if (parsed.isError) { - throw new Error(parsed.message) + throw new Error(parsed.message); } const ccp4File = parsed.result; const { header } = ccp4File; - expect(header.NC).toBe(1) - expect(header.NR).toBe(2) - expect(header.NS).toBe(3) + expect(header.NC).toBe(1); + expect(header.NR).toBe(2); + expect(header.NS).toBe(3); }); }); diff --git a/src/mol-io/reader/_spec/cif.spec.ts b/src/mol-io/reader/_spec/cif.spec.ts index 8b25cf7b17b3aef5dd5708b24ad913316c01e8d1..1934c647614fcb2f5e21a31f06e2e59fda7b3d16 100644 --- a/src/mol-io/reader/_spec/cif.spec.ts +++ b/src/mol-io/reader/_spec/cif.spec.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as Data from '../cif/data-model' -import * as Schema from '../cif/schema' -import { Column } from '../../../mol-data/db' +import * as Data from '../cif/data-model'; +import * as Schema from '../cif/schema'; +import { Column } from '../../../mol-data/db'; import parse from '../cif/text/parser'; const columnData = `123abc d,e,f '4 5 6'`; @@ -33,8 +33,8 @@ namespace TestSchema { str: Column.Schema.str, strList: Column.Schema.List(',', x => x), intList: Column.Schema.List(' ', x => parseInt(x, 10)) - } - export const schema = { test } + }; + export const schema = { test }; } test('cif triple quote', async () => { @@ -71,5 +71,5 @@ describe('schema', () => { expect(ret[0]).toBe(1); expect(ret[1]).toBe(2); expect(ret[2]).toBe(3); - }) + }); }); \ No newline at end of file diff --git a/src/mol-io/reader/_spec/column.spec.ts b/src/mol-io/reader/_spec/column.spec.ts index 43240ae682d137a1fd4f847b559e0d4d34820736..b47ac8da15b1e2f33b4fdd407edc60ae67b64e89 100644 --- a/src/mol-io/reader/_spec/column.spec.ts +++ b/src/mol-io/reader/_spec/column.spec.ts @@ -5,9 +5,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import FixedColumn from '../common/text/column/fixed' -import TokenColumn from '../common/text/column/token' -import { Column, ColumnHelpers } from '../../../mol-data/db' +import FixedColumn from '../common/text/column/fixed'; +import TokenColumn from '../common/text/column/token'; +import { Column, ColumnHelpers } from '../../../mol-data/db'; const lines = [ '1.123 abc', @@ -15,7 +15,7 @@ const lines = [ '1.1 bcd ', '', ' 5' -] +]; const linesData = lines.join('\n'); @@ -40,14 +40,14 @@ describe('fixed text column', () => { expect(col1.value(2)).toBe(1.1); expect(col1.value(3)).toBe(0); expect(col1.value(4)).toBe(5); - }) + }); it('str', () => { expect(col2.value(0)).toBe('abc'); expect(col2.value(1)).toBe('a'); expect(col2.value(2)).toBe('bc'); expect(col2.value(3)).toBe(''); expect(col2.value(4)).toBe(''); - }) + }); }); describe('token text column', () => { @@ -58,7 +58,7 @@ describe('token text column', () => { expect(col1.value(0)).toBe(3); expect(col1.value(1)).toBe(2); expect(col1.value(2)).toBe(1); - }) + }); }); describe('binary column', () => { @@ -73,4 +73,4 @@ describe('binary column', () => { expect(w2.length).toBe(2); for (let i = 0; i < w2.length; i++) expect(w2[i]).toBe(xs[i + 2]); }); -}) +}); diff --git a/src/mol-io/reader/_spec/common.spec.ts b/src/mol-io/reader/_spec/common.spec.ts index a24b244f3a2debb505ee83875ca75d2124256c56..e072d44679b159d2edc41e7146cee7be52f99e61 100644 --- a/src/mol-io/reader/_spec/common.spec.ts +++ b/src/mol-io/reader/_spec/common.spec.ts @@ -8,25 +8,25 @@ import { parseFloat as fastParseFloat, parseInt as fastParseInt, getNumberType, describe('common', () => { it('number-parser fastParseFloat', () => { - expect(fastParseFloat('11.0829(23)', 0, 11)).toBe(11.0829) + expect(fastParseFloat('11.0829(23)', 0, 11)).toBe(11.0829); }); it('number-parser fastParseInt', () => { - expect(fastParseInt('11(23)', 0, 11)).toBe(11) + expect(fastParseInt('11(23)', 0, 11)).toBe(11); }); it('number-parser getNumberType', () => { - expect(getNumberType('11')).toBe(NumberType.Int) - expect(getNumberType('5E93')).toBe(NumberType.Scientific) - expect(getNumberType('0.42')).toBe(NumberType.Float) - expect(getNumberType('Foo123')).toBe(NumberType.NaN) - expect(getNumberType('11.0829(23)')).toBe(NumberType.NaN) - expect(getNumberType('1..2')).toBe(NumberType.NaN) - expect(getNumberType('.')).toBe(NumberType.NaN) - expect(getNumberType('-.')).toBe(NumberType.NaN) - expect(getNumberType('e')).toBe(NumberType.NaN) - expect(getNumberType('-e')).toBe(NumberType.NaN) - expect(getNumberType('1e')).toBe(NumberType.Scientific) - expect(getNumberType('-1e')).toBe(NumberType.Scientific) + expect(getNumberType('11')).toBe(NumberType.Int); + expect(getNumberType('5E93')).toBe(NumberType.Scientific); + expect(getNumberType('0.42')).toBe(NumberType.Float); + expect(getNumberType('Foo123')).toBe(NumberType.NaN); + expect(getNumberType('11.0829(23)')).toBe(NumberType.NaN); + expect(getNumberType('1..2')).toBe(NumberType.NaN); + expect(getNumberType('.')).toBe(NumberType.NaN); + expect(getNumberType('-.')).toBe(NumberType.NaN); + expect(getNumberType('e')).toBe(NumberType.NaN); + expect(getNumberType('-e')).toBe(NumberType.NaN); + expect(getNumberType('1e')).toBe(NumberType.Scientific); + expect(getNumberType('-1e')).toBe(NumberType.Scientific); }); }); \ No newline at end of file diff --git a/src/mol-io/reader/_spec/csv.spec.ts b/src/mol-io/reader/_spec/csv.spec.ts index 3d4dacb2795209a77bbfcb964522b049c2d29c3e..244dd0b8365a5cc20a123380dc2d43e7fd37e531 100644 --- a/src/mol-io/reader/_spec/csv.spec.ts +++ b/src/mol-io/reader/_spec/csv.spec.ts @@ -4,22 +4,22 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { parseCsv } from '../csv/parser' +import { parseCsv } from '../csv/parser'; const csvStringBasic = `StrCol,IntCol,FloatCol # comment string1,-1,-0.34e3 -string2,42,2.44` +string2,42,2.44`; const csvStringAdvanced = `StrCol,"Int Col",FloatCol string1 \t , -1, -0.34e3 # comment " stri -ng2" ,42, 2.44 ` +ng2" ,42, 2.44 `; const tabString = `StrCol\tIntCol\tFloatCol string1\t-1\t-0.34e3 -string2\t42\t2.44` +string2\t42\t2.44`; describe('csv reader', () => { it('basic', async () => { @@ -32,16 +32,16 @@ describe('csv reader', () => { // if (col) console.log(name, col.toStringArray()) // }) - const strCol = csvFile.table.getColumn('StrCol') - if (strCol) expect(strCol.toStringArray()).toEqual(['string1', 'string2']) + const strCol = csvFile.table.getColumn('StrCol'); + if (strCol) expect(strCol.toStringArray()).toEqual(['string1', 'string2']); - const intCol = csvFile.table.getColumn('IntCol') - if (intCol) expect(intCol.toIntArray()).toEqual([-1, 42]) + const intCol = csvFile.table.getColumn('IntCol'); + if (intCol) expect(intCol.toIntArray()).toEqual([-1, 42]); - const floatCol = csvFile.table.getColumn('FloatCol') - if (floatCol) expect(floatCol.toFloatArray()).toEqual([-340.0, 2.44]) + const floatCol = csvFile.table.getColumn('FloatCol'); + if (floatCol) expect(floatCol.toFloatArray()).toEqual([-340.0, 2.44]); - expect.assertions(3) + expect.assertions(3); }); it('advanced', async () => { @@ -49,16 +49,16 @@ describe('csv reader', () => { if (parsed.isError) return; const csvFile = parsed.result; - const strCol = csvFile.table.getColumn('StrCol') - if (strCol) expect(strCol.toStringArray()).toEqual(['string1', ' stri\nng2']) + const strCol = csvFile.table.getColumn('StrCol'); + if (strCol) expect(strCol.toStringArray()).toEqual(['string1', ' stri\nng2']); - const intCol = csvFile.table.getColumn('Int Col') - if (intCol) expect(intCol.toIntArray()).toEqual([-1, 42]) + const intCol = csvFile.table.getColumn('Int Col'); + if (intCol) expect(intCol.toIntArray()).toEqual([-1, 42]); - const floatCol = csvFile.table.getColumn('FloatCol') - if (floatCol) expect(floatCol.toFloatArray()).toEqual([-340.0, 2.44]) + const floatCol = csvFile.table.getColumn('FloatCol'); + if (floatCol) expect(floatCol.toFloatArray()).toEqual([-340.0, 2.44]); - expect.assertions(3) + expect.assertions(3); }); it('tabs', async () => { @@ -66,15 +66,15 @@ describe('csv reader', () => { if (parsed.isError) return; const csvFile = parsed.result; - const strCol = csvFile.table.getColumn('StrCol') - if (strCol) expect(strCol.toStringArray()).toEqual(['string1', 'string2']) + const strCol = csvFile.table.getColumn('StrCol'); + if (strCol) expect(strCol.toStringArray()).toEqual(['string1', 'string2']); - const intCol = csvFile.table.getColumn('IntCol') - if (intCol) expect(intCol.toIntArray()).toEqual([-1, 42]) + const intCol = csvFile.table.getColumn('IntCol'); + if (intCol) expect(intCol.toIntArray()).toEqual([-1, 42]); - const floatCol = csvFile.table.getColumn('FloatCol') - if (floatCol) expect(floatCol.toFloatArray()).toEqual([-340.0, 2.44]) + const floatCol = csvFile.table.getColumn('FloatCol'); + if (floatCol) expect(floatCol.toFloatArray()).toEqual([-340.0, 2.44]); - expect.assertions(3) + expect.assertions(3); }); }); \ No newline at end of file diff --git a/src/mol-io/reader/_spec/dcd.spec.ts b/src/mol-io/reader/_spec/dcd.spec.ts index ffb3393d706de974f322d56adddde2c545c00ef4..29229b9c47ca0339bd962323a96c591476dc4a37 100644 --- a/src/mol-io/reader/_spec/dcd.spec.ts +++ b/src/mol-io/reader/_spec/dcd.spec.ts @@ -7,65 +7,65 @@ import { parseDcd } from '../dcd/parser'; function createDcdData() { - const data = new Uint8Array(4 * 128) + const data = new Uint8Array(4 * 128); - const dv = new DataView(data.buffer) + const dv = new DataView(data.buffer); // set little endian - dv.setInt32(0, 84) + dv.setInt32(0, 84); // set format string - dv.setUint8(4, 'D'.charCodeAt(0)) - dv.setUint8(5, 'R'.charCodeAt(0)) - dv.setUint8(6, 'O'.charCodeAt(0)) - dv.setUint8(7, 'C'.charCodeAt(0)) + dv.setUint8(4, 'D'.charCodeAt(0)); + dv.setUint8(5, 'R'.charCodeAt(0)); + dv.setUint8(6, 'O'.charCodeAt(0)); + dv.setUint8(7, 'C'.charCodeAt(0)); - dv.setInt32(8, 1) // NSET + dv.setInt32(8, 1); // NSET // header end - dv.setInt32(22 * 4, 84) + dv.setInt32(22 * 4, 84); // title - const titleEnd = 164 - const titleStart = 23 * 4 + 1 - dv.setInt32(23 * 4, titleEnd) - dv.setInt32(titleStart + titleEnd + 4 - 1, titleEnd) + const titleEnd = 164; + const titleStart = 23 * 4 + 1; + dv.setInt32(23 * 4, titleEnd); + dv.setInt32(titleStart + titleEnd + 4 - 1, titleEnd); // atoms - const atomStart = 23 * 4 + titleEnd + 8 - dv.setInt32(atomStart, 4) - dv.setInt32(atomStart + 4, 1) // one atom - dv.setInt32(atomStart + 8, 4) + const atomStart = 23 * 4 + titleEnd + 8; + dv.setInt32(atomStart, 4); + dv.setInt32(atomStart + 4, 1); // one atom + dv.setInt32(atomStart + 8, 4); // coords - const coordsStart = atomStart + 12 - dv.setInt32(coordsStart, 4) - dv.setFloat32(coordsStart + 4, 0.1) - dv.setInt32(coordsStart + 8, 4) - dv.setInt32(coordsStart + 12, 4) - dv.setFloat32(coordsStart + 16, 0.2) - dv.setInt32(coordsStart + 20, 4) - dv.setInt32(coordsStart + 24, 4) - dv.setFloat32(coordsStart + 28, 0.3) - dv.setInt32(coordsStart + 32, 4) - - return data + const coordsStart = atomStart + 12; + dv.setInt32(coordsStart, 4); + dv.setFloat32(coordsStart + 4, 0.1); + dv.setInt32(coordsStart + 8, 4); + dv.setInt32(coordsStart + 12, 4); + dv.setFloat32(coordsStart + 16, 0.2); + dv.setInt32(coordsStart + 20, 4); + dv.setInt32(coordsStart + 24, 4); + dv.setFloat32(coordsStart + 28, 0.3); + dv.setInt32(coordsStart + 32, 4); + + return data; } describe('dcd reader', () => { it('basic', async () => { - const data = createDcdData() + const data = createDcdData(); const parsed = await parseDcd(data).run(); if (parsed.isError) { - throw new Error(parsed.message) + throw new Error(parsed.message); } const dcdFile = parsed.result; const { header, frames } = dcdFile; - expect(header.NSET).toBe(1) - expect(header.NATOM).toBe(1) + expect(header.NSET).toBe(1); + expect(header.NATOM).toBe(1); expect(frames[0].x[0]).toBeCloseTo(0.1, 0.0001); expect(frames[0].y[0]).toBeCloseTo(0.2, 0.0001); diff --git a/src/mol-io/reader/_spec/gro.spec.ts b/src/mol-io/reader/_spec/gro.spec.ts index 16a120a387eaeb712c8cb37ca3a8a17df63419d3..2851f1fe1a9a5605df400d395289faca862aa238 100644 --- a/src/mol-io/reader/_spec/gro.spec.ts +++ b/src/mol-io/reader/_spec/gro.spec.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { parseGRO } from '../gro/parser' +import { parseGRO } from '../gro/parser'; const groString = `MD of 2 waters, t= 4.2 6 @@ -15,35 +15,35 @@ const groString = `MD of 2 waters, t= 4.2 2WATER OW1 4 1.275 0.053 0.622 0.2519 0.3140 -0.1734 2WATER HW2 5 1.337 0.002 0.680 -1.0641 -1.1349 0.0257 2WATER HW3 6 1.326 0.120 0.568 1.9427 -0.8216 -0.0244 - 1.82060 2.82060 3.82060` + 1.82060 2.82060 3.82060`; const groStringHighPrecision = `Generated by trjconv : 2168 system t= 15.00000 3 1ETH C1 1 2.735383 2.672010 1.450194 0.2345 -0.1622 0.2097 1ETH H11 2 0.015804 2.716597 1.460588 0.8528 -0.7984 0.6605 1ETH H12 3 2.744822 2.565544 1.409227 -2.3812 2.8618 1.8101 - 1.82060 2.82060 3.82060` + 1.82060 2.82060 3.82060`; describe('gro reader', () => { it('basic', async () => { const parsed = await parseGRO(groString).run(); if (parsed.isError) { - console.log(parsed) + console.log(parsed); return; } const groFile = parsed.result; const data = groFile.structures[0]; const { header, atoms } = data; - expect(header.title).toBe('MD of 2 waters') - expect(header.timeInPs).toBeCloseTo(4.2) + expect(header.title).toBe('MD of 2 waters'); + expect(header.timeInPs).toBeCloseTo(4.2); expect(header.hasVelocities).toBe(true); expect(header.precision.position).toBe(3); expect(header.precision.velocity).toBe(4); - expect(header.box[0]).toBeCloseTo(1.82060, 0.00001) - expect(header.box[1]).toBeCloseTo(2.82060, 0.00001) - expect(header.box[2]).toBeCloseTo(3.82060, 0.00001) + expect(header.box[0]).toBeCloseTo(1.82060, 0.00001); + expect(header.box[1]).toBeCloseTo(2.82060, 0.00001); + expect(header.box[2]).toBeCloseTo(3.82060, 0.00001); expect(atoms.count).toBe(6); @@ -60,7 +60,7 @@ describe('gro reader', () => { const parsed = await parseGRO(groStringHighPrecision).run(); if (parsed.isError) { - console.log(parsed) + console.log(parsed); return; } @@ -68,14 +68,14 @@ describe('gro reader', () => { const data = groFile.structures[0]; const { header, atoms } = data; - expect(header.title).toBe('Generated by trjconv : 2168 system') - expect(header.timeInPs).toBeCloseTo(15) + expect(header.title).toBe('Generated by trjconv : 2168 system'); + expect(header.timeInPs).toBeCloseTo(15); expect(header.hasVelocities).toBe(true); expect(header.precision.position).toBe(6); expect(header.precision.velocity).toBe(4); - expect(header.box[0]).toBeCloseTo(1.82060, 0.00001) - expect(header.box[1]).toBeCloseTo(2.82060, 0.00001) - expect(header.box[2]).toBeCloseTo(3.82060, 0.00001) + expect(header.box[0]).toBeCloseTo(1.82060, 0.00001); + expect(header.box[1]).toBeCloseTo(2.82060, 0.00001); + expect(header.box[2]).toBeCloseTo(3.82060, 0.00001); expect(atoms.count).toBe(3); diff --git a/src/mol-io/reader/_spec/mol.spec.ts b/src/mol-io/reader/_spec/mol.spec.ts index 7944698e6347e3cf3ee500e937b32e67e91abc31..64015df72de92c43698ee86b3aab9013545e1174 100644 --- a/src/mol-io/reader/_spec/mol.spec.ts +++ b/src/mol-io/reader/_spec/mol.spec.ts @@ -1,5 +1,5 @@ -import { parseMol } from '../mol/parser' +import { parseMol } from '../mol/parser'; const MolString = `2244 -OEChem-04072009073D @@ -47,7 +47,7 @@ const MolString = `2244 13 18 1 0 0 0 0 13 19 1 0 0 0 0 13 20 1 0 0 0 0 -M END` +M END`; describe('mol reader', () => { it('basic', async () => { diff --git a/src/mol-io/reader/_spec/mol2.spec.ts b/src/mol-io/reader/_spec/mol2.spec.ts index 04570831700fc0db83cae496f660bbf50ef654ef..eb61ea18057bbfcd99c26f5c5a52f43144204550 100644 --- a/src/mol-io/reader/_spec/mol2.spec.ts +++ b/src/mol-io/reader/_spec/mol2.spec.ts @@ -1,5 +1,5 @@ -import Mol2 from '../mol2/parser' +import Mol2 from '../mol2/parser'; const Mol2String = `@<TRIPOS>MOLECULE 5816 @@ -60,7 +60,7 @@ GASTEIGER 23 11 20 1 24 13 22 1 25 13 23 1 - 26 13 24 1` + 26 13 24 1`; const Mol2StringMultiBlocks = `@<TRIPOS>MOLECULE 5816 @@ -181,7 +181,7 @@ GASTEIGER 23 11 20 1 24 13 22 1 25 13 23 1 - 26 13 24 1` + 26 13 24 1`; const Mol2StringMinimal = `@<TRIPOS>MOLECULE 5816 @@ -242,7 +242,7 @@ GASTEIGER 23 11 20 1 24 13 22 1 25 13 23 1 - 26 13 24 1` + 26 13 24 1`; describe('mol2 reader', () => { it('basic', async () => { @@ -259,13 +259,13 @@ describe('mol2 reader', () => { const { molecule, atoms, bonds } = data; // molecule fields - expect(molecule.mol_name).toBe('5816') - expect(molecule.num_atoms).toBe(26) + expect(molecule.mol_name).toBe('5816'); + expect(molecule.num_atoms).toBe(26); expect(molecule.num_bonds).toBe(26); expect(molecule.num_subst).toBe(0); expect(molecule.num_feat).toBe(0); expect(molecule.num_sets).toBe(0); - expect(molecule.mol_type).toBe('SMALL') + expect(molecule.mol_type).toBe('SMALL'); expect(molecule.charge_type).toBe('GASTEIGER'); expect(molecule.status_bits).toBe(''); expect(molecule.mol_comment).toBe(''); @@ -310,13 +310,13 @@ describe('mol2 reader', () => { const { molecule, atoms, bonds } = data; // molecule fields - expect(molecule.mol_name).toBe('5816') - expect(molecule.num_atoms).toBe(26) + expect(molecule.mol_name).toBe('5816'); + expect(molecule.num_atoms).toBe(26); expect(molecule.num_bonds).toBe(26); expect(molecule.num_subst).toBe(0); expect(molecule.num_feat).toBe(0); expect(molecule.num_sets).toBe(0); - expect(molecule.mol_type).toBe('SMALL') + expect(molecule.mol_type).toBe('SMALL'); expect(molecule.charge_type).toBe('GASTEIGER'); expect(molecule.status_bits).toBe(''); expect(molecule.mol_comment).toBe(''); @@ -361,13 +361,13 @@ describe('mol2 reader', () => { const { molecule, atoms, bonds } = data; // molecule fields - expect(molecule.mol_name).toBe('5816') - expect(molecule.num_atoms).toBe(26) + expect(molecule.mol_name).toBe('5816'); + expect(molecule.num_atoms).toBe(26); expect(molecule.num_bonds).toBe(26); expect(molecule.num_subst).toBe(0); expect(molecule.num_feat).toBe(0); expect(molecule.num_sets).toBe(0); - expect(molecule.mol_type).toBe('SMALL') + expect(molecule.mol_type).toBe('SMALL'); expect(molecule.charge_type).toBe('GASTEIGER'); expect(molecule.status_bits).toBe(''); expect(molecule.mol_comment).toBe(''); diff --git a/src/mol-io/reader/_spec/ply.spec.ts b/src/mol-io/reader/_spec/ply.spec.ts index b6b51f35e49e1f5201ab40f91bf7c4be9e3aa408..0d3c180387baf8cf03d21dff40668b4aff430cb3 100644 --- a/src/mol-io/reader/_spec/ply.spec.ts +++ b/src/mol-io/reader/_spec/ply.spec.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import Ply from '../ply/parser' +import Ply from '../ply/parser'; import { PlyTable, PlyList } from '../ply/schema'; const plyString = `ply @@ -54,7 +54,7 @@ end_header 131.482 160.483 161.621 90 159 210 255 -0.832 -0.431 -0.349 179 21 100 150 24 102 151 20 100 150 20 100 150 30 106 154 20 100 150 171 196 212 3 0 2 1 3 3 5 4 -` +`; const plyCubeString = `ply format ascii 1.0 @@ -107,7 +107,7 @@ end_header 255 255 0 0 255 255 255 0 255 -` +`; describe('ply reader', () => { it('basic', async () => { @@ -115,18 +115,18 @@ describe('ply reader', () => { if (parsed.isError) return; const plyFile = parsed.result; - const vertex = plyFile.getElement('vertex') as PlyTable - if (!vertex) return - const x = vertex.getProperty('x') - if (!x) return - expect(x.value(0)).toEqual(130.901) + const vertex = plyFile.getElement('vertex') as PlyTable; + if (!vertex) return; + const x = vertex.getProperty('x'); + if (!x) return; + expect(x.value(0)).toEqual(130.901); - const face = plyFile.getElement('face') as PlyList - if (!face) return - expect(face.value(0)).toEqual({ count: 3, entries: [0, 2, 1]}) - expect(face.value(1)).toEqual({ count: 3, entries: [3, 5, 4]}) + const face = plyFile.getElement('face') as PlyList; + if (!face) return; + expect(face.value(0)).toEqual({ count: 3, entries: [0, 2, 1]}); + expect(face.value(1)).toEqual({ count: 3, entries: [3, 5, 4]}); - expect.assertions(3) + expect.assertions(3); }); it('material', async () => { @@ -134,18 +134,18 @@ describe('ply reader', () => { if (parsed.isError) return; const plyFile = parsed.result; - const vertex = plyFile.getElement('vertex') as PlyTable - if (!vertex) return - expect(vertex.rowCount).toBe(24) + const vertex = plyFile.getElement('vertex') as PlyTable; + if (!vertex) return; + expect(vertex.rowCount).toBe(24); - const face = plyFile.getElement('face') as PlyList - if (!face) return - expect(face.rowCount).toBe(6) + const face = plyFile.getElement('face') as PlyList; + if (!face) return; + expect(face.rowCount).toBe(6); - const material = plyFile.getElement('face') as PlyTable - if (!material) return - expect(face.rowCount).toBe(6) + const material = plyFile.getElement('face') as PlyTable; + if (!material) return; + expect(face.rowCount).toBe(6); - expect.assertions(3) + expect.assertions(3); }); }); \ No newline at end of file diff --git a/src/mol-io/reader/_spec/psf.spec.ts b/src/mol-io/reader/_spec/psf.spec.ts index 9aac7aad8d8b15dd9743cdbcdadf4dc565562ad2..acc7df1c2b55a6039f7579322b42e9aa816d0415 100644 --- a/src/mol-io/reader/_spec/psf.spec.ts +++ b/src/mol-io/reader/_spec/psf.spec.ts @@ -68,43 +68,43 @@ const psfString = `PSF CMAP CHEQ 31 33 31 34 36 35 35 37 37 38 37 39 39 40 39 41 39 42 -` +`; describe('psf reader', () => { it('basic', async () => { const parsed = await parsePsf(psfString).run(); if (parsed.isError) { - throw new Error(parsed.message) + throw new Error(parsed.message); } const psfFile = parsed.result; const { id, title, atoms, bonds } = psfFile; - expect(id).toBe('PSF CMAP CHEQ') + expect(id).toBe('PSF CMAP CHEQ'); expect(title).toEqual([ 'BETA HARPIN IN IMPLICIT SOLVENT', 'DATE: 11/22/10 16:54: 9 CREATED BY USER: aokur' - ]) + ]); - expect(atoms.atomId.value(0)).toBe(1) - expect(atoms.atomId.value(41)).toBe(42) - expect(atoms.segmentName.value(0)).toBe('ALA3') - expect(atoms.residueId.value(0)).toBe(1) - expect(atoms.residueId.value(41)).toBe(3) - expect(atoms.residueName.value(0)).toBe('ALA') - expect(atoms.atomName.value(0)).toBe('CAY') - expect(atoms.atomName.value(41)).toBe('HT3') - expect(atoms.atomType.value(0)).toBe('24') - expect(atoms.atomType.value(41)).toBe('3') - expect(atoms.charge.value(0)).toBeCloseTo(-0.270000, 0.00001) - expect(atoms.charge.value(41)).toBeCloseTo(0.090000, 0.00001) - expect(atoms.mass.value(0)).toBeCloseTo(12.0110, 0.00001) - expect(atoms.mass.value(41)).toBeCloseTo(1.00800, 0.00001) + expect(atoms.atomId.value(0)).toBe(1); + expect(atoms.atomId.value(41)).toBe(42); + expect(atoms.segmentName.value(0)).toBe('ALA3'); + expect(atoms.residueId.value(0)).toBe(1); + expect(atoms.residueId.value(41)).toBe(3); + expect(atoms.residueName.value(0)).toBe('ALA'); + expect(atoms.atomName.value(0)).toBe('CAY'); + expect(atoms.atomName.value(41)).toBe('HT3'); + expect(atoms.atomType.value(0)).toBe('24'); + expect(atoms.atomType.value(41)).toBe('3'); + expect(atoms.charge.value(0)).toBeCloseTo(-0.270000, 0.00001); + expect(atoms.charge.value(41)).toBeCloseTo(0.090000, 0.00001); + expect(atoms.mass.value(0)).toBeCloseTo(12.0110, 0.00001); + expect(atoms.mass.value(41)).toBeCloseTo(1.00800, 0.00001); - expect(bonds.atomIdA.value(0)).toBe(5) - expect(bonds.atomIdB.value(0)).toBe(1) - expect(bonds.atomIdA.value(40)).toBe(39) - expect(bonds.atomIdB.value(40)).toBe(42) + expect(bonds.atomIdA.value(0)).toBe(5); + expect(bonds.atomIdB.value(0)).toBe(1); + expect(bonds.atomIdA.value(40)).toBe(39); + expect(bonds.atomIdB.value(40)).toBe(42); }); }); diff --git a/src/mol-io/reader/ccp4/parser.ts b/src/mol-io/reader/ccp4/parser.ts index 1677b3c225f68648e60196c2ead9562484f29693..f87b6d455c038824994ba20cd6e4781d00d8b985 100644 --- a/src/mol-io/reader/ccp4/parser.ts +++ b/src/mol-io/reader/ccp4/parser.ts @@ -5,40 +5,40 @@ */ import { Task, RuntimeContext } from '../../../mol-task'; -import { Ccp4File, Ccp4Header } from './schema' -import { ReaderResult as Result } from '../result' +import { Ccp4File, Ccp4Header } from './schema'; +import { ReaderResult as Result } from '../result'; import { FileHandle } from '../../common/file-handle'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; import { TypedArrayValueType, getElementByteSize, TypedArrayBufferContext, readTypedArray, createTypedArrayBufferContext } from '../../../mol-io/common/typed-array'; export async function readCcp4Header(file: FileHandle): Promise<{ header: Ccp4Header, littleEndian: boolean }> { const headerSize = 1024; - const { buffer } = await file.readBuffer(0, headerSize) + const { buffer } = await file.readBuffer(0, headerSize); // 53 MAP Character string 'MAP ' to identify file type const MAP = String.fromCharCode( buffer.readUInt8(52 * 4), buffer.readUInt8(52 * 4 + 1), buffer.readUInt8(52 * 4 + 2), buffer.readUInt8(52 * 4 + 3) - ) + ); if (MAP !== 'MAP ') { throw new Error('ccp4 format error, missing "MAP " string'); } // 54 MACHST Machine stamp indicating machine type which wrote file // 17 and 17 for big-endian or 68 and 65 for little-endian - const MACHST = [ buffer.readUInt8(53 * 4), buffer.readUInt8(53 * 4 + 1) ] - let littleEndian = false + const MACHST = [ buffer.readUInt8(53 * 4), buffer.readUInt8(53 * 4 + 1) ]; + let littleEndian = false; if (MACHST[0] === 68 && MACHST[1] === 65) { littleEndian = true; } else if (MACHST[0] === 17 && MACHST[1] === 17) { littleEndian = false; } else { - const modeLE = buffer.readInt32LE(3 * 4) + const modeLE = buffer.readInt32LE(3 * 4); if (modeLE <= 16) littleEndian = true; } - const readInt = littleEndian ? (o: number) => buffer.readInt32LE(o * 4) : (o: number) => buffer.readInt32BE(o * 4) - const readFloat = littleEndian ? (o: number) => buffer.readFloatLE(o * 4) : (o: number) => buffer.readFloatBE(o * 4) + const readInt = littleEndian ? (o: number) => buffer.readInt32LE(o * 4) : (o: number) => buffer.readInt32BE(o * 4); + const readFloat = littleEndian ? (o: number) => buffer.readFloatLE(o * 4) : (o: number) => buffer.readFloatBE(o * 4); const header: Ccp4Header = { NC: readInt(0), @@ -95,24 +95,24 @@ export async function readCcp4Header(file: FileHandle): Promise<{ header: Ccp4He // TODO bytes 56 NLABL // TODO bytes 57-256 LABEL - } + }; - return { header, littleEndian } + return { header, littleEndian }; } export async function readCcp4Slices(header: Ccp4Header, buffer: TypedArrayBufferContext, file: FileHandle, byteOffset: number, length: number, littleEndian: boolean) { if (isMapmode2to0(header)) { // data from mapmode2to0 is in MODE 0 (Int8) and needs to be scaled and written as float32 - const valueByteOffset = 3 * length + const valueByteOffset = 3 * length; // read int8 data to last quarter of the read buffer await file.readBuffer(byteOffset, buffer.readBuffer, length, valueByteOffset); // get int8 view of last quarter of the read buffer - const int8 = new Int8Array(buffer.valuesBuffer.buffer, valueByteOffset) + const int8 = new Int8Array(buffer.valuesBuffer.buffer, valueByteOffset); // scaling f(x)=b1*x+b0 such that f(-128)=min and f(127)=max - const b1 = (header.AMAX - header.AMIN) / 255.0 - const b0 = 0.5 * (header.AMIN + header.AMAX + b1) + const b1 = (header.AMAX - header.AMIN) / 255.0; + const b0 = 0.5 * (header.AMIN + header.AMAX + b1); for (let j = 0, jl = length; j < jl; ++j) { - buffer.values[j] = b1 * int8[j] + b0 + buffer.values[j] = b1 * int8[j] + b0; } } else { await readTypedArray(buffer, file, byteOffset, length, 0, littleEndian); @@ -121,47 +121,47 @@ export async function readCcp4Slices(header: Ccp4Header, buffer: TypedArrayBuffe function getCcp4DataType(mode: number) { switch (mode) { - case 0: return TypedArrayValueType.Int8 - case 1: return TypedArrayValueType.Int16 - case 2: return TypedArrayValueType.Float32 - case 3: throw new Error('mode 3 unsupported, complex 16-bit integers') - case 4: throw new Error('mode 4 unsupported, complex 32-bit reals') - case 6: TypedArrayValueType.Uint16 - case 16: throw new Error('mode 16 unsupported, unsigned char * 3 (for rgb data, non-standard)') + case 0: return TypedArrayValueType.Int8; + case 1: return TypedArrayValueType.Int16; + case 2: return TypedArrayValueType.Float32; + case 3: throw new Error('mode 3 unsupported, complex 16-bit integers'); + case 4: throw new Error('mode 4 unsupported, complex 32-bit reals'); + case 6: TypedArrayValueType.Uint16; + case 16: throw new Error('mode 16 unsupported, unsigned char * 3 (for rgb data, non-standard)'); } throw new Error(`unknown mode '${mode}'`); } /** check if the file was converted by mapmode2to0, see https://github.com/uglymol/uglymol */ function isMapmode2to0(header: Ccp4Header) { - return header.userFlag1 === -128 && header.userFlag2 === 127 + return header.userFlag1 === -128 && header.userFlag2 === 127; } export function getCcp4ValueType(header: Ccp4Header) { - return isMapmode2to0(header) ? TypedArrayValueType.Float32 : getCcp4DataType(header.MODE) + return isMapmode2to0(header) ? TypedArrayValueType.Float32 : getCcp4DataType(header.MODE); } export function getCcp4DataOffset(header: Ccp4Header) { - return 256 * 4 + header.NSYMBT + return 256 * 4 + header.NSYMBT; } async function parseInternal(file: FileHandle, size: number, ctx: RuntimeContext): Promise<Ccp4File> { await ctx.update({ message: 'Parsing CCP4/MRC/MAP file...' }); - const { header, littleEndian } = await readCcp4Header(file) - const offset = getCcp4DataOffset(header) - const dataType = getCcp4DataType(header.MODE) - const valueType = getCcp4ValueType(header) + const { header, littleEndian } = await readCcp4Header(file); + const offset = getCcp4DataOffset(header); + const dataType = getCcp4DataType(header.MODE); + const valueType = getCcp4ValueType(header); - const count = header.NC * header.NR * header.NS - const elementByteSize = getElementByteSize(dataType) - const byteCount = count * elementByteSize + const count = header.NC * header.NR * header.NS; + const elementByteSize = getElementByteSize(dataType); + const byteCount = count * elementByteSize; - const buffer = createTypedArrayBufferContext(count, valueType) - readCcp4Slices(header, buffer, file, offset, byteCount, littleEndian) + const buffer = createTypedArrayBufferContext(count, valueType); + readCcp4Slices(header, buffer, file, offset, byteCount, littleEndian); const result: Ccp4File = { header, values: buffer.values }; - return result + return result; } export function parseFile(file: FileHandle, size: number) { @@ -171,9 +171,9 @@ export function parseFile(file: FileHandle, size: number) { } catch (e) { return Result.error(e); } - }) + }); } export function parse(buffer: Uint8Array) { - return parseFile(FileHandle.fromBuffer(SimpleBuffer.fromUint8Array(buffer)), buffer.length) + return parseFile(FileHandle.fromBuffer(SimpleBuffer.fromUint8Array(buffer)), buffer.length); } \ No newline at end of file diff --git a/src/mol-io/reader/cif.ts b/src/mol-io/reader/cif.ts index 63883a2fdf4a219d3f125dff0ece117db244264f..09abe2775af03ea7fad947add4fc0ce347204665 100644 --- a/src/mol-io/reader/cif.ts +++ b/src/mol-io/reader/cif.ts @@ -5,16 +5,16 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import parseText from './cif/text/parser' -import parseBinary from './cif/binary/parser' -import { CifFrame } from './cif/data-model' -import { toDatabaseCollection, toDatabase } from './cif/schema' -import { mmCIF_Schema, mmCIF_Database } from './cif/schema/mmcif' -import { CCD_Schema, CCD_Database } from './cif/schema/ccd' -import { BIRD_Schema, BIRD_Database } from './cif/schema/bird' -import { dic_Schema, dic_Database } from './cif/schema/dic' -import { DensityServer_Data_Schema, DensityServer_Data_Database } from './cif/schema/density-server' -import { CifCore_Database, CifCore_Schema, CifCore_Aliases } from './cif/schema/cif-core' +import parseText from './cif/text/parser'; +import parseBinary from './cif/binary/parser'; +import { CifFrame } from './cif/data-model'; +import { toDatabaseCollection, toDatabase } from './cif/schema'; +import { mmCIF_Schema, mmCIF_Database } from './cif/schema/mmcif'; +import { CCD_Schema, CCD_Database } from './cif/schema/ccd'; +import { BIRD_Schema, BIRD_Database } from './cif/schema/bird'; +import { dic_Schema, dic_Database } from './cif/schema/dic'; +import { DensityServer_Data_Schema, DensityServer_Data_Database } from './cif/schema/density-server'; +import { CifCore_Database, CifCore_Schema, CifCore_Aliases } from './cif/schema/cif-core'; export const CIF = { parse: (data: string|Uint8Array) => typeof data === 'string' ? parseText(data) : parseBinary(data), @@ -30,6 +30,6 @@ export const CIF = { cifCore: (frame: CifFrame) => toDatabase<CifCore_Schema, CifCore_Database>(CifCore_Schema, frame, CifCore_Aliases), densityServer: (frame: CifFrame) => toDatabase<DensityServer_Data_Schema, DensityServer_Data_Database>(DensityServer_Data_Schema, frame), } -} +}; -export * from './cif/data-model' \ No newline at end of file +export * from './cif/data-model'; \ No newline at end of file diff --git a/src/mol-io/reader/cif/binary/field.ts b/src/mol-io/reader/cif/binary/field.ts index 09d0271a4216c7ed2f5052d95a6356a99557cb24..5f89e261f9bbf9bcf3709e56e6d101ac0ca255af 100644 --- a/src/mol-io/reader/cif/binary/field.ts +++ b/src/mol-io/reader/cif/binary/field.ts @@ -5,10 +5,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column, ColumnHelpers } from '../../../../mol-data/db' -import * as Data from '../data-model' -import { EncodedColumn, decode } from '../../../common/binary-cif' -import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser' +import { Column, ColumnHelpers } from '../../../../mol-data/db'; +import * as Data from '../data-model'; +import { EncodedColumn, decode } from '../../../common/binary-cif'; +import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../common/text/number-parser'; export default function Field(column: EncodedColumn): Data.CifField { const mask = column.mask ? decode(column.mask) as number[] : void 0; diff --git a/src/mol-io/reader/cif/binary/parser.ts b/src/mol-io/reader/cif/binary/parser.ts index be4ea44c747ddf192e15e27fbe59aebec4c00a9d..de71be472020f5fac7e77e12b2d61a438cc91132 100644 --- a/src/mol-io/reader/cif/binary/parser.ts +++ b/src/mol-io/reader/cif/binary/parser.ts @@ -4,12 +4,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Data from '../data-model' -import { EncodedCategory, EncodedFile } from '../../../common/binary-cif' -import Field from './field' -import { ReaderResult as Result } from '../../result' -import decodeMsgPack from '../../../common/msgpack/decode' -import { Task } from '../../../../mol-task' +import * as Data from '../data-model'; +import { EncodedCategory, EncodedFile } from '../../../common/binary-cif'; +import Field from './field'; +import { ReaderResult as Result } from '../../result'; +import decodeMsgPack from '../../../common/msgpack/decode'; +import { Task } from '../../../../mol-task'; function checkVersions(min: number[], current: number[]) { for (let i = 0; i < 2; i++) { @@ -33,7 +33,7 @@ function Category(data: EncodedCategory): Data.CifCategory { cache[name] = Field(col); return cache[name]; } - } + }; } export default function parse(data: Uint8Array) { @@ -54,5 +54,5 @@ export default function parse(data: Uint8Array) { } catch (e) { return Result.error<Data.CifFile>('' + e); } - }) + }); } \ No newline at end of file diff --git a/src/mol-io/reader/cif/data-model.ts b/src/mol-io/reader/cif/data-model.ts index fa7223cf6ebb326a6e20a4f615cf263a4f4b99cb..3cc29133e9442ec5de6fd1d4ca94704bd80c13ac 100644 --- a/src/mol-io/reader/cif/data-model.ts +++ b/src/mol-io/reader/cif/data-model.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column, ColumnHelpers, Table } from '../../../mol-data/db' -import { Tensor } from '../../../mol-math/linear-algebra' +import { Column, ColumnHelpers, Table } from '../../../mol-data/db'; +import { Tensor } from '../../../mol-math/linear-algebra'; import { getNumberType, NumberType, parseInt as fastParseInt, parseFloat as fastParseFloat } from '../common/text/number-parser'; import { Encoding } from '../../common/binary-cif'; import { Tokens } from '../common/text/tokenizer'; @@ -37,8 +37,8 @@ export function CifBlock(categoryNames: string[], categories: CifCategories, hea return { categoryNames, header, categories, saveFrames, getField(name: string) { - const [ category, field ] = name.split('.') - return categories[category].getField(field || '') + const [ category, field ] = name.split('.'); + return categories[category].getField(field || ''); } }; } @@ -80,11 +80,11 @@ export namespace CifCategory { } export function ofTable(name: string, table: Table<any>) { - const fields: { [name: string]: CifField | undefined } = {} + const fields: { [name: string]: CifField | undefined } = {}; for (const name of table._columns) { - fields[name] = CifField.ofColumn(table[name]) + fields[name] = CifField.ofColumn(table[name]); } - return ofFields(name, fields) + return ofFields(name, fields); } } @@ -145,7 +145,7 @@ export namespace CifField { toStringArray: params => params ? ColumnHelpers.createAndFillArray(rowCount, str, params) : values as string[], toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params), toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params) - } + }; } export function ofNumbers(values: ArrayLike<number>): CifField { @@ -156,11 +156,11 @@ export namespace CifField { const toFloatArray = (params: Column.ToArrayParams<number>) => { if (!params || params.array && values instanceof params.array) { - return values as number[] + return values as number[]; } else { - return ColumnHelpers.createAndFillArray(rowCount, float, params) + return ColumnHelpers.createAndFillArray(rowCount, float, params); } - } + }; return { __array: void 0, @@ -175,7 +175,7 @@ export namespace CifField { toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params), toIntArray: toFloatArray, toFloatArray - } + }; } export function ofTokens(tokens: Tokens): CifField { @@ -218,15 +218,15 @@ export namespace CifField { toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params), toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params), toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params) - } + }; } export function ofColumn(column: Column<any>): CifField { const { rowCount, valueKind, areValuesEqual, isDefined } = column; - let str: CifField['str'] - let int: CifField['int'] - let float: CifField['float'] + let str: CifField['str']; + let int: CifField['int']; + let float: CifField['float']; switch (column.schema.valueType) { case 'float': @@ -234,20 +234,20 @@ export namespace CifField { str = row => { return '' + column.value(row); }; int = column.value; float = column.value; - break + break; case 'str': str = column.value; int = row => { const v = column.value(row); return fastParseInt(v, 0, v.length) || 0; }; float = row => { const v = column.value(row); return fastParseFloat(v, 0, v.length) || 0; }; - break + break; case 'list': const { separator } = column.schema; str = row => column.value(row).join(separator); int = row => NaN; float = row => NaN; - break + break; default: - throw new Error(`unsupported valueType '${column.schema.valueType}'`) + throw new Error(`unsupported valueType '${column.schema.valueType}'`); } return { @@ -263,7 +263,7 @@ export namespace CifField { toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params), toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params), toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params) - } + }; } } @@ -273,15 +273,15 @@ export function tensorFieldNameGetter(field: string, rank: number, zeroIndexed: case 1: return namingVariant === 'brackets' ? (i: number) => `${field}[${i + offset}]` - : (i: number) => `${field}_${i + offset}` + : (i: number) => `${field}_${i + offset}`; case 2: return namingVariant === 'brackets' ? (i: number, j: number) => `${field}[${i + offset}][${j + offset}]` - : (i: number, j: number) => `${field}_${i + offset}${j + offset}` + : (i: number, j: number) => `${field}_${i + offset}${j + offset}`; case 3: return namingVariant === 'brackets' ? (i: number, j: number, k: number) => `${field}[${i + offset}][${j + offset}][${k + offset}]` - : (i: number, j: number, k: number) => `${field}_${i + offset}${j + offset}${k + offset}` + : (i: number, j: number, k: number) => `${field}_${i + offset}${j + offset}${k + offset}`; default: throw new Error('Tensors with rank > 3 or rank 0 are currently not supported.'); } diff --git a/src/mol-io/reader/cif/schema.ts b/src/mol-io/reader/cif/schema.ts index 1fba5439b4d564e612167f08d6b6f2ca86d8843c..44be2a0a9af7450adcae08a57996ec58f344cd92 100644 --- a/src/mol-io/reader/cif/schema.ts +++ b/src/mol-io/reader/cif/schema.ts @@ -5,30 +5,30 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { DatabaseCollection, Database, Table, Column, ColumnHelpers } from '../../../mol-data/db' -import { Tensor } from '../../../mol-math/linear-algebra' -import { arrayEqual } from '../../../mol-util' -import * as Data from './data-model' +import { DatabaseCollection, Database, Table, Column, ColumnHelpers } from '../../../mol-data/db'; +import { Tensor } from '../../../mol-math/linear-algebra'; +import { arrayEqual } from '../../../mol-util'; +import * as Data from './data-model'; export namespace FieldPath { export function canonical(path: string) { - return path.replace('.', '_').replace(/\[/, '_').replace(/(\[|\])/g, '') + return path.replace('.', '_').replace(/\[/, '_').replace(/(\[|\])/g, ''); } export function equal(pathA: string, pathB: string) { - return canonical(pathA) === canonical(pathB) + return canonical(pathA) === canonical(pathB); } export function create(category: string, field: string, asCanonical = false) { - const p = `${category}${field ? `.${field}` : ''}` - return asCanonical ? canonical(p) : p + const p = `${category}${field ? `.${field}` : ''}`; + return asCanonical ? canonical(p) : p; } } export function toDatabaseCollection<Schema extends Database.Schema>(schema: Schema, file: Data.CifFile, aliases?: Data.CifAliases): DatabaseCollection<Schema> { - const dbc: DatabaseCollection<Schema> = {} + const dbc: DatabaseCollection<Schema> = {}; for (const data of file.blocks) { - dbc[data.header] = toDatabase(schema, data, aliases) + dbc[data.header] = toDatabase(schema, data, aliases); } return dbc; } @@ -71,8 +71,8 @@ function createListColumn<T extends number | string>(schema: Column.Schema.List< const itemParse = schema.itemParse; const f = category.getField(key); - const value = f ? (row: number) => f.str(row).split(separator).map(x => itemParse(x.trim())).filter(x => !!x) : (row: number) => [] - const toArray: Column<T[]>['toArray'] = params => ColumnHelpers.createAndFillArray(category.rowCount, value, params) + const value = f ? (row: number) => f.str(row).split(separator).map(x => itemParse(x.trim())).filter(x => !!x) : (row: number) => []; + const toArray: Column<T[]>['toArray'] = params => ColumnHelpers.createAndFillArray(category.rowCount, value, params); return { schema, @@ -98,12 +98,12 @@ function createTensorColumn(schema: Column.Schema.Tensor, category: Data.CifCate category.fieldNames.includes(`${key}_1`) || category.fieldNames.includes(`${key}_11`) || category.fieldNames.includes(`${key}_111`) - ) ? 'underscore' : 'brackets' + ) ? 'underscore' : 'brackets'; - const getName = Data.tensorFieldNameGetter(key, space.rank, zeroOffset, namingVariant) + const getName = Data.tensorFieldNameGetter(key, space.rank, zeroOffset, namingVariant); const first = category.getField(getName(fst, fst, fst)) || Column.Undefined(category.rowCount, schema); const value = (row: number) => Data.getTensor(category, space, row, getName); - const toArray: Column<Tensor.Data>['toArray'] = params => ColumnHelpers.createAndFillArray(category.rowCount, value, params) + const toArray: Column<Tensor.Data>['toArray'] = params => ColumnHelpers.createAndFillArray(category.rowCount, value, params); return { schema, @@ -163,24 +163,24 @@ function createDatabase(schema: Database.Schema, frame: Data.CifFrame, aliases?: type FlatFrame = { [k: string]: Data.CifField } function flattenFrame(frame: Data.CifFrame): FlatFrame { - const flatFrame = Object.create(null) + const flatFrame = Object.create(null); for (const c of Object.keys(frame.categories)) { for (const f of frame.categories[c].fieldNames) { - const p = FieldPath.create(c, f, true) - flatFrame[p] = frame.categories[c].getField(f) + const p = FieldPath.create(c, f, true); + flatFrame[p] = frame.categories[c].getField(f); } } - return flatFrame + return flatFrame; } function getField(field: string, category: string, flatFrame: FlatFrame, aliases?: Data.CifAliases) { - const path = FieldPath.create(category, field) - const canonicalPath = FieldPath.canonical(path) - if (canonicalPath in flatFrame) return flatFrame[canonicalPath] + const path = FieldPath.create(category, field); + const canonicalPath = FieldPath.canonical(path); + if (canonicalPath in flatFrame) return flatFrame[canonicalPath]; if (aliases && path in aliases) { for (const aliased of aliases[path]) { - const canonicalAliased = FieldPath.canonical(aliased) - if (canonicalAliased in flatFrame) return flatFrame[canonicalAliased] + const canonicalAliased = FieldPath.canonical(aliased); + if (canonicalAliased in flatFrame) return flatFrame[canonicalAliased]; } } } @@ -188,16 +188,16 @@ function getField(field: string, category: string, flatFrame: FlatFrame, aliases function createTable(key: string, schema: Table.Schema, frame: Data.CifFrame, aliases?: Data.CifAliases) { let cat = frame.categories[key]; if (aliases) { - const flatFrame = flattenFrame(frame) - const fields: { [k: string]: Data.CifField } = Object.create(null) - const fieldNames: string[] = [] - let rowCount = 0 + const flatFrame = flattenFrame(frame); + const fields: { [k: string]: Data.CifField } = Object.create(null); + const fieldNames: string[] = []; + let rowCount = 0; for (const k of Object.keys(schema)) { - const field = getField(k, key, flatFrame, aliases) + const field = getField(k, key, flatFrame, aliases); if (field) { - fields[k] = field - fieldNames.push(k) - rowCount = field.rowCount + fields[k] = field; + fieldNames.push(k); + rowCount = field.rowCount; } } cat = { @@ -207,7 +207,7 @@ function createTable(key: string, schema: Table.Schema, frame: Data.CifFrame, al getField(name: string) { return fields[name]; } - } + }; } return new CategoryTable(cat || Data.CifCategory.empty(key), schema, !!cat); } \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema/bird.ts b/src/mol-io/reader/cif/schema/bird.ts index 1fccaeff0cfd0ec27489346429cddd909407769d..0c7aca5b264828f7932a08b417beb695be4c80b1 100644 --- a/src/mol-io/reader/cif/schema/bird.ts +++ b/src/mol-io/reader/cif/schema/bird.ts @@ -6,7 +6,7 @@ * @author molstar/ciftools package */ -import { Database, Column } from '../../../../mol-data/db' +import { Database, Column } from '../../../../mol-data/db'; import Schema = Column.Schema @@ -493,7 +493,7 @@ export const BIRD_Schema = { */ action_type: Aliased<'Initial release' | 'Create molecule' | 'Modify type' | 'Modify class' | 'Modify molecule name' | 'Modify representation' | 'Modify sequence' | 'Modify linkage' | 'Modify taxonomy organism' | 'Modify audit' | 'Other modification' | 'Obsolete molecule'>(str), }, -} +}; export type BIRD_Schema = typeof BIRD_Schema; export interface BIRD_Database extends Database<BIRD_Schema> {} \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema/ccd.ts b/src/mol-io/reader/cif/schema/ccd.ts index 8678177ac7c341c2e1df8f0211261916ee18788f..a227051e00329e09af8296126668358058a1208a 100644 --- a/src/mol-io/reader/cif/schema/ccd.ts +++ b/src/mol-io/reader/cif/schema/ccd.ts @@ -6,7 +6,7 @@ * @author molstar/ciftools package */ -import { Database, Column } from '../../../../mol-data/db' +import { Database, Column } from '../../../../mol-data/db'; import Schema = Column.Schema @@ -394,7 +394,7 @@ export const CCD_Schema = { */ program_version: str, }, -} +}; export type CCD_Schema = typeof CCD_Schema; export interface CCD_Database extends Database<CCD_Schema> {} \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema/cif-core.ts b/src/mol-io/reader/cif/schema/cif-core.ts index 940ddc947e39b5933e1b8520c8224c27b98aed2e..baf2a20841afef0a28277595f3f380b261100ca2 100644 --- a/src/mol-io/reader/cif/schema/cif-core.ts +++ b/src/mol-io/reader/cif/schema/cif-core.ts @@ -6,7 +6,7 @@ * @author molstar/ciftools package */ -import { Database, Column } from '../../../../mol-data/db' +import { Database, Column } from '../../../../mol-data/db'; import Schema = Column.Schema @@ -707,7 +707,7 @@ export const CifCore_Schema = { */ source: str, }, -} +}; export const CifCore_Aliases = { 'atom_site_aniso.U': [ @@ -789,7 +789,7 @@ export const CifCore_Aliases = { 'atom_site_aniso_U_33_esd', 'atom_site_anisotrop_U_33_esd', ], -} +}; export type CifCore_Schema = typeof CifCore_Schema; export interface CifCore_Database extends Database<CifCore_Schema> {} \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema/density-server.ts b/src/mol-io/reader/cif/schema/density-server.ts index ef49e0fbc252956b2ad7f77ccecbeda6f041dc61..0379b7f84a73f81b65bfff87ef5524aa00f42251 100644 --- a/src/mol-io/reader/cif/schema/density-server.ts +++ b/src/mol-io/reader/cif/schema/density-server.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Database, Column } from '../../../../mol-data/db' +import { Database, Column } from '../../../../mol-data/db'; import Schema = Column.Schema @@ -29,7 +29,7 @@ export const DensityServer_Header_Schema = { 'query_box_a': Vector(3), 'query_box_b': Vector(3) } -} +}; export const DensityServer_Data_Schema = { volume_data_3d_info: { @@ -59,7 +59,7 @@ export const DensityServer_Data_Schema = { volume_data_3d: { values: float } -} +}; export type DensityServer_Header_Schema = typeof DensityServer_Header_Schema; export interface DensityServer_Header_Database extends Database<DensityServer_Header_Schema> {} diff --git a/src/mol-io/reader/cif/schema/dic.ts b/src/mol-io/reader/cif/schema/dic.ts index cd4b7b3bc5c1bccd7b22a3560b31855e34ff799e..b8478b934ed1556223e0e8de1b1e2db271000ec7 100644 --- a/src/mol-io/reader/cif/schema/dic.ts +++ b/src/mol-io/reader/cif/schema/dic.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Database, Column } from '../../../../mol-data/db' +import { Database, Column } from '../../../../mol-data/db'; import Schema = Column.Schema @@ -14,49 +14,49 @@ const float = Schema.float; const datablock = { id: str, description: str -} +}; const dictionary = { title: str, datablock_id: str, version: str -} +}; const dictionary_history = { version: str, update: str, revision: str -} +}; const sub_category = { id: str, description: str -} +}; const category_group_list = { id: str, parent_id: str, description: str -} +}; const item_type_list = { code: str, primitive_code: str, construct: str, detail: str -} +}; const item_units_list = { code: str, detail: str -} +}; const item_units_conversion = { from_code: str, to_code: str, operator: str, factor: float -} +}; // TODO save frame dic schema @@ -69,7 +69,7 @@ export const dic_Schema = { item_type_list, item_units_list, item_units_conversion -} +}; export type dic_Schema = typeof dic_Schema; export interface dic_Database extends Database<dic_Schema> {} \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema/mmcif-extras.ts b/src/mol-io/reader/cif/schema/mmcif-extras.ts index cb35f4879008bbffd1cc4fbd6c4f577aae29a53a..c886e751b338abc1fcdc5661736e75c4170dc2ab 100644 --- a/src/mol-io/reader/cif/schema/mmcif-extras.ts +++ b/src/mol-io/reader/cif/schema/mmcif-extras.ts @@ -17,10 +17,10 @@ export const mmCIF_residueId_schema = { auth_comp_id: mmCIF_Schema.atom_site.auth_atom_id, auth_seq_id: mmCIF_Schema.atom_site.auth_seq_id, auth_asym_id: mmCIF_Schema.atom_site.auth_asym_id -} +}; export const mmCIF_chemCompBond_schema = { ...mmCIF_Schema.chem_comp_bond, /** Indicates if the bond entry was taken from the protonation variant dictionary */ molstar_protonation_variant: Column.Schema.Str() -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-io/reader/cif/schema/mmcif.ts b/src/mol-io/reader/cif/schema/mmcif.ts index 9a773ef182535d84e4f7f1efcb1ef3204cf3c3d9..48a35347d65596abe966afefc05d6c6cf85600e9 100644 --- a/src/mol-io/reader/cif/schema/mmcif.ts +++ b/src/mol-io/reader/cif/schema/mmcif.ts @@ -6,7 +6,7 @@ * @author molstar/ciftools package */ -import { Database, Column } from '../../../../mol-data/db' +import { Database, Column } from '../../../../mol-data/db'; import Schema = Column.Schema @@ -4679,7 +4679,7 @@ export const mmCIF_Schema = { */ details: str, }, -} +}; export type mmCIF_Schema = typeof mmCIF_Schema; export interface mmCIF_Database extends Database<mmCIF_Schema> {} \ No newline at end of file diff --git a/src/mol-io/reader/cif/text/parser.ts b/src/mol-io/reader/cif/text/parser.ts index 693754053e9743d122d4b07f94ef6ffca1067883..4aa399fa2ade9ee530ebc2e44697aaf439170e4d 100644 --- a/src/mol-io/reader/cif/text/parser.ts +++ b/src/mol-io/reader/cif/text/parser.ts @@ -23,10 +23,10 @@ * */ -import * as Data from '../data-model' -import { Tokens, TokenBuilder, Tokenizer } from '../../common/text/tokenizer' -import { ReaderResult as Result } from '../../result' -import { Task, RuntimeContext, chunkedSubtask } from '../../../../mol-task' +import * as Data from '../data-model'; +import { Tokens, TokenBuilder, Tokenizer } from '../../common/text/tokenizer'; +import { ReaderResult as Result } from '../../result'; +import { Task, RuntimeContext, chunkedSubtask } from '../../../../mol-task'; /** * Types of supported mmCIF tokens. @@ -201,7 +201,7 @@ function eatImportGet(state: TokenizerState) { case 93: // ] ++state.position; state.tokenEnd = state.position; - state.isImportGet = false + state.isImportGet = false; return; default: ++state.position; @@ -459,7 +459,7 @@ function moveNextInternal(state: TokenizerState) { // _ means column name, including _import.get } else if (state.data.charCodeAt(state.tokenStart) === 95) { // _ if (state.inSaveFrame && isImportGet(state)) { - state.isImportGet = true + state.isImportGet = true; } state.tokenType = CifTokenType.ColumnName; // 5th char needs to be _ for data_, save_ or loop_ @@ -527,27 +527,27 @@ function FrameContext(): FrameContext { } function CifCategories(categoryNames: string[], categoryData: { [name: string]: CifCategoryData }): { [name: string]: Data.CifCategory } { - const categories = Object.create(null) + const categories = Object.create(null); for (const name of categoryNames) { - const d = categoryData[name] - categories[name] = Data.CifCategory(d.name, d.rowCount, d.fieldNames, d.fields) + const d = categoryData[name]; + categories[name] = Data.CifCategory(d.name, d.rowCount, d.fieldNames, d.fields); } - return categories + return categories; } function CifBlock(ctx: FrameContext, header: string, saveFrames?: Data.CifFrame[]): Data.CifBlock { - return Data.CifBlock(ctx.categoryNames, CifCategories(ctx.categoryNames, ctx.categoryData), header, saveFrames) + return Data.CifBlock(ctx.categoryNames, CifCategories(ctx.categoryNames, ctx.categoryData), header, saveFrames); } function CifSaveFrame(ctx: FrameContext, header: string): Data.CifBlock { - return Data.CifBlock(ctx.categoryNames, CifCategories(ctx.categoryNames, ctx.categoryData), header) + return Data.CifBlock(ctx.categoryNames, CifCategories(ctx.categoryNames, ctx.categoryData), header); } function addFields(ctx: FrameContext, name: string, rowCount: number, fieldNames: string[], fields: { [k: string]: Data.CifField }) { if (name in ctx.categoryData) { - const cat = ctx.categoryData[name] - cat.fieldNames.push(...fieldNames) - Object.assign(cat.fields, fields) + const cat = ctx.categoryData[name]; + cat.fieldNames.push(...fieldNames); + Object.assign(cat.fields, fields); } else { ctx.categoryData[name] = { name, rowCount, fieldNames, fields }; ctx.categoryNames.push(name); @@ -577,14 +577,14 @@ function handleSingle(tokenizer: TokenizerState, ctx: FrameContext): CifCategory hasError: true, errorLine: tokenizer.lineNumber, errorMessage: 'Expected value.' - } + }; } fields[fieldName] = Data.CifField.ofTokens({ data: tokenizer.data, indices: [tokenizer.tokenStart, tokenizer.tokenEnd], count: 1 }); fieldNames[fieldNames.length] = fieldName; moveNext(tokenizer); } - addFields(ctx, name.substr(1), 1, fieldNames, fields) + addFields(ctx, name.substr(1), 1, fieldNames, fields); return { hasError: false, @@ -665,7 +665,7 @@ async function handleLoop(tokenizer: TokenizerState, ctx: FrameContext): Promise if (isFlat) { for (let i = 0; i < fieldCount; i++) { const fields = { '': Data.CifField.ofTokens(tokens[i]) }; - addFields(ctx, fieldNames[i].substr(1), rowCount, [''], fields) + addFields(ctx, fieldNames[i].substr(1), rowCount, [''], fields); } } else { const fields = Object.create(null); @@ -673,7 +673,7 @@ async function handleLoop(tokenizer: TokenizerState, ctx: FrameContext): Promise fields[fieldNames[i]] = Data.CifField.ofTokens(tokens[i]); } - addFields(ctx, name.substr(1), rowCount, fieldNames, fields) + addFields(ctx, name.substr(1), rowCount, fieldNames, fields); } return { @@ -716,7 +716,7 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) { saveCtx.categoryNames, CifCategories(saveCtx.categoryNames, saveCtx.categoryData), '' ); - let saveHeader = '' + let saveHeader = ''; runtimeCtx.update({ message: 'Parsing...', current: 0, max: data.length }); @@ -734,7 +734,7 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) { } blockHeader = data.substring(tokenizer.tokenStart + 5, tokenizer.tokenEnd); blockCtx = FrameContext(); - saveFrames = [] + saveFrames = []; moveNext(tokenizer); // Save frame } else if (token === CifTokenType.Save) { @@ -767,7 +767,7 @@ async function parseInternal(data: string, runtimeCtx: RuntimeContext) { } // Out of options } else { - console.log(tokenizer.tokenType, Tokenizer.getTokenString(tokenizer)) + console.log(tokenizer.tokenType, Tokenizer.getTokenString(tokenizer)); return error(tokenizer.lineNumber, 'Unexpected token. Expected data_, loop_, or data name.'); } } diff --git a/src/mol-io/reader/common/text/column/fixed.ts b/src/mol-io/reader/common/text/column/fixed.ts index 182ac81d303e7de1b67ef2f1f73c83b7c3bedcdc..09e91f9f07048e44d2c8576e305795811e27c9de 100644 --- a/src/mol-io/reader/common/text/column/fixed.ts +++ b/src/mol-io/reader/common/text/column/fixed.ts @@ -4,14 +4,14 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column, ColumnHelpers } from '../../../../../mol-data/db' -import { trimStr, Tokens } from '../tokenizer' -import { parseIntSkipLeadingWhitespace, parseFloatSkipLeadingWhitespace } from '../number-parser' +import { Column, ColumnHelpers } from '../../../../../mol-data/db'; +import { trimStr, Tokens } from '../tokenizer'; +import { parseIntSkipLeadingWhitespace, parseFloatSkipLeadingWhitespace } from '../number-parser'; export default function FixedColumnProvider(lines: Tokens) { return function<T extends Column.Schema>(offset: number, width: number, type: T) { return FixedColumn(lines, offset, width, type); - } + }; } export function FixedColumn<T extends Column.Schema>(lines: Tokens, offset: number, width: number, schema: T): Column<T['T']> { diff --git a/src/mol-io/reader/common/text/column/token.ts b/src/mol-io/reader/common/text/column/token.ts index df8ea949cba03bc81616e20c4186680c009505bb..bb11bc9dc605d4cf576581a8f7182cbe3b51f92a 100644 --- a/src/mol-io/reader/common/text/column/token.ts +++ b/src/mol-io/reader/common/text/column/token.ts @@ -4,14 +4,14 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column, ColumnHelpers } from '../../../../../mol-data/db' -import { Tokens } from '../tokenizer' -import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../number-parser' +import { Column, ColumnHelpers } from '../../../../../mol-data/db'; +import { Tokens } from '../tokenizer'; +import { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../number-parser'; export default function TokenColumnProvider(tokens: Tokens) { return function<T extends Column.Schema>(type: T) { return TokenColumn(tokens, type); - } + }; } export function TokenColumn<T extends Column.Schema>(tokens: Tokens, schema: T): Column<T['T']> { @@ -49,5 +49,5 @@ export function areValuesEqualProvider(tokens: Tokens) { } } return true; - } + }; } \ No newline at end of file diff --git a/src/mol-io/reader/common/text/number-parser.ts b/src/mol-io/reader/common/text/number-parser.ts index 4f609cec74eaf9779186f09704a50875c1baf658..e1d2a6ad6a810cb2603b0b8881c7a284279ca330 100644 --- a/src/mol-io/reader/common/text/number-parser.ts +++ b/src/mol-io/reader/common/text/number-parser.ts @@ -111,7 +111,7 @@ export function getNumberType(str: string): NumberType { // string is . or -. if (str.charCodeAt(start) === 46 && end - start === 1) { - return NumberType.NaN + return NumberType.NaN; } while (start < end) { diff --git a/src/mol-io/reader/common/text/tokenizer.ts b/src/mol-io/reader/common/text/tokenizer.ts index 3e4b75391327cfa1a1afc665479c558faa485651..b9b74aac01de75a1367057977178d4674cd0bff1 100644 --- a/src/mol-io/reader/common/text/tokenizer.ts +++ b/src/mol-io/reader/common/text/tokenizer.ts @@ -6,9 +6,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { chunkedSubtask, RuntimeContext } from '../../../../mol-task' +import { chunkedSubtask, RuntimeContext } from '../../../../mol-task'; -export { Tokenizer } +export { Tokenizer }; interface Tokenizer { data: string, @@ -45,10 +45,10 @@ namespace Tokenizer { /** Resets the state */ export function reset (state: Tokenizer) { - state.position = 0 - state.lineNumber = 1 - state.tokenStart = 0 - state.tokenEnd = 0 + state.position = 0; + state.lineNumber = 1; + state.tokenStart = 0; + state.tokenEnd = 0; } /** @@ -132,7 +132,7 @@ namespace Tokenizer { export function readAllLines(data: string) { const state = Tokenizer(data); - const tokens = TokenBuilder.create(state.data, Math.max(data.length / 80, 2)) + const tokens = TokenBuilder.create(state.data, Math.max(data.length / 80, 2)); while (markLine(state)) { TokenBuilder.add(tokens, state.tokenStart, state.tokenEnd); } @@ -277,13 +277,13 @@ export namespace TokenBuilder { } export function create(data: string, size: number): Tokens { - size = Math.max(10, size) + size = Math.max(10, size); return <Builder>{ data, indicesLenMinus2: (size - 2) | 0, count: 0, offset: 0, indices: new Uint32Array(size) - } + }; } } \ No newline at end of file diff --git a/src/mol-io/reader/csv/data-model.ts b/src/mol-io/reader/csv/data-model.ts index 7c538467e25bf5eb2143ba569af1af41fe02e3e1..0c0dbf026c73bed312603f5e07f177c81582beaa 100644 --- a/src/mol-io/reader/csv/data-model.ts +++ b/src/mol-io/reader/csv/data-model.ts @@ -4,9 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { CifField as CsvColumn } from '../cif/data-model' +import { CifField as CsvColumn } from '../cif/data-model'; -export { CsvColumn } +export { CsvColumn }; export interface CsvFile { readonly table: CsvTable diff --git a/src/mol-io/reader/csv/field.ts b/src/mol-io/reader/csv/field.ts index cf2b6449e3a1602e0ca0c8015ad574c47de281ad..41ec167dde5076127140448a01f41740dde71615 100644 --- a/src/mol-io/reader/csv/field.ts +++ b/src/mol-io/reader/csv/field.ts @@ -6,4 +6,4 @@ import { CifField } from '../cif/data-model'; -export const Field = CifField.ofTokens \ No newline at end of file +export const Field = CifField.ofTokens; \ No newline at end of file diff --git a/src/mol-io/reader/csv/parser.ts b/src/mol-io/reader/csv/parser.ts index 18897338fc0d215f4b683c29232989f18bac8638..706f79cddad02ba4761900b7b235b3690c5f423d 100644 --- a/src/mol-io/reader/csv/parser.ts +++ b/src/mol-io/reader/csv/parser.ts @@ -5,11 +5,11 @@ */ // import { Column } from 'mol-data/db' -import { Tokens, TokenBuilder, Tokenizer } from '../common/text/tokenizer' -import * as Data from './data-model' -import { Field } from './field' -import { ReaderResult as Result } from '../result' -import { Task, RuntimeContext, chunkedSubtask, } from '../../../mol-task' +import { Tokens, TokenBuilder, Tokenizer } from '../common/text/tokenizer'; +import * as Data from './data-model'; +import { Field } from './field'; +import { ReaderResult as Result } from '../result'; +import { Task, RuntimeContext, chunkedSubtask, } from '../../../mol-task'; const enum CsvTokenType { Value = 0, @@ -40,7 +40,7 @@ interface State { function State(data: string, runtimeCtx: RuntimeContext, opts: CsvOptions): State { - const tokenizer = Tokenizer(data) + const tokenizer = Tokenizer(data); return { data, tokenizer, @@ -70,7 +70,7 @@ function State(data: string, runtimeCtx: RuntimeContext, opts: CsvOptions): Stat function eatValue(state: Tokenizer, delimiterCharCode: number) { while (state.position < state.length) { const c = state.data.charCodeAt(state.position); - ++state.position + ++state.position; switch (c) { case 10: // \n case 13: // \r @@ -105,7 +105,7 @@ function eatQuoted(state: Tokenizer, quoteCharCode: number, delimiterCharCode: n state.tokenStart++; state.tokenEnd = state.position; ++state.position; - return skipEmpty(state, delimiterCharCode) + return skipEmpty(state, delimiterCharCode); } } ++state.position; @@ -123,7 +123,7 @@ function skipEmpty(state: Tokenizer, delimiterCharCode: number) { if (c !== 9 && c !== 32 && c !== delimiterCharCode) { // \t or ' ' return c === 10 || c === 13; // \n or \r } - ++state.position + ++state.position; } } @@ -159,8 +159,8 @@ function skipWhitespace(state: Tokenizer) { function skipLine(state: Tokenizer) { while (state.position < state.length) { const c = state.data.charCodeAt(state.position); - if (c === 10 || c === 13) return // \n or \r - ++state.position + if (c === 10 || c === 13) return; // \n or \r + ++state.position; } } @@ -169,7 +169,7 @@ function skipLine(state: Tokenizer) { * Returns true when the current char is a newline, i.e. indicating a full record. */ function moveNextInternal(state: State) { - const tokenizer = state.tokenizer + const tokenizer = state.tokenizer; skipWhitespace(tokenizer); if (tokenizer.position >= tokenizer.length) { @@ -203,23 +203,23 @@ function moveNext(state: State) { while (state.tokenType === CsvTokenType.Comment) { newRecord = moveNextInternal(state); } - return newRecord + return newRecord; } function readRecordsChunk(chunkSize: number, state: State) { - if (state.tokenType === CsvTokenType.End) return 0 + if (state.tokenType === CsvTokenType.End) return 0; let counter = 0; - let newRecord: boolean | undefined + let newRecord: boolean | undefined; const { tokens, tokenizer } = state; while (state.tokenType === CsvTokenType.Value && counter < chunkSize) { TokenBuilder.add(tokens[state.fieldCount % state.columnCount], tokenizer.tokenStart, tokenizer.tokenEnd); - ++state.fieldCount + ++state.fieldCount; newRecord = moveNext(state); if (newRecord) { - ++state.recordCount + ++state.recordCount; ++counter; } } @@ -228,48 +228,48 @@ function readRecordsChunk(chunkSize: number, state: State) { function readRecordsChunks(state: State) { let newRecord = moveNext(state); - if (newRecord) ++state.recordCount + if (newRecord) ++state.recordCount; return chunkedSubtask(state.runtimeCtx, 100000, state, readRecordsChunk, (ctx, state) => ctx.update({ message: 'Parsing...', current: state.tokenizer.position, max: state.data.length })); } function addColumn (state: State) { - state.columnNames.push(Tokenizer.getTokenString(state.tokenizer)) - state.tokens.push(TokenBuilder.create(state.tokenizer.data, state.data.length / 80)) + state.columnNames.push(Tokenizer.getTokenString(state.tokenizer)); + state.tokens.push(TokenBuilder.create(state.tokenizer.data, state.data.length / 80)); } function init(state: State) { - let newRecord = moveNext(state) + let newRecord = moveNext(state); while (!newRecord) { - addColumn(state) + addColumn(state); newRecord = moveNext(state); } - addColumn(state) - state.columnCount = state.columnNames.length + addColumn(state); + state.columnCount = state.columnNames.length; if (state.noColumnNamesRecord) { - state.columnNames.forEach((x, i, arr) => arr[i] = i + '') - Tokenizer.reset(state.tokenizer) + state.columnNames.forEach((x, i, arr) => arr[i] = i + ''); + Tokenizer.reset(state.tokenizer); } } async function handleRecords(state: State): Promise<Data.CsvTable> { - init(state) - await readRecordsChunks(state) + init(state); + await readRecordsChunks(state); const columns: Data.CsvColumns = Object.create(null); for (let i = 0; i < state.columnCount; ++i) { columns[state.columnNames[i]] = Field(state.tokens[i]); } - return Data.CsvTable(state.recordCount, state.columnNames, columns) + return Data.CsvTable(state.recordCount, state.columnNames, columns); } async function parseInternal(data: string, ctx: RuntimeContext, opts: CsvOptions): Promise<Result<Data.CsvFile>> { const state = State(data, ctx, opts); ctx.update({ message: 'Parsing...', current: 0, max: data.length }); - const table = await handleRecords(state) - const result = Data.CsvFile(table) + const table = await handleRecords(state); + const result = Data.CsvFile(table); return Result.success(result); } @@ -281,7 +281,7 @@ interface CsvOptions { } export function parseCsv(data: string, opts?: Partial<CsvOptions>) { - const completeOpts = Object.assign({}, { quote: '"', comment: '#', delimiter: ',', noColumnNames: false }, opts) + const completeOpts = Object.assign({}, { quote: '"', comment: '#', delimiter: ',', noColumnNames: false }, opts); return Task.create<Result<Data.CsvFile>>('Parse CSV', async ctx => { return await parseInternal(data, ctx, completeOpts); }); diff --git a/src/mol-io/reader/csv/schema.ts b/src/mol-io/reader/csv/schema.ts index da4529753d64a9d41c3cfab71213c7523dae4010..7e9b8f3211d9485f0faa433f276533a8e80f622c 100644 --- a/src/mol-io/reader/csv/schema.ts +++ b/src/mol-io/reader/csv/schema.ts @@ -4,4 +4,4 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export { toTable } from '../cif/schema' \ No newline at end of file +export { toTable } from '../cif/schema'; \ No newline at end of file diff --git a/src/mol-io/reader/dcd/parser.ts b/src/mol-io/reader/dcd/parser.ts index 7770ab7e750e12b4b0a8c4065e5e41deebf2517e..861410dede95e8cb61cdac26b7bd5901560f131c 100644 --- a/src/mol-io/reader/dcd/parser.ts +++ b/src/mol-io/reader/dcd/parser.ts @@ -4,12 +4,12 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ReaderResult as Result } from '../result' -import { Task } from '../../../mol-task' -import { Cell } from '../../../mol-math/geometry/spacegroup/cell' -import { Vec3 } from '../../../mol-math/linear-algebra' -import { Mutable } from '../../../mol-util/type-helpers' -import { uint8ToString } from '../../common/binary' +import { ReaderResult as Result } from '../result'; +import { Task } from '../../../mol-task'; +import { Cell } from '../../../mol-math/geometry/spacegroup/cell'; +import { Vec3 } from '../../../mol-math/linear-algebra'; +import { Mutable } from '../../../mol-util/type-helpers'; +import { uint8ToString } from '../../common/binary'; export interface DcdHeader { readonly NSET: number, @@ -59,157 +59,157 @@ export function _parseDcd(data: Uint8Array): DcdFile { // Z(I), I=1,NATOM // ========================================================================== - const dv = new DataView(data.buffer) + const dv = new DataView(data.buffer); - const header: Mutable<DcdHeader> = Object.create(null) - const frames: DcdFrame[] = [] + const header: Mutable<DcdHeader> = Object.create(null); + const frames: DcdFrame[] = []; - let nextPos = 0 + let nextPos = 0; // header block - const intView = new Int32Array(data.buffer, 0, 23) - const ef = intView[0] !== dv.getInt32(0) // endianess flag + const intView = new Int32Array(data.buffer, 0, 23); + const ef = intView[0] !== dv.getInt32(0); // endianess flag // swap byte order when big endian (84 indicates little endian) if (intView[0] !== 84) { - const n = data.byteLength + const n = data.byteLength; for (let i = 0; i < n; i += 4) { - dv.setFloat32(i, dv.getFloat32(i), true) + dv.setFloat32(i, dv.getFloat32(i), true); } } if (intView[0] !== 84) { - throw new Error('dcd bad format, header block start') + throw new Error('dcd bad format, header block start'); } // format indicator, should read 'CORD' const formatString = String.fromCharCode( dv.getUint8(4), dv.getUint8(5), dv.getUint8(6), dv.getUint8(7) - ) + ); if (formatString !== 'CORD') { - throw new Error('dcd bad format, format string') + throw new Error('dcd bad format, format string'); } - let isCharmm = false - let extraBlock = false - let fourDims = false + let isCharmm = false; + let extraBlock = false; + let fourDims = false; // version field in charmm, unused in X-PLOR if (intView[22] !== 0) { - isCharmm = true - if (intView[12] !== 0) extraBlock = true - if (intView[13] === 1) fourDims = true + isCharmm = true; + if (intView[12] !== 0) extraBlock = true; + if (intView[13] === 1) fourDims = true; } - header.NSET = intView[2] - header.ISTART = intView[3] - header.NSAVC = intView[4] - header.NAMNF = intView[10] + header.NSET = intView[2]; + header.ISTART = intView[3]; + header.NSAVC = intView[4]; + header.NAMNF = intView[10]; if (isCharmm) { - header.DELTA = dv.getFloat32(44, ef) + header.DELTA = dv.getFloat32(44, ef); } else { - header.DELTA = dv.getFloat64(44, ef) + header.DELTA = dv.getFloat64(44, ef); } if (intView[22] !== 84) { - throw new Error('dcd bad format, header block end') + throw new Error('dcd bad format, header block end'); } - nextPos = nextPos + 21 * 4 + 8 + nextPos = nextPos + 21 * 4 + 8; // title block - const titleEnd = dv.getInt32(nextPos, ef) - const titleStart = nextPos + 1 + const titleEnd = dv.getInt32(nextPos, ef); + const titleStart = nextPos + 1; if ((titleEnd - 4) % 80 !== 0) { - throw new Error('dcd bad format, title block start') + throw new Error('dcd bad format, title block start'); } - header.TITLE = uint8ToString(data.subarray(titleStart, titleEnd)) + header.TITLE = uint8ToString(data.subarray(titleStart, titleEnd)); if (dv.getInt32(titleStart + titleEnd + 4 - 1, ef) !== titleEnd) { - throw new Error('dcd bad format, title block end') + throw new Error('dcd bad format, title block end'); } - nextPos = nextPos + titleEnd + 8 + nextPos = nextPos + titleEnd + 8; // natom block if (dv.getInt32(nextPos, ef) !== 4) { - throw new Error('dcd bad format, natom block start') + throw new Error('dcd bad format, natom block start'); } - header.NATOM = dv.getInt32(nextPos + 4, ef) + header.NATOM = dv.getInt32(nextPos + 4, ef); if (dv.getInt32(nextPos + 8, ef) !== 4) { - throw new Error('dcd bad format, natom block end') + throw new Error('dcd bad format, natom block end'); } - nextPos = nextPos + 4 + 8 + nextPos = nextPos + 4 + 8; // fixed atoms block if (header.NAMNF > 0) { // TODO read coordinates and indices of fixed atoms - throw new Error('dcd format with fixed atoms unsupported, aborting') + throw new Error('dcd format with fixed atoms unsupported, aborting'); } // frames - const natom = header.NATOM - const natom4 = natom * 4 + const natom = header.NATOM; + const natom4 = natom * 4; for (let i = 0, n = header.NSET; i < n; ++i) { const frame: Mutable<DcdFrame> = Object.create({ elementCount: natom - }) + }); if (extraBlock) { - nextPos += 4 // block start + nextPos += 4; // block start // cell: A, alpha, B, beta, gamma, C (doubles) const size = Vec3.create( dv.getFloat64(nextPos, ef), dv.getFloat64(nextPos + 2 * 8, ef), dv.getFloat64(nextPos + 5 * 8, ef) - ) + ); const anglesInRadians = Vec3.create( dv.getFloat64(nextPos + 1, ef), dv.getFloat64(nextPos + 3 * 8, ef), dv.getFloat64(nextPos + 4 * 8, ef) - ) - frame.cell = Cell.create(size, anglesInRadians) - nextPos += 48 - nextPos += 4 // block end + ); + frame.cell = Cell.create(size, anglesInRadians); + nextPos += 48; + nextPos += 4; // block end } // xyz coordinates for (let j = 0; j < 3; ++j) { if (dv.getInt32(nextPos, ef) !== natom4) { - throw new Error(`dcd bad format, coord block start: ${i}, ${j}`) + throw new Error(`dcd bad format, coord block start: ${i}, ${j}`); } - nextPos += 4 // block start - const c = new Float32Array(data.buffer, nextPos, natom) - if (j === 0) frame.x = c - else if (j === 1) frame.y = c - else frame.z = c + nextPos += 4; // block start + const c = new Float32Array(data.buffer, nextPos, natom); + if (j === 0) frame.x = c; + else if (j === 1) frame.y = c; + else frame.z = c; - nextPos += natom4 + nextPos += natom4; if (dv.getInt32(nextPos, ef) !== natom4) { - throw new Error(`dcd bad format, coord block end: ${i}, ${j}`) + throw new Error(`dcd bad format, coord block end: ${i}, ${j}`); } - nextPos += 4 // block end + nextPos += 4; // block end } if (fourDims) { - const bytes = dv.getInt32(nextPos, ef) - nextPos += 4 + bytes + 4 // block start + skip + block end + const bytes = dv.getInt32(nextPos, ef); + nextPos += 4 + bytes + 4; // block start + skip + block end } - frames.push(frame) + frames.push(frame); } - return { header, frames } + return { header, frames }; } export function parseDcd(data: Uint8Array) { return Task.create<Result<DcdFile>>('Parse DCD', async ctx => { try { - const dcdFile = _parseDcd(data) - return Result.success(dcdFile) + const dcdFile = _parseDcd(data); + return Result.success(dcdFile); } catch (e) { - return Result.error(e) + return Result.error(e); } - }) + }); } \ No newline at end of file diff --git a/src/mol-io/reader/dsn6/parser.ts b/src/mol-io/reader/dsn6/parser.ts index b58df1f080dc2458e8c3722472f5aa92ed677eb0..b8e4f40c7c5ccba19ec46b29e18131940aed35ed 100644 --- a/src/mol-io/reader/dsn6/parser.ts +++ b/src/mol-io/reader/dsn6/parser.ts @@ -5,8 +5,8 @@ */ import { Task, RuntimeContext } from '../../../mol-task'; -import { Dsn6File, Dsn6Header } from './schema' -import { ReaderResult as Result } from '../result' +import { Dsn6File, Dsn6Header } from './schema'; +import { ReaderResult as Result } from '../result'; import { FileHandle } from '../../common/file-handle'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; @@ -32,12 +32,12 @@ function parseBrixHeader(str: string): Dsn6Header { divisor: parseFloat(str.substr(138, 12)), summand: parseInt(str.substr(155, 8)), sigma: parseFloat(str.substr(170, 12)) - } + }; } function parseDsn6Header(buffer: SimpleBuffer, littleEndian: boolean): Dsn6Header { - const readInt = littleEndian ? (o: number) => buffer.readInt16LE(o * 2) : (o: number) => buffer.readInt16BE(o * 2) - const factor = 1 / readInt(17) + const readInt = littleEndian ? (o: number) => buffer.readInt16LE(o * 2) : (o: number) => buffer.readInt16BE(o * 2); + const factor = 1 / readInt(17); return { xStart: readInt(0), yStart: readInt(1), @@ -57,55 +57,55 @@ function parseDsn6Header(buffer: SimpleBuffer, littleEndian: boolean): Dsn6Heade divisor: readInt(15) / 100, summand: readInt(16), sigma: undefined - } + }; } function getBlocks(header: Dsn6Header) { - const { xExtent, yExtent, zExtent } = header - const xBlocks = Math.ceil(xExtent / 8) - const yBlocks = Math.ceil(yExtent / 8) - const zBlocks = Math.ceil(zExtent / 8) - return { xBlocks, yBlocks, zBlocks } + const { xExtent, yExtent, zExtent } = header; + const xBlocks = Math.ceil(xExtent / 8); + const yBlocks = Math.ceil(yExtent / 8); + const zBlocks = Math.ceil(zExtent / 8); + return { xBlocks, yBlocks, zBlocks }; } export async function readDsn6Header(file: FileHandle): Promise<{ header: Dsn6Header, littleEndian: boolean }> { - const { buffer } = await file.readBuffer(0, dsn6HeaderSize) - const brixStr = String.fromCharCode.apply(null, buffer) as string - const isBrix = brixStr.startsWith(':-)') - const littleEndian = isBrix || buffer.readInt16LE(18 * 2) === 100 - const header = isBrix ? parseBrixHeader(brixStr) : parseDsn6Header(buffer, littleEndian) - return { header, littleEndian } + const { buffer } = await file.readBuffer(0, dsn6HeaderSize); + const brixStr = String.fromCharCode.apply(null, buffer) as string; + const isBrix = brixStr.startsWith(':-)'); + const littleEndian = isBrix || buffer.readInt16LE(18 * 2) === 100; + const header = isBrix ? parseBrixHeader(brixStr) : parseDsn6Header(buffer, littleEndian); + return { header, littleEndian }; } export async function parseDsn6Values(header: Dsn6Header, source: Uint8Array, target: Float32Array, littleEndian: boolean) { if (!littleEndian) { // even though the values are one byte they need to be swapped like they are 2 - SimpleBuffer.flipByteOrderInPlace2(source.buffer) + SimpleBuffer.flipByteOrderInPlace2(source.buffer); } - const { divisor, summand, xExtent, yExtent, zExtent } = header - const { xBlocks, yBlocks, zBlocks } = getBlocks(header) + const { divisor, summand, xExtent, yExtent, zExtent } = header; + const { xBlocks, yBlocks, zBlocks } = getBlocks(header); - let offset = 0 + let offset = 0; // loop over blocks for (let zz = 0; zz < zBlocks; ++zz) { for (let yy = 0; yy < yBlocks; ++yy) { for (let xx = 0; xx < xBlocks; ++xx) { // loop inside block for (let k = 0; k < 8; ++k) { - const z = 8 * zz + k + const z = 8 * zz + k; for (let j = 0; j < 8; ++j) { - const y = 8 * yy + j + const y = 8 * yy + j; for (let i = 0; i < 8; ++i) { - const x = 8 * xx + i + const x = 8 * xx + i; // check if remaining slice-part contains values if (x < xExtent && y < yExtent && z < zExtent) { - const idx = ((((x * yExtent) + y) * zExtent) + z) - target[idx] = (source[offset] - summand) / divisor - ++offset + const idx = ((((x * yExtent) + y) * zExtent) + z); + target[idx] = (source[offset] - summand) / divisor; + ++offset; } else { - offset += 8 - i - break + offset += 8 - i; + break; } } } @@ -116,23 +116,23 @@ export async function parseDsn6Values(header: Dsn6Header, source: Uint8Array, ta } export function getDsn6Counts(header: Dsn6Header) { - const { xExtent, yExtent, zExtent } = header - const { xBlocks, yBlocks, zBlocks } = getBlocks(header) - const valueCount = xExtent * yExtent * zExtent - const count = xBlocks * 8 * yBlocks * 8 * zBlocks * 8 - const elementByteSize = 1 - const byteCount = count * elementByteSize - return { count, byteCount, valueCount } + const { xExtent, yExtent, zExtent } = header; + const { xBlocks, yBlocks, zBlocks } = getBlocks(header); + const valueCount = xExtent * yExtent * zExtent; + const count = xBlocks * 8 * yBlocks * 8 * zBlocks * 8; + const elementByteSize = 1; + const byteCount = count * elementByteSize; + return { count, byteCount, valueCount }; } async function parseInternal(file: FileHandle, size: number, ctx: RuntimeContext): Promise<Dsn6File> { await ctx.update({ message: 'Parsing DSN6/BRIX file...' }); - const { header, littleEndian } = await readDsn6Header(file) - const { buffer } = await file.readBuffer(dsn6HeaderSize, size - dsn6HeaderSize) - const { valueCount } = getDsn6Counts(header) + const { header, littleEndian } = await readDsn6Header(file); + const { buffer } = await file.readBuffer(dsn6HeaderSize, size - dsn6HeaderSize); + const { valueCount } = getDsn6Counts(header); - const values = new Float32Array(valueCount) - await parseDsn6Values(header, buffer, values, littleEndian) + const values = new Float32Array(valueCount); + await parseDsn6Values(header, buffer, values, littleEndian); const result: Dsn6File = { header, values }; return result; @@ -145,9 +145,9 @@ export function parseFile(file: FileHandle, size: number) { } catch (e) { return Result.error(e); } - }) + }); } export function parse(buffer: Uint8Array) { - return parseFile(FileHandle.fromBuffer(SimpleBuffer.fromUint8Array(buffer)), buffer.length) + return parseFile(FileHandle.fromBuffer(SimpleBuffer.fromUint8Array(buffer)), buffer.length); } \ No newline at end of file diff --git a/src/mol-io/reader/gro/parser.ts b/src/mol-io/reader/gro/parser.ts index 92134b5882ac2a54fe442f1d6edce2a9c911165a..3037a9bf3f3eb363d0df38a8992f4af7039017e8 100644 --- a/src/mol-io/reader/gro/parser.ts +++ b/src/mol-io/reader/gro/parser.ts @@ -5,12 +5,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column } from '../../../mol-data/db' -import { Tokenizer } from '../common/text/tokenizer' -import FixedColumn from '../common/text/column/fixed' -import * as Schema from './schema' -import { ReaderResult as Result } from '../result' -import { Task, RuntimeContext } from '../../../mol-task' +import { Column } from '../../../mol-data/db'; +import { Tokenizer } from '../common/text/tokenizer'; +import FixedColumn from '../common/text/column/fixed'; +import * as Schema from './schema'; +import { ReaderResult as Result } from '../result'; +import { Task, RuntimeContext } from '../../../mol-task'; interface State { tokenizer: Tokenizer, diff --git a/src/mol-io/reader/gro/schema.d.ts b/src/mol-io/reader/gro/schema.d.ts index c2ef84426e4176e0d3ba54bfe31c441eb1e3e4cc..8705a2fee3e965b073575bf976f2c88119f41946 100644 --- a/src/mol-io/reader/gro/schema.d.ts +++ b/src/mol-io/reader/gro/schema.d.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column } from '../../../mol-data/db' +import { Column } from '../../../mol-data/db'; export interface GroHeader { title: string, diff --git a/src/mol-io/reader/mol/parser.ts b/src/mol-io/reader/mol/parser.ts index e0fec0c6774d4602ef64f555000522001f90067f..666b35f9c6efdce876377dff0f2200741da258da 100644 --- a/src/mol-io/reader/mol/parser.ts +++ b/src/mol-io/reader/mol/parser.ts @@ -56,7 +56,7 @@ function handleAtoms(tokenizer: Tokenizer, count: number): MolFile['atoms'] { y: TokenColumn(y)(Column.Schema.float), z: TokenColumn(z)(Column.Schema.float), type_symbol: TokenColumn(type_symbol)(Column.Schema.str) - } + }; } function handleBonds(tokenizer: Tokenizer, count: number): MolFile['bonds'] { @@ -81,7 +81,7 @@ function handleBonds(tokenizer: Tokenizer, count: number): MolFile['bonds'] { atomIdxA: TokenColumn(atomIdxA)(Column.Schema.int), atomIdxB: TokenColumn(atomIdxB)(Column.Schema.int), order: TokenColumn(order)(Column.Schema.int) - } + }; } function parseInternal(data: string): Result<MolFile> { @@ -104,12 +104,12 @@ function parseInternal(data: string): Result<MolFile> { comment, atoms, bonds - } + }; return Result.success(result); } export function parseMol(data: string) { return Task.create<Result<MolFile>>('Parse Mol', async () => { - return parseInternal(data) + return parseInternal(data); }); } \ No newline at end of file diff --git a/src/mol-io/reader/mol2/parser.ts b/src/mol-io/reader/mol2/parser.ts index 4e9429f31c8937bb4b4ffa0cafa5d87027aca480..cb7324fef37ad29bb40909d59e2ae0e4b4ec6ee0 100644 --- a/src/mol-io/reader/mol2/parser.ts +++ b/src/mol-io/reader/mol2/parser.ts @@ -11,12 +11,12 @@ // but not // const undefPooledStr = UndefinedColumn(molecule.num_atoms, ColumnType.pooledStr); // because latter actuall return a column of zeros -import { Column } from '../../../mol-data/db' -import { TokenBuilder, Tokenizer } from '../common/text/tokenizer' -import TokenColumn from '../common/text/column/token' -import * as Schema from './schema' -import { ReaderResult as Result } from '../result' -import { Task, RuntimeContext, chunkedSubtask } from '../../../mol-task' +import { Column } from '../../../mol-data/db'; +import { TokenBuilder, Tokenizer } from '../common/text/tokenizer'; +import TokenColumn from '../common/text/column/token'; +import * as Schema from './schema'; +import { ReaderResult as Result } from '../result'; +import { Task, RuntimeContext, chunkedSubtask } from '../../../mol-task'; const { skipWhitespace, eatValue, markLine, getTokenString, readLine } = Tokenizer; @@ -76,12 +76,12 @@ function handleMolecule(state: State) { molecule.charge_type = getTokenString(tokenizer); markLine(tokenizer); - if (getTokenString(tokenizer) === '') return - molecule.status_bits = getTokenString(tokenizer) + if (getTokenString(tokenizer) === '') return; + molecule.status_bits = getTokenString(tokenizer); markLine(tokenizer); - if (getTokenString(tokenizer) === '') return - molecule.mol_comment = getTokenString(tokenizer) + if (getTokenString(tokenizer) === '') return; + molecule.mol_comment = getTokenString(tokenizer); } function isStatus_bit(aString: string): boolean { @@ -108,7 +108,7 @@ async function handleAtoms(state: State): Promise<Schema.Mol2Atoms> { const initialTokenizerPosition = tokenizer.position; const initialTokenizerLineNumber = tokenizer.lineNumber; const firstLine = readLine(tokenizer); - const firstLineArray = firstLine.trim().split(/\s+/g) + const firstLineArray = firstLine.trim().split(/\s+/g); const firstLineLength = firstLineArray.length; // optional columns are in order "integer string float string". @@ -160,10 +160,10 @@ async function handleAtoms(state: State): Promise<Schema.Mol2Atoms> { const undefStr = Column.Undefined(molecule.num_atoms, Column.Schema.str); let numOfColumn = 6; - if (hasSubst_id) { numOfColumn++ } - if (hasSubst_name) { numOfColumn++ } - if (hasCharge) { numOfColumn++ } - if (hasStatus_bit) { numOfColumn++ } + if (hasSubst_id) { numOfColumn++; } + if (hasSubst_name) { numOfColumn++; } + if (hasCharge) { numOfColumn++; } + if (hasStatus_bit) { numOfColumn++; } tokenizer.position = initialTokenizerPosition; tokenizer.lineNumber = initialTokenizerLineNumber; @@ -250,7 +250,7 @@ async function handleBonds(state: State): Promise<Schema.Mol2Bonds> { const initialTokenizerPosition = tokenizer.position; const initialTokenizerLineNumber = tokenizer.lineNumber; const firstLine = readLine(tokenizer); - const firstLineArray = firstLine.trim().split(/\s+/g) + const firstLineArray = firstLine.trim().split(/\s+/g); const firstLineLength = firstLineArray.length; if (firstLineLength === 5) { hasStatus_bit = true; @@ -273,7 +273,7 @@ async function handleBonds(state: State): Promise<Schema.Mol2Bonds> { const undefStr = Column.Undefined(molecule.num_bonds, Column.Schema.str); let numberOfColumn = 4; - if (hasStatus_bit) { numberOfColumn++ } + if (hasStatus_bit) { numberOfColumn++; } tokenizer.position = initialTokenizerPosition; tokenizer.lineNumber = initialTokenizerLineNumber; diff --git a/src/mol-io/reader/mol2/schema.d.ts b/src/mol-io/reader/mol2/schema.d.ts index b444b47e6fdba91be00c3fcd1c17c88d86c1393e..9c1bac1070990fc376defe55990e6e1581a97744 100644 --- a/src/mol-io/reader/mol2/schema.d.ts +++ b/src/mol-io/reader/mol2/schema.d.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column } from '../../../mol-data/db' +import { Column } from '../../../mol-data/db'; // Full format http://chemyang.ccnu.edu.cn/ccb/server/AIMMS/mol2.pdf // there are many records but for now ignore (pass over) all but the following diff --git a/src/mol-io/reader/obj/parser.ts b/src/mol-io/reader/obj/parser.ts index 675d75195d4b68076d24c5eb5b718ff842d0e69e..1c9f9af114317c0555b393d52032050ddde56d2a 100644 --- a/src/mol-io/reader/obj/parser.ts +++ b/src/mol-io/reader/obj/parser.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ReaderResult as Result } from '../result' -import { Task, RuntimeContext } from '../../../mol-task' +import { ReaderResult as Result } from '../result'; +import { Task, RuntimeContext } from '../../../mol-task'; import { Mesh } from '../../../mol-geo/geometry/mesh/mesh'; async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Mesh>> { diff --git a/src/mol-io/reader/ply/parser.ts b/src/mol-io/reader/ply/parser.ts index 976cc989a412e3c655a1b829b1ae665ca23d1654..fab8403e19a2f7ed35f37821543876e08afdecf0 100644 --- a/src/mol-io/reader/ply/parser.ts +++ b/src/mol-io/reader/ply/parser.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ReaderResult as Result } from '../result' -import { Task, RuntimeContext } from '../../../mol-task' +import { ReaderResult as Result } from '../result'; +import { Task, RuntimeContext } from '../../../mol-task'; import { PlyFile, PlyType, PlyElement } from './schema'; import { Tokenizer, TokenBuilder, Tokens } from '../common/text/tokenizer'; import { Column } from '../../../mol-data/db'; @@ -26,7 +26,7 @@ interface State { } function State(data: string, runtimeCtx: RuntimeContext): State { - const tokenizer = Tokenizer(data) + const tokenizer = Tokenizer(data); return { data, tokenizer, @@ -35,7 +35,7 @@ function State(data: string, runtimeCtx: RuntimeContext): State { comments: [], elementSpecs: [], elements: [] - } + }; } type ColumnProperty = { kind: 'column', type: PlyType, name: string } @@ -47,37 +47,37 @@ type ListElementSpec = { kind: 'list', name: string, count: number, property: Li type ElementSpec = TableElementSpec | ListElementSpec function markHeader(tokenizer: Tokenizer) { - const endHeaderIndex = tokenizer.data.indexOf('end_header', tokenizer.position) - if (endHeaderIndex === -1) throw new Error(`no 'end_header' record found`) + const endHeaderIndex = tokenizer.data.indexOf('end_header', tokenizer.position); + if (endHeaderIndex === -1) throw new Error(`no 'end_header' record found`); // TODO set `tokenizer.lineNumber` correctly - tokenizer.tokenStart = tokenizer.position - tokenizer.tokenEnd = endHeaderIndex - tokenizer.position = endHeaderIndex - Tokenizer.eatLine(tokenizer) + tokenizer.tokenStart = tokenizer.position; + tokenizer.tokenEnd = endHeaderIndex; + tokenizer.position = endHeaderIndex; + Tokenizer.eatLine(tokenizer); } function parseHeader(state: State) { - const { tokenizer, comments, elementSpecs } = state + const { tokenizer, comments, elementSpecs } = state; - markHeader(tokenizer) - const headerLines = Tokenizer.getTokenString(tokenizer).split(/\r?\n/) + markHeader(tokenizer); + const headerLines = Tokenizer.getTokenString(tokenizer).split(/\r?\n/); - if (headerLines[0] !== 'ply') throw new Error(`data not starting with 'ply'`) - if (headerLines[1] !== 'format ascii 1.0') throw new Error(`format not 'ascii 1.0'`) + if (headerLines[0] !== 'ply') throw new Error(`data not starting with 'ply'`); + if (headerLines[1] !== 'format ascii 1.0') throw new Error(`format not 'ascii 1.0'`); - let currentName: string | undefined - let currentCount: number | undefined - let currentProperties: Property[] | undefined + let currentName: string | undefined; + let currentCount: number | undefined; + let currentProperties: Property[] | undefined; function addCurrentElementSchema() { if (currentName !== undefined && currentCount !== undefined && currentProperties !== undefined) { - let isList = false + let isList = false; for (let i = 0, il = currentProperties.length; i < il; ++i) { - const p = currentProperties[i] + const p = currentProperties[i]; if (p.kind === 'list') { - isList = true - break + isList = true; + break; } } if (isList && currentProperties.length !== 1) { @@ -90,58 +90,58 @@ function parseHeader(state: State) { name: currentName, count: currentCount, property: currentProperties[0] as ListProperty - }) + }); } else { elementSpecs.push({ kind: 'table', name: currentName, count: currentCount, properties: currentProperties as ColumnProperty[] - }) + }); } } } for (let i = 2, il = headerLines.length; i < il; ++i) { - const l = headerLines[i] - const ls = l.split(' ') + const l = headerLines[i]; + const ls = l.split(' '); if (l.startsWith('comment')) { - comments.push(l.substr(8)) + comments.push(l.substr(8)); } else if (l.startsWith('element')) { - addCurrentElementSchema() - currentProperties = [] - currentName = ls[1] - currentCount = parseInt(ls[2]) + addCurrentElementSchema(); + currentProperties = []; + currentName = ls[1]; + currentCount = parseInt(ls[2]); } else if (l.startsWith('property')) { - if (currentProperties === undefined) throw new Error(`properties outside of element`) + if (currentProperties === undefined) throw new Error(`properties outside of element`); if (ls[1] === 'list') { currentProperties.push({ kind: 'list', countType: PlyType(ls[2]), dataType: PlyType(ls[3]), name: ls[4] - }) + }); } else { currentProperties.push({ kind: 'column', type: PlyType(ls[1]), name: ls[2] - }) + }); } } else if (l.startsWith('end_header')) { - addCurrentElementSchema() + addCurrentElementSchema(); } else { - console.warn('unknown header line') + console.warn('unknown header line'); } } } function parseElements(state: State) { - const { elementSpecs } = state + const { elementSpecs } = state; for (let i = 0, il = elementSpecs.length; i < il; ++i) { - const spec = elementSpecs[i] - if (spec.kind === 'table') parseTableElement(state, spec) - else if (spec.kind === 'list') parseListElement(state, spec) + const spec = elementSpecs[i]; + if (spec.kind === 'table') parseTableElement(state, spec); + else if (spec.kind === 'list') parseListElement(state, spec); } } @@ -150,41 +150,41 @@ function getColumnSchema(type: PlyType): Column.Schema { case 'char': case 'uchar': case 'int8': case 'uint8': case 'short': case 'ushort': case 'int16': case 'uint16': case 'int': case 'uint': case 'int32': case 'uint32': - return Column.Schema.int + return Column.Schema.int; case 'float': case 'double': case 'float32': case 'float64': - return Column.Schema.float + return Column.Schema.float; } } function parseTableElement(state: State, spec: TableElementSpec) { - const { elements, tokenizer } = state - const { count, properties } = spec - const propertyCount = properties.length - const propertyNames: string[] = [] - const propertyTypes: PlyType[] = [] - const propertyTokens: Tokens[] = [] - const propertyColumns = new Map<string, Column<number>>() + const { elements, tokenizer } = state; + const { count, properties } = spec; + const propertyCount = properties.length; + const propertyNames: string[] = []; + const propertyTypes: PlyType[] = []; + const propertyTokens: Tokens[] = []; + const propertyColumns = new Map<string, Column<number>>(); for (let i = 0, il = propertyCount; i < il; ++i) { - const tokens = TokenBuilder.create(tokenizer.data, count * 2) - propertyTokens.push(tokens) + const tokens = TokenBuilder.create(tokenizer.data, count * 2); + propertyTokens.push(tokens); } for (let i = 0, il = count; i < il; ++i) { for (let j = 0, jl = propertyCount; j < jl; ++j) { - Tokenizer.skipWhitespace(tokenizer) - Tokenizer.markStart(tokenizer) - Tokenizer.eatValue(tokenizer) - TokenBuilder.addUnchecked(propertyTokens[j], tokenizer.tokenStart, tokenizer.tokenEnd) + Tokenizer.skipWhitespace(tokenizer); + Tokenizer.markStart(tokenizer); + Tokenizer.eatValue(tokenizer); + TokenBuilder.addUnchecked(propertyTokens[j], tokenizer.tokenStart, tokenizer.tokenEnd); } } for (let i = 0, il = propertyCount; i < il; ++i) { - const { type, name } = properties[i] - const column = TokenColumn(propertyTokens[i], getColumnSchema(type)) - propertyNames.push(name) - propertyTypes.push(type) - propertyColumns.set(name, column) + const { type, name } = properties[i]; + const column = TokenColumn(propertyTokens[i], getColumnSchema(type)); + propertyNames.push(name); + propertyTypes.push(type); + propertyColumns.set(name, column); } elements.push({ @@ -193,38 +193,38 @@ function parseTableElement(state: State, spec: TableElementSpec) { propertyNames, propertyTypes, getProperty: (name: string) => propertyColumns.get(name) - }) + }); } function parseListElement(state: State, spec: ListElementSpec) { - const { elements, tokenizer } = state - const { count, property } = spec + const { elements, tokenizer } = state; + const { count, property } = spec; // initial tokens size assumes triangle index data - const tokens = TokenBuilder.create(tokenizer.data, count * 2 * 3) + const tokens = TokenBuilder.create(tokenizer.data, count * 2 * 3); - const offsets = new Uint32Array(count + 1) - let entryCount = 0 + const offsets = new Uint32Array(count + 1); + let entryCount = 0; for (let i = 0, il = count; i < il; ++i) { - Tokenizer.skipWhitespace(tokenizer) - Tokenizer.markStart(tokenizer) + Tokenizer.skipWhitespace(tokenizer); + Tokenizer.markStart(tokenizer); while (Tokenizer.skipWhitespace(tokenizer) !== 10) { - ++entryCount - Tokenizer.markStart(tokenizer) - Tokenizer.eatValue(tokenizer) - TokenBuilder.addToken(tokens, tokenizer) + ++entryCount; + Tokenizer.markStart(tokenizer); + Tokenizer.eatValue(tokenizer); + TokenBuilder.addToken(tokens, tokenizer); } - offsets[i + 1] = entryCount + offsets[i + 1] = entryCount; } /** holds row value entries transiently */ const listValue = { entries: [] as number[], count: 0 - } + }; - const column = TokenColumn(tokens, getColumnSchema(property.dataType)) + const column = TokenColumn(tokens, getColumnSchema(property.dataType)); elements.push({ kind: 'list', @@ -232,32 +232,32 @@ function parseListElement(state: State, spec: ListElementSpec) { name: property.name, type: property.dataType, value: (row: number) => { - const offset = offsets[row] + 1 - const count = column.value(offset - 1) + const offset = offsets[row] + 1; + const count = column.value(offset - 1); for (let i = offset, il = offset + count; i < il; ++i) { - listValue.entries[i - offset] = column.value(i) + listValue.entries[i - offset] = column.value(i); } - listValue.count = count - return listValue + listValue.count = count; + return listValue; } - }) + }); } async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<PlyFile>> { const state = State(data, ctx); ctx.update({ message: 'Parsing...', current: 0, max: data.length }); - parseHeader(state) - parseElements(state) - const { elements, elementSpecs, comments } = state - const elementNames = elementSpecs.map(s => s.name) - const result = PlyFile(elements, elementNames, comments) + parseHeader(state); + parseElements(state); + const { elements, elementSpecs, comments } = state; + const elementNames = elementSpecs.map(s => s.name); + const result = PlyFile(elements, elementNames, comments); return Result.success(result); } export function parse(data: string) { return Task.create<Result<PlyFile>>('Parse PLY', async ctx => { - return await parseInternal(data, ctx) - }) + return await parseInternal(data, ctx); + }); } export default parse; \ No newline at end of file diff --git a/src/mol-io/reader/ply/schema.ts b/src/mol-io/reader/ply/schema.ts index f113959a8735bc85d10a492198fb65ab1e28beff..13a4b801264f702a5c808057523994252dfe1a57 100644 --- a/src/mol-io/reader/ply/schema.ts +++ b/src/mol-io/reader/ply/schema.ts @@ -27,12 +27,12 @@ export const PlyTypeByteLength = { 'uint32': 4, 'float32': 4, 'float64': 8 -} +}; export type PlyType = keyof typeof PlyTypeByteLength -export const PlyTypes = new Set(Object.keys(PlyTypeByteLength)) +export const PlyTypes = new Set(Object.keys(PlyTypeByteLength)); export function PlyType(str: string) { - if (!PlyTypes.has(str)) throw new Error(`unknown ply type '${str}'`) - return str as PlyType + if (!PlyTypes.has(str)) throw new Error(`unknown ply type '${str}'`); + return str as PlyType; } export interface PlyFile { @@ -42,15 +42,15 @@ export interface PlyFile { } export function PlyFile(elements: PlyElement[], elementNames: string[], comments: string[]): PlyFile { - const elementMap = new Map<string, PlyElement>() + const elementMap = new Map<string, PlyElement>(); for (let i = 0, il = elementNames.length; i < il; ++i) { - elementMap.set(elementNames[i], elements[i]) + elementMap.set(elementNames[i], elements[i]); } return { comments, elementNames, getElement: (name: string) => { - return elementMap.get(name) + return elementMap.get(name); } }; } diff --git a/src/mol-io/reader/psf/parser.ts b/src/mol-io/reader/psf/parser.ts index 8d49708b90ece98f04ae5f41c238d59af48d3728..4a9dbfbb198e40a54af3bbe50e4f780e7cbae264 100644 --- a/src/mol-io/reader/psf/parser.ts +++ b/src/mol-io/reader/psf/parser.ts @@ -4,9 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Task, RuntimeContext, chunkedSubtask } from '../../../mol-task' -import { Tokenizer, TokenBuilder } from '../common/text/tokenizer' -import { ReaderResult as Result } from '../result' +import { Task, RuntimeContext, chunkedSubtask } from '../../../mol-task'; +import { Tokenizer, TokenBuilder } from '../common/text/tokenizer'; +import { ReaderResult as Result } from '../result'; import TokenColumn from '../common/text/column/token'; import { Column } from '../../../mol-data/db'; @@ -35,56 +35,56 @@ export interface PsfFile { const { readLine, skipWhitespace, eatValue, eatLine, markStart } = Tokenizer; -const reWhitespace = /\s+/ -const reTitle = /(^\*|REMARK)*/ +const reWhitespace = /\s+/; +const reTitle = /(^\*|REMARK)*/; function State(tokenizer: Tokenizer, runtimeCtx: RuntimeContext) { return { tokenizer, runtimeCtx, - } + }; } type State = ReturnType<typeof State> async function handleAtoms(state: State, count: number): Promise<PsfFile['atoms']> { - const { tokenizer } = state - - const atomId = TokenBuilder.create(tokenizer.data, count * 2) - const segmentName = TokenBuilder.create(tokenizer.data, count * 2) - const residueId = TokenBuilder.create(tokenizer.data, count * 2) - const residueName = TokenBuilder.create(tokenizer.data, count * 2) - const atomName = TokenBuilder.create(tokenizer.data, count * 2) - const atomType = TokenBuilder.create(tokenizer.data, count * 2) - const charge = TokenBuilder.create(tokenizer.data, count * 2) - const mass = TokenBuilder.create(tokenizer.data, count * 2) - - const { length } = tokenizer - let linesAlreadyRead = 0 + const { tokenizer } = state; + + const atomId = TokenBuilder.create(tokenizer.data, count * 2); + const segmentName = TokenBuilder.create(tokenizer.data, count * 2); + const residueId = TokenBuilder.create(tokenizer.data, count * 2); + const residueName = TokenBuilder.create(tokenizer.data, count * 2); + const atomName = TokenBuilder.create(tokenizer.data, count * 2); + const atomType = TokenBuilder.create(tokenizer.data, count * 2); + const charge = TokenBuilder.create(tokenizer.data, count * 2); + const mass = TokenBuilder.create(tokenizer.data, count * 2); + + const { length } = tokenizer; + let linesAlreadyRead = 0; await chunkedSubtask(state.runtimeCtx, 10, void 0, chunkSize => { - const linesToRead = Math.min(count - linesAlreadyRead, chunkSize) + const linesToRead = Math.min(count - linesAlreadyRead, chunkSize); for (let i = 0; i < linesToRead; ++i) { for (let j = 0; j < 8; ++j) { - skipWhitespace(tokenizer) - markStart(tokenizer) - eatValue(tokenizer) + skipWhitespace(tokenizer); + markStart(tokenizer); + eatValue(tokenizer); switch (j) { - case 0: TokenBuilder.addUnchecked(atomId, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 1: TokenBuilder.addUnchecked(segmentName, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 2: TokenBuilder.addUnchecked(residueId, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 3: TokenBuilder.addUnchecked(residueName, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 4: TokenBuilder.addUnchecked(atomName, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 5: TokenBuilder.addUnchecked(atomType, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 6: TokenBuilder.addUnchecked(charge, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 7: TokenBuilder.addUnchecked(mass, tokenizer.tokenStart, tokenizer.tokenEnd); break + case 0: TokenBuilder.addUnchecked(atomId, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 1: TokenBuilder.addUnchecked(segmentName, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 2: TokenBuilder.addUnchecked(residueId, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 3: TokenBuilder.addUnchecked(residueName, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 4: TokenBuilder.addUnchecked(atomName, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 5: TokenBuilder.addUnchecked(atomType, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 6: TokenBuilder.addUnchecked(charge, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 7: TokenBuilder.addUnchecked(mass, tokenizer.tokenStart, tokenizer.tokenEnd); break; } } // ignore any extra columns - eatLine(tokenizer) - markStart(tokenizer) + eatLine(tokenizer); + markStart(tokenizer); } - linesAlreadyRead += linesToRead - return linesToRead - }, ctx => ctx.update({ message: 'Parsing...', current: tokenizer.position, max: length })) + linesAlreadyRead += linesToRead; + return linesToRead; + }, ctx => ctx.update({ message: 'Parsing...', current: tokenizer.position, max: length })); return { count, @@ -96,72 +96,72 @@ async function handleAtoms(state: State, count: number): Promise<PsfFile['atoms' atomType: TokenColumn(atomType)(Column.Schema.str), charge: TokenColumn(charge)(Column.Schema.float), mass: TokenColumn(mass)(Column.Schema.float) - } + }; } async function handleBonds(state: State, count: number): Promise<PsfFile['bonds']> { - const { tokenizer } = state + const { tokenizer } = state; - const atomIdA = TokenBuilder.create(tokenizer.data, count * 2) - const atomIdB = TokenBuilder.create(tokenizer.data, count * 2) + const atomIdA = TokenBuilder.create(tokenizer.data, count * 2); + const atomIdB = TokenBuilder.create(tokenizer.data, count * 2); - const { length } = tokenizer - let bondsAlreadyRead = 0 + const { length } = tokenizer; + let bondsAlreadyRead = 0; await chunkedSubtask(state.runtimeCtx, 10, void 0, chunkSize => { - const bondsToRead = Math.min(count - bondsAlreadyRead, chunkSize) + const bondsToRead = Math.min(count - bondsAlreadyRead, chunkSize); for (let i = 0; i < bondsToRead; ++i) { for (let j = 0; j < 2; ++j) { - skipWhitespace(tokenizer) - markStart(tokenizer) - eatValue(tokenizer) + skipWhitespace(tokenizer); + markStart(tokenizer); + eatValue(tokenizer); switch (j) { - case 0: TokenBuilder.addUnchecked(atomIdA, tokenizer.tokenStart, tokenizer.tokenEnd); break - case 1: TokenBuilder.addUnchecked(atomIdB, tokenizer.tokenStart, tokenizer.tokenEnd); break + case 0: TokenBuilder.addUnchecked(atomIdA, tokenizer.tokenStart, tokenizer.tokenEnd); break; + case 1: TokenBuilder.addUnchecked(atomIdB, tokenizer.tokenStart, tokenizer.tokenEnd); break; } } } - bondsAlreadyRead += bondsToRead - return bondsToRead - }, ctx => ctx.update({ message: 'Parsing...', current: tokenizer.position, max: length })) + bondsAlreadyRead += bondsToRead; + return bondsToRead; + }, ctx => ctx.update({ message: 'Parsing...', current: tokenizer.position, max: length })); return { count, atomIdA: TokenColumn(atomIdA)(Column.Schema.int), atomIdB: TokenColumn(atomIdB)(Column.Schema.int), - } + }; } function parseTitle(state: State, count: number) { - const title: string[] = [] + const title: string[] = []; for (let i = 0; i < count; ++i) { - const line = readLine(state.tokenizer) - title.push(line.replace(reTitle, '').trim()) + const line = readLine(state.tokenizer); + title.push(line.replace(reTitle, '').trim()); } - return title + return title; } async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<PsfFile>> { const tokenizer = Tokenizer(data); const state = State(tokenizer, ctx); - let title = undefined as string[] | undefined - let atoms = undefined as PsfFile['atoms'] | undefined - let bonds = undefined as PsfFile['bonds'] | undefined + let title = undefined as string[] | undefined; + let atoms = undefined as PsfFile['atoms'] | undefined; + let bonds = undefined as PsfFile['bonds'] | undefined; - const id = readLine(state.tokenizer).trim() + const id = readLine(state.tokenizer).trim(); while(tokenizer.tokenEnd < tokenizer.length) { - const line = readLine(state.tokenizer).trim() + const line = readLine(state.tokenizer).trim(); if (line.includes('!NTITLE')) { - const numTitle = parseInt(line.split(reWhitespace)[0]) - title = parseTitle(state, numTitle) + const numTitle = parseInt(line.split(reWhitespace)[0]); + title = parseTitle(state, numTitle); } else if (line.includes('!NATOM')) { - const numAtoms = parseInt(line.split(reWhitespace)[0]) - atoms = await handleAtoms(state, numAtoms) + const numAtoms = parseInt(line.split(reWhitespace)[0]); + atoms = await handleAtoms(state, numAtoms); } else if (line.includes('!NBOND')) { - const numBonds = parseInt(line.split(reWhitespace)[0]) - bonds = await handleBonds(state, numBonds) - break // TODO: don't break when the below are implemented + const numBonds = parseInt(line.split(reWhitespace)[0]); + bonds = await handleBonds(state, numBonds); + break; // TODO: don't break when the below are implemented } else if (line.includes('!NTHETA')) { // TODO } else if (line.includes('!NPHI')) { @@ -186,15 +186,15 @@ async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result< } if (title === undefined) { - title = [] + title = []; } if (atoms === undefined) { - return Result.error('no atoms data') + return Result.error('no atoms data'); } if (bonds === undefined) { - return Result.error('no bonds data') + return Result.error('no bonds data'); } const result: PsfFile = { @@ -202,12 +202,12 @@ async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result< title, atoms, bonds - } + }; return Result.success(result); } export function parsePsf(data: string) { return Task.create<Result<PsfFile>>('Parse PSF', async ctx => { - return await parseInternal(data, ctx) + return await parseInternal(data, ctx); }); } \ No newline at end of file diff --git a/src/mol-io/reader/result.ts b/src/mol-io/reader/result.ts index 255ae0c9eac4e20d0068d2c266db1fa47e696b8c..a02d79bb4b8a7cfbc5f0886a9c8cd9615922c733 100644 --- a/src/mol-io/reader/result.ts +++ b/src/mol-io/reader/result.ts @@ -39,4 +39,4 @@ namespace ReaderResult { } } -export { ReaderResult } \ No newline at end of file +export { ReaderResult }; \ No newline at end of file diff --git a/src/mol-io/writer/_spec/cif.spec.ts b/src/mol-io/writer/_spec/cif.spec.ts index fba3f3c51ce81a7b14f07a9d420afe878fda4568..0478ad12672efe84ad030e4ce35e6b465cd75a56 100644 --- a/src/mol-io/writer/_spec/cif.spec.ts +++ b/src/mol-io/writer/_spec/cif.spec.ts @@ -1,6 +1,6 @@ -import * as Data from '../../reader/cif/data-model' +import * as Data from '../../reader/cif/data-model'; import { CifWriter } from '../cif'; -import decodeMsgPack from '../../common/msgpack/decode' +import decodeMsgPack from '../../common/msgpack/decode'; import { EncodedFile, EncodedCategory } from '../../common/binary-cif'; import Field from '../../reader/cif/binary/field'; import * as C from '../cif/encoder'; @@ -130,7 +130,7 @@ function process(encoder: C.Encoder) { for (const cat of [atom_site, other_fields]) { const fields: CifWriter.Field[] = []; for (const f of cat.fieldNames) { - fields.push(wrap(f, cat.getField(f)!)) + fields.push(wrap(f, cat.getField(f)!)); } encoder.writeCategory(getCategoryInstanceProvider(cat, fields)); } @@ -179,5 +179,5 @@ function Category(data: EncodedCategory): Data.CifCategory { cache[name] = Field(col); return cache[name]; } - } + }; } \ No newline at end of file diff --git a/src/mol-io/writer/cif.ts b/src/mol-io/writer/cif.ts index 56926fab870c445fb830a6a9e67396c051433377..1ba4fc45d32d7719d08f0e8de00003fa0e276e3b 100644 --- a/src/mol-io/writer/cif.ts +++ b/src/mol-io/writer/cif.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import TextEncoder from './cif/encoder/text' -import BinaryEncoder, { BinaryEncodingProvider } from './cif/encoder/binary' -import * as _Encoder from './cif/encoder' +import TextEncoder from './cif/encoder/text'; +import BinaryEncoder, { BinaryEncodingProvider } from './cif/encoder/binary'; +import * as _Encoder from './cif/encoder'; import { ArrayEncoding, ArrayEncoder } from '../common/binary-cif'; import { CifFrame } from '../reader/cif'; @@ -52,7 +52,7 @@ export namespace CifWriter { const ff = cat.getField(f); return ff && ff.binaryEncoding ? ArrayEncoder.fromEncoding(ff.binaryEncoding) : void 0; } - } + }; }; export function createEncodingProviderFromJsonConfig(hints: EncodingStrategyHint[]): BinaryEncodingProvider { @@ -65,7 +65,7 @@ export namespace CifWriter { } } } - } + }; } function resolveEncoding(hint: EncodingStrategyHint): ArrayEncoder { diff --git a/src/mol-io/writer/cif/encoder.ts b/src/mol-io/writer/cif/encoder.ts index 098c18a95b8b0d48290fabd3c0310ba540cc076b..02005fd2b90ba61bad0ebbc61bd560dcd1f1b1a9 100644 --- a/src/mol-io/writer/cif/encoder.ts +++ b/src/mol-io/writer/cif/encoder.ts @@ -5,10 +5,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import Iterator from '../../../mol-data/iterator' -import { Column, Table, Database, DatabaseCollection } from '../../../mol-data/db' -import { Tensor } from '../../../mol-math/linear-algebra' -import EncoderBase from '../encoder' +import Iterator from '../../../mol-data/iterator'; +import { Column, Table, Database, DatabaseCollection } from '../../../mol-data/db'; +import { Tensor } from '../../../mol-math/linear-algebra'; +import EncoderBase from '../encoder'; import { ArrayEncoder, ArrayEncoding } from '../../common/binary-cif'; import { BinaryEncodingProvider } from './encoder/binary'; @@ -70,7 +70,7 @@ export namespace Field { } export function index(name: string) { - return int(name, (e, d, i) => i + 1, { typedArray: Int32Array, encoder: ArrayEncoding.by(ArrayEncoding.delta).and(ArrayEncoding.runLength).and(ArrayEncoding.integerPacking) }) + return int(name, (e, d, i) => i + 1, { typedArray: Int32Array, encoder: ArrayEncoding.by(ArrayEncoding.delta).and(ArrayEncoding.runLength).and(ArrayEncoding.integerPacking) }); } export class Builder<K = number, D = any, N extends string = string> { @@ -191,13 +191,13 @@ export namespace Category { field_whitelist.includes(full); } } - } + }; } export const DefaultFilter: Filter = { includeCategory(cat) { return true; }, includeField(cat, field) { return true; } - } + }; export interface Formatter { getFormat(categoryName: string, fieldName: string): Field.Format | undefined @@ -205,7 +205,7 @@ export namespace Category { export const DefaultFormatter: Formatter = { getFormat(cat, field) { return void 0; } - } + }; export function ofTable(table: Table, indices?: ArrayLike<number>): Category.Instance { if (indices) { @@ -247,7 +247,7 @@ export namespace Encoder { export function writeDatabaseCollection(encoder: Encoder, collection: DatabaseCollection<Database.Schema>) { for (const name of Object.keys(collection)) { - writeDatabase(encoder, name, collection[name]) + writeDatabase(encoder, name, collection[name]); } } } @@ -269,37 +269,37 @@ function columnValueKind(k: string) { } function getTensorDefinitions(field: string, space: Tensor.Space) { - const fieldDefinitions: Field[] = [] - const type = Field.Type.Float - const valueKind = columnValueKind(field) + const fieldDefinitions: Field[] = []; + const type = Field.Type.Float; + const valueKind = columnValueKind(field); if (space.rank === 1) { - const rows = space.dimensions[0] + const rows = space.dimensions[0]; for (let i = 0; i < rows; i++) { - const name = `${field}[${i + 1}]` - fieldDefinitions.push({ name, type, value: columnTensorValue(field, i), valueKind }) + const name = `${field}[${i + 1}]`; + fieldDefinitions.push({ name, type, value: columnTensorValue(field, i), valueKind }); } } else if (space.rank === 2) { - const rows = space.dimensions[0], cols = space.dimensions[1] + const rows = space.dimensions[0], cols = space.dimensions[1]; for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { - const name = `${field}[${i + 1}][${j + 1}]` - fieldDefinitions.push({ name, type, value: columnTensorValue(field, i, j), valueKind }) + const name = `${field}[${i + 1}][${j + 1}]`; + fieldDefinitions.push({ name, type, value: columnTensorValue(field, i, j), valueKind }); } } } else if (space.rank === 3) { - const d0 = space.dimensions[0], d1 = space.dimensions[1], d2 = space.dimensions[2] + const d0 = space.dimensions[0], d1 = space.dimensions[1], d2 = space.dimensions[2]; for (let i = 0; i < d0; i++) { for (let j = 0; j < d1; j++) { for (let k = 0; k < d2; k++) { - const name = `${field}[${i + 1}][${j + 1}][${k + 1}]` - fieldDefinitions.push({ name, type, value: columnTensorValue(field, i, j, k), valueKind }) + const name = `${field}[${i + 1}][${j + 1}][${k + 1}]`; + fieldDefinitions.push({ name, type, value: columnTensorValue(field, i, j, k), valueKind }); } } } } else { - throw new Error('Tensors with rank > 3 or rank 0 are currently not supported.') + throw new Error('Tensors with rank > 3 or rank 0 are currently not supported.'); } - return fieldDefinitions + return fieldDefinitions; } function cifFieldsFromTableSchema(schema: Table.Schema) { @@ -313,9 +313,9 @@ function cifFieldsFromTableSchema(schema: Table.Schema) { } else if (t.valueType === 'str') { fields.push({ name: k, type: Field.Type.Str, value: columnValue(k), valueKind: columnValueKind(k) }); } else if (t.valueType === 'list') { - fields.push({ name: k, type: Field.Type.Str, value: columnListValue(k), valueKind: columnValueKind(k) }) + fields.push({ name: k, type: Field.Type.Str, value: columnListValue(k), valueKind: columnValueKind(k) }); } else if (t.valueType === 'tensor') { - fields.push(...getTensorDefinitions(k, t.space)) + fields.push(...getTensorDefinitions(k, t.space)); } else { throw new Error(`Unknown valueType ${t.valueType}`); } diff --git a/src/mol-io/writer/cif/encoder/binary.ts b/src/mol-io/writer/cif/encoder/binary.ts index a80e1afeb8c9ccca75f3a6ffff755c80c6ae4b4d..7bafaca3d0ad81fb69b25f6abbd9eed8ac032e74 100644 --- a/src/mol-io/writer/cif/encoder/binary.ts +++ b/src/mol-io/writer/cif/encoder/binary.ts @@ -6,13 +6,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column } from '../../../../mol-data/db' -import encodeMsgPack from '../../../common/msgpack/encode' +import { Column } from '../../../../mol-data/db'; +import encodeMsgPack from '../../../common/msgpack/encode'; import { EncodedColumn, EncodedData, EncodedFile, EncodedDataBlock, EncodedCategory, ArrayEncoder, ArrayEncoding as E, VERSION -} from '../../../common/binary-cif' -import { Field, Category, Encoder } from '../encoder' -import Writer from '../../writer' +} from '../../../common/binary-cif'; +import { Field, Category, Encoder } from '../encoder'; +import Writer from '../../writer'; import { getIncludedFields, getCategoryInstanceData, CategoryInstanceData } from './util'; import { classifyIntArray, classifyFloatArray } from '../../../common/binary-cif/classifier'; import { ArrayCtor } from '../../../../mol-util/type-helpers'; diff --git a/src/mol-io/writer/cif/encoder/text.ts b/src/mol-io/writer/cif/encoder/text.ts index 3c7c6cf9d6191031fa9a40a3929c2f4d81a04e11..bfb15d7e21b6314ea9104ae6030468004eb5435f 100644 --- a/src/mol-io/writer/cif/encoder/text.ts +++ b/src/mol-io/writer/cif/encoder/text.ts @@ -6,10 +6,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Column } from '../../../../mol-data/db' -import StringBuilder from '../../../../mol-util/string-builder' -import { Category, Field, Encoder } from '../encoder' -import Writer from '../../writer' +import { Column } from '../../../../mol-data/db'; +import StringBuilder from '../../../../mol-util/string-builder'; +import { Category, Field, Encoder } from '../encoder'; +import Writer from '../../writer'; import { getFieldDigitCount, getIncludedFields, getCategoryInstanceData, CategoryInstanceData } from './util'; export default class TextEncoder implements Encoder<string> { diff --git a/src/mol-io/writer/cif/encoder/util.ts b/src/mol-io/writer/cif/encoder/util.ts index 0669e20e564a39550cb173f782124f794ff1a384..25e9b62c0333d6a2041c9ea6f144061e1ea7dfa8 100644 --- a/src/mol-io/writer/cif/encoder/util.ts +++ b/src/mol-io/writer/cif/encoder/util.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Iterator } from '../../../../mol-data' +import { Iterator } from '../../../../mol-data'; import { Field, Category } from '../encoder'; export function getFieldDigitCount(field: Field) { diff --git a/src/mol-io/writer/encoder.ts b/src/mol-io/writer/encoder.ts index 4db1cd02f9a960b73e2e07a7130cbf6f71313075..71d584880d17744962edb7d8353d9bfb4b4f6c9a 100644 --- a/src/mol-io/writer/encoder.ts +++ b/src/mol-io/writer/encoder.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Writer from './writer' +import Writer from './writer'; interface Encoder { encode(): void, @@ -12,4 +12,4 @@ interface Encoder { getSize(): number } -export default Encoder \ No newline at end of file +export default Encoder; \ No newline at end of file diff --git a/src/mol-io/writer/writer.ts b/src/mol-io/writer/writer.ts index 977989a9d3a0e502d298ce436272f8360b47374c..31848939c90f51eb0131948b3ea35773add90759 100644 --- a/src/mol-io/writer/writer.ts +++ b/src/mol-io/writer/writer.ts @@ -13,4 +13,4 @@ namespace Writer { } -export default Writer \ No newline at end of file +export default Writer; \ No newline at end of file diff --git a/src/mol-math/geometry.ts b/src/mol-math/geometry.ts index 329bf8c6a98f370cb67ac989d8d67915374bd53a..c6d57c90af405f72cf6f621e6cf8c22ef7bf04b8 100644 --- a/src/mol-math/geometry.ts +++ b/src/mol-math/geometry.ts @@ -5,11 +5,11 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export * from './geometry/common' -export * from './geometry/symmetry-operator' -export * from './geometry/spacegroup/construction' -export * from './geometry/lookup3d/common' -export * from './geometry/lookup3d/grid' -export * from './geometry/primitives/box3d' -export * from './geometry/primitives/sphere3d' -export * from './geometry/primitives/axes3d' \ No newline at end of file +export * from './geometry/common'; +export * from './geometry/symmetry-operator'; +export * from './geometry/spacegroup/construction'; +export * from './geometry/lookup3d/common'; +export * from './geometry/lookup3d/grid'; +export * from './geometry/primitives/box3d'; +export * from './geometry/primitives/sphere3d'; +export * from './geometry/primitives/axes3d'; \ No newline at end of file diff --git a/src/mol-math/geometry/_spec/lookup3d.spec.ts b/src/mol-math/geometry/_spec/lookup3d.spec.ts index 679593fc745cea23c9a15439ed57ec3eda412500..1641a2c6e85a431a265c4d8708baf453976b872a 100644 --- a/src/mol-math/geometry/_spec/lookup3d.spec.ts +++ b/src/mol-math/geometry/_spec/lookup3d.spec.ts @@ -16,8 +16,8 @@ const rs = [0, 0.5, 1 / 3]; describe('GridLookup3d', () => { it('basic', () => { - const position = { x: xs, y: ys, z: zs, indices: OrderedSet.ofBounds(0, 3) } - const boundary = getBoundary(position) + const position = { x: xs, y: ys, z: zs, indices: OrderedSet.ofBounds(0, 3) }; + const boundary = getBoundary(position); const grid = GridLookup3D(position, boundary); let r = grid.find(0, 0, 0, 0); @@ -30,8 +30,8 @@ describe('GridLookup3d', () => { }); it('radius', () => { - const position = { x: xs, y: ys, z: zs, radius: [0, 0.5, 1 / 3], indices: OrderedSet.ofBounds(0, 3) } - const boundary = getBoundary(position) + const position = { x: xs, y: ys, z: zs, radius: [0, 0.5, 1 / 3], indices: OrderedSet.ofBounds(0, 3) }; + const boundary = getBoundary(position); const grid = GridLookup3D(position, boundary); let r = grid.find(0, 0, 0, 0); @@ -44,8 +44,8 @@ describe('GridLookup3d', () => { }); it('indexed', () => { - const position = { x: xs, y: ys, z: zs, indices: OrderedSet.ofSingleton(1), radius: rs } - const boundary = getBoundary(position) + const position = { x: xs, y: ys, z: zs, indices: OrderedSet.ofSingleton(1), radius: rs }; + const boundary = getBoundary(position); const grid = GridLookup3D(position, boundary); let r = grid.find(0, 0, 0, 0); diff --git a/src/mol-math/geometry/_spec/spacegroup.spec.ts b/src/mol-math/geometry/_spec/spacegroup.spec.ts index 7783f936c638b226e08433d1a85a8fad57a91696..766b60536e173bf5f13390aea66fac980768daa4 100644 --- a/src/mol-math/geometry/_spec/spacegroup.spec.ts +++ b/src/mol-math/geometry/_spec/spacegroup.spec.ts @@ -8,29 +8,29 @@ import { Spacegroup, SpacegroupCell } from '../spacegroup/construction'; import { Vec3 } from '../../linear-algebra'; function getSpacegroup(name: string) { - const size = Vec3.create(1, 1, 1) - const anglesInRadians = Vec3.create(Math.PI / 2, Math.PI / 2, Math.PI / 2) - const cell = SpacegroupCell.create(name, size, anglesInRadians) - return Spacegroup.create(cell) + const size = Vec3.create(1, 1, 1); + const anglesInRadians = Vec3.create(Math.PI / 2, Math.PI / 2, Math.PI / 2); + const cell = SpacegroupCell.create(name, size, anglesInRadians); + return Spacegroup.create(cell); } function checkOperatorsXyz(name: string, expected: string[]) { - const spacegroup = getSpacegroup(name) + const spacegroup = getSpacegroup(name); for (let i = 0, il = spacegroup.operators.length; i < il; ++i) { - const op = spacegroup.operators[i] - const actual = Spacegroup.getOperatorXyz(op) - expect(actual).toBe(expected[i]) + const op = spacegroup.operators[i]; + const actual = Spacegroup.getOperatorXyz(op); + expect(actual).toBe(expected[i]); } } describe('Spacegroup', () => { it('operators xyz', () => { - checkOperatorsXyz('P 1', ['X,Y,Z']) - checkOperatorsXyz('P -1', ['X,Y,Z', '-X,-Y,-Z']) - checkOperatorsXyz('P 1 21 1', ['X,Y,Z', '-X,1/2+Y,-Z']) - checkOperatorsXyz('P 1 21/m 1', ['X,Y,Z', '-X,1/2+Y,-Z', '-X,-Y,-Z', 'X,1/2-Y,Z']) - checkOperatorsXyz('P 41', ['X,Y,Z', '-X,-Y,1/2+Z', '-Y,X,1/4+Z', 'Y,-X,3/4+Z']) - checkOperatorsXyz('P 41 21 2', ['X,Y,Z', '-X,-Y,1/2+Z', '1/2-Y,1/2+X,1/4+Z', '1/2+Y,1/2-X,3/4+Z', '1/2-X,1/2+Y,1/4-Z', '1/2+X,1/2-Y,3/4-Z', 'Y,X,-Z', '-Y,-X,1/2-Z']) - checkOperatorsXyz('P 3', ['X,Y,Z', '-Y,X-Y,Z', 'Y-X,-X,Z']) + checkOperatorsXyz('P 1', ['X,Y,Z']); + checkOperatorsXyz('P -1', ['X,Y,Z', '-X,-Y,-Z']); + checkOperatorsXyz('P 1 21 1', ['X,Y,Z', '-X,1/2+Y,-Z']); + checkOperatorsXyz('P 1 21/m 1', ['X,Y,Z', '-X,1/2+Y,-Z', '-X,-Y,-Z', 'X,1/2-Y,Z']); + checkOperatorsXyz('P 41', ['X,Y,Z', '-X,-Y,1/2+Z', '-Y,X,1/4+Z', 'Y,-X,3/4+Z']); + checkOperatorsXyz('P 41 21 2', ['X,Y,Z', '-X,-Y,1/2+Z', '1/2-Y,1/2+X,1/4+Z', '1/2+Y,1/2-X,3/4+Z', '1/2-X,1/2+Y,1/4-Z', '1/2+X,1/2-Y,3/4-Z', 'Y,X,-Z', '-Y,-X,1/2-Z']); + checkOperatorsXyz('P 3', ['X,Y,Z', '-Y,X-Y,Z', 'Y-X,-X,Z']); }); -}) +}); diff --git a/src/mol-math/geometry/boundary-helper.ts b/src/mol-math/geometry/boundary-helper.ts index 96e605ba239a814341398c2399e0eed14d50c9dc..d23569ca71c3a97d6142a6db1d786c59cbd16816 100644 --- a/src/mol-math/geometry/boundary-helper.ts +++ b/src/mol-math/geometry/boundary-helper.ts @@ -20,28 +20,28 @@ export class BoundaryHelper { centroidHelper = new CentroidHelper() private computeExtrema(i: number, p: Vec3) { - const d = Vec3.dot(this.dir[i], p) + const d = Vec3.dot(this.dir[i], p); if (d < this.minDist[i]) { - this.minDist[i] = d - Vec3.copy(this.extrema[i * 2], p) + this.minDist[i] = d; + Vec3.copy(this.extrema[i * 2], p); } if (d > this.maxDist[i]) { - this.maxDist[i] = d - Vec3.copy(this.extrema[i * 2 + 1], p) + this.maxDist[i] = d; + Vec3.copy(this.extrema[i * 2 + 1], p); } } private computeSphereExtrema(i: number, center: Vec3, radius: number) { - const d = Vec3.dot(this.dir[i], center) + const d = Vec3.dot(this.dir[i], center); if (d - radius < this.minDist[i]) { - this.minDist[i] = d - radius - Vec3.scaleAndSub(this.extrema[i * 2], center, this.dir[i], radius) + this.minDist[i] = d - radius; + Vec3.scaleAndSub(this.extrema[i * 2], center, this.dir[i], radius); } if (d + radius > this.maxDist[i]) { - this.maxDist[i] = d + radius - Vec3.scaleAndAdd(this.extrema[i * 2 + 1], center, this.dir[i], radius) + this.maxDist[i] = d + radius; + Vec3.scaleAndAdd(this.extrema[i * 2 + 1], center, this.dir[i], radius); } } @@ -57,13 +57,13 @@ export class BoundaryHelper { includePosition(p: Vec3) { for (let i = 0, il = this.dir.length; i < il; ++i) { - this.computeExtrema(i, p) + this.computeExtrema(i, p); } } includePositionRadius(center: Vec3, radius: number) { for (let i = 0, il = this.dir.length; i < il; ++i) { - this.computeSphereExtrema(i, center, radius) + this.computeSphereExtrema(i, center, radius); } } @@ -77,7 +77,7 @@ export class BoundaryHelper { radiusSphere(s: Sphere3D) { if (Sphere3D.hasExtrema(s)) { for (const e of s.extrema) { - this.radiusPosition(e) + this.radiusPosition(e); } } else { this.radiusPositionRadius(s.center, s.radius); @@ -93,73 +93,73 @@ export class BoundaryHelper { } getSphere(sphere?: Sphere3D) { - return Sphere3D.setExtrema(this.centroidHelper.getSphere(sphere), this.extrema) + return Sphere3D.setExtrema(this.centroidHelper.getSphere(sphere), this.extrema); } getBox(box?: Box3D) { - if (!box) box = Box3D() - Box3D.setEmpty(box) + if (!box) box = Box3D(); + Box3D.setEmpty(box); for (let i = 0; i < this.extrema.length; i++) { - Box3D.add(box, this.extrema[i]) + Box3D.add(box, this.extrema[i]); } - return box + return box; } reset() { for (let i = 0, il = this.dir.length; i < il; ++i) { - this.minDist[i] = Infinity - this.maxDist[i] = -Infinity - this.extrema[i * 2] = Vec3() - this.extrema[i * 2 + 1] = Vec3() + this.minDist[i] = Infinity; + this.maxDist[i] = -Infinity; + this.extrema[i * 2] = Vec3(); + this.extrema[i * 2 + 1] = Vec3(); } - this.centroidHelper.reset() + this.centroidHelper.reset(); } constructor(quality: EposQuality) { - this.dir = getEposDir(quality) - this.reset() + this.dir = getEposDir(quality); + this.reset(); } } type EposQuality = '6' | '14' | '26' | '98' function getEposDir(quality: EposQuality) { - let dir: number[][] + let dir: number[][]; switch (quality) { - case '6': dir = [ ...Type001 ]; break - case '14': dir = [ ...Type001, ...Type111 ]; break - case '26': dir = [ ...Type001, ...Type111, ...Type011 ]; break - case '98': dir = [ ...Type001, ...Type111, ...Type011, ...Type012, ...Type112, ...Type122 ]; break + case '6': dir = [ ...Type001 ]; break; + case '14': dir = [ ...Type001, ...Type111 ]; break; + case '26': dir = [ ...Type001, ...Type111, ...Type011 ]; break; + case '98': dir = [ ...Type001, ...Type111, ...Type011, ...Type012, ...Type112, ...Type122 ]; break; } return dir.map(a => { - const v = Vec3.create(a[0], a[1], a[2]) - return Vec3.normalize(v, v) - }) + const v = Vec3.create(a[0], a[1], a[2]); + return Vec3.normalize(v, v); + }); } const Type001 = [ [1, 0, 0], [0, 1, 0], [0, 0, 1] -] +]; const Type111 = [ [1, 1, 1], [-1, 1, 1], [-1, -1, 1], [1, -1, 1] -] +]; const Type011 = [ [1, 1, 0], [1, -1, 0], [1, 0, 1], [1, 0, -1], [0, 1, 1], [0, 1, -1] -] +]; const Type012 = [ [0, 1, 2], [0, 2, 1], [1, 0, 2], [2, 0, 1], [1, 2, 0], [2, 1, 0], [0, 1, -2], [0, 2, -1], [1, 0, -2], [2, 0, -1], [1, -2, 0], [2, -1, 0] -] +]; const Type112 = [ [1, 1, 2], [2, 1, 1], [1, 2, 1], [1, -1, 2], [1, 1, -2], [1, -1, -2], [2, -1, 1], [2, 1, -1], [2, -1, -1], [1, -2, 1], [1, 2, -1], [1, -2, -1] -] +]; const Type122 = [ [2, 2, 1], [1, 2, 2], [2, 1, 2], [2, -2, 1], [2, 2, -1], [2, -2, -1], [1, -2, 2], [1, 2, -2], [1, -2, -2], [2, -1, 2], [2, 1, -2], [2, -1, -2] -] \ No newline at end of file +]; \ No newline at end of file diff --git a/src/mol-math/geometry/boundary.ts b/src/mol-math/geometry/boundary.ts index 16865fa7a38c87e3ed78280c18d5d9bdc7abc323..d3a21e816d7c3425dc6e60211829caea839505dd 100644 --- a/src/mol-math/geometry/boundary.ts +++ b/src/mol-math/geometry/boundary.ts @@ -14,7 +14,7 @@ import { Box3D, Sphere3D } from '../geometry'; const boundaryHelperCoarse = new BoundaryHelper('14'); const boundaryHelperFine = new BoundaryHelper('98'); function getBoundaryHelper(count: number) { - return count > 100_000 ? boundaryHelperCoarse : boundaryHelperFine + return count > 100_000 ? boundaryHelperCoarse : boundaryHelperFine; } export type Boundary = { readonly box: Box3D, readonly sphere: Sphere3D } @@ -37,15 +37,15 @@ export function getBoundary(data: PositionData): Boundary { boundaryHelper.radiusPositionRadius(p, (radius && radius[i]) || 0); } - const sphere = boundaryHelper.getSphere() + const sphere = boundaryHelper.getSphere(); if (!radius && OrderedSet.size(indices) <= 98) { - const extrema: Vec3[] = [] + const extrema: Vec3[] = []; for (let t = 0, _t = OrderedSet.size(indices); t < _t; t++) { const i = OrderedSet.getAt(indices, t); extrema.push(Vec3.create(x[i], y[i], z[i])); } - Sphere3D.setExtrema(sphere, extrema) + Sphere3D.setExtrema(sphere, extrema); } return { box: boundaryHelper.getBox(), sphere }; diff --git a/src/mol-math/geometry/centroid-helper.ts b/src/mol-math/geometry/centroid-helper.ts index 807866493df5547d3f4287d6c3b3eeb0748bc26a..0398cfe68bb74d128f9f36eea050cc58da0baee1 100644 --- a/src/mol-math/geometry/centroid-helper.ts +++ b/src/mol-math/geometry/centroid-helper.ts @@ -8,7 +8,7 @@ import { Vec3 } from '../../mol-math/linear-algebra/3d'; import { Sphere3D } from './primitives/sphere3d'; -export { CentroidHelper } +export { CentroidHelper }; class CentroidHelper { private count = 0; @@ -44,10 +44,10 @@ class CentroidHelper { } getSphere(sphere?: Sphere3D): Sphere3D { - if (!sphere) sphere = Sphere3D() - Vec3.copy(sphere.center, this.center) - sphere.radius = Math.sqrt(this.radiusSq) - return sphere + if (!sphere) sphere = Sphere3D(); + Vec3.copy(sphere.center, this.center); + sphere.radius = Math.sqrt(this.radiusSq); + return sphere; } getCount() { @@ -58,9 +58,9 @@ class CentroidHelper { } namespace CentroidHelper { - const helper = new CentroidHelper() - const posA = Vec3() - const posB = Vec3() + const helper = new CentroidHelper(); + const posA = Vec3(); + const posB = Vec3(); export function fromArrays({ x, y, z }: { x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number> }, to: Sphere3D) { helper.reset(); @@ -75,41 +75,41 @@ namespace CentroidHelper { helper.radiusStep(posA); } Vec3.copy(to.center, helper.center); - to.radius = Math.sqrt(helper.radiusSq) + to.radius = Math.sqrt(helper.radiusSq); return to; } export function fromProvider(count: number, getter: (i: number, pos: Vec3) => void, to: Sphere3D) { helper.reset(); for (let i = 0; i < count; i++) { - getter(i, posA) + getter(i, posA); helper.includeStep(posA); } helper.finishedIncludeStep(); for (let i = 0; i < count; i++) { - getter(i, posA) + getter(i, posA); helper.radiusStep(posA); } Vec3.copy(to.center, helper.center); - to.radius = Math.sqrt(helper.radiusSq) + to.radius = Math.sqrt(helper.radiusSq); return to; } export function fromPairProvider(count: number, getter: (i: number, posA: Vec3, posB: Vec3) => void, to: Sphere3D) { helper.reset(); for (let i = 0; i < count; i++) { - getter(i, posA, posB) + getter(i, posA, posB); helper.includeStep(posA); helper.includeStep(posB); } helper.finishedIncludeStep(); for (let i = 0; i < count; i++) { - getter(i, posA, posB) + getter(i, posA, posB); helper.radiusStep(posA); helper.radiusStep(posB); } Vec3.copy(to.center, helper.center); - to.radius = Math.sqrt(helper.radiusSq) + to.radius = Math.sqrt(helper.radiusSq); return to; } } \ No newline at end of file diff --git a/src/mol-math/geometry/common.ts b/src/mol-math/geometry/common.ts index 4d37da1f4cb58bab7244577213b983658cb32f96..16a09e84d2dbb8419bef27a166b9067b56da0d80 100644 --- a/src/mol-math/geometry/common.ts +++ b/src/mol-math/geometry/common.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { OrderedSet } from '../../mol-data/int' +import { OrderedSet } from '../../mol-data/int'; import { Mat4, Tensor, Vec3, Vec2 } from '../linear-algebra'; import { Box3D } from '../geometry'; import { Texture } from '../../mol-gl/webgl/texture'; @@ -38,9 +38,9 @@ export type DensityTextureData = { } export function fillGridDim(length: number, start: number, step: number) { - const a = new Float32Array(length) + const a = new Float32Array(length); for (let i = 0; i < a.length; i++) { - a[i] = start + (step * i) + a[i] = start + (step * i); } - return a + return a; } \ No newline at end of file diff --git a/src/mol-math/geometry/distance-transform.ts b/src/mol-math/geometry/distance-transform.ts index 4d86a3a59ffe4919c586d2528568af0fc4197b4d..7c9938c4bf50dd4cb25de9da0b1938a57a081107 100644 --- a/src/mol-math/geometry/distance-transform.ts +++ b/src/mol-math/geometry/distance-transform.ts @@ -12,20 +12,20 @@ import { NumberArray } from '../../mol-util/type-helpers'; export function edt(data: NumberArray, width: number, height: number, f: NumberArray, d: NumberArray, v: NumberArray, z: NumberArray) { for (let x = 0; x < width; x++) { for (let y = 0; y < height; y++) { - f[y] = data[y * width + x] + f[y] = data[y * width + x]; } - edt1d(f, d, v, z, height) + edt1d(f, d, v, z, height); for (let y = 0; y < height; y++) { - data[y * width + x] = d[y] + data[y * width + x] = d[y]; } } for (let y = 0; y < height; y++) { for (let x = 0; x < width; x++) { - f[x] = data[y * width + x] + f[x] = data[y * width + x]; } - edt1d(f, d, v, z, width) + edt1d(f, d, v, z, width); for (let x = 0; x < width; x++) { - data[y * width + x] = Math.sqrt(d[x]) + data[y * width + x] = Math.sqrt(d[x]); } } } @@ -34,24 +34,24 @@ export function edt(data: NumberArray, width: number, height: number, f: NumberA * 1D squared distance transform */ function edt1d(f: NumberArray, d: NumberArray, v: NumberArray, z: NumberArray, n: number) { - v[0] = 0 - z[0] = Number.MIN_SAFE_INTEGER - z[1] = Number.MAX_SAFE_INTEGER + v[0] = 0; + z[0] = Number.MIN_SAFE_INTEGER; + z[1] = Number.MAX_SAFE_INTEGER; for (let q = 1, k = 0; q < n; q++) { - let s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]) + let s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]); while (s <= z[k]) { - k-- - s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]) + k--; + s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k]); } - k++ - v[k] = q - z[k] = s - z[k + 1] = Number.MAX_SAFE_INTEGER + k++; + v[k] = q; + z[k] = s; + z[k + 1] = Number.MAX_SAFE_INTEGER; } for (let q = 0, k = 0; q < n; q++) { - while (z[k + 1] < q) k++ - d[q] = (q - v[k]) * (q - v[k]) + f[v[k]] + while (z[k + 1] < q) k++; + d[q] = (q - v[k]) * (q - v[k]) + f[v[k]]; } } diff --git a/src/mol-math/geometry/gaussian-density.ts b/src/mol-math/geometry/gaussian-density.ts index e106332477d0f64d2ce8fd8c5d253920c5011c6d..f20f07421a64e2842f9d2a787edc10d2e73cccf4 100644 --- a/src/mol-math/geometry/gaussian-density.ts +++ b/src/mol-math/geometry/gaussian-density.ts @@ -24,18 +24,18 @@ export const DefaultGaussianDensityGPUProps = { resolution: 1, radiusOffset: 0, smoothness: 1.5, -} +}; export type GaussianDensityGPUProps = typeof DefaultGaussianDensityGPUProps export const DefaultGaussianDensityProps = { ...DefaultGaussianDensityGPUProps, useGpu: true, -} +}; export type GaussianDensityProps = typeof DefaultGaussianDensityProps export function computeGaussianDensity(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps, webgl?: WebGLContext) { return Task.create('Gaussian Density', async ctx => { - return await GaussianDensity(ctx, position, box, radius, props, webgl) + return await GaussianDensity(ctx, position, box, radius, props, webgl); }); } @@ -43,22 +43,22 @@ export async function GaussianDensity(ctx: RuntimeContext, position: PositionDat if (props.useGpu) { if (!GaussianDensityGPU) throw 'GPU computation not supported on this platform'; if (!webgl) throw 'No WebGL context provided'; - return GaussianDensityGPU(position, box, radius, props, webgl) + return GaussianDensityGPU(position, box, radius, props, webgl); } else { - return await GaussianDensityCPU(ctx, position, box, radius, props) + return await GaussianDensityCPU(ctx, position, box, radius, props); } } export function computeGaussianDensityTexture(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext, texture?: Texture) { - return _computeGaussianDensityTexture(webgl.isWebGL2 ? '3d' : '2d', position, box, radius, props, webgl, texture) + return _computeGaussianDensityTexture(webgl.isWebGL2 ? '3d' : '2d', position, box, radius, props, webgl, texture); } export function computeGaussianDensityTexture2d(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext, texture?: Texture) { - return _computeGaussianDensityTexture('2d', position, box, radius, props, webgl, texture) + return _computeGaussianDensityTexture('2d', position, box, radius, props, webgl, texture); } export function computeGaussianDensityTexture3d(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext, texture?: Texture) { - return _computeGaussianDensityTexture('2d', position, box, radius, props, webgl, texture) + return _computeGaussianDensityTexture('2d', position, box, radius, props, webgl, texture); } function _computeGaussianDensityTexture(type: '2d' | '3d', position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext, texture?: Texture) { diff --git a/src/mol-math/geometry/gaussian-density/cpu.ts b/src/mol-math/geometry/gaussian-density/cpu.ts index f5b3b84bfdaaebebe5866bf998413fe95af0830b..f51689adb17c40a02e1a99a91a7e96b147a2b3ea 100644 --- a/src/mol-math/geometry/gaussian-density/cpu.ts +++ b/src/mol-math/geometry/gaussian-density/cpu.ts @@ -12,96 +12,96 @@ import { OrderedSet } from '../../../mol-data/int'; import { GaussianDensityProps } from '../gaussian-density'; export async function GaussianDensityCPU(ctx: RuntimeContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityProps): Promise<DensityData> { - const { resolution, radiusOffset, smoothness } = props - const scaleFactor = 1 / resolution + const { resolution, radiusOffset, smoothness } = props; + const scaleFactor = 1 / resolution; - const { indices, x, y, z, id } = position - const n = OrderedSet.size(indices) - const radii = new Float32Array(n) + const { indices, x, y, z, id } = position; + const n = OrderedSet.size(indices); + const radii = new Float32Array(n); - let maxRadius = 0 + let maxRadius = 0; for (let i = 0; i < n; ++i) { - const r = radius(OrderedSet.getAt(indices, i)) + radiusOffset - if (maxRadius < r) maxRadius = r - radii[i] = r + const r = radius(OrderedSet.getAt(indices, i)) + radiusOffset; + if (maxRadius < r) maxRadius = r; + radii[i] = r; } - const pad = maxRadius * 2 + resolution + const pad = maxRadius * 2 + resolution; const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad)); - const min = expandedBox.min - const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor) - const dim = Box3D.size(Vec3(), scaledBox) - Vec3.ceil(dim, dim) + const min = expandedBox.min; + const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor); + const dim = Box3D.size(Vec3(), scaledBox); + Vec3.ceil(dim, dim); - const space = Tensor.Space(dim, [0, 1, 2], Float32Array) - const data = space.create() - const field = Tensor.create(space, data) + const space = Tensor.Space(dim, [0, 1, 2], Float32Array); + const data = space.create(); + const field = Tensor.create(space, data); - const idData = space.create() - idData.fill(-1) - const idField = Tensor.create(space, idData) + const idData = space.create(); + idData.fill(-1); + const idField = Tensor.create(space, idData); - const [ dimX, dimY, dimZ ] = dim - const iu = dimZ, iv = dimY, iuv = iu * iv + const [ dimX, dimY, dimZ ] = dim; + const iu = dimZ, iv = dimY, iuv = iu * iv; - const gridx = fillGridDim(dim[0], min[0], resolution) - const gridy = fillGridDim(dim[1], min[1], resolution) - const gridz = fillGridDim(dim[2], min[2], resolution) + const gridx = fillGridDim(dim[0], min[0], resolution); + const gridy = fillGridDim(dim[1], min[1], resolution); + const gridz = fillGridDim(dim[2], min[2], resolution); - const densData = space.create() + const densData = space.create(); - const alpha = smoothness - const updateChunk = Math.ceil(100000 / ((Math.pow(Math.pow(maxRadius, 3), 3) * scaleFactor))) + const alpha = smoothness; + const updateChunk = Math.ceil(100000 / ((Math.pow(Math.pow(maxRadius, 3), 3) * scaleFactor))); function accumulateRange(begI: number, endI: number) { for (let i = begI; i < endI; ++i) { - const j = OrderedSet.getAt(indices, i) - const vx = x[j], vy = y[j], vz = z[j] + const j = OrderedSet.getAt(indices, i); + const vx = x[j], vy = y[j], vz = z[j]; - const rad = radii[i] - const rSq = rad * rad - const rSqInv = 1 / rSq + const rad = radii[i]; + const rSq = rad * rad; + const rSqInv = 1 / rSq; - const r2 = rad * 2 - const r2sq = r2 * r2 + const r2 = rad * 2; + const r2sq = r2 * r2; // Number of grid points, round this up... - const ng = Math.ceil(r2 * scaleFactor) + const ng = Math.ceil(r2 * scaleFactor); // Center of the atom, mapped to grid points (take floor) - const iax = Math.floor(scaleFactor * (vx - min[0])) - const iay = Math.floor(scaleFactor * (vy - min[1])) - const iaz = Math.floor(scaleFactor * (vz - min[2])) + const iax = Math.floor(scaleFactor * (vx - min[0])); + const iay = Math.floor(scaleFactor * (vy - min[1])); + const iaz = Math.floor(scaleFactor * (vz - min[2])); // Extents of grid to consider for this atom - const begX = Math.max(0, iax - ng) - const begY = Math.max(0, iay - ng) - const begZ = Math.max(0, iaz - ng) + const begX = Math.max(0, iax - ng); + const begY = Math.max(0, iay - ng); + const begZ = Math.max(0, iaz - ng); // Add two to these points: // - iax are floor'd values so this ensures coverage // - these are loop limits (exclusive) - const endX = Math.min(dimX, iax + ng + 2) - const endY = Math.min(dimY, iay + ng + 2) - const endZ = Math.min(dimZ, iaz + ng + 2) + const endX = Math.min(dimX, iax + ng + 2); + const endY = Math.min(dimY, iay + ng + 2); + const endZ = Math.min(dimZ, iaz + ng + 2); for (let xi = begX; xi < endX; ++xi) { - const dx = gridx[xi] - vx - const xIdx = xi * iuv + const dx = gridx[xi] - vx; + const xIdx = xi * iuv; for (let yi = begY; yi < endY; ++yi) { - const dy = gridy[yi] - vy - const dxySq = dx * dx + dy * dy - const xyIdx = yi * iu + xIdx + const dy = gridy[yi] - vy; + const dxySq = dx * dx + dy * dy; + const xyIdx = yi * iu + xIdx; for (let zi = begZ; zi < endZ; ++zi) { - const dz = gridz[zi] - vz - const dSq = dxySq + dz * dz + const dz = gridz[zi] - vz; + const dSq = dxySq + dz * dz; if (dSq <= r2sq) { - const dens = Math.exp(-alpha * (dSq * rSqInv)) - const idx = zi + xyIdx - data[idx] += dens + const dens = Math.exp(-alpha * (dSq * rSqInv)); + const idx = zi + xyIdx; + data[idx] += dens; if (dens > densData[idx]) { - densData[idx] = dens - idData[idx] = id ? id[i] : i + densData[idx] = dens; + idData[idx] = id ? id[i] : i; } } } @@ -112,21 +112,21 @@ export async function GaussianDensityCPU(ctx: RuntimeContext, position: Position async function accumulate() { for (let i = 0; i < n; i += updateChunk) { - accumulateRange(i, Math.min(i + updateChunk, n)) + accumulateRange(i, Math.min(i + updateChunk, n)); if (ctx.shouldUpdate) { - await ctx.update({ message: 'filling density grid', current: i, max: n }) + await ctx.update({ message: 'filling density grid', current: i, max: n }); } } } // console.time('gaussian density cpu') - await accumulate() + await accumulate(); // console.timeEnd('gaussian density cpu') - const transform = Mat4.identity() - Mat4.fromScaling(transform, Vec3.create(resolution, resolution, resolution)) - Mat4.setTranslation(transform, expandedBox.min) + const transform = Mat4.identity(); + Mat4.fromScaling(transform, Vec3.create(resolution, resolution, resolution)); + Mat4.setTranslation(transform, expandedBox.min); - return { field, idField, transform } + return { field, idField, transform }; } \ No newline at end of file diff --git a/src/mol-math/geometry/gaussian-density/gpu.ts b/src/mol-math/geometry/gaussian-density/gpu.ts index 0a3017adf8d93fb3857ab73fee1f43c334f6f6d2..61204ab8160a841379e3dfd07907a60d22376f4c 100644 --- a/src/mol-math/geometry/gaussian-density/gpu.ts +++ b/src/mol-math/geometry/gaussian-density/gpu.ts @@ -5,21 +5,21 @@ * @author Michael Krone <michael.krone@uni-tuebingen.de> */ -import { PositionData, DensityData, DensityTextureData } from '../common' -import { Box3D } from '../../geometry' -import { GaussianDensityGPUProps } from '../gaussian-density' -import { OrderedSet } from '../../../mol-data/int' -import { Vec3, Tensor, Mat4, Vec2 } from '../../linear-algebra' -import { ValueCell } from '../../../mol-util' -import { createComputeRenderable, ComputeRenderable } from '../../../mol-gl/renderable' +import { PositionData, DensityData, DensityTextureData } from '../common'; +import { Box3D } from '../../geometry'; +import { GaussianDensityGPUProps } from '../gaussian-density'; +import { OrderedSet } from '../../../mol-data/int'; +import { Vec3, Tensor, Mat4, Vec2 } from '../../linear-algebra'; +import { ValueCell } from '../../../mol-util'; +import { createComputeRenderable, ComputeRenderable } from '../../../mol-gl/renderable'; import { WebGLContext } from '../../../mol-gl/webgl/context'; import { Texture } from '../../../mol-gl/webgl/texture'; import { decodeFloatRGB } from '../../../mol-util/float-packing'; import { ShaderCode } from '../../../mol-gl/shader-code'; import { createComputeRenderItem } from '../../../mol-gl/webgl/render-item'; import { ValueSpec, AttributeSpec, UniformSpec, TextureSpec, DefineSpec, Values } from '../../../mol-gl/renderable/schema'; -import gaussian_density_vert from '../../../mol-gl/shader/gaussian-density.vert' -import gaussian_density_frag from '../../../mol-gl/shader/gaussian-density.frag' +import gaussian_density_vert from '../../../mol-gl/shader/gaussian-density.vert'; +import gaussian_density_frag from '../../../mol-gl/shader/gaussian-density.frag'; export const GaussianDensitySchema = { drawCount: ValueSpec('number'), @@ -43,48 +43,48 @@ export const GaussianDensitySchema = { dGridTexType: DefineSpec('string', ['2d', '3d']), dCalcType: DefineSpec('string', ['density', 'minDistance', 'groupId']), -} +}; export const GaussianDensityShaderCode = ShaderCode( 'gaussian-density', gaussian_density_vert, gaussian_density_frag, { standardDerivatives: false, fragDepth: false } -) +); export function GaussianDensityGPU(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, webgl: WebGLContext): DensityData { // always use texture2d when the gaussian density needs to be downloaded from the GPU, // it's faster than texture3d // console.time('GaussianDensityTexture2d') - const { scale, bbox, texture, gridDim, gridTexDim } = calcGaussianDensityTexture2d(webgl, position, box, radius, props) + const { scale, bbox, texture, gridDim, gridTexDim } = calcGaussianDensityTexture2d(webgl, position, box, radius, props); // webgl.waitForGpuCommandsCompleteSync() // console.timeEnd('GaussianDensityTexture2d') - const { field, idField } = fieldFromTexture2d(webgl, texture, gridDim, gridTexDim) + const { field, idField } = fieldFromTexture2d(webgl, texture, gridDim, gridTexDim); - return { field, idField, transform: getTransform(scale, bbox) } + return { field, idField, transform: getTransform(scale, bbox) }; } export function GaussianDensityTexture(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): DensityTextureData { return webgl.isWebGL2 ? GaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture) : - GaussianDensityTexture2d(webgl, position, box, radius, props, oldTexture) + GaussianDensityTexture2d(webgl, position, box, radius, props, oldTexture); } export function GaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): DensityTextureData { - return finalizeGaussianDensityTexture(calcGaussianDensityTexture2d(webgl, position, box, radius, props, oldTexture)) + return finalizeGaussianDensityTexture(calcGaussianDensityTexture2d(webgl, position, box, radius, props, oldTexture)); } export function GaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, oldTexture?: Texture): DensityTextureData { - return finalizeGaussianDensityTexture(calcGaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture)) + return finalizeGaussianDensityTexture(calcGaussianDensityTexture3d(webgl, position, box, radius, props, oldTexture)); } function finalizeGaussianDensityTexture({ texture, scale, bbox, gridDim, gridTexDim, gridTexScale }: GaussianDensityTextureData): DensityTextureData { - return { transform: getTransform(scale, bbox), texture, bbox, gridDim, gridTexDim, gridTexScale } + return { transform: getTransform(scale, bbox), texture, bbox, gridDim, gridTexDim, gridTexScale }; } function getTransform(scale: Vec3, bbox: Box3D) { - const transform = Mat4.identity() - Mat4.fromScaling(transform, scale) - Mat4.setTranslation(transform, bbox.min) - return transform + const transform = Mat4.identity(); + Mat4.fromScaling(transform, scale); + Mat4.setTranslation(transform, bbox.min); + return transform; } // @@ -99,162 +99,162 @@ type GaussianDensityTextureData = { } function calcGaussianDensityTexture2d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): GaussianDensityTextureData { - const { smoothness } = props + const { smoothness } = props; - const { drawCount, positions, radii, groups, scale, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props) - const [ dx, dy, dz ] = dim - const { texDimX, texDimY, texCols, powerOfTwoSize } = getTexture2dSize(dim) + const { drawCount, positions, radii, groups, scale, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props); + const [ dx, dy, dz ] = dim; + const { texDimX, texDimY, texCols, powerOfTwoSize } = getTexture2dSize(dim); // console.log({ texDimX, texDimY, texCols, powerOfTwoSize, dim }) - const gridTexDim = Vec3.create(texDimX, texDimY, 0) - const gridTexScale = Vec2.create(texDimX / powerOfTwoSize, texDimY / powerOfTwoSize) + const gridTexDim = Vec3.create(texDimX, texDimY, 0); + const gridTexScale = Vec2.create(texDimX / powerOfTwoSize, texDimY / powerOfTwoSize); - const minDistanceTexture = webgl.resources.texture('image-float32', 'rgba', 'float', 'nearest') - minDistanceTexture.define(powerOfTwoSize, powerOfTwoSize) + const minDistanceTexture = webgl.resources.texture('image-float32', 'rgba', 'float', 'nearest'); + minDistanceTexture.define(powerOfTwoSize, powerOfTwoSize); - const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, gridTexDim, gridTexScale, smoothness, props.resolution) + const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, gridTexDim, gridTexScale, smoothness, props.resolution); // - const { gl, resources, state } = webgl - const { uCurrentSlice, uCurrentX, uCurrentY } = renderable.values + const { gl, resources, state } = webgl; + const { uCurrentSlice, uCurrentX, uCurrentY } = renderable.values; - const framebuffer = resources.framebuffer() - framebuffer.bind() - setRenderingDefaults(webgl) + const framebuffer = resources.framebuffer(); + framebuffer.bind(); + setRenderingDefaults(webgl); if (!texture) { - texture = resources.texture('image-float32', 'rgba', 'float', 'nearest') - texture.define(powerOfTwoSize, powerOfTwoSize) + texture = resources.texture('image-float32', 'rgba', 'float', 'nearest'); + texture.define(powerOfTwoSize, powerOfTwoSize); } else if (texture.getWidth() !== powerOfTwoSize || texture.getHeight() !== powerOfTwoSize) { - texture.define(powerOfTwoSize, powerOfTwoSize) + texture.define(powerOfTwoSize, powerOfTwoSize); } // console.log(renderable) function render(fbTex: Texture, clear: boolean) { - state.currentRenderItemId = -1 - fbTex.attachFramebuffer(framebuffer, 0) - if (clear) gl.clear(gl.COLOR_BUFFER_BIT) - let currCol = 0 - let currY = 0 - let currX = 0 + state.currentRenderItemId = -1; + fbTex.attachFramebuffer(framebuffer, 0); + if (clear) gl.clear(gl.COLOR_BUFFER_BIT); + let currCol = 0; + let currY = 0; + let currX = 0; for (let i = 0; i < dz; ++i) { if (currCol >= texCols) { - currCol -= texCols - currY += dy - currX = 0 - ValueCell.update(uCurrentY, currY) + currCol -= texCols; + currY += dy; + currX = 0; + ValueCell.update(uCurrentY, currY); } // console.log({ i, currX, currY }) - ValueCell.update(uCurrentX, currX) - ValueCell.update(uCurrentSlice, i) - gl.viewport(currX, currY, dx, dy) - renderable.render() - ++currCol - currX += dx + ValueCell.update(uCurrentX, currX); + ValueCell.update(uCurrentSlice, i); + gl.viewport(currX, currY, dx, dy); + renderable.render(); + ++currCol; + currX += dx; } - gl.finish() + gl.finish(); } - setupDensityRendering(webgl, renderable) - render(texture, true) + setupDensityRendering(webgl, renderable); + render(texture, true); - setupMinDistanceRendering(webgl, renderable) - render(minDistanceTexture, true) + setupMinDistanceRendering(webgl, renderable); + render(minDistanceTexture, true); - setupGroupIdRendering(webgl, renderable) - render(texture, false) + setupGroupIdRendering(webgl, renderable); + render(texture, false); // printTexture(webgl, texture, 1) - return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale } + return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim, gridTexScale }; } function calcGaussianDensityTexture3d(webgl: WebGLContext, position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps, texture?: Texture): GaussianDensityTextureData { - const { gl, resources } = webgl - const { smoothness } = props + const { gl, resources } = webgl; + const { smoothness } = props; - const { drawCount, positions, radii, groups, scale, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props) - const [ dx, dy, dz ] = dim - const minDistanceTexture = resources.texture('volume-float32', 'rgba', 'float', 'nearest') - minDistanceTexture.define(dx, dy, dz) + const { drawCount, positions, radii, groups, scale, expandedBox, dim } = prepareGaussianDensityData(position, box, radius, props); + const [ dx, dy, dz ] = dim; + const minDistanceTexture = resources.texture('volume-float32', 'rgba', 'float', 'nearest'); + minDistanceTexture.define(dx, dy, dz); - const gridTexScale = Vec2.create(1, 1) + const gridTexScale = Vec2.create(1, 1); - const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, dim, gridTexScale, smoothness, props.resolution) + const renderable = getGaussianDensityRenderable(webgl, drawCount, positions, radii, groups, minDistanceTexture, expandedBox, dim, dim, gridTexScale, smoothness, props.resolution); // - const { uCurrentSlice } = renderable.values + const { uCurrentSlice } = renderable.values; - const framebuffer = resources.framebuffer() - framebuffer.bind() - setRenderingDefaults(webgl) - gl.viewport(0, 0, dx, dy) + const framebuffer = resources.framebuffer(); + framebuffer.bind(); + setRenderingDefaults(webgl); + gl.viewport(0, 0, dx, dy); - if (!texture) texture = resources.texture('volume-float32', 'rgba', 'float', 'nearest') - texture.define(dx, dy, dz) + if (!texture) texture = resources.texture('volume-float32', 'rgba', 'float', 'nearest'); + texture.define(dx, dy, dz); function render(fbTex: Texture) { for (let i = 0; i < dz; ++i) { - ValueCell.update(uCurrentSlice, i) - fbTex.attachFramebuffer(framebuffer, 0, i) - renderable.render() + ValueCell.update(uCurrentSlice, i); + fbTex.attachFramebuffer(framebuffer, 0, i); + renderable.render(); } } - setupMinDistanceRendering(webgl, renderable) - render(minDistanceTexture) + setupMinDistanceRendering(webgl, renderable); + render(minDistanceTexture); - setupDensityRendering(webgl, renderable) - render(texture) + setupDensityRendering(webgl, renderable); + render(texture); - setupGroupIdRendering(webgl, renderable) - render(texture) + setupGroupIdRendering(webgl, renderable); + render(texture); - return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim: dim, gridTexScale } + return { texture, scale, bbox: expandedBox, gridDim: dim, gridTexDim: dim, gridTexScale }; } // function prepareGaussianDensityData(position: PositionData, box: Box3D, radius: (index: number) => number, props: GaussianDensityGPUProps) { - const { resolution, radiusOffset } = props - const scaleFactor = 1 / resolution + const { resolution, radiusOffset } = props; + const scaleFactor = 1 / resolution; - const { indices, x, y, z, id } = position - const n = OrderedSet.size(indices) + const { indices, x, y, z, id } = position; + const n = OrderedSet.size(indices); - const positions = new Float32Array(n * 3) - const radii = new Float32Array(n) - const groups = new Float32Array(n) + const positions = new Float32Array(n * 3); + const radii = new Float32Array(n); + const groups = new Float32Array(n); - let maxRadius = 0 + let maxRadius = 0; for (let i = 0; i < n; ++i) { const j = OrderedSet.getAt(indices, i); - positions[i * 3] = x[j] - positions[i * 3 + 1] = y[j] - positions[i * 3 + 2] = z[j] - const r = radius(j) + radiusOffset - if (maxRadius < r) maxRadius = r - radii[i] = r - groups[i] = id ? id[i] : i + positions[i * 3] = x[j]; + positions[i * 3 + 1] = y[j]; + positions[i * 3 + 2] = z[j]; + const r = radius(j) + radiusOffset; + if (maxRadius < r) maxRadius = r; + radii[i] = r; + groups[i] = id ? id[i] : i; } - const pad = maxRadius * 2 + resolution * 4 + const pad = maxRadius * 2 + resolution * 4; const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad)); - const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor) - const dim = Box3D.size(Vec3(), scaledBox) - Vec3.ceil(dim, dim) + const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor); + const dim = Box3D.size(Vec3(), scaledBox); + Vec3.ceil(dim, dim); - const scale = Vec3.create(resolution, resolution, resolution) + const scale = Vec3.create(resolution, resolution, resolution); - return { drawCount: n, positions, radii, groups, scale, expandedBox, dim } + return { drawCount: n, positions, radii, groups, scale, expandedBox, dim }; } function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, positions: Float32Array, radii: Float32Array, groups: Float32Array, minDistanceTexture: Texture, box: Box3D, gridDim: Vec3, gridTexDim: Vec3, gridTexScale: Vec2, smoothness: number, resolution: number) { - const extent = Vec3.sub(Vec3.zero(), box.max, box.min) + const extent = Vec3.sub(Vec3.zero(), box.max, box.min); const values: Values<typeof GaussianDensitySchema> = { drawCount: ValueCell.create(drawCount), @@ -278,123 +278,123 @@ function getGaussianDensityRenderable(webgl: WebGLContext, drawCount: number, po dGridTexType: ValueCell.create(minDistanceTexture.getDepth() > 0 ? '3d' : '2d'), dCalcType: ValueCell.create('minDistance'), - } + }; - const schema = { ...GaussianDensitySchema } - const shaderCode = GaussianDensityShaderCode - const renderItem = createComputeRenderItem(webgl, 'points', shaderCode, schema, values) + const schema = { ...GaussianDensitySchema }; + const shaderCode = GaussianDensityShaderCode; + const renderItem = createComputeRenderItem(webgl, 'points', shaderCode, schema, values); - return createComputeRenderable(renderItem, values) + return createComputeRenderable(renderItem, values); } function setRenderingDefaults(ctx: WebGLContext) { - const { gl, state } = ctx - state.disable(gl.CULL_FACE) - state.enable(gl.BLEND) - state.disable(gl.DEPTH_TEST) - state.disable(gl.SCISSOR_TEST) - state.depthMask(false) - state.clearColor(0, 0, 0, 0) + const { gl, state } = ctx; + state.disable(gl.CULL_FACE); + state.enable(gl.BLEND); + state.disable(gl.DEPTH_TEST); + state.disable(gl.SCISSOR_TEST); + state.depthMask(false); + state.clearColor(0, 0, 0, 0); } function setupMinDistanceRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) { - const { gl, state } = webgl - ValueCell.update(renderable.values.dCalcType, 'minDistance') - renderable.update() - state.colorMask(false, false, false, true) - state.blendFunc(gl.ONE, gl.ONE) + const { gl, state } = webgl; + ValueCell.update(renderable.values.dCalcType, 'minDistance'); + renderable.update(); + state.colorMask(false, false, false, true); + state.blendFunc(gl.ONE, gl.ONE); // the shader writes 1 - dist so we set blending to MAX if (!webgl.extensions.blendMinMax) { - throw new Error('GPU gaussian surface calculation requires EXT_blend_minmax') + throw new Error('GPU gaussian surface calculation requires EXT_blend_minmax'); } - state.blendEquation(webgl.extensions.blendMinMax.MAX) + state.blendEquation(webgl.extensions.blendMinMax.MAX); } function setupDensityRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) { - const { gl, state } = webgl - ValueCell.update(renderable.values.dCalcType, 'density') - renderable.update() - state.colorMask(false, false, false, true) - state.blendFunc(gl.ONE, gl.ONE) + const { gl, state } = webgl; + ValueCell.update(renderable.values.dCalcType, 'density'); + renderable.update(); + state.colorMask(false, false, false, true); + state.blendFunc(gl.ONE, gl.ONE); // state.colorMask(true, true, true, true) // state.blendFuncSeparate(gl.ONE, gl.ZERO, gl.ONE, gl.ONE) - state.blendEquation(gl.FUNC_ADD) + state.blendEquation(gl.FUNC_ADD); } function setupGroupIdRendering(webgl: WebGLContext, renderable: ComputeRenderable<any>) { - const { gl, state } = webgl - ValueCell.update(renderable.values.dCalcType, 'groupId') - renderable.update() + const { gl, state } = webgl; + ValueCell.update(renderable.values.dCalcType, 'groupId'); + renderable.update(); // overwrite color, don't change alpha - state.colorMask(true, true, true, false) - state.blendFunc(gl.ONE, gl.ZERO) - state.blendEquation(gl.FUNC_ADD) + state.colorMask(true, true, true, false); + state.blendFunc(gl.ONE, gl.ZERO); + state.blendEquation(gl.FUNC_ADD); } function getTexture2dSize(gridDim: Vec3) { - const area = gridDim[0] * gridDim[1] * gridDim[2] - const squareDim = Math.sqrt(area) - const powerOfTwoSize = Math.pow(2, Math.ceil(Math.log(squareDim) / Math.log(2))) - - let texDimX = 0 - let texDimY = gridDim[1] - let texRows = 1 - let texCols = gridDim[2] + const area = gridDim[0] * gridDim[1] * gridDim[2]; + const squareDim = Math.sqrt(area); + const powerOfTwoSize = Math.pow(2, Math.ceil(Math.log(squareDim) / Math.log(2))); + + let texDimX = 0; + let texDimY = gridDim[1]; + let texRows = 1; + let texCols = gridDim[2]; if (powerOfTwoSize < gridDim[0] * gridDim[2]) { - texCols = Math.floor(powerOfTwoSize / gridDim[0]) - texRows = Math.ceil(gridDim[2] / texCols) - texDimX = texCols * gridDim[0] - texDimY *= texRows + texCols = Math.floor(powerOfTwoSize / gridDim[0]); + texRows = Math.ceil(gridDim[2] / texCols); + texDimX = texCols * gridDim[0]; + texDimY *= texRows; } else { - texDimX = gridDim[0] * gridDim[2] + texDimX = gridDim[0] * gridDim[2]; } - return { texDimX, texDimY, texRows, texCols, powerOfTwoSize: texDimY < powerOfTwoSize ? powerOfTwoSize : powerOfTwoSize * 2 } + return { texDimX, texDimY, texRows, texCols, powerOfTwoSize: texDimY < powerOfTwoSize ? powerOfTwoSize : powerOfTwoSize * 2 }; } export function fieldFromTexture2d(ctx: WebGLContext, texture: Texture, dim: Vec3, texDim: Vec3) { // console.time('fieldFromTexture2d') - const { resources } = ctx - const [ dx, dy, dz ] = dim + const { resources } = ctx; + const [ dx, dy, dz ] = dim; // const { width, height } = texture - const [ width, height ] = texDim - const fboTexCols = Math.floor(width / dx) + const [ width, height ] = texDim; + const fboTexCols = Math.floor(width / dx); - const space = Tensor.Space(dim, [2, 1, 0], Float32Array) - const data = space.create() - const field = Tensor.create(space, data) - const idData = space.create() - const idField = Tensor.create(space, idData) + const space = Tensor.Space(dim, [2, 1, 0], Float32Array); + const data = space.create(); + const field = Tensor.create(space, data); + const idData = space.create(); + const idField = Tensor.create(space, idData); // const image = new Uint8Array(width * height * 4) - const image = new Float32Array(width * height * 4) + const image = new Float32Array(width * height * 4); - const framebuffer = resources.framebuffer() - framebuffer.bind() - texture.attachFramebuffer(framebuffer, 0) - ctx.readPixels(0, 0, width, height, image) + const framebuffer = resources.framebuffer(); + framebuffer.bind(); + texture.attachFramebuffer(framebuffer, 0); + ctx.readPixels(0, 0, width, height, image); // printImageData(createImageData(image, width, height), 1/3) - let j = 0 - let tmpCol = 0 - let tmpRow = 0 + let j = 0; + let tmpCol = 0; + let tmpRow = 0; for (let iz = 0; iz < dz; ++iz) { if (tmpCol >= fboTexCols ) { - tmpCol = 0 - tmpRow += dy + tmpCol = 0; + tmpRow += dy; } for (let iy = 0; iy < dy; ++iy) { for (let ix = 0; ix < dx; ++ix) { - const idx = 4 * (tmpCol * dx + (iy + tmpRow) * width + ix) - data[j] = image[idx + 3] // / 255 - idData[j] = decodeFloatRGB(image[idx] * 255, image[idx + 1] * 255, image[idx + 2] * 255) - j++ + const idx = 4 * (tmpCol * dx + (iy + tmpRow) * width + ix); + data[j] = image[idx + 3]; // / 255 + idData[j] = decodeFloatRGB(image[idx] * 255, image[idx + 1] * 255, image[idx + 2] * 255); + j++; } } - tmpCol++ + tmpCol++; } // console.timeEnd('fieldFromTexture2d') - return { field, idField } + return { field, idField }; } \ No newline at end of file diff --git a/src/mol-math/geometry/lookup3d/common.ts b/src/mol-math/geometry/lookup3d/common.ts index b01d83777f918f1a096f60b94ef05e7adb80db37..cc2c5bd5a8018f99e7cfbabb7f41e4d351375ee6 100644 --- a/src/mol-math/geometry/lookup3d/common.ts +++ b/src/mol-math/geometry/lookup3d/common.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Box3D } from '../primitives/box3d' -import { Sphere3D } from '../primitives/sphere3d' +import { Box3D } from '../primitives/box3d'; +import { Sphere3D } from '../primitives/sphere3d'; export interface Result<T> { count: number, @@ -33,8 +33,8 @@ export namespace Result { out.indices[i] = result.indices[i]; out.squaredDistances[i] = result.squaredDistances[i]; } - out.count = result.count - return out + out.count = result.count; + return out; } } diff --git a/src/mol-math/geometry/lookup3d/grid.ts b/src/mol-math/geometry/lookup3d/grid.ts index 1bce1f2f5b96d67ebe11705e426951b834a82357..ef1f719b83b9ed7d39512aa8aac96a68e55af3f1 100644 --- a/src/mol-math/geometry/lookup3d/grid.ts +++ b/src/mol-math/geometry/lookup3d/grid.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Result, Lookup3D } from './common' +import { Result, Lookup3D } from './common'; import { Box3D } from '../primitives/box3d'; import { Sphere3D } from '../primitives/sphere3d'; import { PositionData } from '../common'; @@ -21,7 +21,7 @@ function GridLookup3D<T extends number = number>(data: PositionData, boundary: B return new GridLookup3DImpl<T>(data, boundary, cellSizeOrCount); } -export { GridLookup3D } +export { GridLookup3D }; class GridLookup3DImpl<T extends number = number> implements GridLookup3D<T> { private ctx: QueryContext<T>; @@ -53,7 +53,7 @@ class GridLookup3DImpl<T extends number = number> implements GridLookup3D<T> { this.ctx = createContext<T>(structure); this.boundary = { box: structure.boundingBox, sphere: structure.boundingSphere }; this.buckets = { offset: structure.bucketOffset, count: structure.bucketCounts, array: structure.bucketArray }; - this.result = this.ctx.result + this.result = this.ctx.result; } } @@ -112,7 +112,7 @@ function _build(state: BuildState): Grid3D { const idx = (((x * sY) + y) * sZ) + z; if ((grid[idx] += 1) === 1) { - bucketCount += 1 + bucketCount += 1; } bucketIndex[t] = idx; } @@ -142,7 +142,7 @@ function _build(state: BuildState): Grid3D { const bucketFill = new Int32Array(bucketCount); const bucketArray = new Int32Array(elementCount); for (let i = 0; i < elementCount; i++) { - const bucketIdx = grid[bucketIndex[i]] + const bucketIdx = grid[bucketIndex[i]]; if (bucketIdx > 0) { const k = bucketIdx - 1; bucketArray[bucketOffset[k] + bucketFill[k]] = i; @@ -163,7 +163,7 @@ function _build(state: BuildState): Grid3D { expandedBox: state.expandedBox, boundingBox: state.boundingBox, boundingSphere: state.boundingSphere - } + }; } function build(data: PositionData, boundary: Boundary, cellSizeOrCount?: Vec3 | number) { @@ -176,8 +176,8 @@ function build(data: PositionData, boundary: Boundary, cellSizeOrCount?: Vec3 | const elementCount = OrderedSet.size(indices); - const cellCount = typeof cellSizeOrCount === 'number' ? cellSizeOrCount : 32 - const cellSize = Array.isArray(cellSizeOrCount) && cellSizeOrCount + const cellCount = typeof cellSizeOrCount === 'number' ? cellSizeOrCount : 32; + const cellSize = Array.isArray(cellSizeOrCount) && cellSizeOrCount; if (cellSize) { size = [Math.ceil(S[0] / cellSize[0]), Math.ceil(S[1] / cellSize[1]), Math.ceil(S[2] / cellSize[2])]; @@ -210,7 +210,7 @@ function build(data: PositionData, boundary: Boundary, cellSizeOrCount?: Vec3 | boundingSphere: boundary.sphere, elementCount, delta - } + }; return _build(state); } @@ -226,7 +226,7 @@ interface QueryContext<T extends number = number> { } function createContext<T extends number = number>(grid: Grid3D): QueryContext<T> { - return { grid, x: 0.1, y: 0.1, z: 0.1, radius: 0.1, result: Result.create(), isCheck: false } + return { grid, x: 0.1, y: 0.1, z: 0.1, radius: 0.1, result: Result.create(), isCheck: false }; } function query<T extends number = number>(ctx: QueryContext<T>): boolean { diff --git a/src/mol-math/geometry/molecular-surface.ts b/src/mol-math/geometry/molecular-surface.ts index db8c97c0d28d2a587c1ef18d28f1ffcf38444a35..42b4e332a50a0b3559d816bc83fda8f9adb62b3c 100644 --- a/src/mol-math/geometry/molecular-surface.ts +++ b/src/mol-math/geometry/molecular-surface.ts @@ -18,30 +18,30 @@ import { BaseGeometry } from '../../mol-geo/geometry/base'; import { Boundary } from '../../mol-model/structure/structure/util/boundary'; function normalToLine (out: Vec3, p: Vec3) { - out[0] = out[1] = out[2] = 1.0 + out[0] = out[1] = out[2] = 1.0; if (p[0] !== 0) { - out[0] = (p[1] + p[2]) / -p[0] + out[0] = (p[1] + p[2]) / -p[0]; } else if (p[1] !== 0) { - out[1] = (p[0] + p[2]) / -p[1] + out[1] = (p[0] + p[2]) / -p[1]; } else if (p[2] !== 0) { - out[2] = (p[0] + p[1]) / -p[2] + out[2] = (p[0] + p[1]) / -p[2]; } - return out + return out; } type AnglesTables = { cosTable: Float32Array, sinTable: Float32Array } function getAngleTables (probePositions: number): AnglesTables { - let theta = 0.0 - const step = 2 * Math.PI / probePositions + let theta = 0.0; + const step = 2 * Math.PI / probePositions; - const cosTable = new Float32Array(probePositions) - const sinTable = new Float32Array(probePositions) + const cosTable = new Float32Array(probePositions); + const sinTable = new Float32Array(probePositions); for (let i = 0; i < probePositions; i++) { - cosTable[i] = Math.cos(theta) - sinTable[i] = Math.sin(theta) - theta += step + cosTable[i] = Math.cos(theta); + sinTable[i] = Math.sin(theta); + theta += step; } - return { cosTable, sinTable} + return { cosTable, sinTable}; } // @@ -50,8 +50,8 @@ export const MolecularSurfaceCalculationParams = { probeRadius: PD.Numeric(1.4, { min: 0, max: 10, step: 0.1 }, { description: 'Radius of the probe tracing the molecular surface.' }), resolution: PD.Numeric(0.5, { min: 0.01, max: 20, step: 0.01 }, { description: 'Grid resolution/cell spacing.', ...BaseGeometry.CustomQualityParamInfo }), probePositions: PD.Numeric(30, { min: 12, max: 90, step: 1 }, { description: 'Number of positions tested for probe target intersection.', ...BaseGeometry.CustomQualityParamInfo }), -} -export const DefaultMolecularSurfaceCalculationProps = PD.getDefaultValues(MolecularSurfaceCalculationParams) +}; +export const DefaultMolecularSurfaceCalculationProps = PD.getDefaultValues(MolecularSurfaceCalculationParams); export type MolecularSurfaceCalculationProps = typeof DefaultMolecularSurfaceCalculationProps @@ -59,7 +59,7 @@ export async function calcMolecularSurface(ctx: RuntimeContext, position: Requir // Field generation method adapted from AstexViewer (Mike Hartshorn) by Fred Ludlow. // Other parts based heavily on NGL (Alexander Rose) EDT Surface class - let lastClip = -1 + let lastClip = -1; /** * Is the point at x,y,z obscured by any of the atoms specifeid by indices in neighbours. @@ -71,35 +71,35 @@ export async function calcMolecularSurface(ctx: RuntimeContext, position: Requir */ function obscured(x: number, y: number, z: number, a: number, b: number) { if (lastClip !== -1) { - const ai = lastClip + const ai = lastClip; if (ai !== a && ai !== b && singleAtomObscures(ai, x, y, z)) { - return ai + return ai; } else { - lastClip = -1 + lastClip = -1; } } for (let j = 0, jl = neighbours.count; j < jl; ++j) { - const ai = OrderedSet.getAt(indices, neighbours.indices[j]) + const ai = OrderedSet.getAt(indices, neighbours.indices[j]); if (ai !== a && ai !== b && singleAtomObscures(ai, x, y, z)) { - lastClip = ai - return ai + lastClip = ai; + return ai; } } - return -1 + return -1; } /** * `ai` must be a resolved index */ function singleAtomObscures(ai: number, x: number, y: number, z: number) { - const r = radius[ai] - const dx = px[ai] - x - const dy = py[ai] - y - const dz = pz[ai] - z - const dSq = dx * dx + dy * dy + dz * dz - return dSq < (r * r) + const r = radius[ai]; + const dx = px[ai] - x; + const dy = py[ai] - y; + const dz = pz[ai] - z; + const dSq = dx * dx + dy * dy + dz * dz; + return dSq < (r * r); } /** @@ -114,63 +114,63 @@ export async function calcMolecularSurface(ctx: RuntimeContext, position: Requir */ function projectPointsRange (begI: number, endI: number) { for (let i = begI; i < endI; ++i) { - const j = OrderedSet.getAt(indices, i) - const vx = px[j], vy = py[j], vz = pz[j] - const rad = radius[j] - const rSq = rad * rad + const j = OrderedSet.getAt(indices, i); + const vx = px[j], vy = py[j], vz = pz[j]; + const rad = radius[j]; + const rSq = rad * rad; - lookup3d.find(vx, vy, vz, rad) + lookup3d.find(vx, vy, vz, rad); // Number of grid points, round this up... - const ng = Math.ceil(rad * scaleFactor) + const ng = Math.ceil(rad * scaleFactor); // Center of the atom, mapped to grid points (take floor) - const iax = Math.floor(scaleFactor * (vx - minX)) - const iay = Math.floor(scaleFactor * (vy - minY)) - const iaz = Math.floor(scaleFactor * (vz - minZ)) + const iax = Math.floor(scaleFactor * (vx - minX)); + const iay = Math.floor(scaleFactor * (vy - minY)); + const iaz = Math.floor(scaleFactor * (vz - minZ)); // Extents of grid to consider for this atom - const begX = Math.max(0, iax - ng) - const begY = Math.max(0, iay - ng) - const begZ = Math.max(0, iaz - ng) + const begX = Math.max(0, iax - ng); + const begY = Math.max(0, iay - ng); + const begZ = Math.max(0, iaz - ng); // Add two to these points: // - iax are floor'd values so this ensures coverage // - these are loop limits (exclusive) - const endX = Math.min(dimX, iax + ng + 2) - const endY = Math.min(dimY, iay + ng + 2) - const endZ = Math.min(dimZ, iaz + ng + 2) + const endX = Math.min(dimX, iax + ng + 2); + const endY = Math.min(dimY, iay + ng + 2); + const endZ = Math.min(dimZ, iaz + ng + 2); for (let xi = begX; xi < endX; ++xi) { - const dx = gridx[xi] - vx - const xIdx = xi * iuv + const dx = gridx[xi] - vx; + const xIdx = xi * iuv; for (let yi = begY; yi < endY; ++yi) { - const dy = gridy[yi] - vy - const dxySq = dx * dx + dy * dy - const xyIdx = yi * iu + xIdx + const dy = gridy[yi] - vy; + const dxySq = dx * dx + dy * dy; + const xyIdx = yi * iu + xIdx; for (let zi = begZ; zi < endZ; ++zi) { - const dz = gridz[zi] - vz - const dSq = dxySq + dz * dz + const dz = gridz[zi] - vz; + const dSq = dxySq + dz * dz; if (dSq < rSq) { - const idx = zi + xyIdx + const idx = zi + xyIdx; // if unvisited, make positive - if (data[idx] < 0.0) data[idx] *= -1 + if (data[idx] < 0.0) data[idx] *= -1; // Project on to the surface of the sphere // sp is the projected point ( dx, dy, dz ) * ( ra / d ) - const d = Math.sqrt(dSq) - const ap = rad / d - const spx = dx * ap + vx - const spy = dy * ap + vy - const spz = dz * ap + vz + const d = Math.sqrt(dSq); + const ap = rad / d; + const spx = dx * ap + vx; + const spy = dy * ap + vy; + const spz = dz * ap + vz; if (obscured(spx, spy, spz, j, -1) === -1) { - const dd = rad - d + const dd = rad - d; if (dd < data[idx]) { - data[idx] = dd - idData[idx] = id[i] + data[idx] = dd; + idData[idx] = id[i]; } } } @@ -182,108 +182,108 @@ export async function calcMolecularSurface(ctx: RuntimeContext, position: Requir async function projectPoints() { for (let i = 0; i < n; i += updateChunk) { - projectPointsRange(i, Math.min(i + updateChunk, n)) + projectPointsRange(i, Math.min(i + updateChunk, n)); if (ctx.shouldUpdate) { - await ctx.update({ message: 'projecting points', current: i, max: n }) + await ctx.update({ message: 'projecting points', current: i, max: n }); } } } // Vectors for Torus Projection - const atob = Vec3() - const mid = Vec3() - const n1 = Vec3() - const n2 = Vec3() + const atob = Vec3(); + const mid = Vec3(); + const n1 = Vec3(); + const n2 = Vec3(); /** * `a` and `b` must be resolved indices */ function projectTorus(a: number, b: number) { - const rA = radius[a] - const rB = radius[b] - const dx = atob[0] = px[b] - px[a] - const dy = atob[1] = py[b] - py[a] - const dz = atob[2] = pz[b] - pz[a] - const dSq = dx * dx + dy * dy + dz * dz + const rA = radius[a]; + const rB = radius[b]; + const dx = atob[0] = px[b] - px[a]; + const dy = atob[1] = py[b] - py[a]; + const dz = atob[2] = pz[b] - pz[a]; + const dSq = dx * dx + dy * dy + dz * dz; // This check now redundant as already done in AVHash.withinRadii // if (dSq > ((rA + rB) * (rA + rB))) { return } - const d = Math.sqrt(dSq) + const d = Math.sqrt(dSq); // Find angle between a->b vector and the circle // of their intersection by cosine rule - const cosA = (rA * rA + d * d - rB * rB) / (2.0 * rA * d) + const cosA = (rA * rA + d * d - rB * rB) / (2.0 * rA * d); // distance along a->b at intersection - const dmp = rA * cosA + const dmp = rA * cosA; - Vec3.normalize(atob, atob) + Vec3.normalize(atob, atob); // Create normal to line - normalToLine(n1, atob) - Vec3.normalize(n1, n1) + normalToLine(n1, atob); + Vec3.normalize(n1, n1); // Cross together for second normal vector - Vec3.cross(n2, atob, n1) - Vec3.normalize(n2, n2) + Vec3.cross(n2, atob, n1); + Vec3.normalize(n2, n2); // r is radius of circle of intersection - const rInt = Math.sqrt(rA * rA - dmp * dmp) + const rInt = Math.sqrt(rA * rA - dmp * dmp); - Vec3.scale(n1, n1, rInt) - Vec3.scale(n2, n2, rInt) - Vec3.scale(atob, atob, dmp) + Vec3.scale(n1, n1, rInt); + Vec3.scale(n2, n2, rInt); + Vec3.scale(atob, atob, dmp); - mid[0] = atob[0] + px[a] - mid[1] = atob[1] + py[a] - mid[2] = atob[2] + pz[a] + mid[0] = atob[0] + px[a]; + mid[1] = atob[1] + py[a]; + mid[2] = atob[2] + pz[a]; - lastClip = -1 + lastClip = -1; for (let i = 0; i < probePositions; ++i) { - const cost = cosTable[i] - const sint = sinTable[i] + const cost = cosTable[i]; + const sint = sinTable[i]; - const px = mid[0] + cost * n1[0] + sint * n2[0] - const py = mid[1] + cost * n1[1] + sint * n2[1] - const pz = mid[2] + cost * n1[2] + sint * n2[2] + const px = mid[0] + cost * n1[0] + sint * n2[0]; + const py = mid[1] + cost * n1[1] + sint * n2[1]; + const pz = mid[2] + cost * n1[2] + sint * n2[2]; if (obscured(px, py, pz, a, b) === -1) { - const iax = Math.floor(scaleFactor * (px - minX)) - const iay = Math.floor(scaleFactor * (py - minY)) - const iaz = Math.floor(scaleFactor * (pz - minZ)) + const iax = Math.floor(scaleFactor * (px - minX)); + const iay = Math.floor(scaleFactor * (py - minY)); + const iaz = Math.floor(scaleFactor * (pz - minZ)); - const begX = Math.max(0, iax - ngTorus) - const begY = Math.max(0, iay - ngTorus) - const begZ = Math.max(0, iaz - ngTorus) + const begX = Math.max(0, iax - ngTorus); + const begY = Math.max(0, iay - ngTorus); + const begZ = Math.max(0, iaz - ngTorus); - const endX = Math.min(dimX, iax + ngTorus + 2) - const endY = Math.min(dimY, iay + ngTorus + 2) - const endZ = Math.min(dimZ, iaz + ngTorus + 2) + const endX = Math.min(dimX, iax + ngTorus + 2); + const endY = Math.min(dimY, iay + ngTorus + 2); + const endZ = Math.min(dimZ, iaz + ngTorus + 2); for (let xi = begX; xi < endX; ++xi) { - const dx = px - gridx[xi] - const xIdx = xi * iuv + const dx = px - gridx[xi]; + const xIdx = xi * iuv; for (let yi = begY; yi < endY; ++yi) { - const dy = py - gridy[yi] - const dxySq = dx * dx + dy * dy - const xyIdx = yi * iu + xIdx + const dy = py - gridy[yi]; + const dxySq = dx * dx + dy * dy; + const xyIdx = yi * iu + xIdx; for (let zi = begZ; zi < endZ; ++zi) { - const dz = pz - gridz[zi] - const dSq = dxySq + dz * dz + const dz = pz - gridz[zi]; + const dSq = dxySq + dz * dz; - const idx = zi + xyIdx - const current = data[idx] + const idx = zi + xyIdx; + const current = data[idx]; if (current > 0.0 && dSq < (current * current)) { - data[idx] = Math.sqrt(dSq) + data[idx] = Math.sqrt(dSq); // Is this grid point closer to a or b? // Take dot product of atob and gridpoint->p (dx, dy, dz) - const dp = dx * atob[0] + dy * atob[1] + dz * atob[2] - idData[idx] = id[OrderedSet.indexOf(indices, dp < 0.0 ? b : a)] + const dp = dx * atob[0] + dy * atob[1] + dz * atob[2]; + idData[idx] = id[OrderedSet.indexOf(indices, dp < 0.0 ? b : a)]; } } } @@ -294,81 +294,81 @@ export async function calcMolecularSurface(ctx: RuntimeContext, position: Requir function projectToriiRange (begI: number, endI: number) { for (let i = begI; i < endI; ++i) { - const k = OrderedSet.getAt(indices, i) - lookup3d.find(px[k], py[k], pz[k], radius[k]) + const k = OrderedSet.getAt(indices, i); + lookup3d.find(px[k], py[k], pz[k], radius[k]); for (let j = 0, jl = neighbours.count; j < jl; ++j) { - const l = OrderedSet.getAt(indices, neighbours.indices[j]) - if (k < l) projectTorus(k, l) + const l = OrderedSet.getAt(indices, neighbours.indices[j]); + if (k < l) projectTorus(k, l); } } } async function projectTorii() { for (let i = 0; i < n; i += updateChunk) { - projectToriiRange(i, Math.min(i + updateChunk, n)) + projectToriiRange(i, Math.min(i + updateChunk, n)); if (ctx.shouldUpdate) { - await ctx.update({ message: 'projecting torii', current: i, max: n }) + await ctx.update({ message: 'projecting torii', current: i, max: n }); } } } // console.time('MolecularSurface') // console.time('MolecularSurface createState') - const { resolution, probeRadius, probePositions } = props - const scaleFactor = 1 / resolution - const ngTorus = Math.max(5, 2 + Math.floor(probeRadius * scaleFactor)) + const { resolution, probeRadius, probePositions } = props; + const scaleFactor = 1 / resolution; + const ngTorus = Math.max(5, 2 + Math.floor(probeRadius * scaleFactor)); - const cellSize = Vec3.create(maxRadius, maxRadius, maxRadius) - Vec3.scale(cellSize, cellSize, 2) - const lookup3d = GridLookup3D(position, boundary, cellSize) - const neighbours = lookup3d.result - if (box === null) box = lookup3d.boundary.box + const cellSize = Vec3.create(maxRadius, maxRadius, maxRadius); + Vec3.scale(cellSize, cellSize, 2); + const lookup3d = GridLookup3D(position, boundary, cellSize); + const neighbours = lookup3d.result; + if (box === null) box = lookup3d.boundary.box; - const { indices, x: px, y: py, z: pz, id, radius } = position - const n = OrderedSet.size(indices) + const { indices, x: px, y: py, z: pz, id, radius } = position; + const n = OrderedSet.size(indices); - const pad = maxRadius + resolution + const pad = maxRadius + resolution; const expandedBox = Box3D.expand(Box3D(), box, Vec3.create(pad, pad, pad)); - const [ minX, minY, minZ ] = expandedBox.min - const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor) - const dim = Box3D.size(Vec3(), scaledBox) - Vec3.ceil(dim, dim) + const [ minX, minY, minZ ] = expandedBox.min; + const scaledBox = Box3D.scale(Box3D(), expandedBox, scaleFactor); + const dim = Box3D.size(Vec3(), scaledBox); + Vec3.ceil(dim, dim); - const [ dimX, dimY, dimZ ] = dim - const iu = dimZ, iv = dimY, iuv = iu * iv + const [ dimX, dimY, dimZ ] = dim; + const iu = dimZ, iv = dimY, iuv = iu * iv; - const { cosTable, sinTable } = getAngleTables(probePositions) + const { cosTable, sinTable } = getAngleTables(probePositions); - const space = Tensor.Space(dim, [0, 1, 2], Float32Array) - const data = space.create() - const idData = space.create() + const space = Tensor.Space(dim, [0, 1, 2], Float32Array); + const data = space.create(); + const idData = space.create(); - data.fill(-1001.0) - idData.fill(-1) + data.fill(-1001.0); + idData.fill(-1); - const gridx = fillGridDim(dimX, minX, resolution) - const gridy = fillGridDim(dimY, minY, resolution) - const gridz = fillGridDim(dimZ, minZ, resolution) + const gridx = fillGridDim(dimX, minX, resolution); + const gridy = fillGridDim(dimY, minY, resolution); + const gridz = fillGridDim(dimZ, minZ, resolution); - const updateChunk = Math.ceil(100000 / ((Math.pow(Math.pow(maxRadius, 3), 3) * scaleFactor))) + const updateChunk = Math.ceil(100000 / ((Math.pow(Math.pow(maxRadius, 3), 3) * scaleFactor))); // console.timeEnd('MolecularSurface createState') // console.time('MolecularSurface projectPoints') - await projectPoints() + await projectPoints(); // console.timeEnd('MolecularSurface projectPoints') // console.time('MolecularSurface projectTorii') - await projectTorii() + await projectTorii(); // console.timeEnd('MolecularSurface projectTorii') // console.timeEnd('MolecularSurface') - const field = Tensor.create(space, data) - const idField = Tensor.create(space, idData) + const field = Tensor.create(space, data); + const idField = Tensor.create(space, idData); - const transform = Mat4.identity() - Mat4.fromScaling(transform, Vec3.create(resolution, resolution, resolution)) - Mat4.setTranslation(transform, expandedBox.min) + const transform = Mat4.identity(); + Mat4.fromScaling(transform, Vec3.create(resolution, resolution, resolution)); + Mat4.setTranslation(transform, expandedBox.min); // console.log({ field, idField, transform, updateChunk }) - return { field, idField, transform } + return { field, idField, transform }; } \ No newline at end of file diff --git a/src/mol-math/geometry/primitives/axes3d.ts b/src/mol-math/geometry/primitives/axes3d.ts index 8528631a2f3548beab12f718fce55d0a9d4d297c..bb70f70ef48dcb5af3a4883bf6b62e9762790c04 100644 --- a/src/mol-math/geometry/primitives/axes3d.ts +++ b/src/mol-math/geometry/primitives/axes3d.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3, Mat4, Mat3 } from '../../linear-algebra' +import { Vec3, Mat4, Mat3 } from '../../linear-algebra'; interface Axes3D { origin: Vec3, dirA: Vec3, dirB: Vec3, dirC: Vec3 } @@ -13,8 +13,8 @@ function Axes3D() { } namespace Axes3D { - export function create(origin: Vec3, dirA: Vec3, dirB: Vec3, dirC: Vec3): Axes3D { return { origin, dirA, dirB, dirC } } - export function empty(): Axes3D { return { origin: Vec3(), dirA: Vec3(), dirB: Vec3(), dirC: Vec3() } } + export function create(origin: Vec3, dirA: Vec3, dirB: Vec3, dirC: Vec3): Axes3D { return { origin, dirA, dirB, dirC }; } + export function empty(): Axes3D { return { origin: Vec3(), dirA: Vec3(), dirB: Vec3(), dirC: Vec3() }; } export function copy(out: Axes3D, a: Axes3D): Axes3D { Vec3.copy(out.origin, a.origin); @@ -33,31 +33,31 @@ namespace Axes3D { return Vec3.set(size, Vec3.magnitude(axes.dirA) * 2, Vec3.magnitude(axes.dirB) * 2, Vec3.magnitude(axes.dirC) * 2); } - const tmpSizeV = Vec3() + const tmpSizeV = Vec3(); /** Get volume of the oriented box wrapping the axes */ export function volume(axes: Axes3D): number { - size(tmpSizeV, axes) - return tmpSizeV[0] * tmpSizeV[1] * tmpSizeV[2] + size(tmpSizeV, axes); + return tmpSizeV[0] * tmpSizeV[1] * tmpSizeV[2]; } export function normalize(out: Axes3D, a: Axes3D) { - Vec3.copy(out.origin, a.origin) - Vec3.normalize(out.dirA, a.dirA) - Vec3.normalize(out.dirB, a.dirB) - Vec3.normalize(out.dirC, a.dirC) + Vec3.copy(out.origin, a.origin); + Vec3.normalize(out.dirA, a.dirA); + Vec3.normalize(out.dirB, a.dirB); + Vec3.normalize(out.dirC, a.dirC); return out; } - const tmpTransformMat3 = Mat3.zero() + const tmpTransformMat3 = Mat3.zero(); /** Transform axes with a Mat4 */ export function transform(out: Axes3D, a: Axes3D, m: Mat4): Axes3D { - Vec3.transformMat4(out.origin, a.origin, m) - const n = Mat3.directionTransform(tmpTransformMat3, m) - Vec3.transformMat3(out.dirA, a.dirA, n) - Vec3.transformMat3(out.dirB, a.dirB, n) - Vec3.transformMat3(out.dirC, a.dirC, n) - return out + Vec3.transformMat4(out.origin, a.origin, m); + const n = Mat3.directionTransform(tmpTransformMat3, m); + Vec3.transformMat3(out.dirA, a.dirA, n); + Vec3.transformMat3(out.dirB, a.dirB, n); + Vec3.transformMat3(out.dirC, a.dirC, n); + return out; } } -export { Axes3D } \ No newline at end of file +export { Axes3D }; \ No newline at end of file diff --git a/src/mol-math/geometry/primitives/box3d.ts b/src/mol-math/geometry/primitives/box3d.ts index 7a7e16165c44310b2a4cf51b5dedb160ed5dc1c8..4e7cd66cb4d446b751e8033352dfaacd0966373b 100644 --- a/src/mol-math/geometry/primitives/box3d.ts +++ b/src/mol-math/geometry/primitives/box3d.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3, Mat4 } from '../../linear-algebra' -import { PositionData } from '../common' +import { Vec3, Mat4 } from '../../linear-algebra'; +import { PositionData } from '../common'; import { OrderedSet } from '../../../mol-data/int'; import { Sphere3D } from './sphere3d'; @@ -31,10 +31,10 @@ namespace Box3D { } export function fromSphere3D(out: Box3D, sphere: Sphere3D): Box3D { - const r = Vec3.create(sphere.radius, sphere.radius, sphere.radius) - Vec3.sub(out.min, sphere.center, r) - Vec3.add(out.max, sphere.center, r) - return out + const r = Vec3.create(sphere.radius, sphere.radius, sphere.radius); + Vec3.sub(out.min, sphere.center, r); + Vec3.add(out.max, sphere.center, r); + return out; } export function computeBounding(data: PositionData): Box3D { @@ -51,7 +51,7 @@ namespace Box3D { max[1] = Math.max(y[i], max[1]); max[2] = Math.max(z[i], max[2]); } - return { min, max } + return { min, max }; } /** Get size/extent of the box */ @@ -59,55 +59,55 @@ namespace Box3D { return Vec3.sub(size, box.max, box.min); } - const tmpSizeV = Vec3() + const tmpSizeV = Vec3(); /** Get volume of the box */ export function volume(box: Box3D): number { - size(tmpSizeV, box) - return tmpSizeV[0] * tmpSizeV[1] * tmpSizeV[2] + size(tmpSizeV, box); + return tmpSizeV[0] * tmpSizeV[1] * tmpSizeV[2]; } export function setEmpty(box: Box3D): Box3D { - Vec3.set(box.min, Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE) - Vec3.set(box.max, -Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE) - return box + Vec3.set(box.min, Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE); + Vec3.set(box.max, -Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); + return box; } /** Add point to box */ export function add(box: Box3D, point: Vec3): Box3D { - Vec3.min(box.min, box.min, point) - Vec3.max(box.max, box.max, point) - return box + Vec3.min(box.min, box.min, point); + Vec3.max(box.max, box.max, point); + return box; } /** Expand box by delta */ export function expand(out: Box3D, box: Box3D, delta: Vec3): Box3D { - Vec3.sub(out.min, box.min, delta) - Vec3.add(out.max, box.max, delta) - return out + Vec3.sub(out.min, box.min, delta); + Vec3.add(out.max, box.max, delta); + return out; } export function scale(out: Box3D, box: Box3D, scale: number) { - Vec3.scale(out.min, box.min, scale) - Vec3.scale(out.max, box.max, scale) + Vec3.scale(out.min, box.min, scale); + Vec3.scale(out.max, box.max, scale); return out; } - const tmpTransformV = Vec3() + const tmpTransformV = Vec3(); /** Transform box with a Mat4 */ export function transform(out: Box3D, box: Box3D, m: Mat4): Box3D { - const [ minX, minY, minZ ] = box.min - const [ maxX, maxY, maxZ ] = box.max - setEmpty(out) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, minY, minZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, minY, maxZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, maxY, minZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, maxY, maxZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, minY, minZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, minY, maxZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, maxY, minZ), m)) - add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, maxY, maxZ), m)) - return out + const [ minX, minY, minZ ] = box.min; + const [ maxX, maxY, maxZ ] = box.max; + setEmpty(out); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, minY, minZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, minY, maxZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, maxY, minZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, maxY, maxZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, minY, minZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, minY, maxZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, maxY, minZ), m)); + add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, maxY, maxZ), m)); + return out; } } -export { Box3D } \ No newline at end of file +export { Box3D }; \ No newline at end of file diff --git a/src/mol-math/geometry/primitives/sphere3d.ts b/src/mol-math/geometry/primitives/sphere3d.ts index d0d87737d959e748058c59bb50974adf2c7670ff..516fb0ef5253f941040b2a2270c376f02bcc43ab 100644 --- a/src/mol-math/geometry/primitives/sphere3d.ts +++ b/src/mol-math/geometry/primitives/sphere3d.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3, Mat4, EPSILON } from '../../linear-algebra' -import { PositionData } from '../common' +import { Vec3, Mat4, EPSILON } from '../../linear-algebra'; +import { PositionData } from '../common'; import { OrderedSet } from '../../../mol-data/int'; import { NumberArray, PickRequired } from '../../../mol-util/type-helpers'; import { Box3D } from './box3d'; @@ -24,39 +24,39 @@ function Sphere3D() { namespace Sphere3D { export function hasExtrema(sphere: Sphere3D): sphere is PickRequired<Sphere3D, 'extrema'> { - return sphere.extrema !== undefined + return sphere.extrema !== undefined; } export function create(center: Vec3, radius: number): Sphere3D { return { center, radius }; } export function zero(): Sphere3D { return { center: Vec3(), radius: 0 }; } export function clone(a: Sphere3D): Sphere3D { - const out = create(Vec3.clone(a.center), a.radius) - if (hasExtrema(a)) out.extrema = a.extrema + const out = create(Vec3.clone(a.center), a.radius); + if (hasExtrema(a)) out.extrema = a.extrema; return out; } export function set(out: Sphere3D, center: Vec3, radius: number) { - Vec3.copy(out.center, center) - out.radius = radius - return out + Vec3.copy(out.center, center); + out.radius = radius; + return out; } export function copy(out: Sphere3D, a: Sphere3D) { - Vec3.copy(out.center, a.center) - out.radius = a.radius - if (hasExtrema(a)) setExtrema(out, a.extrema) + Vec3.copy(out.center, a.center); + out.radius = a.radius; + if (hasExtrema(a)) setExtrema(out, a.extrema); return out; } export function setExtrema(out: Sphere3D, extrema: Vec3[]): Sphere3D { if (out.extrema !== undefined) { - out.extrema.length = 0 - out.extrema.push(...extrema) + out.extrema.length = 0; + out.extrema.push(...extrema); } else { - out.extrema = [...extrema] + out.extrema = [...extrema]; } - return out + return out; } export function computeBounding(data: PositionData): Sphere3D { @@ -90,73 +90,73 @@ namespace Sphere3D { /** Transform sphere with a Mat4 */ export function transform(out: Sphere3D, sphere: Sphere3D, m: Mat4): Sphere3D { - Vec3.transformMat4(out.center, sphere.center, m) - out.radius = sphere.radius * Mat4.getMaxScaleOnAxis(m) - return out + Vec3.transformMat4(out.center, sphere.center, m); + out.radius = sphere.radius * Mat4.getMaxScaleOnAxis(m); + return out; } export function toArray(s: Sphere3D, out: NumberArray, offset: number) { - Vec3.toArray(s.center, out, offset) - out[offset + 3] = s.radius + Vec3.toArray(s.center, out, offset); + out[offset + 3] = s.radius; } export function fromArray(out: Sphere3D, array: NumberArray, offset: number) { - Vec3.fromArray(out.center, array, offset) - out.radius = array[offset + 3] - return out + Vec3.fromArray(out.center, array, offset); + out.radius = array[offset + 3]; + return out; } export function fromBox3D(out: Sphere3D, box: Box3D) { - Vec3.scale(out.center, Vec3.add(out.center, box.max, box.min), 0.5) - out.radius = Vec3.distance(out.center, box.max) - return out + Vec3.scale(out.center, Vec3.add(out.center, box.max, box.min), 0.5); + out.radius = Vec3.distance(out.center, box.max); + return out; } export function fromAxes3D(out: Sphere3D, axes: Axes3D) { - Vec3.copy(out.center, axes.origin) - out.radius = Math.max(Vec3.magnitude(axes.dirA), Vec3.magnitude(axes.dirB), Vec3.magnitude(axes.dirC)) - return out + Vec3.copy(out.center, axes.origin); + out.radius = Math.max(Vec3.magnitude(axes.dirA), Vec3.magnitude(axes.dirB), Vec3.magnitude(axes.dirC)); + return out; } - const tmpAddVec3 = Vec3() + const tmpAddVec3 = Vec3(); export function addVec3(out: Sphere3D, s: Sphere3D, v: Vec3) { - const d = Vec3.distance(s.center, v) - if (d < s.radius) return Sphere3D.copy(out, s) - Vec3.sub(tmpAddVec3, s.center, v) - Vec3.sub(tmpAddVec3, s.center, tmpAddVec3) - Vec3.setMagnitude(tmpAddVec3, tmpAddVec3, s.radius) - Vec3.scale(out.center, Vec3.add(tmpAddVec3, tmpAddVec3, v), 0.5) - out.radius = Vec3.distance(out.center, v) - return out + const d = Vec3.distance(s.center, v); + if (d < s.radius) return Sphere3D.copy(out, s); + Vec3.sub(tmpAddVec3, s.center, v); + Vec3.sub(tmpAddVec3, s.center, tmpAddVec3); + Vec3.setMagnitude(tmpAddVec3, tmpAddVec3, s.radius); + Vec3.scale(out.center, Vec3.add(tmpAddVec3, tmpAddVec3, v), 0.5); + out.radius = Vec3.distance(out.center, v); + return out; } /** Expand sphere radius by another sphere */ export function expandBySphere(out: Sphere3D, sphere: Sphere3D, by: Sphere3D) { - Vec3.copy(out.center, sphere.center) - out.radius = Math.max(sphere.radius, Vec3.distance(sphere.center, by.center) + by.radius) + Vec3.copy(out.center, sphere.center); + out.radius = Math.max(sphere.radius, Vec3.distance(sphere.center, by.center) + by.radius); if (hasExtrema(sphere) && hasExtrema(by)) { setExtrema(out, [ ...sphere.extrema.map(e => Vec3.clone(e)), ...by.extrema.map(e => Vec3.clone(e)) - ]) + ]); } - return out + return out; } - const tmpDir = Vec3() + const tmpDir = Vec3(); /** Expand sphere radius by delta */ export function expand(out: Sphere3D, sphere: Sphere3D, delta: number): Sphere3D { - Vec3.copy(out.center, sphere.center) - out.radius = sphere.radius + delta + Vec3.copy(out.center, sphere.center); + out.radius = sphere.radius + delta; if (hasExtrema(sphere)) { setExtrema(out, sphere.extrema.map(e => { - Vec3.sub(tmpDir, e, sphere.center) - const dist = Vec3.distance(sphere.center, e) - Vec3.normalize(tmpDir, tmpDir) - return Vec3.scaleAndAdd(Vec3(), sphere.center, tmpDir, dist + delta) - })) + Vec3.sub(tmpDir, e, sphere.center); + const dist = Vec3.distance(sphere.center, e); + Vec3.normalize(tmpDir, tmpDir); + return Vec3.scaleAndAdd(Vec3(), sphere.center, tmpDir, dist + delta); + })); } - return out + return out; } /** @@ -182,23 +182,23 @@ namespace Sphere3D { export function includes(a: Sphere3D, b: Sphere3D) { if (hasExtrema(b)) { for (const e of b.extrema) { - if (Vec3.distance(a.center, e) > a.radius) return false + if (Vec3.distance(a.center, e) > a.radius) return false; } - return true + return true; } else { - return Vec3.distance(a.center, b.center) + b.radius <= a.radius + return Vec3.distance(a.center, b.center) + b.radius <= a.radius; } } /** Check if `a` and `b` are overlapping */ export function overlaps(a: Sphere3D, b: Sphere3D) { - return Vec3.distance(a.center, b.center) <= a.radius + b.radius + return Vec3.distance(a.center, b.center) <= a.radius + b.radius; } /** Get the signed distance of `a` and `b` */ export function distance(a: Sphere3D, b: Sphere3D) { - return Vec3.distance(a.center, b.center) - a.radius + b.radius + return Vec3.distance(a.center, b.center) - a.radius + b.radius; } } -export { Sphere3D } \ No newline at end of file +export { Sphere3D }; \ No newline at end of file diff --git a/src/mol-math/geometry/spacegroup/cell.ts b/src/mol-math/geometry/spacegroup/cell.ts index 4f7deda347a80168157c52895aeff813b77de89c..5b78661bbbf7c4eff3e2709d22e93ebb90c64338 100644 --- a/src/mol-math/geometry/spacegroup/cell.ts +++ b/src/mol-math/geometry/spacegroup/cell.ts @@ -4,9 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3 } from '../../linear-algebra' +import { Vec3 } from '../../linear-algebra'; -export { Cell } +export { Cell }; interface Cell { readonly size: Vec3 @@ -14,10 +14,10 @@ interface Cell { } function Cell() { - return Cell.empty() + return Cell.empty(); } namespace Cell { - export function create(size: Vec3, anglesInRadians: Vec3): Cell { return { size, anglesInRadians } } - export function empty(): Cell { return { size: Vec3(), anglesInRadians: Vec3() } } + export function create(size: Vec3, anglesInRadians: Vec3): Cell { return { size, anglesInRadians }; } + export function empty(): Cell { return { size: Vec3(), anglesInRadians: Vec3() }; } } \ No newline at end of file diff --git a/src/mol-math/geometry/spacegroup/construction.ts b/src/mol-math/geometry/spacegroup/construction.ts index 6ac668ceefecadc84ac66f344210d3ab448c03ba..e895c0af977ed81275c60ca9bab9d7e6bbe6ec79 100644 --- a/src/mol-math/geometry/spacegroup/construction.ts +++ b/src/mol-math/geometry/spacegroup/construction.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Vec3, Mat4 } from '../../linear-algebra' -import { SpacegroupName, TransformData, GroupData, getSpacegroupIndex, OperatorData, SpacegroupNumber } from './tables' +import { Vec3, Mat4 } from '../../linear-algebra'; +import { SpacegroupName, TransformData, GroupData, getSpacegroupIndex, OperatorData, SpacegroupNumber } from './tables'; import { SymmetryOperator } from '../../geometry'; interface SpacegroupCell { @@ -44,11 +44,11 @@ namespace SpacegroupCell { export function create(nameOrNumber: number | string | SpacegroupName, size: Vec3, anglesInRadians: Vec3): SpacegroupCell { const index = getSpacegroupIndex(nameOrNumber); if (index < 0) { - console.warn(`Unknown spacegroup '${nameOrNumber}', returning a 'P 1' with cellsize [1, 1, 1]`) + console.warn(`Unknown spacegroup '${nameOrNumber}', returning a 'P 1' with cellsize [1, 1, 1]`); return Zero; } - const volume = size[0] * size[1] * size[2] + const volume = size[0] * size[1] * size[2]; const alpha = anglesInRadians[0]; const beta = anglesInRadians[1]; @@ -82,8 +82,8 @@ namespace Spacegroup { export function create(cell: SpacegroupCell): Spacegroup { const operators = GroupData[cell.index].map(i => getOperatorMatrix(OperatorData[i])); - const name = SpacegroupName[cell.index] - const num = SpacegroupNumber[cell.index] + const name = SpacegroupName[cell.index]; + const num = SpacegroupNumber[cell.index]; return { name, num, cell, operators }; } @@ -109,26 +109,26 @@ namespace Spacegroup { return SymmetryOperator.create(`${spgrOp + 1}_${5 + i}${5 + j}${5 + k}`, operator, { hkl: Vec3.create(i, j, k), spgrOp }); } - const _translationRef = Vec3() - const _translationRefSymop = Vec3() - const _translationSymop = Vec3() + const _translationRef = Vec3(); + const _translationRefSymop = Vec3(); + const _translationSymop = Vec3(); export function setOperatorMatrixRef(spacegroup: Spacegroup, index: number, i: number, j: number, k: number, ref: Vec3, target: Mat4) { Vec3.set(_ijkVec, i, j, k); - Vec3.floor(_translationRef, ref) + Vec3.floor(_translationRef, ref); - Mat4.copy(target, spacegroup.operators[index]) + Mat4.copy(target, spacegroup.operators[index]); - Vec3.floor(_translationRefSymop, Vec3.transformMat4(_translationRefSymop, ref, target)) + Vec3.floor(_translationRefSymop, Vec3.transformMat4(_translationRefSymop, ref, target)); - Mat4.getTranslation(_translationSymop, target) - Vec3.sub(_translationSymop, _translationSymop, _translationRefSymop) - Vec3.add(_translationSymop, _translationSymop, _translationRef) - Vec3.add(_translationSymop, _translationSymop, _ijkVec) + Mat4.getTranslation(_translationSymop, target); + Vec3.sub(_translationSymop, _translationSymop, _translationRefSymop); + Vec3.add(_translationSymop, _translationSymop, _translationRef); + Vec3.add(_translationSymop, _translationSymop, _ijkVec); - Mat4.setTranslation(target, _translationSymop) - Mat4.mul(target, spacegroup.cell.fromFractional, target) - Mat4.mul(target, target, spacegroup.cell.toFractional) - return target + Mat4.setTranslation(target, _translationSymop); + Mat4.mul(target, spacegroup.cell.fromFractional, target); + Mat4.mul(target, target, spacegroup.cell.toFractional); + return target; } /** @@ -152,48 +152,48 @@ namespace Spacegroup { formatElement(getRotation(op[0], op[4], op[8]), getShift(op[12])), formatElement(getRotation(op[1], op[5], op[9]), getShift(op[13])), formatElement(getRotation(op[2], op[6], op[10]), getShift(op[14])) - ].join(',') + ].join(','); } function getRotation(x: number, y: number, z: number) { - let r: string[] = [] - if (x > 0) r.push('+X') - else if (x < 0) r.push('-X') - if (y > 0) r.push('+Y') - else if (y < 0) r.push('-Y') - if (z > 0) r.push('+Z') - else if (z < 0) r.push('-Z') + let r: string[] = []; + if (x > 0) r.push('+X'); + else if (x < 0) r.push('-X'); + if (y > 0) r.push('+Y'); + else if (y < 0) r.push('-Y'); + if (z > 0) r.push('+Z'); + else if (z < 0) r.push('-Z'); if (r.length === 1) { - return r[0].charAt(0) === '+' ? r[0].substr(1) : r[0] + return r[0].charAt(0) === '+' ? r[0].substr(1) : r[0]; } if (r.length === 2) { - const s0 = r[0].charAt(0) - const s1 = r[1].charAt(0) - if (s0 === '+') return `${r[0].substr(1)}${r[1]}` - if (s1 === '+') return `${r[1].substr(1)}${r[0]}` + const s0 = r[0].charAt(0); + const s1 = r[1].charAt(0); + if (s0 === '+') return `${r[0].substr(1)}${r[1]}`; + if (s1 === '+') return `${r[1].substr(1)}${r[0]}`; } - throw new Error(`unknown rotation '${r}', ${x} ${y} ${z}`) + throw new Error(`unknown rotation '${r}', ${x} ${y} ${z}`); } function getShift(s: number) { switch (s) { - case 1 / 2: return '1/2' - case 1 / 4: return '1/4' - case 3 / 4: return '3/4' - case 1 / 3: return '1/3' - case 2 / 3: return '2/3' - case 1 / 6: return '1/6' - case 5 / 6: return '5/6' + case 1 / 2: return '1/2'; + case 1 / 4: return '1/4'; + case 3 / 4: return '3/4'; + case 1 / 3: return '1/3'; + case 2 / 3: return '2/3'; + case 1 / 6: return '1/6'; + case 5 / 6: return '5/6'; } - return '' + return ''; } function formatElement(rotation: string, shift: string) { - if (shift === '') return rotation - if (rotation.length > 2) return `${rotation}+${shift}` - return rotation.charAt(0) === '-' ? `${shift}${rotation}` : `${shift}+${rotation}` + if (shift === '') return rotation; + if (rotation.length > 2) return `${rotation}+${shift}`; + return rotation.charAt(0) === '-' ? `${shift}${rotation}` : `${shift}+${rotation}`; } } -export { Spacegroup, SpacegroupCell } \ No newline at end of file +export { Spacegroup, SpacegroupCell }; \ No newline at end of file diff --git a/src/mol-math/geometry/spacegroup/tables.ts b/src/mol-math/geometry/spacegroup/tables.ts index 4a1e2acd033952ff6f4bf0964684fa99c3463af1..925249a87d31bb1a9000b52d2b6cbff2f1be34f3 100644 --- a/src/mol-math/geometry/spacegroup/tables.ts +++ b/src/mol-math/geometry/spacegroup/tables.ts @@ -1349,116 +1349,116 @@ export const SpacegroupNameToIndexMap = { export function getSpacegroupIndexFromNumber(num: number) { // 38 spacegroup variants as given CCP4s symop.lib switch (num) { - case 1146: return 146 - case 1148: return 149 - case 1155: return 157 - case 1160: return 163 - case 1161: return 165 - case 1166: return 171 - case 1167: return 173 + case 1146: return 146; + case 1148: return 149; + case 1155: return 157; + case 1160: return 163; + case 1161: return 165; + case 1166: return 171; + case 1167: return 173; - case 1003: return 237 // 'P 1 1 2' !(dyad along z) - case 1004: return 238 // 'P 1 1 21' !(unique axis c) - case 1005: return 239 // 'B 1 1 2' 'B 2' - case 2005: return 240 // 'A 1 2 1' - case 3005: return 241 // 'C 1 21 1' ! (Origin on screw at 1/4X) - case 4005: return 242 // 'I 1 2 1' 'I 2' !!! GJK @ 2003-06-02 - case 5005: return 243 // 'I 1 21 1' - case 1006: return 244 // 'P 1 1 m' - case 1007: return 245 // 'P 1 1 b' - case 1008: return 246 // 'B 1 1 m' - case 1009: return 247 // 'B 1 1 b' - case 1010: return 248 // 'P 1 1 2/m' - case 1011: return 249 // 'P 1 1 21/m' - case 1012: return 250 // 'B 1 1 2/m' - case 1013: return 251 // 'P 1 1 2/b' - case 1014: return 252 // 'P 1 1 21/b' - case 2014: return 253 // 'P 1 21/n 1' - case 3014: return 254 // 'P 1 21/a 1' - case 1015: return 255 // 'B 1 1 2/b' - case 1017: return 256 // 'P 21 2 2' !(unique axis a) - case 2017: return 257 // 'P 2 21 2' !(unique axis b) - case 1018: return 258 // 'P 21 21 2 (a)' ! origin on 21 21, shift (1/4,1/4,0) - case 2018: return 259 // 'P 21 2 21' !(unique axis b) - case 3018: return 260 // 'P 2 21 21' !(unique axis a) - case 1020: return 261 // 'C 2 2 21a)' ! P212121 with C centring, shift(1/4,0,0) - case 1021: return 262 // 'C 2 2 2a' ! C21212a origin on 21 21 - case 1022: return 263 // 'F 2 2 2a' ! same as 1018 with face centring shift (1/4,0,0) - case 1023: return 264 // 'I 2 2 2a' ! as 1018 with origin shift (1/4,1/4,1/4) - case 1059: return 265 // 'P 21/m 21/m 2/n a' - case 1094: return 266 // 'P 42 21 2a' ! (as P21212a) origin on 21 21 ie Shift 1/4,1/4,1/4 - case 1197: return 267 // 'I 2 3a' ! Expansion of 1023 which is an expansion of 1018 + case 1003: return 237; // 'P 1 1 2' !(dyad along z) + case 1004: return 238; // 'P 1 1 21' !(unique axis c) + case 1005: return 239; // 'B 1 1 2' 'B 2' + case 2005: return 240; // 'A 1 2 1' + case 3005: return 241; // 'C 1 21 1' ! (Origin on screw at 1/4X) + case 4005: return 242; // 'I 1 2 1' 'I 2' !!! GJK @ 2003-06-02 + case 5005: return 243; // 'I 1 21 1' + case 1006: return 244; // 'P 1 1 m' + case 1007: return 245; // 'P 1 1 b' + case 1008: return 246; // 'B 1 1 m' + case 1009: return 247; // 'B 1 1 b' + case 1010: return 248; // 'P 1 1 2/m' + case 1011: return 249; // 'P 1 1 21/m' + case 1012: return 250; // 'B 1 1 2/m' + case 1013: return 251; // 'P 1 1 2/b' + case 1014: return 252; // 'P 1 1 21/b' + case 2014: return 253; // 'P 1 21/n 1' + case 3014: return 254; // 'P 1 21/a 1' + case 1015: return 255; // 'B 1 1 2/b' + case 1017: return 256; // 'P 21 2 2' !(unique axis a) + case 2017: return 257; // 'P 2 21 2' !(unique axis b) + case 1018: return 258; // 'P 21 21 2 (a)' ! origin on 21 21, shift (1/4,1/4,0) + case 2018: return 259; // 'P 21 2 21' !(unique axis b) + case 3018: return 260; // 'P 2 21 21' !(unique axis a) + case 1020: return 261; // 'C 2 2 21a)' ! P212121 with C centring, shift(1/4,0,0) + case 1021: return 262; // 'C 2 2 2a' ! C21212a origin on 21 21 + case 1022: return 263; // 'F 2 2 2a' ! same as 1018 with face centring shift (1/4,0,0) + case 1023: return 264; // 'I 2 2 2a' ! as 1018 with origin shift (1/4,1/4,1/4) + case 1059: return 265; // 'P 21/m 21/m 2/n a' + case 1094: return 266; // 'P 42 21 2a' ! (as P21212a) origin on 21 21 ie Shift 1/4,1/4,1/4 + case 1197: return 267; // 'I 2 3a' ! Expansion of 1023 which is an expansion of 1018 } - let offset = 0 - if (num > 146) ++offset - if (num > 148) ++offset - if (num > 155) ++offset - if (num > 160) ++offset - if (num > 161) ++offset - if (num > 166) ++offset - if (num > 167) ++offset + let offset = 0; + if (num > 146) ++offset; + if (num > 148) ++offset; + if (num > 155) ++offset; + if (num > 160) ++offset; + if (num > 161) ++offset; + if (num > 166) ++offset; + if (num > 167) ++offset; - return num - 1 + offset + return num - 1 + offset; } export function getSpacegroupNumberFromIndex(idx: number) { - if (idx < 146) return idx + 1 - if (idx === 146) return 1146 + if (idx < 146) return idx + 1; + if (idx === 146) return 1146; - if (idx < 149) return idx + 1 - 1 - if (idx === 149) return 1148 + if (idx < 149) return idx + 1 - 1; + if (idx === 149) return 1148; - if (idx < 157) return idx + 1 - 2 - if (idx === 157) return 1155 + if (idx < 157) return idx + 1 - 2; + if (idx === 157) return 1155; - if (idx < 163) return idx + 1 - 3 - if (idx === 163) return 1160 + if (idx < 163) return idx + 1 - 3; + if (idx === 163) return 1160; - if (idx < 165) return idx + 1 - 4 - if (idx === 165) return 1161 + if (idx < 165) return idx + 1 - 4; + if (idx === 165) return 1161; - if (idx < 171) return idx + 1 - 5 - if (idx === 171) return 1166 + if (idx < 171) return idx + 1 - 5; + if (idx === 171) return 1166; - if (idx < 173) return idx + 1 - 6 - if (idx === 173) return 1167 + if (idx < 173) return idx + 1 - 6; + if (idx === 173) return 1167; - if (idx < 237) return idx + 1 - 7 - if (idx === 237) return 1003 - if (idx === 238) return 1004 - if (idx === 239) return 1005 - if (idx === 240) return 2005 - if (idx === 241) return 3005 - if (idx === 242) return 4005 - if (idx === 243) return 5005 - if (idx === 244) return 1006 - if (idx === 245) return 1007 - if (idx === 246) return 1008 - if (idx === 247) return 1009 - if (idx === 248) return 1010 - if (idx === 249) return 1011 - if (idx === 250) return 1012 - if (idx === 251) return 1013 - if (idx === 252) return 1014 + if (idx < 237) return idx + 1 - 7; + if (idx === 237) return 1003; + if (idx === 238) return 1004; + if (idx === 239) return 1005; + if (idx === 240) return 2005; + if (idx === 241) return 3005; + if (idx === 242) return 4005; + if (idx === 243) return 5005; + if (idx === 244) return 1006; + if (idx === 245) return 1007; + if (idx === 246) return 1008; + if (idx === 247) return 1009; + if (idx === 248) return 1010; + if (idx === 249) return 1011; + if (idx === 250) return 1012; + if (idx === 251) return 1013; + if (idx === 252) return 1014; - if (idx === 253) return 2014 - if (idx === 254) return 3014 - if (idx === 255) return 1015 - if (idx === 256) return 1017 - if (idx === 257) return 2017 - if (idx === 258) return 1018 - if (idx === 259) return 2018 - if (idx === 260) return 3018 - if (idx === 261) return 1020 - if (idx === 262) return 1021 - if (idx === 263) return 1022 - if (idx === 264) return 1023 - if (idx === 265) return 1059 - if (idx === 266) return 1094 - if (idx === 267) return 1197 + if (idx === 253) return 2014; + if (idx === 254) return 3014; + if (idx === 255) return 1015; + if (idx === 256) return 1017; + if (idx === 257) return 2017; + if (idx === 258) return 1018; + if (idx === 259) return 2018; + if (idx === 260) return 3018; + if (idx === 261) return 1020; + if (idx === 262) return 1021; + if (idx === 263) return 1022; + if (idx === 264) return 1023; + if (idx === 265) return 1059; + if (idx === 266) return 1094; + if (idx === 267) return 1197; - throw new Error(`unknown spacegroup index '${idx}'`) + throw new Error(`unknown spacegroup index '${idx}'`); } export type SpacegroupName = keyof typeof SpacegroupNameToIndexMap @@ -1476,7 +1476,7 @@ export const SpacegroupName: { [idx: number]: SpacegroupName } = (function () { export const SpacegroupNumber: { [idx: number]: number } = (function () { const numbers = Object.create(null); for (const n of Object.keys(SpacegroupNameToIndexMap)) { - const idx = (SpacegroupNameToIndexMap as any)[n] + const idx = (SpacegroupNameToIndexMap as any)[n]; numbers[idx] = getSpacegroupNumberFromIndex(idx); } return numbers; diff --git a/src/mol-math/geometry/symmetry-operator.ts b/src/mol-math/geometry/symmetry-operator.ts index 8359c017284b94453ec6ad41882ece7ebded6d79..ec1eb05dfa261f34c097b091674ede0f9a3864db 100644 --- a/src/mol-math/geometry/symmetry-operator.ts +++ b/src/mol-math/geometry/symmetry-operator.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Vec3, Mat4, Mat3, Quat } from '../linear-algebra/3d' +import { Vec3, Mat4, Mat3, Quat } from '../linear-algebra/3d'; import { lerp as scalar_lerp } from '../../mol-math/interpolate'; import { defaults } from '../../mol-util'; @@ -43,7 +43,7 @@ interface SymmetryOperator { } namespace SymmetryOperator { - export const DefaultName = '1_555' + export const DefaultName = '1_555'; export const Default: SymmetryOperator = create(DefaultName, Mat4.identity()); export const RotationTranslationEpsilon = 0.005; @@ -69,7 +69,7 @@ namespace SymmetryOperator { if (typeof info.spgrOp !== 'undefined' && typeof info.hkl !== 'undefined' && info.spgrOp !== -1) { const [i, j, k] = info.hkl; - return `-${info.spgrOp + 1}_${5 + i}${5 + j}${5 + k}` + return `-${info.spgrOp + 1}_${5 + i}${5 + j}${5 + k}`; } if (info.ncsId) { @@ -175,7 +175,7 @@ namespace SymmetryOperator { } } -export { SymmetryOperator } +export { SymmetryOperator }; function _zeroRadius(i: number) { return 0; } @@ -205,7 +205,7 @@ function projectX({ matrix: m }: SymmetryOperator, { x: xs, y: ys, z: zs }: Symm return (i: number) => { const x = xs[i], y = ys[i], z = zs[i], w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0; return (xx * x + yy * y + zz * z + tx) / w; - } + }; } function projectY({ matrix: m }: SymmetryOperator, { x: xs, y: ys, z: zs }: SymmetryOperator.Coordinates) { @@ -219,7 +219,7 @@ function projectY({ matrix: m }: SymmetryOperator, { x: xs, y: ys, z: zs }: Symm return (i: number) => { const x = xs[i], y = ys[i], z = zs[i], w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0; return (xx * x + yy * y + zz * z + ty) / w; - } + }; } function projectZ({ matrix: m }: SymmetryOperator, { x: xs, y: ys, z: zs }: SymmetryOperator.Coordinates) { @@ -233,7 +233,7 @@ function projectZ({ matrix: m }: SymmetryOperator, { x: xs, y: ys, z: zs }: Symm return (i: number) => { const x = xs[i], y = ys[i], z = zs[i], w = (m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0; return (xx * x + yy * y + zz * z + tz) / w; - } + }; } function identityPosition<T extends number>({ x, y, z }: SymmetryOperator.Coordinates): SymmetryOperator.CoordinateMapper<T> { @@ -242,7 +242,7 @@ function identityPosition<T extends number>({ x, y, z }: SymmetryOperator.Coordi s[1] = y[i]; s[2] = z[i]; return s; - } + }; } function generalPosition<T extends number>({ matrix: m }: SymmetryOperator, { x: xs, y: ys, z: zs }: SymmetryOperator.Coordinates) { @@ -254,7 +254,7 @@ function generalPosition<T extends number>({ matrix: m }: SymmetryOperator, { x: r[1] = m[1] * x + m[5] * y + m[9] * z + m[13]; r[2] = m[2] * x + m[6] * y + m[10] * z + m[14]; return r; - } + }; } return (i: T, r: Vec3): Vec3 => { r[0] = xs[i]; @@ -262,5 +262,5 @@ function generalPosition<T extends number>({ matrix: m }: SymmetryOperator, { x: r[2] = zs[i]; Vec3.transformMat4(r, r, m); return r; - } + }; } \ No newline at end of file diff --git a/src/mol-math/graph.ts b/src/mol-math/graph.ts index f1e24c2f39e5cbaef4ae6e7c6f8e5d1ed5dc9f05..7b5f333325bed17654767b0a57b3fea27de60a24 100644 --- a/src/mol-math/graph.ts +++ b/src/mol-math/graph.ts @@ -4,4 +4,4 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './graph/int-adjacency-graph' \ No newline at end of file +export * from './graph/int-adjacency-graph'; \ No newline at end of file diff --git a/src/mol-math/graph/_spec/int-graph.spec.ts b/src/mol-math/graph/_spec/int-graph.spec.ts index 5d0315e658ef3e3662a08149f8d10b18cfe770ba..4f23f133569c860af106231f9092a4d1e2b5d00d 100644 --- a/src/mol-math/graph/_spec/int-graph.spec.ts +++ b/src/mol-math/graph/_spec/int-graph.spec.ts @@ -39,5 +39,5 @@ describe('IntGraph', () => { expect(induced.vertexCount).toBe(2); expect(induced.edgeCount).toBe(1); expect(induced.edgeProps.prop[induced.getEdgeIndex(0, 1)]).toBe(11); - }) + }); }); \ No newline at end of file diff --git a/src/mol-math/graph/inter-unit-graph.ts b/src/mol-math/graph/inter-unit-graph.ts index 751e9fc7ffa7af270769448b2b98c12d2805c9c5..2de0b7708235771f1af5e57643e6adec17697c88 100644 --- a/src/mol-math/graph/inter-unit-graph.ts +++ b/src/mol-math/graph/inter-unit-graph.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { UniqueArray } from '../../mol-data/generic' +import { UniqueArray } from '../../mol-data/generic'; -export { InterUnitGraph } +export { InterUnitGraph }; class InterUnitGraph<Unit extends InterUnitGraph.UnitBase, VertexIndex extends number, EdgeProps extends InterUnitGraph.EdgePropsBase = {}> { /** Number of inter-unit edges */ @@ -25,58 +25,58 @@ class InterUnitGraph<Unit extends InterUnitGraph.UnitBase, VertexIndex extends n /** Index into this.edges */ getEdgeIndex(indexA: VertexIndex, unitA: Unit, indexB: VertexIndex, unitB: Unit): number { - const edgeKey = InterUnitGraph.getEdgeKey<Unit, VertexIndex>(indexA, unitA, indexB, unitB) - const index = this.edgeKeyIndex.get(edgeKey) - return index !== undefined ? index : -1 + const edgeKey = InterUnitGraph.getEdgeKey<Unit, VertexIndex>(indexA, unitA, indexB, unitB); + const index = this.edgeKeyIndex.get(edgeKey); + return index !== undefined ? index : -1; } /** Check if edge exists */ hasEdge(indexA: VertexIndex, unitA: Unit, indexB: VertexIndex, unitB: Unit): boolean { - return this.getEdgeIndex(indexA, unitA, indexB, unitB) !== -1 + return this.getEdgeIndex(indexA, unitA, indexB, unitB) !== -1; } /** Get inter-unit edge given a pair of indices and units */ getEdge(indexA: VertexIndex, unitA: Unit, indexB: VertexIndex, unitB: Unit): InterUnitGraph.Edge<Unit, VertexIndex, EdgeProps> | undefined { - const index = this.getEdgeIndex(indexA, unitA, indexB, unitB) - return index !== -1 ? this.edges[index] : undefined + const index = this.getEdgeIndex(indexA, unitA, indexB, unitB); + return index !== -1 ? this.edges[index] : undefined; } /** Indices into this.edges */ getEdgeIndices(index: VertexIndex, unit: Unit): ReadonlyArray<number> { - return this.vertexKeyIndex.get(InterUnitGraph.getVertexKey(index, unit)) || [] + return this.vertexKeyIndex.get(InterUnitGraph.getVertexKey(index, unit)) || []; } constructor(protected readonly map: Map<number, InterUnitGraph.UnitPairEdges<Unit, VertexIndex, EdgeProps>[]>) { - let count = 0 - const edges: (InterUnitGraph.Edge<Unit, VertexIndex, EdgeProps>)[] = [] - const edgeKeyIndex = new Map<string, number>() - const vertexKeyIndex = new Map<string, number[]>() + let count = 0; + const edges: (InterUnitGraph.Edge<Unit, VertexIndex, EdgeProps>)[] = []; + const edgeKeyIndex = new Map<string, number>(); + const vertexKeyIndex = new Map<string, number[]>(); this.map.forEach(pairEdgesArray => { pairEdgesArray.forEach(pairEdges => { - count += pairEdges.edgeCount + count += pairEdges.edgeCount; pairEdges.connectedIndices.forEach(indexA => { pairEdges.getEdges(indexA).forEach(edgeInfo => { - const { unitA, unitB } = pairEdges - - const edgeKey = InterUnitGraph.getEdgeKey(indexA, unitA, edgeInfo.indexB, unitB) - edgeKeyIndex.set(edgeKey, edges.length) - - const vertexKey = InterUnitGraph.getVertexKey(indexA, unitA) - const e = vertexKeyIndex.get(vertexKey) - if (e === undefined) vertexKeyIndex.set(vertexKey, [edges.length]) - else e.push(edges.length) - - edges.push({ ...edgeInfo, indexA, unitA, unitB }) - }) - }) - }) - }) - - this.edgeCount = count - this.edges = edges - this.edgeKeyIndex = edgeKeyIndex - this.vertexKeyIndex = vertexKeyIndex + const { unitA, unitB } = pairEdges; + + const edgeKey = InterUnitGraph.getEdgeKey(indexA, unitA, edgeInfo.indexB, unitB); + edgeKeyIndex.set(edgeKey, edges.length); + + const vertexKey = InterUnitGraph.getVertexKey(indexA, unitA); + const e = vertexKeyIndex.get(vertexKey); + if (e === undefined) vertexKeyIndex.set(vertexKey, [edges.length]); + else e.push(edges.length); + + edges.push({ ...edgeInfo, indexA, unitA, unitB }); + }); + }); + }); + }); + + this.edgeCount = count; + this.edges = edges; + this.edgeKeyIndex = edgeKeyIndex; + this.vertexKeyIndex = vertexKeyIndex; } } @@ -119,11 +119,11 @@ namespace InterUnitGraph { } export function getEdgeKey<Unit extends UnitBase, VertexIndex extends number>(indexA: VertexIndex, unitA: Unit, indexB: VertexIndex, unitB: Unit) { - return `${indexA}|${unitA.id}|${indexB}|${unitB.id}` + return `${indexA}|${unitA.id}|${indexB}|${unitB.id}`; } export function getVertexKey<Unit extends UnitBase, VertexIndex extends number>(index: VertexIndex, unit: Unit) { - return `${index}|${unit.id}` + return `${index}|${unit.id}`; } // @@ -146,27 +146,27 @@ namespace InterUnitGraph { private map = new Map<number, UnitPairEdges<Unit, VertexIndex, EdgeProps>[]>(); startUnitPair(unitA: Unit, unitB: Unit) { - this.uA = unitA - this.uB = unitB - this.mapAB = new Map() - this.mapBA = new Map() - this.linkedA = UniqueArray.create() - this.linkedB = UniqueArray.create() - this.linkCount = 0 + this.uA = unitA; + this.uB = unitB; + this.mapAB = new Map(); + this.mapBA = new Map(); + this.linkedA = UniqueArray.create(); + this.linkedB = UniqueArray.create(); + this.linkCount = 0; } finishUnitPair() { - if (this.linkCount === 0) return - addMapEntry(this.map, this.uA.id, new UnitPairEdges(this.uA, this.uB, this.linkCount, this.linkedA.array, this.mapAB)) - addMapEntry(this.map, this.uB.id, new UnitPairEdges(this.uB, this.uA, this.linkCount, this.linkedB.array, this.mapBA)) + if (this.linkCount === 0) return; + addMapEntry(this.map, this.uA.id, new UnitPairEdges(this.uA, this.uB, this.linkCount, this.linkedA.array, this.mapAB)); + addMapEntry(this.map, this.uB.id, new UnitPairEdges(this.uB, this.uA, this.linkCount, this.linkedB.array, this.mapBA)); } add(indexA: VertexIndex, indexB: VertexIndex, props: EdgeProps) { - addMapEntry(this.mapAB, indexA, { indexB, props }) - addMapEntry(this.mapBA, indexB, { indexB: indexA, props }) - UniqueArray.add(this.linkedA, indexA, indexA) - UniqueArray.add(this.linkedB, indexB, indexB) - this.linkCount += 1 + addMapEntry(this.mapAB, indexA, { indexB, props }); + addMapEntry(this.mapBA, indexB, { indexB: indexA, props }); + UniqueArray.add(this.linkedA, indexA, indexA); + UniqueArray.add(this.linkedB, indexB, indexB); + this.linkCount += 1; } getMap(): Map<number, InterUnitGraph.UnitPairEdges<Unit, VertexIndex, EdgeProps>[]> { diff --git a/src/mol-math/interpolate.ts b/src/mol-math/interpolate.ts index 5712434ee8e3f6259a01d83598fa42ae6ddfe9ef..29c2e1ccae6f44ff198ce18d2acd60b6f603f489 100644 --- a/src/mol-math/interpolate.ts +++ b/src/mol-math/interpolate.ts @@ -5,63 +5,63 @@ */ export function normalize (value: number, min: number, max: number) { - return (value - min) / (max - min) + return (value - min) / (max - min); } export function clamp (value: number, min: number, max: number) { - return Math.max(min, Math.min(max, value)) + return Math.max(min, Math.min(max, value)); } export function pclamp (value: number) { - return clamp(value, 0, 100) + return clamp(value, 0, 100); } export function saturate (value: number) { - return clamp(value, 0, 1) + return clamp(value, 0, 1); } export function damp (value: number, dampingFactor: number) { - const dampedValue = value * dampingFactor - return Math.abs(dampedValue) < 0.1 ? 0 : dampedValue + const dampedValue = value * dampingFactor; + return Math.abs(dampedValue) < 0.1 ? 0 : dampedValue; } export function lerp (start: number, stop: number, alpha: number) { - return start + (stop - start) * alpha + return start + (stop - start) * alpha; } /** Catmul-Rom spline */ export function spline (p0: number, p1: number, p2: number, p3: number, t: number, tension: number) { - const v0 = (p2 - p0) * tension - const v1 = (p3 - p1) * tension - const t2 = t * t - const t3 = t * t2 - return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1 + const v0 = (p2 - p0) * tension; + const v1 = (p3 - p1) * tension; + const t2 = t * t; + const t3 = t * t2; + return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1; } export function quadraticBezier(p0: number, p1: number, p2: number, t: number) { - const k = 1 - t - return (k * k * p0) + (2 * k * t * p1) + (t * t * p2) + const k = 1 - t; + return (k * k * p0) + (2 * k * t * p1) + (t * t * p2); } export function smoothstep (min: number, max: number, x: number) { - x = saturate(normalize(x, min, max)) - return x * x * (3 - 2 * x) + x = saturate(normalize(x, min, max)); + return x * x * (3 - 2 * x); } export function smootherstep (min: number, max: number, x: number) { - x = saturate(normalize(x, min, max)) - return x * x * x * (x * (x * 6 - 15) + 10) + x = saturate(normalize(x, min, max)); + return x * x * x * (x * (x * 6 - 15) + 10); } export function smootheststep (min: number, max: number, x: number) { - x = saturate(normalize(x, min, max)) - return -20 * Math.pow(x, 7) + 70 * Math.pow(x, 6) - 84 * Math.pow(x, 5) + 35 * Math.pow(x, 4) + x = saturate(normalize(x, min, max)); + return -20 * Math.pow(x, 7) + 70 * Math.pow(x, 6) - 84 * Math.pow(x, 5) + 35 * Math.pow(x, 4); } export function almostIdentity (value: number, start: number, stop: number) { - if (value > start) return value - const a = 2 * stop - start - const b = 2 * start - 3 * stop - const t = value / start - return (a * t + b) * t * t + stop + if (value > start) return value; + const a = 2 * stop - start; + const b = 2 * start - 3 * stop; + const t = value / start; + return (a * t + b) * t * t + stop; } \ No newline at end of file diff --git a/src/mol-math/linear-algebra.ts b/src/mol-math/linear-algebra.ts index 20ffdc270398f55572af9a3ca3a8f71fc67adc61..de1d1546193d0d38260551cbb1564d6669272abf 100644 --- a/src/mol-math/linear-algebra.ts +++ b/src/mol-math/linear-algebra.ts @@ -4,5 +4,5 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './linear-algebra/3d' -export * from './linear-algebra/tensor' \ No newline at end of file +export * from './linear-algebra/3d'; +export * from './linear-algebra/tensor'; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d.ts b/src/mol-math/linear-algebra/3d.ts index 8a4b938b032048457aba4768e068aa72b03e8826..fc244da737a18f87d49f5a32bcdd7571e131170b 100644 --- a/src/mol-math/linear-algebra/3d.ts +++ b/src/mol-math/linear-algebra/3d.ts @@ -17,15 +17,15 @@ * furnished to do so, subject to the following conditions: */ -import Mat4 from './3d/mat4' -import Mat3 from './3d/mat3' -import Vec2 from './3d/vec2' -import Vec3 from './3d/vec3' -import Vec4 from './3d/vec4' -import Quat from './3d/quat' -import { EPSILON } from './3d/common' +import Mat4 from './3d/mat4'; +import Mat3 from './3d/mat3'; +import Vec2 from './3d/vec2'; +import Vec3 from './3d/vec3'; +import Vec4 from './3d/vec4'; +import Quat from './3d/quat'; +import { EPSILON } from './3d/common'; -export { Mat4, Mat3, Vec2, Vec3, Vec4, Quat, EPSILON } +export { Mat4, Mat3, Vec2, Vec3, Vec4, Quat, EPSILON }; export type Vec<T> = T extends 4 ? Vec4 : diff --git a/src/mol-math/linear-algebra/3d/mat3.ts b/src/mol-math/linear-algebra/3d/mat3.ts index 3917a310f1bb56482b131159475f698dcf7e3ba3..b8dd9ac73a7ae303cc43ac3efaec3b73a85bfbca 100644 --- a/src/mol-math/linear-algebra/3d/mat3.ts +++ b/src/mol-math/linear-algebra/3d/mat3.ts @@ -17,7 +17,7 @@ * furnished to do so, subject to the following conditions: */ -import { Mat4, Vec3, EPSILON } from '../3d' +import { Mat4, Vec3, EPSILON } from '../3d'; import { NumberArray } from '../../../mol-util/type-helpers'; interface Mat3 extends Array<number> { [d: number]: number, '@type': 'mat3', length: 9 } @@ -76,16 +76,16 @@ namespace Mat3 { } export function fromArray(a: Mat3, array: NumberArray, offset: number) { - a[0] = array[offset + 0] - a[1] = array[offset + 1] - a[2] = array[offset + 2] - a[3] = array[offset + 3] - a[4] = array[offset + 4] - a[5] = array[offset + 5] - a[6] = array[offset + 6] - a[7] = array[offset + 7] - a[8] = array[offset + 8] - return a + a[0] = array[offset + 0]; + a[1] = array[offset + 1]; + a[2] = array[offset + 2]; + a[3] = array[offset + 3]; + a[4] = array[offset + 4]; + a[5] = array[offset + 5]; + a[6] = array[offset + 6]; + a[7] = array[offset + 7]; + a[8] = array[offset + 8]; + return a; } /** @@ -106,15 +106,15 @@ namespace Mat3 { export function create(a00: number, a01: number, a02: number, a10: number, a11: number, a12: number, a20: number, a21: number, a22: number): Mat3 { const out = zero(); - out[0] = a00 - out[1] = a01 - out[2] = a02 - out[3] = a10 - out[4] = a11 - out[5] = a12 - out[6] = a20 - out[7] = a21 - out[8] = a22 + out[0] = a00; + out[1] = a01; + out[2] = a02; + out[3] = a10; + out[4] = a11; + out[5] = a12; + out[6] = a20; + out[7] = a21; + out[8] = a22; return out; } @@ -124,8 +124,8 @@ namespace Mat3 { } export function hasNaN(m: Mat3) { - for (let i = 0; i < 9; i++) if (isNaN(m[i])) return true - return false + for (let i = 0; i < 9; i++) if (isNaN(m[i])) return true; + return false; } /** @@ -278,33 +278,33 @@ namespace Mat3 { } export function trace(a: Mat3) { - return a[0] + a[4] + a[8] + return a[0] + a[4] + a[8]; } export function sub(out: Mat3, a: Mat3, b: Mat3) { - out[0] = a[0] - b[0] - out[1] = a[1] - b[1] - out[2] = a[2] - b[2] - out[3] = a[3] - b[3] - out[4] = a[4] - b[4] - out[5] = a[5] - b[5] - out[6] = a[6] - b[6] - out[7] = a[7] - b[7] - out[8] = a[8] - b[8] - return out + out[0] = a[0] - b[0]; + out[1] = a[1] - b[1]; + out[2] = a[2] - b[2]; + out[3] = a[3] - b[3]; + out[4] = a[4] - b[4]; + out[5] = a[5] - b[5]; + out[6] = a[6] - b[6]; + out[7] = a[7] - b[7]; + out[8] = a[8] - b[8]; + return out; } export function add(out: Mat3, a: Mat3, b: Mat3) { - out[0] = a[0] + b[0] - out[1] = a[1] + b[1] - out[2] = a[2] + b[2] - out[3] = a[3] + b[3] - out[4] = a[4] + b[4] - out[5] = a[5] + b[5] - out[6] = a[6] + b[6] - out[7] = a[7] + b[7] - out[8] = a[8] + b[8] - return out + out[0] = a[0] + b[0]; + out[1] = a[1] + b[1]; + out[2] = a[2] + b[2]; + out[3] = a[3] + b[3]; + out[4] = a[4] + b[4]; + out[5] = a[5] + b[5]; + out[6] = a[6] + b[6]; + out[7] = a[7] + b[7]; + out[8] = a[8] + b[8]; + return out; } export function mul(out: Mat3, a: Mat3, b: Mat3) { @@ -331,127 +331,127 @@ namespace Mat3 { } export function subScalar(out: Mat3, a: Mat3, s: number) { - out[0] = a[0] - s - out[1] = a[1] - s - out[2] = a[2] - s - out[3] = a[3] - s - out[4] = a[4] - s - out[5] = a[5] - s - out[6] = a[6] - s - out[7] = a[7] - s - out[8] = a[8] - s - return out + out[0] = a[0] - s; + out[1] = a[1] - s; + out[2] = a[2] - s; + out[3] = a[3] - s; + out[4] = a[4] - s; + out[5] = a[5] - s; + out[6] = a[6] - s; + out[7] = a[7] - s; + out[8] = a[8] - s; + return out; } export function addScalar(out: Mat3, a: Mat3, s: number) { - out[0] = a[0] + s - out[1] = a[1] + s - out[2] = a[2] + s - out[3] = a[3] + s - out[4] = a[4] + s - out[5] = a[5] + s - out[6] = a[6] + s - out[7] = a[7] + s - out[8] = a[8] + s - return out + out[0] = a[0] + s; + out[1] = a[1] + s; + out[2] = a[2] + s; + out[3] = a[3] + s; + out[4] = a[4] + s; + out[5] = a[5] + s; + out[6] = a[6] + s; + out[7] = a[7] + s; + out[8] = a[8] + s; + return out; } export function mulScalar(out: Mat3, a: Mat3, s: number) { - out[0] = a[0] * s - out[1] = a[1] * s - out[2] = a[2] * s - out[3] = a[3] * s - out[4] = a[4] * s - out[5] = a[5] * s - out[6] = a[6] * s - out[7] = a[7] * s - out[8] = a[8] * s - return out + out[0] = a[0] * s; + out[1] = a[1] * s; + out[2] = a[2] * s; + out[3] = a[3] * s; + out[4] = a[4] * s; + out[5] = a[5] * s; + out[6] = a[6] * s; + out[7] = a[7] * s; + out[8] = a[8] * s; + return out; } - const piThird = Math.PI / 3 - const tmpB = Mat3() + const piThird = Math.PI / 3; + const tmpB = Mat3(); /** * Given a real symmetric 3x3 matrix A, compute the eigenvalues * * From https://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices */ export function symmetricEigenvalues(out: Vec3, a: Mat3) { - const p1 = a[1] * a[1] + a[2] * a[2] + a[5] * a[5] + const p1 = a[1] * a[1] + a[2] * a[2] + a[5] * a[5]; if (p1 === 0) { - out[0] = a[0] - out[1] = a[4] - out[2] = a[8] + out[0] = a[0]; + out[1] = a[4]; + out[2] = a[8]; } else { - const q = trace(a) / 3 - const a1 = a[0] - q - const a2 = a[4] - q - const a3 = a[8] - q - const p2 = a1 * a1 + a2 * a2 + a3 * a3 + 2 * p1 - const p = Math.sqrt(p2 / 6) - mulScalar(tmpB, Identity, q) - sub(tmpB, a, tmpB) - mulScalar(tmpB, tmpB, (1 / p)) - const r = determinant(tmpB) / 2 + const q = trace(a) / 3; + const a1 = a[0] - q; + const a2 = a[4] - q; + const a3 = a[8] - q; + const p2 = a1 * a1 + a2 * a2 + a3 * a3 + 2 * p1; + const p = Math.sqrt(p2 / 6); + mulScalar(tmpB, Identity, q); + sub(tmpB, a, tmpB); + mulScalar(tmpB, tmpB, (1 / p)); + const r = determinant(tmpB) / 2; // In exact arithmetic for a symmetric matrix -1 <= r <= 1 // but computation error can leave it slightly outside this range. const phi = r <= -1 ? piThird : r >= 1 ? - 0 : Math.acos(r) / 3 + 0 : Math.acos(r) / 3; // the eigenvalues satisfy eig3 <= eig2 <= eig1 - out[0] = q + 2 * p * Math.cos(phi) - out[2] = q + 2 * p * Math.cos(phi + (2 * piThird)) - out[1] = 3 * q - out[0] - out[2] // since trace(A) = eig1 + eig2 + eig3 + out[0] = q + 2 * p * Math.cos(phi); + out[2] = q + 2 * p * Math.cos(phi + (2 * piThird)); + out[1] = 3 * q - out[0] - out[2]; // since trace(A) = eig1 + eig2 + eig3 } - return out + return out; } - const tmpR0 = [0.1, 0.0, 0.0] as Vec3 - const tmpR1 = [0.1, 0.0, 0.0] as Vec3 - const tmpR2 = [0.1, 0.0, 0.0] as Vec3 - const tmpR0xR1 = [0.1, 0.0, 0.0] as Vec3 - const tmpR0xR2 = [0.1, 0.0, 0.0] as Vec3 - const tmpR1xR2 = [0.1, 0.0, 0.0] as Vec3 + const tmpR0 = [0.1, 0.0, 0.0] as Vec3; + const tmpR1 = [0.1, 0.0, 0.0] as Vec3; + const tmpR2 = [0.1, 0.0, 0.0] as Vec3; + const tmpR0xR1 = [0.1, 0.0, 0.0] as Vec3; + const tmpR0xR2 = [0.1, 0.0, 0.0] as Vec3; + const tmpR1xR2 = [0.1, 0.0, 0.0] as Vec3; /** * Calculates the eigenvector for the given eigenvalue `e` of matrix `a` */ export function eigenvector(out: Vec3, a: Mat3, e: number) { - Vec3.set(tmpR0, a[0] - e, a[1], a[2]) - Vec3.set(tmpR1, a[1], a[4] - e, a[5]) - Vec3.set(tmpR2, a[2], a[5], a[8] - e) - Vec3.cross(tmpR0xR1, tmpR0, tmpR1) - Vec3.cross(tmpR0xR2, tmpR0, tmpR2) - Vec3.cross(tmpR1xR2, tmpR1, tmpR2) - const d0 = Vec3.dot(tmpR0xR1, tmpR0xR1) - const d1 = Vec3.dot(tmpR0xR2, tmpR0xR2) - const d2 = Vec3.dot(tmpR1xR2, tmpR1xR2) - let dmax = d0 - let imax = 0 + Vec3.set(tmpR0, a[0] - e, a[1], a[2]); + Vec3.set(tmpR1, a[1], a[4] - e, a[5]); + Vec3.set(tmpR2, a[2], a[5], a[8] - e); + Vec3.cross(tmpR0xR1, tmpR0, tmpR1); + Vec3.cross(tmpR0xR2, tmpR0, tmpR2); + Vec3.cross(tmpR1xR2, tmpR1, tmpR2); + const d0 = Vec3.dot(tmpR0xR1, tmpR0xR1); + const d1 = Vec3.dot(tmpR0xR2, tmpR0xR2); + const d2 = Vec3.dot(tmpR1xR2, tmpR1xR2); + let dmax = d0; + let imax = 0; if (d1 > dmax) { - dmax = d1 - imax = 1 + dmax = d1; + imax = 1; } - if (d2 > dmax) imax = 2 + if (d2 > dmax) imax = 2; if (imax === 0) { - Vec3.scale(out, tmpR0xR1, 1 / Math.sqrt(d0)) + Vec3.scale(out, tmpR0xR1, 1 / Math.sqrt(d0)); } else if (imax === 1) { - Vec3.scale(out, tmpR0xR2, 1 / Math.sqrt(d1)) + Vec3.scale(out, tmpR0xR2, 1 / Math.sqrt(d1)); } else { - Vec3.scale(out, tmpR1xR2, 1 / Math.sqrt(d2)) + Vec3.scale(out, tmpR1xR2, 1 / Math.sqrt(d2)); } - return out + return out; } /** * Get matrix to transform directions, e.g. normals */ export function directionTransform(out: Mat3, t: Mat4) { - Mat3.fromMat4(out, t) - Mat3.invert(out, out) - Mat3.transpose(out, out) - return out + Mat3.fromMat4(out, t); + Mat3.invert(out, out); + Mat3.transpose(out, out); + return out; } - export const Identity: ReadonlyMat3 = identity() + export const Identity: ReadonlyMat3 = identity(); } -export default Mat3 \ No newline at end of file +export default Mat3; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d/mat4.ts b/src/mol-math/linear-algebra/3d/mat4.ts index e935e6ae3b8a1790a312eeaff188a86d14c93bcb..56ae7dc3ab2240f46f7c2c5056a8b07bbaada8ae 100644 --- a/src/mol-math/linear-algebra/3d/mat4.ts +++ b/src/mol-math/linear-algebra/3d/mat4.ts @@ -17,7 +17,7 @@ * furnished to do so, subject to the following conditions: */ -import { EPSILON, equalEps } from './common' +import { EPSILON, equalEps } from './common'; import Vec3 from './vec3'; import Quat from './quat'; import { degToRad } from '../../misc'; @@ -105,8 +105,8 @@ namespace Mat4 { } export function hasNaN(m: Mat4) { - for (let i = 0; i < 16; i++) if (isNaN(m[i])) return true - return false + for (let i = 0; i < 16; i++) if (isNaN(m[i])) return true; + return false; } export function areEqual(a: Mat4, b: Mat4, eps: number) { @@ -145,23 +145,23 @@ namespace Mat4 { } export function fromArray(a: Mat4, array: NumberArray, offset: number) { - a[0] = array[offset + 0] - a[1] = array[offset + 1] - a[2] = array[offset + 2] - a[3] = array[offset + 3] - a[4] = array[offset + 4] - a[5] = array[offset + 5] - a[6] = array[offset + 6] - a[7] = array[offset + 7] - a[8] = array[offset + 8] - a[9] = array[offset + 9] - a[10] = array[offset + 10] - a[11] = array[offset + 11] - a[12] = array[offset + 12] - a[13] = array[offset + 13] - a[14] = array[offset + 14] - a[15] = array[offset + 15] - return a + a[0] = array[offset + 0]; + a[1] = array[offset + 1]; + a[2] = array[offset + 2]; + a[3] = array[offset + 3]; + a[4] = array[offset + 4]; + a[5] = array[offset + 5]; + a[6] = array[offset + 6]; + a[7] = array[offset + 7]; + a[8] = array[offset + 8]; + a[9] = array[offset + 9]; + a[10] = array[offset + 10]; + a[11] = array[offset + 11]; + a[12] = array[offset + 12]; + a[13] = array[offset + 13]; + a[14] = array[offset + 14]; + a[15] = array[offset + 15]; + return a; } export function copy(out: Mat4, a: Mat4) { @@ -511,7 +511,7 @@ namespace Mat4 { out[2] = view[0]; out[6] = view[1]; out[10] = view[2]; - return out + return out; } export function rotate(out: Mat4, a: Mat4, rad: number, axis: Vec3) { @@ -747,7 +747,7 @@ namespace Mat4 { * Allows for improper rotations */ export function isRotationAndTranslation(a: Mat4, eps?: number) { - return _isRotationAndTranslation(a, typeof eps !== 'undefined' ? eps : EPSILON) + return _isRotationAndTranslation(a, typeof eps !== 'undefined' ? eps : EPSILON); } function _isRotationAndTranslation(a: Mat4, eps: number) { @@ -776,11 +776,11 @@ namespace Mat4 { * [ 0 0 0 1 ] */ export function isTranslationAndUniformScaling(a: Mat4, eps?: number) { - return _isTranslationAndUniformScaling(a, typeof eps !== 'undefined' ? eps : EPSILON) + return _isTranslationAndUniformScaling(a, typeof eps !== 'undefined' ? eps : EPSILON); } function _isTranslationAndUniformScaling(a: Mat4, eps: number) { - const a00 = a[0] + const a00 = a[0]; return ( // 0 base scaling equalEps(a[1], 0, eps) && @@ -796,7 +796,7 @@ namespace Mat4 { equalEps(a[11], 0, eps) && // 12, 13, 14 translation can be anything equalEps(a[15], 1, eps) - ) + ); } export function fromQuat(out: Mat4, q: Quat) { @@ -1049,43 +1049,43 @@ namespace Mat4 { } export function getMaxScaleOnAxis(m: Mat4) { - const scaleXSq = m[0] * m[0] + m[1] * m[1] + m[2] * m[2] - const scaleYSq = m[4] * m[4] + m[5] * m[5] + m[6] * m[6] - const scaleZSq = m[8] * m[8] + m[9] * m[9] + m[10] * m[10] - return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq)) + const scaleXSq = m[0] * m[0] + m[1] * m[1] + m[2] * m[2]; + const scaleYSq = m[4] * m[4] + m[5] * m[5] + m[6] * m[6]; + const scaleZSq = m[8] * m[8] + m[9] * m[9] + m[10] * m[10]; + return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq)); } - const xAxis = Vec3.create(1, 0, 0) - const yAxis = Vec3.create(0, 1, 0) - const zAxis = Vec3.create(0, 0, 1) + const xAxis = Vec3.create(1, 0, 0); + const yAxis = Vec3.create(0, 1, 0); + const zAxis = Vec3.create(0, 0, 1); /** Rotation matrix for 90deg around x-axis */ - export const rotX90: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(90), xAxis) + export const rotX90: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(90), xAxis); /** Rotation matrix for 180deg around x-axis */ - export const rotX180: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(180), xAxis) + export const rotX180: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(180), xAxis); /** Rotation matrix for 90deg around y-axis */ - export const rotY90: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(90), yAxis) + export const rotY90: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(90), yAxis); /** Rotation matrix for 180deg around y-axis */ - export const rotY180: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(180), yAxis) + export const rotY180: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(180), yAxis); /** Rotation matrix for 270deg around y-axis */ - export const rotY270: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(270), yAxis) + export const rotY270: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(270), yAxis); /** Rotation matrix for 90deg around z-axis */ - export const rotZ90: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(90), zAxis) + export const rotZ90: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(90), zAxis); /** Rotation matrix for 180deg around z-axis */ - export const rotZ180: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(180), zAxis) + export const rotZ180: ReadonlyMat4 = Mat4.fromRotation(Mat4(), degToRad(180), zAxis); /** Rotation matrix for 90deg around first x-axis and then y-axis */ - export const rotXY90: ReadonlyMat4 = Mat4.mul(Mat4(), rotX90, rotY90) + export const rotXY90: ReadonlyMat4 = Mat4.mul(Mat4(), rotX90, rotY90); /** Rotation matrix for 90deg around first z-axis and then y-axis */ - export const rotZY90: ReadonlyMat4 = Mat4.mul(Mat4(), rotZ90, rotY90) + export const rotZY90: ReadonlyMat4 = Mat4.mul(Mat4(), rotZ90, rotY90); /** Rotation matrix for 90deg around first z-axis and then y-axis and then z-axis */ - export const rotZYZ90: ReadonlyMat4 = Mat4.mul(Mat4(), rotZY90, rotZ90) + export const rotZYZ90: ReadonlyMat4 = Mat4.mul(Mat4(), rotZY90, rotZ90); /** Rotation matrix for 90deg around first z-axis and then 180deg around x-axis */ - export const rotZ90X180: ReadonlyMat4 = Mat4.mul(Mat4(), rotZ90, rotX180) + export const rotZ90X180: ReadonlyMat4 = Mat4.mul(Mat4(), rotZ90, rotX180); /** Rotation matrix for 90deg around first y-axis and then 180deg around z-axis */ - export const rotY90Z180: ReadonlyMat4 = Mat4.mul(Mat4(), rotY90, rotZ180) + export const rotY90Z180: ReadonlyMat4 = Mat4.mul(Mat4(), rotY90, rotZ180); /** Identity matrix */ - export const id: ReadonlyMat4 = Mat4.identity() + export const id: ReadonlyMat4 = Mat4.identity(); } -export default Mat4 \ No newline at end of file +export default Mat4; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d/quat.ts b/src/mol-math/linear-algebra/3d/quat.ts index d62524c853ff6658c47d6250548e73d837700169..40eb9e0efa8b270e785e8475bdf218f1cb2121d4 100644 --- a/src/mol-math/linear-algebra/3d/quat.ts +++ b/src/mol-math/linear-algebra/3d/quat.ts @@ -56,7 +56,7 @@ namespace Quat { } export function hasNaN(q: Quat) { - return isNaN(q[0]) || isNaN(q[1]) || isNaN(q[2]) || isNaN(q[3]) + return isNaN(q[0]) || isNaN(q[1]) || isNaN(q[2]) || isNaN(q[3]); } export function create(x: number, y: number, z: number, w: number) { @@ -277,32 +277,32 @@ namespace Quat { return out; } - const fromUnitVec3Temp = Vec3() + const fromUnitVec3Temp = Vec3(); /** Quaternion from two normalized unit vectors. */ export function fromUnitVec3 (out: Quat, a: Vec3, b: Vec3) { // assumes a and b are normalized - let r = Vec3.dot(a, b) + 1 + let r = Vec3.dot(a, b) + 1; if (r < EPSILON) { // If u and v are exactly opposite, rotate 180 degrees // around an arbitrary orthogonal axis. Axis normalisation // can happen later, when we normalise the quaternion. - r = 0 + r = 0; if (Math.abs(a[0]) > Math.abs(a[2])) { - Vec3.set(fromUnitVec3Temp, -a[1], a[0], 0) + Vec3.set(fromUnitVec3Temp, -a[1], a[0], 0); } else { - Vec3.set(fromUnitVec3Temp, 0, -a[2], a[1]) + Vec3.set(fromUnitVec3Temp, 0, -a[2], a[1]); } } else { // Otherwise, build quaternion the standard way. - Vec3.cross(fromUnitVec3Temp, a, b) + Vec3.cross(fromUnitVec3Temp, a, b); } - out[0] = fromUnitVec3Temp[0] - out[1] = fromUnitVec3Temp[1] - out[2] = fromUnitVec3Temp[2] - out[3] = r - normalize(out, out) - return out + out[0] = fromUnitVec3Temp[0]; + out[1] = fromUnitVec3Temp[1]; + out[2] = fromUnitVec3Temp[2]; + out[3] = r; + normalize(out, out); + return out; } export function clone(a: Quat) { @@ -323,11 +323,11 @@ namespace Quat { } export function fromArray(a: Quat, array: NumberArray, offset: number) { - a[0] = array[offset + 0] - a[1] = array[offset + 1] - a[2] = array[offset + 2] - a[3] = array[offset + 3] - return a + a[0] = array[offset + 0]; + a[1] = array[offset + 1]; + a[2] = array[offset + 2]; + a[3] = array[offset + 3]; + return a; } export function copy(out: Quat, a: Quat) { @@ -442,7 +442,7 @@ namespace Quat { return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)} ${a[3].toPrecision(precision)}]`; } - export const Identity: ReadonlyQuat = identity() + export const Identity: ReadonlyQuat = identity(); } -export default Quat \ No newline at end of file +export default Quat; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d/vec2.ts b/src/mol-math/linear-algebra/3d/vec2.ts index 16d922951c4a529e21573838a29e6078967c7009..cded99bd759f147a6cb2606be029b900409cc704 100644 --- a/src/mol-math/linear-algebra/3d/vec2.ts +++ b/src/mol-math/linear-algebra/3d/vec2.ts @@ -47,7 +47,7 @@ namespace Vec2 { } export function hasNaN(a: Vec2) { - return isNaN(a[0]) || isNaN(a[1]) + return isNaN(a[0]) || isNaN(a[1]); } export function toArray(a: Vec2, out: NumberArray, offset: number) { @@ -57,9 +57,9 @@ namespace Vec2 { } export function fromArray(a: Vec2, array: NumberArray, offset: number) { - a[0] = array[offset + 0] - a[1] = array[offset + 1] - return a + a[0] = array[offset + 0]; + a[1] = array[offset + 1]; + return a; } export function copy(out: Vec2, a: Vec2) { @@ -173,4 +173,4 @@ namespace Vec2 { } } -export default Vec2 \ No newline at end of file +export default Vec2; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d/vec3.ts b/src/mol-math/linear-algebra/3d/vec3.ts index 7d111c071ebfa5ab534637f1c2fb73d66e5bb9ab..fa9846712f498114d7fc896e6f97cf12165c3b48 100644 --- a/src/mol-math/linear-algebra/3d/vec3.ts +++ b/src/mol-math/linear-algebra/3d/vec3.ts @@ -19,10 +19,10 @@ import Mat4 from './mat4'; import { Quat, Mat3, EPSILON } from '../3d'; -import { spline as _spline, quadraticBezier as _quadraticBezier, clamp } from '../../interpolate' +import { spline as _spline, quadraticBezier as _quadraticBezier, clamp } from '../../interpolate'; import { NumberArray } from '../../../mol-util/type-helpers'; -export { ReadonlyVec3 } +export { ReadonlyVec3 }; interface Vec3 extends Array<number> { [d: number]: number, '@type': 'vec3', length: 3 } interface ReadonlyVec3 extends Array<number> { readonly [d: number]: number, '@type': 'vec3', length: 3 } @@ -47,14 +47,14 @@ namespace Vec3 { } export function hasNaN(a: Vec3) { - return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]) + return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]); } export function setNaN(out: Vec3) { out[0] = NaN; out[1] = NaN; out[2] = NaN; - return out + return out; } export function fromObj(v: { x: number, y: number, z: number }): Vec3 { @@ -66,17 +66,17 @@ namespace Vec3 { } export function fromArray(v: Vec3, array: ArrayLike<number>, offset: number) { - v[0] = array[offset + 0] - v[1] = array[offset + 1] - v[2] = array[offset + 2] - return v + v[0] = array[offset + 0]; + v[1] = array[offset + 1]; + v[2] = array[offset + 2]; + return v; } export function toArray(v: Vec3, out: NumberArray, offset: number) { - out[offset + 0] = v[0] - out[offset + 1] = v[1] - out[offset + 2] = v[2] - return out + out[offset + 0] = v[0]; + out[offset + 1] = v[1]; + out[offset + 2] = v[2]; + return out; } export function create(x: number, y: number, z: number): Vec3 { @@ -239,7 +239,7 @@ namespace Vec3 { } export function setMagnitude(out: Vec3, a: Vec3, l: number) { - return Vec3.scale(out, Vec3.normalize(out, a), l) + return Vec3.scale(out, Vec3.normalize(out, a), l); } /** @@ -303,7 +303,7 @@ namespace Vec3 { return out; } - const slerpRelVec = Vec3.zero() + const slerpRelVec = Vec3.zero(); export function slerp(out: Vec3, a: Vec3, b: Vec3, t: number) { const dot = clamp(Vec3.dot(a, b), -1, 1); const theta = Math.acos(dot) * t; @@ -502,7 +502,7 @@ namespace Vec3 { /** Project `point` onto `vector` starting from `origin` */ export function projectPointOnVector(out: Vec3, point: Vec3, vector: Vec3, origin: Vec3) { - sub(out, copy(out, point), origin) + sub(out, copy(out, point), origin); const scalar = dot(vector, out) / squaredMagnitude(vector); return add(out, scale(out, copy(out, vector), scalar), origin); } @@ -512,7 +512,7 @@ namespace Vec3 { return scale(out, vector, scalar); } - const tmpProject = Vec3() + const tmpProject = Vec3(); export function projectOnPlane(out: Vec3, p: Vec3, normal: Vec3) { projectOnVector(tmpProject, p, normal); return sub(out, p, tmpProject); @@ -528,9 +528,9 @@ namespace Vec3 { * i.e. where the dot product is > 0 */ export function matchDirection(out: Vec3, a: Vec3, b: Vec3) { - if (Vec3.dot(a, b) > 0) Vec3.copy(out, a) - else Vec3.negate(out, Vec3.copy(out, a)) - return out + if (Vec3.dot(a, b) > 0) Vec3.copy(out, a); + else Vec3.negate(out, Vec3.copy(out, a)); + return out; } const triangleNormalTmpAB = zero(); @@ -546,14 +546,14 @@ namespace Vec3 { return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)}]`; } - export const origin: ReadonlyVec3 = Vec3.create(0, 0, 0) + export const origin: ReadonlyVec3 = Vec3.create(0, 0, 0); - export const unit: ReadonlyVec3 = Vec3.create(1, 1, 1) - export const negUnit: ReadonlyVec3 = Vec3.create(-1, -1, -1) + export const unit: ReadonlyVec3 = Vec3.create(1, 1, 1); + export const negUnit: ReadonlyVec3 = Vec3.create(-1, -1, -1); - export const unitX: ReadonlyVec3 = Vec3.create(1, 0, 0) - export const unitY: ReadonlyVec3 = Vec3.create(0, 1, 0) - export const unitZ: ReadonlyVec3 = Vec3.create(0, 0, 1) + export const unitX: ReadonlyVec3 = Vec3.create(1, 0, 0); + export const unitY: ReadonlyVec3 = Vec3.create(0, 1, 0); + export const unitZ: ReadonlyVec3 = Vec3.create(0, 0, 1); } -export default Vec3 \ No newline at end of file +export default Vec3; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/3d/vec4.ts b/src/mol-math/linear-algebra/3d/vec4.ts index 32f5ddfbcb30a22ced43acca89f193da50ee694c..fa98ff02cf529d654159d2a61582fc57cd2a205a 100644 --- a/src/mol-math/linear-algebra/3d/vec4.ts +++ b/src/mol-math/linear-algebra/3d/vec4.ts @@ -54,7 +54,7 @@ namespace Vec4 { } export function hasNaN(a: Vec4) { - return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]) || isNaN(a[3]) + return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]) || isNaN(a[3]); } export function toArray(a: Vec4, out: NumberArray, offset: number) { @@ -66,11 +66,11 @@ namespace Vec4 { } export function fromArray(a: Vec4, array: NumberArray, offset: number) { - a[0] = array[offset + 0] - a[1] = array[offset + 1] - a[2] = array[offset + 2] - a[3] = array[offset + 3] - return a + a[0] = array[offset + 0]; + a[1] = array[offset + 1]; + a[2] = array[offset + 2]; + a[3] = array[offset + 3]; + return a; } export function toVec3Array(a: Vec4, out: NumberArray, offset: number) { @@ -80,11 +80,11 @@ namespace Vec4 { } export function fromVec3Array(a: Vec4, array: NumberArray, offset: number) { - a[0] = array[offset + 0] - a[1] = array[offset + 1] - a[2] = array[offset + 2] - a[3] = 0 - return a + a[0] = array[offset + 0]; + a[1] = array[offset + 1]; + a[2] = array[offset + 2]; + a[3] = 0; + return a; } export function copy(out: Vec4, a: Vec4) { @@ -232,4 +232,4 @@ namespace Vec4 { } } -export default Vec4 \ No newline at end of file +export default Vec4; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/_spec/mat3.spec.ts b/src/mol-math/linear-algebra/_spec/mat3.spec.ts index 35901555c356fc166634682b23c77ff0012fb3f6..d1007d8b2e87c708eca74609b1122c177058d094 100644 --- a/src/mol-math/linear-algebra/_spec/mat3.spec.ts +++ b/src/mol-math/linear-algebra/_spec/mat3.spec.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Mat3, Vec3 } from '../3d' +import { Mat3, Vec3 } from '../3d'; describe('Mat3', () => { it('symmetricEigenvalues', () => { @@ -12,8 +12,8 @@ describe('Mat3', () => { 0.1945, -0.0219, -0.0416, -0.0219, 0.1995, -0.0119, -0.0416, -0.0119, 0.3673 - ) - const e = Vec3.create(0.377052701425898, 0.21713981522725134, 0.1671074833468507) + ); + const e = Vec3.create(0.377052701425898, 0.21713981522725134, 0.1671074833468507); expect(Vec3.equals(e, Mat3.symmetricEigenvalues(Vec3(), m))).toBe(true); }); @@ -22,11 +22,11 @@ describe('Mat3', () => { 0.1945, -0.0219, -0.0416, -0.0219, 0.1995, -0.0119, -0.0416, -0.0119, 0.3673 - ) - const e = Vec3.create(0.377052701425898, 0.21713981522725134, 0.1671074833468507) - const v0 = Vec3.create(-0.2176231019882068, -0.038522620041966125, 0.9752723687391808) - const v1 = Vec3.create(-0.5905636938047126, 0.8007524989198634, -0.10014968314142503) - const v2 = Vec3.create(0.7770937582036648, 0.5977553372576602, 0.19701230352667118) + ); + const e = Vec3.create(0.377052701425898, 0.21713981522725134, 0.1671074833468507); + const v0 = Vec3.create(-0.2176231019882068, -0.038522620041966125, 0.9752723687391808); + const v1 = Vec3.create(-0.5905636938047126, 0.8007524989198634, -0.10014968314142503); + const v2 = Vec3.create(0.7770937582036648, 0.5977553372576602, 0.19701230352667118); expect(Vec3.equals(v0, Mat3.eigenvector(Vec3(), m, e[0]))).toBe(true); expect(Vec3.equals(v1, Mat3.eigenvector(Vec3(), m, e[1]))).toBe(true); diff --git a/src/mol-math/linear-algebra/_spec/mat4.spec.ts b/src/mol-math/linear-algebra/_spec/mat4.spec.ts index 4b6668e8d63eafe34f08378ca552856b4a733284..df801e27bf592b513112d201a5ecd761eaa53d90 100644 --- a/src/mol-math/linear-algebra/_spec/mat4.spec.ts +++ b/src/mol-math/linear-algebra/_spec/mat4.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Mat4, Vec3 } from '../3d' +import { Mat4, Vec3 } from '../3d'; describe('Mat4', () => { it('permutation', () => { diff --git a/src/mol-math/linear-algebra/_spec/tensor.spec.ts b/src/mol-math/linear-algebra/_spec/tensor.spec.ts index 1c5ace38f1fe4a5b8affb8aa6e874e396f9f297c..f8cd6c1fc68d0cbf9b1765c91a55e5e26d44e92a 100644 --- a/src/mol-math/linear-algebra/_spec/tensor.spec.ts +++ b/src/mol-math/linear-algebra/_spec/tensor.spec.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Tensor as T } from '../tensor' -import { Mat4 } from '../3d' +import { Tensor as T } from '../tensor'; +import { Mat4 } from '../3d'; describe('tensor', () => { it('vector', () => { @@ -24,7 +24,7 @@ describe('tensor', () => { it('matrix cm', () => { const M = T.ColumnMajorMatrix(3, 2, Int32Array); - const data = M.create() + const data = M.create(); // rows: [ [0, 1], [1, 2], [2, 3] ] for (let i = 0; i < 3; i++) { @@ -68,7 +68,7 @@ describe('tensor', () => { it('2d ij', () => { const M = T.Space([3, 4], [0, 1]); const data = M.create(); - const exp = new Float64Array(3 * 4) + const exp = new Float64Array(3 * 4); let o = 0; for (let i = 0; i < 3; i++) { @@ -86,7 +86,7 @@ describe('tensor', () => { it('2d ji', () => { const M = T.Space([3, 4], [1, 0]); const data = M.create(); - const exp = new Float64Array(3 * 4) + const exp = new Float64Array(3 * 4); let o = 0; for (let j = 0; j < 4; j++) { @@ -104,7 +104,7 @@ describe('tensor', () => { it('3d ijk', () => { const M = T.Space([3, 4, 5], [0, 1, 2]); const data = M.create(); - const exp = new Float64Array(3 * 4 * 5) + const exp = new Float64Array(3 * 4 * 5); let o = 0; for (let i = 0; i < 3; i++) { @@ -124,7 +124,7 @@ describe('tensor', () => { it('3d ikj', () => { const M = T.Space([3, 3, 3], [0, 2, 1]); const data = M.create(); - const exp = new Float64Array(3 * 3 * 3) + const exp = new Float64Array(3 * 3 * 3); let o = 0; for (let i = 0; i < 3; i++) { @@ -144,7 +144,7 @@ describe('tensor', () => { it('3d jik', () => { const M = T.Space([3, 3, 3], [1, 0, 2]); const data = M.create(); - const exp = new Float64Array(3 * 3 * 3) + const exp = new Float64Array(3 * 3 * 3); let o = 0; for (let j = 0; j < 3; j++) { @@ -163,7 +163,7 @@ describe('tensor', () => { it('3d jki', () => { const M = T.Space([3, 3, 3], [1, 2, 0]); const data = M.create(); - const exp = new Float64Array(3 * 3 * 3) + const exp = new Float64Array(3 * 3 * 3); let o = 0; for (let j = 0; j < 3; j++) { @@ -183,7 +183,7 @@ describe('tensor', () => { it('3d kij', () => { const M = T.Space([3, 3, 3], [2, 0, 1]); const data = M.create(); - const exp = new Float64Array(3 * 3 * 3) + const exp = new Float64Array(3 * 3 * 3); let o = 0; for (let k = 0; k < 3; k++) { @@ -203,7 +203,7 @@ describe('tensor', () => { it('3d kji', () => { const M = T.Space([3, 3, 3], [2, 1, 0]); const data = M.create(); - const exp = new Float64Array(3 * 3 * 3) + const exp = new Float64Array(3 * 3 * 3); let o = 0; for (let k = 0; k < 3; k++) { @@ -223,7 +223,7 @@ describe('tensor', () => { it('4d jikl', () => { const M = T.Space([2, 3, 4, 5], [1, 0, 2, 3]); const data = M.create(); - const exp = new Float64Array(2 * 3 * 4 * 5) + const exp = new Float64Array(2 * 3 * 4 * 5); let o = 0; for (let j = 0; j < 3; j++) { @@ -245,7 +245,7 @@ describe('tensor', () => { it('4d jilk', () => { const M = T.Space([2, 3, 4, 5], [1, 0, 3, 2]); const data = M.create(); - const exp = new Float64Array(2 * 3 * 4 * 5) + const exp = new Float64Array(2 * 3 * 4 * 5); let o = 0; for (let j = 0; j < 3; j++) { diff --git a/src/mol-math/linear-algebra/_spec/vec3.spec.ts b/src/mol-math/linear-algebra/_spec/vec3.spec.ts index bb98228acaf7b051186c8dd54cc985d81159ce52..38909706a44b00afc45b86bb2cb33ea273748c43 100644 --- a/src/mol-math/linear-algebra/_spec/vec3.spec.ts +++ b/src/mol-math/linear-algebra/_spec/vec3.spec.ts @@ -1,4 +1,4 @@ -import { Vec3 } from '../3d' +import { Vec3 } from '../3d'; describe('vec3', () => { const vec1 = [ 1, 2, 3 ] as Vec3; @@ -11,4 +11,4 @@ describe('vec3', () => { expect(Vec3.angle(orthVec1, orthVec2) * 360 / (2 * Math.PI)).toBe(90.0); expect(Vec3.angle(vec1, vec2)).toBeCloseTo(0.666946); }); -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-math/linear-algebra/matrix/evd.ts b/src/mol-math/linear-algebra/matrix/evd.ts index 7bd2056ae88331e749a83771f1981b249e937c84..25ca7b28dba59fdc05e50736763a9cdaac5aeab4 100644 --- a/src/mol-math/linear-algebra/matrix/evd.ts +++ b/src/mol-math/linear-algebra/matrix/evd.ts @@ -22,7 +22,7 @@ export namespace EVD { eigenValues: <any>new Float64Array(size), D: <any>new Float64Array(size), E: <any>new Float64Array(size) - } + }; } /** diff --git a/src/mol-math/linear-algebra/matrix/matrix.ts b/src/mol-math/linear-algebra/matrix/matrix.ts index a05e52de4d01b278cb9d8f72653f303fb9b7037f..44cfbbc12e0210dc76d2e11ab6778fb81da61f54 100644 --- a/src/mol-math/linear-algebra/matrix/matrix.ts +++ b/src/mol-math/linear-algebra/matrix/matrix.ts @@ -16,8 +16,8 @@ interface Matrix<N extends number = number, M extends number = number> { namespace Matrix { export function create<N extends number, M extends number>(cols: N, rows: M, ctor: { new (size: number): NumberArray } = Float32Array): Matrix<N, M> { - const size = cols * rows - return { data: new ctor(size), size, cols, rows } + const size = cols * rows; + return { data: new ctor(size), size, cols, rows }; } /** Get element assuming data are stored in column-major order */ @@ -28,88 +28,88 @@ namespace Matrix { /** Set element assuming data are stored in column-major order */ export function set<N extends number, M extends number>(m: Matrix<N, M>, i: number, j: number, value: number) { m.data[m.rows * j + i] = value; - return m + return m; } /** Add to element assuming data are stored in column-major order */ export function add<N extends number, M extends number>(m: Matrix<N, M>, i: number, j: number, value: number) { m.data[m.rows * j + i] += value; - return m + return m; } /** Zero out the matrix */ export function makeZero<N extends number, M extends number>(m: Matrix<N, M>) { - m.data.fill(0.0) - return m + m.data.fill(0.0); + return m; } export function clone<N extends number, M extends number>(m: Matrix<N, M>): Matrix<N, M> { - return { data: m.data.slice(), size: m.size, cols: m.cols, rows: m.rows } + return { data: m.data.slice(), size: m.size, cols: m.cols, rows: m.rows }; } export function fromArray<N extends number, M extends number>(data: NumberArray, cols: N, rows: M): Matrix<N, M> { - return { data, size: cols * rows, cols, rows } + return { data, size: cols * rows, cols, rows }; } export function transpose<N extends number, M extends number>(out: Matrix<M, N>, mat: Matrix<N, M>): Matrix<M, N> { if (out.cols !== mat.rows || out.rows !== mat.cols) { - throw new Error('transpose: matrix dimensions incompatible') + throw new Error('transpose: matrix dimensions incompatible'); } if (out.data === mat.data) { - throw new Error('transpose: matrices share memory') + throw new Error('transpose: matrices share memory'); } - const nrows = mat.rows, ncols = mat.cols - const md = mat.data, mtd = out.data + const nrows = mat.rows, ncols = mat.cols; + const md = mat.data, mtd = out.data; for (let i = 0, mi = 0, mti = 0; i < nrows; mti += 1, mi += ncols, ++i) { - let ri = mti - for (let j = 0; j < ncols; ri += nrows, j++) mtd[ri] = md[mi + j] + let ri = mti; + for (let j = 0; j < ncols; ri += nrows, j++) mtd[ri] = md[mi + j]; } - return out + return out; } /** out = matA * matB' */ export function multiplyABt<NA extends number, NB extends number, M extends number>(out: Matrix<M, M>, matA: Matrix<NA, M>, matB: Matrix<NB, M>): Matrix<M, M> { - const ncols = matA.cols, nrows = matA.rows, mrows = matB.rows - const ad = matA.data, bd = matB.data, cd = out.data + const ncols = matA.cols, nrows = matA.rows, mrows = matB.rows; + const ad = matA.data, bd = matB.data, cd = out.data; for (let i = 0, matAp = 0, outP = 0; i < nrows; matAp += ncols, i++) { for (let pB = 0, j = 0; j < mrows; outP++, j++) { - let sum = 0.0 - let pMatA = matAp + let sum = 0.0; + let pMatA = matAp; for (let k = 0; k < ncols; pMatA++, pB++, k++) { - sum += ad[pMatA] * bd[pB] + sum += ad[pMatA] * bd[pB]; } - cd[outP] = sum + cd[outP] = sum; } } - return out + return out; } /** Get the mean of rows in `mat` */ export function meanRows<N extends number, M extends number, V extends Vec<N>>(mat: Matrix<N, M>): V { - const nrows = mat.rows, ncols = mat.cols - const md = mat.data - const mean = new Array(ncols) as V + const nrows = mat.rows, ncols = mat.cols; + const md = mat.data; + const mean = new Array(ncols) as V; - for (let j = 0; j < ncols; ++j) mean[ j ] = 0.0 + for (let j = 0; j < ncols; ++j) mean[ j ] = 0.0; for (let i = 0, p = 0; i < nrows; ++i) { - for (let j = 0; j < ncols; ++j, ++p) mean[ j ] += md[ p ] + for (let j = 0; j < ncols; ++j, ++p) mean[ j ] += md[ p ]; } - for (let j = 0; j < ncols; ++j) mean[ j ] /= nrows + for (let j = 0; j < ncols; ++j) mean[ j ] /= nrows; - return mean + return mean; } /** Subtract `row` from all rows in `mat` */ export function subRows<N extends number, M extends number>(mat: Matrix<N, M>, row: NumberArray) { - const nrows = mat.rows, ncols = mat.cols - const md = mat.data + const nrows = mat.rows, ncols = mat.cols; + const md = mat.data; for (let i = 0, p = 0; i < nrows; ++i) { - for (let j = 0; j < ncols; ++j, ++p) md[ p ] -= row[ j ] + for (let j = 0; j < ncols; ++j, ++p) md[ p ] -= row[ j ]; } - return mat + return mat; } } -export default Matrix \ No newline at end of file +export default Matrix; \ No newline at end of file diff --git a/src/mol-math/linear-algebra/matrix/principal-axes.ts b/src/mol-math/linear-algebra/matrix/principal-axes.ts index e8fd57230e72cfb314b2ee3dafdde571fc379f5b..2481d069fe59f2b95c6580b5907eb31aa387c19f 100644 --- a/src/mol-math/linear-algebra/matrix/principal-axes.ts +++ b/src/mol-math/linear-algebra/matrix/principal-axes.ts @@ -10,7 +10,7 @@ import { svd } from './svd'; import { NumberArray } from '../../../mol-util/type-helpers'; import { Axes3D } from '../../geometry'; -export { PrincipalAxes } +export { PrincipalAxes }; interface PrincipalAxes { momentsAxes: Axes3D @@ -19,124 +19,124 @@ interface PrincipalAxes { namespace PrincipalAxes { export function ofPositions(positions: NumberArray): PrincipalAxes { - const momentsAxes = calculateMomentsAxes(positions) - const boxAxes = calculateBoxAxes(positions, momentsAxes) - return { momentsAxes, boxAxes } + const momentsAxes = calculateMomentsAxes(positions); + const boxAxes = calculateBoxAxes(positions, momentsAxes); + return { momentsAxes, boxAxes }; } export function calculateMomentsAxes(positions: NumberArray): Axes3D { if (positions.length === 3) { - return Axes3D.create(Vec3.fromArray(Vec3(), positions, 0), Vec3.create(1, 0, 0), Vec3.create(0, 1, 0), Vec3.create(0, 1, 0)) + return Axes3D.create(Vec3.fromArray(Vec3(), positions, 0), Vec3.create(1, 0, 0), Vec3.create(0, 1, 0), Vec3.create(0, 1, 0)); } - const points = Matrix.fromArray(positions, 3, positions.length / 3) - const n = points.rows - const n3 = n / 3 - const A = Matrix.create(3, 3) - const W = Matrix.create(1, 3) - const U = Matrix.create(3, 3) - const V = Matrix.create(3, 3) + const points = Matrix.fromArray(positions, 3, positions.length / 3); + const n = points.rows; + const n3 = n / 3; + const A = Matrix.create(3, 3); + const W = Matrix.create(1, 3); + const U = Matrix.create(3, 3); + const V = Matrix.create(3, 3); // calculate - const mean = Matrix.meanRows(points) - const pointsM = Matrix.subRows(Matrix.clone(points), mean) - const pointsT = Matrix.transpose(Matrix.create(n, 3), pointsM) - Matrix.multiplyABt(A, pointsT, pointsT) - svd(A, W, U, V) + const mean = Matrix.meanRows(points); + const pointsM = Matrix.subRows(Matrix.clone(points), mean); + const pointsT = Matrix.transpose(Matrix.create(n, 3), pointsM); + Matrix.multiplyABt(A, pointsT, pointsT); + svd(A, W, U, V); // origin - const origin = Vec3.create(mean[0], mean[1], mean[2]) + const origin = Vec3.create(mean[0], mean[1], mean[2]); // directions - const dirA = Vec3.create(U.data[0], U.data[3], U.data[6]) - const dirB = Vec3.create(U.data[1], U.data[4], U.data[7]) - const dirC = Vec3.create(U.data[2], U.data[5], U.data[8]) - Vec3.scale(dirA, dirA, Math.sqrt(W.data[0] / n3)) - Vec3.scale(dirB, dirB, Math.sqrt(W.data[1] / n3)) - Vec3.scale(dirC, dirC, Math.sqrt(W.data[2] / n3)) - - return Axes3D.create(origin, dirA, dirB, dirC) + const dirA = Vec3.create(U.data[0], U.data[3], U.data[6]); + const dirB = Vec3.create(U.data[1], U.data[4], U.data[7]); + const dirC = Vec3.create(U.data[2], U.data[5], U.data[8]); + Vec3.scale(dirA, dirA, Math.sqrt(W.data[0] / n3)); + Vec3.scale(dirB, dirB, Math.sqrt(W.data[1] / n3)); + Vec3.scale(dirC, dirC, Math.sqrt(W.data[2] / n3)); + + return Axes3D.create(origin, dirA, dirB, dirC); } - const tmpBoxVec = Vec3() - const tmpBoxVecA = Vec3() - const tmpBoxVecB = Vec3() - const tmpBoxVecC = Vec3() + const tmpBoxVec = Vec3(); + const tmpBoxVecA = Vec3(); + const tmpBoxVecB = Vec3(); + const tmpBoxVecC = Vec3(); /** * Get the scale/length for each dimension for a box around the axes * to enclose the given positions */ export function calculateBoxAxes(positions: NumberArray, momentsAxes: Axes3D): Axes3D { if (positions.length === 3) { - return Axes3D.clone(momentsAxes) + return Axes3D.clone(momentsAxes); } - let d1a = -Infinity - let d1b = -Infinity - let d2a = -Infinity - let d2b = -Infinity - let d3a = -Infinity - let d3b = -Infinity + let d1a = -Infinity; + let d1b = -Infinity; + let d2a = -Infinity; + let d2b = -Infinity; + let d3a = -Infinity; + let d3b = -Infinity; - const p = Vec3() - const t = Vec3() + const p = Vec3(); + const t = Vec3(); - const center = momentsAxes.origin - const normVecA = Vec3.normalize(tmpBoxVecA, momentsAxes.dirA) - const normVecB = Vec3.normalize(tmpBoxVecB, momentsAxes.dirB) - const normVecC = Vec3.normalize(tmpBoxVecC, momentsAxes.dirC) + const center = momentsAxes.origin; + const normVecA = Vec3.normalize(tmpBoxVecA, momentsAxes.dirA); + const normVecB = Vec3.normalize(tmpBoxVecB, momentsAxes.dirB); + const normVecC = Vec3.normalize(tmpBoxVecC, momentsAxes.dirC); for (let i = 0, il = positions.length; i < il; i += 3) { - Vec3.projectPointOnVector(p, Vec3.fromArray(p, positions, i), normVecA, center) - const dp1 = Vec3.dot(normVecA, Vec3.normalize(t, Vec3.sub(t, p, center))) - const dt1 = Vec3.distance(p, center) + Vec3.projectPointOnVector(p, Vec3.fromArray(p, positions, i), normVecA, center); + const dp1 = Vec3.dot(normVecA, Vec3.normalize(t, Vec3.sub(t, p, center))); + const dt1 = Vec3.distance(p, center); if (dp1 > 0) { - if (dt1 > d1a) d1a = dt1 + if (dt1 > d1a) d1a = dt1; } else { - if (dt1 > d1b) d1b = dt1 + if (dt1 > d1b) d1b = dt1; } - Vec3.projectPointOnVector(p, Vec3.fromArray(p, positions, i), normVecB, center) - const dp2 = Vec3.dot(normVecB, Vec3.normalize(t, Vec3.sub(t, p, center))) - const dt2 = Vec3.distance(p, center) + Vec3.projectPointOnVector(p, Vec3.fromArray(p, positions, i), normVecB, center); + const dp2 = Vec3.dot(normVecB, Vec3.normalize(t, Vec3.sub(t, p, center))); + const dt2 = Vec3.distance(p, center); if (dp2 > 0) { - if (dt2 > d2a) d2a = dt2 + if (dt2 > d2a) d2a = dt2; } else { - if (dt2 > d2b) d2b = dt2 + if (dt2 > d2b) d2b = dt2; } - Vec3.projectPointOnVector(p, Vec3.fromArray(p, positions, i), normVecC, center) - const dp3 = Vec3.dot(normVecC, Vec3.normalize(t, Vec3.sub(t, p, center))) - const dt3 = Vec3.distance(p, center) + Vec3.projectPointOnVector(p, Vec3.fromArray(p, positions, i), normVecC, center); + const dp3 = Vec3.dot(normVecC, Vec3.normalize(t, Vec3.sub(t, p, center))); + const dt3 = Vec3.distance(p, center); if (dp3 > 0) { - if (dt3 > d3a) d3a = dt3 + if (dt3 > d3a) d3a = dt3; } else { - if (dt3 > d3b) d3b = dt3 + if (dt3 > d3b) d3b = dt3; } } - const dirA = Vec3.setMagnitude(Vec3(), normVecA, (d1a + d1b) / 2) - const dirB = Vec3.setMagnitude(Vec3(), normVecB, (d2a + d2b) / 2) - const dirC = Vec3.setMagnitude(Vec3(), normVecC, (d3a + d3b) / 2) + const dirA = Vec3.setMagnitude(Vec3(), normVecA, (d1a + d1b) / 2); + const dirB = Vec3.setMagnitude(Vec3(), normVecB, (d2a + d2b) / 2); + const dirC = Vec3.setMagnitude(Vec3(), normVecC, (d3a + d3b) / 2); - const origin = Vec3() + const origin = Vec3(); const addCornerHelper = function (d1: number, d2: number, d3: number) { - Vec3.copy(tmpBoxVec, center) - Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, normVecA, d1) - Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, normVecB, d2) - Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, normVecC, d3) - Vec3.add(origin, origin, tmpBoxVec) - } - addCornerHelper(d1a, d2a, d3a) - addCornerHelper(d1a, d2a, -d3b) - addCornerHelper(d1a, -d2b, -d3b) - addCornerHelper(d1a, -d2b, d3a) - addCornerHelper(-d1b, -d2b, -d3b) - addCornerHelper(-d1b, -d2b, d3a) - addCornerHelper(-d1b, d2a, d3a) - addCornerHelper(-d1b, d2a, -d3b) - Vec3.scale(origin, origin, 1 / 8) - - return Axes3D.create(origin, dirA, dirB, dirC) + Vec3.copy(tmpBoxVec, center); + Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, normVecA, d1); + Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, normVecB, d2); + Vec3.scaleAndAdd(tmpBoxVec, tmpBoxVec, normVecC, d3); + Vec3.add(origin, origin, tmpBoxVec); + }; + addCornerHelper(d1a, d2a, d3a); + addCornerHelper(d1a, d2a, -d3b); + addCornerHelper(d1a, -d2b, -d3b); + addCornerHelper(d1a, -d2b, d3a); + addCornerHelper(-d1b, -d2b, -d3b); + addCornerHelper(-d1b, -d2b, d3a); + addCornerHelper(-d1b, d2a, d3a); + addCornerHelper(-d1b, d2a, -d3b); + Vec3.scale(origin, origin, 1 / 8); + + return Axes3D.create(origin, dirA, dirB, dirC); } } \ No newline at end of file diff --git a/src/mol-math/linear-algebra/matrix/svd.ts b/src/mol-math/linear-algebra/matrix/svd.ts index a735eefeeaaf7408bb1663f69990355f159490c1..fe58158de5aaba2c4fd54d5e846dc94b4a54ca1a 100644 --- a/src/mol-math/linear-algebra/matrix/svd.ts +++ b/src/mol-math/linear-algebra/matrix/svd.ts @@ -10,284 +10,284 @@ import { NumberArray } from '../../../mol-util/type-helpers'; // svd method adapted from http://inspirit.github.io/jsfeat/ MIT Eugene Zatepyakin export function swap(A: NumberArray, i0: number, i1: number, t: number) { - t = A[i0] - A[i0] = A[i1] - A[i1] = t + t = A[i0]; + A[i0] = A[i1]; + A[i1] = t; } export function hypot(a: number, b: number) { - a = Math.abs(a) - b = Math.abs(b) + a = Math.abs(a); + b = Math.abs(b); if (a > b) { - b /= a - return a * Math.sqrt(1.0 + b * b) + b /= a; + return a * Math.sqrt(1.0 + b * b); } if (b > 0) { - a /= b - return b * Math.sqrt(1.0 + a * a) + a /= b; + return b * Math.sqrt(1.0 + a * a); } - return 0.0 + return 0.0; } -const EPSILON = 0.0000001192092896 -const FLT_MIN = 1E-37 +const EPSILON = 0.0000001192092896; +const FLT_MIN = 1E-37; export function JacobiSVDImpl(At: NumberArray, astep: number, _W: NumberArray, Vt: NumberArray, vstep: number, m: number, n: number, n1: number) { - const eps = EPSILON * 2.0 - const minval = FLT_MIN - let i = 0 - let j = 0 - let k = 0 - let iter = 0 - const maxIter = Math.max(m, 30) - let Ai = 0 - let Aj = 0 - let Vi = 0 - let Vj = 0 - let changed = 0 - let c = 0.0 - let s = 0.0 - let t = 0.0 - let t0 = 0.0 - let t1 = 0.0 - let sd = 0.0 - let beta = 0.0 - let gamma = 0.0 - let delta = 0.0 - let a = 0.0 - let p = 0.0 - let b = 0.0 - let seed = 0x1234 - let val = 0.0 - let val0 = 0.0 - let asum = 0.0 - - const W = new Float64Array(n << 3) + const eps = EPSILON * 2.0; + const minval = FLT_MIN; + let i = 0; + let j = 0; + let k = 0; + let iter = 0; + const maxIter = Math.max(m, 30); + let Ai = 0; + let Aj = 0; + let Vi = 0; + let Vj = 0; + let changed = 0; + let c = 0.0; + let s = 0.0; + let t = 0.0; + let t0 = 0.0; + let t1 = 0.0; + let sd = 0.0; + let beta = 0.0; + let gamma = 0.0; + let delta = 0.0; + let a = 0.0; + let p = 0.0; + let b = 0.0; + let seed = 0x1234; + let val = 0.0; + let val0 = 0.0; + let asum = 0.0; + + const W = new Float64Array(n << 3); for (; i < n; i++) { for (k = 0, sd = 0; k < m; k++) { - t = At[i * astep + k] - sd += t * t + t = At[i * astep + k]; + sd += t * t; } - W[i] = sd + W[i] = sd; if (Vt) { for (k = 0; k < n; k++) { - Vt[i * vstep + k] = 0 + Vt[i * vstep + k] = 0; } - Vt[i * vstep + i] = 1 + Vt[i * vstep + i] = 1; } } for (; iter < maxIter; iter++) { - changed = 0 + changed = 0; for (i = 0; i < n - 1; i++) { for (j = i + 1; j < n; j++) { - Ai = (i * astep) | 0 - Aj = (j * astep) | 0 - a = W[i] - p = 0 - b = W[j] + Ai = (i * astep) | 0; + Aj = (j * astep) | 0; + a = W[i]; + p = 0; + b = W[j]; - k = 2 - p += At[Ai] * At[Aj] - p += At[Ai + 1] * At[Aj + 1] + k = 2; + p += At[Ai] * At[Aj]; + p += At[Ai + 1] * At[Aj + 1]; - for (; k < m; k++) { p += At[Ai + k] * At[Aj + k] } + for (; k < m; k++) { p += At[Ai + k] * At[Aj + k]; } - if (Math.abs(p) <= eps * Math.sqrt(a * b)) continue + if (Math.abs(p) <= eps * Math.sqrt(a * b)) continue; - p *= 2.0 - beta = a - b - gamma = hypot(p, beta) + p *= 2.0; + beta = a - b; + gamma = hypot(p, beta); if (beta < 0) { - delta = (gamma - beta) * 0.5 - s = Math.sqrt(delta / gamma) - c = (p / (gamma * s * 2.0)) + delta = (gamma - beta) * 0.5; + s = Math.sqrt(delta / gamma); + c = (p / (gamma * s * 2.0)); } else { - c = Math.sqrt((gamma + beta) / (gamma * 2.0)) - s = (p / (gamma * c * 2.0)) + c = Math.sqrt((gamma + beta) / (gamma * 2.0)); + s = (p / (gamma * c * 2.0)); } - a = 0.0 - b = 0.0 + a = 0.0; + b = 0.0; - k = 2 // unroll - t0 = c * At[Ai] + s * At[Aj] - t1 = -s * At[Ai] + c * At[Aj] - At[Ai] = t0; At[Aj] = t1 - a += t0 * t0; b += t1 * t1 + k = 2; // unroll + t0 = c * At[Ai] + s * At[Aj]; + t1 = -s * At[Ai] + c * At[Aj]; + At[Ai] = t0; At[Aj] = t1; + a += t0 * t0; b += t1 * t1; - t0 = c * At[Ai + 1] + s * At[Aj + 1] - t1 = -s * At[Ai + 1] + c * At[Aj + 1] - At[Ai + 1] = t0; At[Aj + 1] = t1 - a += t0 * t0; b += t1 * t1 + t0 = c * At[Ai + 1] + s * At[Aj + 1]; + t1 = -s * At[Ai + 1] + c * At[Aj + 1]; + At[Ai + 1] = t0; At[Aj + 1] = t1; + a += t0 * t0; b += t1 * t1; for (; k < m; k++) { - t0 = c * At[Ai + k] + s * At[Aj + k] - t1 = -s * At[Ai + k] + c * At[Aj + k] - At[Ai + k] = t0; At[Aj + k] = t1 + t0 = c * At[Ai + k] + s * At[Aj + k]; + t1 = -s * At[Ai + k] + c * At[Aj + k]; + At[Ai + k] = t0; At[Aj + k] = t1; - a += t0 * t0; b += t1 * t1 + a += t0 * t0; b += t1 * t1; } - W[i] = a - W[j] = b + W[i] = a; + W[j] = b; - changed = 1 + changed = 1; if (Vt) { - Vi = (i * vstep) | 0 - Vj = (j * vstep) | 0 + Vi = (i * vstep) | 0; + Vj = (j * vstep) | 0; - k = 2 - t0 = c * Vt[Vi] + s * Vt[Vj] - t1 = -s * Vt[Vi] + c * Vt[Vj] - Vt[Vi] = t0; Vt[Vj] = t1 + k = 2; + t0 = c * Vt[Vi] + s * Vt[Vj]; + t1 = -s * Vt[Vi] + c * Vt[Vj]; + Vt[Vi] = t0; Vt[Vj] = t1; - t0 = c * Vt[Vi + 1] + s * Vt[Vj + 1] - t1 = -s * Vt[Vi + 1] + c * Vt[Vj + 1] - Vt[Vi + 1] = t0; Vt[Vj + 1] = t1 + t0 = c * Vt[Vi + 1] + s * Vt[Vj + 1]; + t1 = -s * Vt[Vi + 1] + c * Vt[Vj + 1]; + Vt[Vi + 1] = t0; Vt[Vj + 1] = t1; for (; k < n; k++) { - t0 = c * Vt[Vi + k] + s * Vt[Vj + k] - t1 = -s * Vt[Vi + k] + c * Vt[Vj + k] - Vt[Vi + k] = t0; Vt[Vj + k] = t1 + t0 = c * Vt[Vi + k] + s * Vt[Vj + k]; + t1 = -s * Vt[Vi + k] + c * Vt[Vj + k]; + Vt[Vi + k] = t0; Vt[Vj + k] = t1; } } } } - if (changed === 0) break + if (changed === 0) break; } for (i = 0; i < n; i++) { for (k = 0, sd = 0; k < m; k++) { - t = At[i * astep + k] - sd += t * t + t = At[i * astep + k]; + sd += t * t; } - W[i] = Math.sqrt(sd) + W[i] = Math.sqrt(sd); } for (i = 0; i < n - 1; i++) { - j = i + j = i; for (k = i + 1; k < n; k++) { - if (W[j] < W[k]) { j = k } + if (W[j] < W[k]) { j = k; } } if (i !== j) { - swap(W, i, j, sd) + swap(W, i, j, sd); if (Vt) { for (k = 0; k < m; k++) { - swap(At, i * astep + k, j * astep + k, t) + swap(At, i * astep + k, j * astep + k, t); } for (k = 0; k < n; k++) { - swap(Vt, i * vstep + k, j * vstep + k, t) + swap(Vt, i * vstep + k, j * vstep + k, t); } } } } for (i = 0; i < n; i++) { - _W[i] = W[i] + _W[i] = W[i]; } if (!Vt) { - return + return; } for (i = 0; i < n1; i++) { - sd = i < n ? W[i] : 0 + sd = i < n ? W[i] : 0; while (sd <= minval) { // if we got a zero singular value, then in order to get the corresponding left singular vector // we generate a random vector, project it to the previously computed left singular vectors, // subtract the projection and normalize the difference. - val0 = (1.0 / m) + val0 = (1.0 / m); for (k = 0; k < m; k++) { - seed = (seed * 214013 + 2531011) - val = (((seed >> 16) & 0x7fff) & 256) !== 0 ? val0 : -val0 - At[i * astep + k] = val + seed = (seed * 214013 + 2531011); + val = (((seed >> 16) & 0x7fff) & 256) !== 0 ? val0 : -val0; + At[i * astep + k] = val; } for (iter = 0; iter < 2; iter++) { for (j = 0; j < i; j++) { - sd = 0 + sd = 0; for (k = 0; k < m; k++) { - sd += At[i * astep + k] * At[j * astep + k] + sd += At[i * astep + k] * At[j * astep + k]; } - asum = 0.0 + asum = 0.0; for (k = 0; k < m; k++) { - t = (At[i * astep + k] - sd * At[j * astep + k]) - At[i * astep + k] = t - asum += Math.abs(t) + t = (At[i * astep + k] - sd * At[j * astep + k]); + At[i * astep + k] = t; + asum += Math.abs(t); } - asum = asum ? 1.0 / asum : 0 + asum = asum ? 1.0 / asum : 0; for (k = 0; k < m; k++) { - At[i * astep + k] *= asum + At[i * astep + k] *= asum; } } } - sd = 0 + sd = 0; for (k = 0; k < m; k++) { - t = At[i * astep + k] - sd += t * t + t = At[i * astep + k]; + sd += t * t; } - sd = Math.sqrt(sd) + sd = Math.sqrt(sd); } - s = (1.0 / sd) + s = (1.0 / sd); for (k = 0; k < m; k++) { - At[i * astep + k] *= s + At[i * astep + k] *= s; } } } export function svd(A: Matrix, W: Matrix, U: Matrix, V: Matrix) { - let at = 0 - let i = 0 - const _m = A.rows - const _n = A.cols - let m = _m - let n = _n + let at = 0; + let i = 0; + const _m = A.rows; + const _n = A.cols; + let m = _m; + let n = _n; if (m < n) { - at = 1 - i = m - m = n - n = i + at = 1; + i = m; + m = n; + n = i; } - const amt = Matrix.create(m, m) - const wmt = Matrix.create(1, n) - const vmt = Matrix.create(n, n) + const amt = Matrix.create(m, m); + const wmt = Matrix.create(1, n); + const vmt = Matrix.create(n, n); if (at === 0) { - Matrix.transpose(amt, A) + Matrix.transpose(amt, A); } else { for (i = 0; i < _n * _m; i++) { - amt.data[i] = A.data[i] + amt.data[i] = A.data[i]; } for (; i < n * m; i++) { - amt.data[i] = 0 + amt.data[i] = 0; } } - JacobiSVDImpl(amt.data, m, wmt.data, vmt.data, n, m, n, m) + JacobiSVDImpl(amt.data, m, wmt.data, vmt.data, n, m, n, m); if (W) { for (i = 0; i < n; i++) { - W.data[i] = wmt.data[i] + W.data[i] = wmt.data[i]; } for (; i < _n; i++) { - W.data[i] = 0 + W.data[i] = 0; } } if (at === 0) { - if (U) Matrix.transpose(U, amt) - if (V) Matrix.transpose(V, vmt) + if (U) Matrix.transpose(U, amt); + if (V) Matrix.transpose(V, vmt); } else { - if (U) Matrix.transpose(U, vmt) - if (V) Matrix.transpose(V, amt) + if (U) Matrix.transpose(U, vmt); + if (V) Matrix.transpose(V, amt); } } \ No newline at end of file diff --git a/src/mol-math/linear-algebra/tensor.ts b/src/mol-math/linear-algebra/tensor.ts index 68a17214169ea387b449f1c7f69cc1c3820bb9f6..c85cfacded23295956cb3fd4d8a4e1d977d6437c 100644 --- a/src/mol-math/linear-algebra/tensor.ts +++ b/src/mol-math/linear-algebra/tensor.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Mat4, Vec3, Vec4, Mat3 } from './3d' +import { Mat4, Vec3, Vec4, Mat3 } from './3d'; export interface Tensor { data: Tensor.Data, space: Tensor.Space } @@ -39,7 +39,7 @@ export namespace Tensor { const accessDimensions = [1]; for (let i = 1; i < dimensions.length; i++) accessDimensions[i] = dimensions[axisOrderFastToSlow[i - 1]]; - return { dimensions, axisOrderFastToSlow, axisOrderSlowToFast, accessDimensions, defaultCtor: ctor || Float64Array } + return { dimensions, axisOrderFastToSlow, axisOrderSlowToFast, accessDimensions, defaultCtor: ctor || Float64Array }; } export function create(space: Space, data: Data): Tensor { return { space, data }; } @@ -121,7 +121,7 @@ export namespace Tensor { add: (t, i, j, x) => t[i * cols + j] += x }; } - throw new Error('bad axis order') + throw new Error('bad axis order'); } case 3: { if (ao[0] === 0 && ao[1] === 1 && ao[2] === 2) { // 012 ijk @@ -172,7 +172,7 @@ export namespace Tensor { add: (t, i, j, k, x ) => t[k + j * u + i * uv] += x }; } - throw new Error('bad axis order') + throw new Error('bad axis order'); } default: return { get: (t, ...c) => t[dataOffset(layout, c)], diff --git a/src/mol-math/misc.ts b/src/mol-math/misc.ts index 316829ccb0607c0e62f69d76bee17c9eebaeadf9..be4bffd07caab73b18d09bccf8644e5424310032 100644 --- a/src/mol-math/misc.ts +++ b/src/mol-math/misc.ts @@ -4,36 +4,36 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export const halfPI = Math.PI / 2 +export const halfPI = Math.PI / 2; export function degToRad (deg: number) { - return deg * 0.01745 // deg * Math.PI / 180 + return deg * 0.01745; // deg * Math.PI / 180 } export function radToDeg (rad: number) { - return rad * 57.29578 // rad * 180 / Math.PI + return rad * 57.29578; // rad * 180 / Math.PI } export function isPowerOfTwo (x: number) { - return (x !== 0) && (x & (x - 1)) === 0 + return (x !== 0) && (x & (x - 1)) === 0; } /** return the value that has the largest absolute value */ export function absMax(...values: number[]) { - let max = 0 - let absMax = 0 + let max = 0; + let absMax = 0; for (let i = 0, il = values.length; i < il; ++i) { - const value = values[i] - const abs = Math.abs(value) + const value = values[i]; + const abs = Math.abs(value); if (abs > absMax) { - max = value - absMax = abs + max = value; + absMax = abs; } } - return max + return max; } /** Length of an arc with angle in radians */ export function arcLength(angle: number, radius: number) { - return angle * radius + return angle * radius; } \ No newline at end of file diff --git a/src/mol-model-formats/shape/ply.ts b/src/mol-model-formats/shape/ply.ts index 5da7df227bbb30f7b8275f37377ac7533c9d21c2..e7e2b5f4ceb43a88fcc7ef4a09f94f7df047fffd 100644 --- a/src/mol-model-formats/shape/ply.ts +++ b/src/mol-model-formats/shape/ply.ts @@ -24,49 +24,49 @@ import { stringToWords } from '../../mol-util/string'; // TODO support missing face element function createPlyShapeParams(plyFile?: PlyFile) { - const vertex = plyFile && plyFile.getElement('vertex') as PlyTable - const material = plyFile && plyFile.getElement('material') as PlyTable + const vertex = plyFile && plyFile.getElement('vertex') as PlyTable; + const material = plyFile && plyFile.getElement('material') as PlyTable; - const defaultValues = { group: '', vRed: '', vGreen: '', vBlue: '', mRed: '', mGreen: '', mBlue: '' } + const defaultValues = { group: '', vRed: '', vGreen: '', vBlue: '', mRed: '', mGreen: '', mBlue: '' }; - const groupOptions: [string, string][] = [['', '']] - const colorOptions: [string, string][] = [['', '']] + const groupOptions: [string, string][] = [['', '']]; + const colorOptions: [string, string][] = [['', '']]; if (vertex) { for (let i = 0, il = vertex.propertyNames.length; i < il; ++i) { - const name = vertex.propertyNames[i] - const type = vertex.propertyTypes[i] + const name = vertex.propertyNames[i]; + const type = vertex.propertyTypes[i]; if ( type === 'uchar' || type === 'uint8' || type === 'ushort' || type === 'uint16' || type === 'uint' || type === 'uint32' - ) groupOptions.push([ name, name ]) - if (type === 'uchar' || type === 'uint8') colorOptions.push([ name, name ]) + ) groupOptions.push([ name, name ]); + if (type === 'uchar' || type === 'uint8') colorOptions.push([ name, name ]); } // TODO hardcoded as convenience for data provided by MegaMol - if (vertex.propertyNames.includes('atomid')) defaultValues.group = 'atomid' - else if (vertex.propertyNames.includes('material_index')) defaultValues.group = 'material_index' + if (vertex.propertyNames.includes('atomid')) defaultValues.group = 'atomid'; + else if (vertex.propertyNames.includes('material_index')) defaultValues.group = 'material_index'; - if (vertex.propertyNames.includes('red')) defaultValues.vRed = 'red' - if (vertex.propertyNames.includes('green')) defaultValues.vGreen = 'green' - if (vertex.propertyNames.includes('blue')) defaultValues.vBlue = 'blue' + if (vertex.propertyNames.includes('red')) defaultValues.vRed = 'red'; + if (vertex.propertyNames.includes('green')) defaultValues.vGreen = 'green'; + if (vertex.propertyNames.includes('blue')) defaultValues.vBlue = 'blue'; } - const materialOptions: [string, string][] = [['', '']] + const materialOptions: [string, string][] = [['', '']]; if (material) { for (let i = 0, il = material.propertyNames.length; i < il; ++i) { - const name = material.propertyNames[i] - const type = material.propertyTypes[i] - if (type === 'uchar' || type === 'uint8') materialOptions.push([ name, name ]) + const name = material.propertyNames[i]; + const type = material.propertyTypes[i]; + if (type === 'uchar' || type === 'uint8') materialOptions.push([ name, name ]); } - if (material.propertyNames.includes('red')) defaultValues.mRed = 'red' - if (material.propertyNames.includes('green')) defaultValues.mGreen = 'green' - if (material.propertyNames.includes('blue')) defaultValues.mBlue = 'blue' + if (material.propertyNames.includes('red')) defaultValues.mRed = 'red'; + if (material.propertyNames.includes('green')) defaultValues.mGreen = 'green'; + if (material.propertyNames.includes('blue')) defaultValues.mBlue = 'blue'; } const defaultColoring = defaultValues.vRed && defaultValues.vGreen && defaultValues.vBlue ? 'vertex' : - defaultValues.mRed && defaultValues.mGreen && defaultValues.mBlue ? 'material' : 'uniform' + defaultValues.mRed && defaultValues.mGreen && defaultValues.mBlue ? 'material' : 'uniform'; return { ...Mesh.Params, @@ -92,191 +92,191 @@ function createPlyShapeParams(plyFile?: PlyFile) { }, { isFlat: true }), none: PD.Group({ }) }), - } + }; } -export const PlyShapeParams = createPlyShapeParams() +export const PlyShapeParams = createPlyShapeParams(); export type PlyShapeParams = typeof PlyShapeParams function addVerticesRange(begI: number, endI: number, state: MeshBuilder.State, vertex: PlyTable, groupIds: ArrayLike<number>) { - const { vertices, normals, groups } = state + const { vertices, normals, groups } = state; - const x = vertex.getProperty('x') - const y = vertex.getProperty('y') - const z = vertex.getProperty('z') - if (!x || !y || !z) throw new Error('missing coordinate properties') + const x = vertex.getProperty('x'); + const y = vertex.getProperty('y'); + const z = vertex.getProperty('z'); + if (!x || !y || !z) throw new Error('missing coordinate properties'); - const nx = vertex.getProperty('nx') - const ny = vertex.getProperty('ny') - const nz = vertex.getProperty('nz') + const nx = vertex.getProperty('nx'); + const ny = vertex.getProperty('ny'); + const nz = vertex.getProperty('nz'); - const hasNormals = !!nx && !!ny && !!nz + const hasNormals = !!nx && !!ny && !!nz; for (let i = begI; i < endI; ++i) { - ChunkedArray.add3(vertices, x.value(i), y.value(i), z.value(i)) + ChunkedArray.add3(vertices, x.value(i), y.value(i), z.value(i)); if (hasNormals) ChunkedArray.add3(normals, nx!.value(i), ny!.value(i), nz!.value(i)); - ChunkedArray.add(groups, groupIds[i]) + ChunkedArray.add(groups, groupIds[i]); } } function addFacesRange(begI: number, endI: number, state: MeshBuilder.State, face: PlyList) { - const { indices } = state + const { indices } = state; for (let i = begI; i < endI; ++i) { - const { entries, count } = face.value(i) + const { entries, count } = face.value(i); if (count === 3) { // triangle - ChunkedArray.add3(indices, entries[0], entries[1], entries[2]) + ChunkedArray.add3(indices, entries[0], entries[1], entries[2]); } else if (count === 4) { // quadrilateral - ChunkedArray.add3(indices, entries[2], entries[1], entries[0]) - ChunkedArray.add3(indices, entries[2], entries[0], entries[3]) + ChunkedArray.add3(indices, entries[2], entries[1], entries[0]); + ChunkedArray.add3(indices, entries[2], entries[0], entries[3]); } } } async function getMesh(ctx: RuntimeContext, vertex: PlyTable, face: PlyList, groupIds: ArrayLike<number>, mesh?: Mesh) { - const builderState = MeshBuilder.createState(vertex.rowCount, vertex.rowCount / 4, mesh) + const builderState = MeshBuilder.createState(vertex.rowCount, vertex.rowCount / 4, mesh); - const x = vertex.getProperty('x') - const y = vertex.getProperty('y') - const z = vertex.getProperty('z') - if (!x || !y || !z) throw new Error('missing coordinate properties') + const x = vertex.getProperty('x'); + const y = vertex.getProperty('y'); + const z = vertex.getProperty('z'); + if (!x || !y || !z) throw new Error('missing coordinate properties'); - const nx = vertex.getProperty('nx') - const ny = vertex.getProperty('ny') - const nz = vertex.getProperty('nz') + const nx = vertex.getProperty('nx'); + const ny = vertex.getProperty('ny'); + const nz = vertex.getProperty('nz'); - const hasNormals = !!nx && !!ny && !!nz - const updateChunk = 100000 + const hasNormals = !!nx && !!ny && !!nz; + const updateChunk = 100000; for (let i = 0, il = vertex.rowCount; i < il; i += updateChunk) { - addVerticesRange(i, Math.min(i + updateChunk, il), builderState, vertex, groupIds) + addVerticesRange(i, Math.min(i + updateChunk, il), builderState, vertex, groupIds); if (ctx.shouldUpdate) { - await ctx.update({ message: 'adding ply mesh vertices', current: i, max: il }) + await ctx.update({ message: 'adding ply mesh vertices', current: i, max: il }); } } for (let i = 0, il = face.rowCount; i < il; i += updateChunk) { - addFacesRange(i, Math.min(i + updateChunk, il), builderState, face) + addFacesRange(i, Math.min(i + updateChunk, il), builderState, face); if (ctx.shouldUpdate) { - await ctx.update({ message: 'adding ply mesh faces', current: i, max: il }) + await ctx.update({ message: 'adding ply mesh faces', current: i, max: il }); } } const m = MeshBuilder.getMesh(builderState); - if (!hasNormals) Mesh.computeNormals(m) + if (!hasNormals) Mesh.computeNormals(m); - return m + return m; } -const int = Column.Schema.int +const int = Column.Schema.int; type Grouping = { ids: ArrayLike<number>, map: ArrayLike<number>, label: string } function getGrouping(vertex: PlyTable, props: PD.Values<PlyShapeParams>): Grouping { - const { grouping } = props - const { rowCount } = vertex - const column = grouping.name === 'vertex' ? vertex.getProperty(grouping.params.group) : undefined - const label = grouping.name === 'vertex' ? stringToWords(grouping.params.group) : 'Vertex' - - const ids = column ? column.toArray({ array: Uint32Array }) : fillSerial(new Uint32Array(rowCount)) - const maxId = column ? arrayMax(ids) : rowCount - 1 // assumes uint ids - const map = new Uint32Array(maxId + 1) - for (let i = 0, il = ids.length; i < il; ++i) map[ids[i]] = i - return { ids, map, label } + const { grouping } = props; + const { rowCount } = vertex; + const column = grouping.name === 'vertex' ? vertex.getProperty(grouping.params.group) : undefined; + const label = grouping.name === 'vertex' ? stringToWords(grouping.params.group) : 'Vertex'; + + const ids = column ? column.toArray({ array: Uint32Array }) : fillSerial(new Uint32Array(rowCount)); + const maxId = column ? arrayMax(ids) : rowCount - 1; // assumes uint ids + const map = new Uint32Array(maxId + 1); + for (let i = 0, il = ids.length; i < il; ++i) map[ids[i]] = i; + return { ids, map, label }; } type Coloring = { kind: 'vertex' | 'material' | 'uniform', red: Column<number>, green: Column<number>, blue: Column<number> } function getColoring(vertex: PlyTable, material: PlyTable | undefined, props: PD.Values<PlyShapeParams>): Coloring { - const { coloring } = props - const { rowCount } = vertex + const { coloring } = props; + const { rowCount } = vertex; - let red: Column<number>, green: Column<number>, blue: Column<number> + let red: Column<number>, green: Column<number>, blue: Column<number>; if (coloring.name === 'vertex') { - red = vertex.getProperty(coloring.params.red) || Column.ofConst(127, rowCount, int) - green = vertex.getProperty(coloring.params.green) || Column.ofConst(127, rowCount, int) - blue = vertex.getProperty(coloring.params.blue) || Column.ofConst(127, rowCount, int) + red = vertex.getProperty(coloring.params.red) || Column.ofConst(127, rowCount, int); + green = vertex.getProperty(coloring.params.green) || Column.ofConst(127, rowCount, int); + blue = vertex.getProperty(coloring.params.blue) || Column.ofConst(127, rowCount, int); } else if (coloring.name === 'material') { - red = (material && material.getProperty(coloring.params.red)) || Column.ofConst(127, rowCount, int) - green = (material && material.getProperty(coloring.params.green)) || Column.ofConst(127, rowCount, int) - blue = (material && material.getProperty(coloring.params.blue)) || Column.ofConst(127, rowCount, int) + red = (material && material.getProperty(coloring.params.red)) || Column.ofConst(127, rowCount, int); + green = (material && material.getProperty(coloring.params.green)) || Column.ofConst(127, rowCount, int); + blue = (material && material.getProperty(coloring.params.blue)) || Column.ofConst(127, rowCount, int); } else { - const [r, g, b] = Color.toRgb(coloring.params.color) - red = Column.ofConst(r, rowCount, int) - green = Column.ofConst(g, rowCount, int) - blue = Column.ofConst(b, rowCount, int) + const [r, g, b] = Color.toRgb(coloring.params.color); + red = Column.ofConst(r, rowCount, int); + green = Column.ofConst(g, rowCount, int); + blue = Column.ofConst(b, rowCount, int); } - return { kind: coloring.name, red, green, blue } + return { kind: coloring.name, red, green, blue }; } function createShape(plyFile: PlyFile, mesh: Mesh, coloring: Coloring, grouping: Grouping) { - const { kind, red, green, blue } = coloring - const { ids, map, label } = grouping + const { kind, red, green, blue } = coloring; + const { ids, map, label } = grouping; return Shape.create( 'ply-mesh', plyFile, mesh, (groupId: number) => { - const idx = kind === 'material' ? groupId : map[groupId] - return Color.fromRgb(red.value(idx), green.value(idx), blue.value(idx)) + const idx = kind === 'material' ? groupId : map[groupId]; + return Color.fromRgb(red.value(idx), green.value(idx), blue.value(idx)); }, () => 1, // size: constant (groupId: number) => { - return `${label} ${ids[groupId]}` + return `${label} ${ids[groupId]}`; } - ) + ); } function makeShapeGetter() { - let _plyFile: PlyFile | undefined - let _props: PD.Values<PlyShapeParams> | undefined + let _plyFile: PlyFile | undefined; + let _props: PD.Values<PlyShapeParams> | undefined; - let _shape: Shape<Mesh> - let _mesh: Mesh - let _coloring: Coloring - let _grouping: Grouping + let _shape: Shape<Mesh>; + let _mesh: Mesh; + let _coloring: Coloring; + let _grouping: Grouping; const getShape = async (ctx: RuntimeContext, plyFile: PlyFile, props: PD.Values<PlyShapeParams>, shape?: Shape<Mesh>) => { - const vertex = plyFile.getElement('vertex') as PlyTable - if (!vertex) throw new Error('missing vertex element') + const vertex = plyFile.getElement('vertex') as PlyTable; + if (!vertex) throw new Error('missing vertex element'); - const face = plyFile.getElement('face') as PlyList - if (!face) throw new Error('missing face element') + const face = plyFile.getElement('face') as PlyList; + if (!face) throw new Error('missing face element'); - const material = plyFile.getElement('material') as PlyTable + const material = plyFile.getElement('material') as PlyTable; - let newMesh = false - let newColor = false + let newMesh = false; + let newColor = false; if (!_plyFile || _plyFile !== plyFile) { - newMesh = true + newMesh = true; } if (!_props || !PD.isParamEqual(PlyShapeParams.grouping, _props.grouping, props.grouping)) { - newMesh = true + newMesh = true; } if (!_props || !PD.isParamEqual(PlyShapeParams.coloring, _props.coloring, props.coloring)) { - newColor = true + newColor = true; } if (newMesh) { - _coloring = getColoring(vertex, material, props) - _grouping = getGrouping(vertex, props) - _mesh = await getMesh(ctx, vertex, face, _grouping.ids, shape && shape.geometry) - _shape = createShape(plyFile, _mesh, _coloring, _grouping) + _coloring = getColoring(vertex, material, props); + _grouping = getGrouping(vertex, props); + _mesh = await getMesh(ctx, vertex, face, _grouping.ids, shape && shape.geometry); + _shape = createShape(plyFile, _mesh, _coloring, _grouping); } else if (newColor) { - _coloring = getColoring(vertex, material, props) - _shape = createShape(plyFile, _mesh, _coloring, _grouping) + _coloring = getColoring(vertex, material, props); + _shape = createShape(plyFile, _mesh, _coloring, _grouping); } - _plyFile = plyFile - _props = deepClone(props) + _plyFile = plyFile; + _props = deepClone(props); - return _shape - } - return getShape + return _shape; + }; + return getShape; } export function shapeFromPly(source: PlyFile, params?: {}) { @@ -287,6 +287,6 @@ export function shapeFromPly(source: PlyFile, params?: {}) { params: createPlyShapeParams(source), getShape: makeShapeGetter(), geometryUtils: Mesh.Utils - } - }) + }; + }); } \ No newline at end of file diff --git a/src/mol-model-formats/structure/3dg.ts b/src/mol-model-formats/structure/3dg.ts index 74d5eba815f6560164c043e521319fb44401f6f8..ca82890bfe29deaff4c872b43a00130fb961bde7 100644 --- a/src/mol-model-formats/structure/3dg.ts +++ b/src/mol-model-formats/structure/3dg.ts @@ -16,20 +16,20 @@ import { BasicSchema, createBasic } from './basic/schema'; import { createModels } from './basic/parser'; function getBasic(table: File3DG['table']) { - const entityIds = new Array<string>(table._rowCount) - const entityBuilder = new EntityBuilder() + const entityIds = new Array<string>(table._rowCount); + const entityBuilder = new EntityBuilder(); - const seqIdStarts = table.position.toArray({ array: Uint32Array }) - const seqIdEnds = new Uint32Array(table._rowCount) - const stride = seqIdStarts[1] - seqIdStarts[0] + const seqIdStarts = table.position.toArray({ array: Uint32Array }); + const seqIdEnds = new Uint32Array(table._rowCount); + const stride = seqIdStarts[1] - seqIdStarts[0]; - const objectRadius = stride / 3500 + const objectRadius = stride / 3500; for (let i = 0, il = table._rowCount; i < il; ++i) { - const chr = table.chromosome.value(i) - const entityId = entityBuilder.getEntityId(chr, MoleculeType.DNA, chr) - entityIds[i] = entityId - seqIdEnds[i] = seqIdStarts[i] + stride - 1 + const chr = table.chromosome.value(i); + const entityId = entityBuilder.getEntityId(chr, MoleculeType.DNA, chr); + entityIds[i] = entityId; + seqIdEnds[i] = seqIdStarts[i] + stride - 1; } const ihm_sphere_obj_site = Table.ofPartialColumns(BasicSchema.ihm_sphere_obj_site, { @@ -46,7 +46,7 @@ function getBasic(table: File3DG['table']) { object_radius: Column.ofConst(objectRadius, table._rowCount, Column.Schema.float), rmsf: Column.ofConst(0, table._rowCount, Column.Schema.float), model_id: Column.ofConst(1, table._rowCount, Column.Schema.int), - }, table._rowCount) + }, table._rowCount); return createBasic({ entity: entityBuilder.getEntityTable(), @@ -55,18 +55,18 @@ function getBasic(table: File3DG['table']) { model_name: Column.ofStringArray(['3DG Model']), }, 1), ihm_sphere_obj_site - }) + }); } // -export { Format3dg } +export { Format3dg }; type Format3dg = ModelFormat<File3DG> namespace Format3dg { export function is(x: ModelFormat): x is Format3dg { - return x.kind === '3dg' + return x.kind === '3dg'; } export function from3dg(file3dg: File3DG): Format3dg { @@ -77,7 +77,7 @@ namespace Format3dg { export function trajectoryFrom3DG(file3dg: File3DG): Task<Model.Trajectory> { return Task.create('Parse 3DG', async ctx => { const format = Format3dg.from3dg(file3dg); - const basic = getBasic(file3dg.table) + const basic = getBasic(file3dg.table); return createModels(basic, format, ctx); - }) + }); } diff --git a/src/mol-model-formats/structure/_spec/cif-core.spec.ts b/src/mol-model-formats/structure/_spec/cif-core.spec.ts index 51c4b868da264e145e2e8e6da09437c2141a2fd8..559faac6420df35a6dd1138fd941bf4df76be437 100644 --- a/src/mol-model-formats/structure/_spec/cif-core.spec.ts +++ b/src/mol-model-formats/structure/_spec/cif-core.spec.ts @@ -72,28 +72,28 @@ C7 0.041(4) 0.072(5) 0.055(5) 0.013(5) 0.006(4) -0.015(4) C1 0.061(5) 0.067(5) 0.043(5) -0.002(4) 0.017(4) -0.005(4) C3 0.038(4) 0.090(6) 0.054(5) 0.003(5) 0.013(4) -0.018(4) C6 0.045(4) 0.043(4) 0.038(4) 0.004(4) 0.008(3) -0.002(4) -` +`; describe('cif-core read', () => { it('frame', async () => { - const parsed = await CIF.parseText(cifCoreString).run() - if (parsed.isError) return - const cifFile = parsed.result - const block = cifFile.blocks[0] + const parsed = await CIF.parseText(cifCoreString).run(); + if (parsed.isError) return; + const cifFile = parsed.result; + const block = cifFile.blocks[0]; - expect(block.getField('cell_length_a')!.float(0)).toBe(11.0829) - expect.assertions(1) + expect(block.getField('cell_length_a')!.float(0)).toBe(11.0829); + expect.assertions(1); }); it('schema', async () => { - const parsed = await CIF.parseText(cifCoreString).run() - if (parsed.isError) return - const cifFile = parsed.result - const block = cifFile.blocks[0] - const cifCore = CIF.schema.cifCore(block) + const parsed = await CIF.parseText(cifCoreString).run(); + if (parsed.isError) return; + const cifFile = parsed.result; + const block = cifFile.blocks[0]; + const cifCore = CIF.schema.cifCore(block); - expect(cifCore.cell.length_a.value(0)).toBe(11.0829) - expect(cifCore.atom_site_aniso.U.value(0)).toEqual(new Float64Array([ 0.0425, 0, 0, 0.00089, 0.0423, 0, 0.01515, 0.00066, 0.0375 ])) - expect.assertions(2) + expect(cifCore.cell.length_a.value(0)).toBe(11.0829); + expect(cifCore.atom_site_aniso.U.value(0)).toEqual(new Float64Array([ 0.0425, 0, 0, 0.00089, 0.0423, 0, 0.01515, 0.00066, 0.0375 ])); + expect.assertions(2); }); }); \ No newline at end of file diff --git a/src/mol-model-formats/structure/_spec/pdb.spec.ts b/src/mol-model-formats/structure/_spec/pdb.spec.ts index 32c26556729e5960b40307023106ad5a108d5589..a106e038ca0b10cbbc568c63d24406238cfb4f17 100644 --- a/src/mol-model-formats/structure/_spec/pdb.spec.ts +++ b/src/mol-model-formats/structure/_spec/pdb.spec.ts @@ -12,15 +12,15 @@ const records = [ ['ATOM 38 CA SER A 3 146.430 138.150 162.270 0.00 0.00', 'C'], ['ATOM 38 NA SER A 3 146.430 138.150 162.270 0.00 0.00', 'NA'], ['ATOM 38 NAA SER A 3 146.430 138.150 162.270 0.00 0.00', 'N'], -] +]; describe('PDB to-cif', () => { it('guess-element-symbol', () => { for (let i = 0, il = records.length; i < il; ++i) { - const [ data, element ] = records[i] - const tokens = TokenBuilder.create(data, 2) - guessElementSymbolTokens(tokens, data, 12, 16) - expect(data.substring(tokens.indices[0], tokens.indices[1])).toBe(element) + const [ data, element ] = records[i]; + const tokens = TokenBuilder.create(data, 2); + guessElementSymbolTokens(tokens, data, 12, 16); + expect(data.substring(tokens.indices[0], tokens.indices[1])).toBe(element); } }); }); \ No newline at end of file diff --git a/src/mol-model-formats/structure/basic/atomic.ts b/src/mol-model-formats/structure/basic/atomic.ts index e6af80287732a026f9ae0a784bfdf342688df16b..d6dcc438d792f7b5b458995547f7f38147b3f10f 100644 --- a/src/mol-model-formats/structure/basic/atomic.ts +++ b/src/mol-model-formats/structure/basic/atomic.ts @@ -91,14 +91,14 @@ function getConformation(atom_site: AtomSite): AtomicConformation { x: atom_site.Cartn_x.toArray({ array: Float32Array }), y: atom_site.Cartn_y.toArray({ array: Float32Array }), z: atom_site.Cartn_z.toArray({ array: Float32Array }), - } + }; } function isHierarchyDataEqual(a: AtomicData, b: AtomicData) { // TODO need to cast because of how TS handles type resolution for interfaces https://github.com/Microsoft/TypeScript/issues/15300 return Table.areEqual(a.chains, b.chains) && Table.areEqual(a.residues, b.residues) - && Table.areEqual(a.atoms, b.atoms) + && Table.areEqual(a.atoms, b.atoms); } function createChainOperatorMappingAndSubstituteNames(hierarchy: AtomicData, format: ModelFormat) { @@ -171,7 +171,7 @@ function getAtomicHierarchy(atom_site: AtomSite, sourceIndex: Column<number>, en const hierarchySegments: AtomicSegments = { residueAtomSegments: Segmentation.ofOffsets(hierarchyOffsets.residues, Interval.ofBounds(0, atom_site._rowCount)), chainAtomSegments: Segmentation.ofOffsets(hierarchyOffsets.chains, Interval.ofBounds(0, atom_site._rowCount)), - } + }; const index = getAtomicIndex(hierarchyData, entities, hierarchySegments); const derived = getAtomicDerivedData(hierarchyData, index, chemicalComponentMap); @@ -180,7 +180,7 @@ function getAtomicHierarchy(atom_site: AtomSite, sourceIndex: Column<number>, en } export function getAtomicHierarchyAndConformation(atom_site: AtomSite, sourceIndex: Column<number>, entities: Entities, chemicalComponentMap: Model['properties']['chemicalComponentMap'], format: ModelFormat, previous?: Model) { - const { sameAsPrevious, hierarchy, chainOperatorMapping } = getAtomicHierarchy(atom_site, sourceIndex, entities, chemicalComponentMap, format, previous) - const conformation = getConformation(atom_site) + const { sameAsPrevious, hierarchy, chainOperatorMapping } = getAtomicHierarchy(atom_site, sourceIndex, entities, chemicalComponentMap, format, previous); + const conformation = getConformation(atom_site); return { sameAsPrevious, hierarchy, conformation, chainOperatorMapping }; } \ No newline at end of file diff --git a/src/mol-model-formats/structure/basic/coarse.ts b/src/mol-model-formats/structure/basic/coarse.ts index 7cb248ec5f9cdd75753331e3072363e4deb572f4..009fc36ba8ac1faba154d845f4c31c3b9a79d3ac 100644 --- a/src/mol-model-formats/structure/basic/coarse.ts +++ b/src/mol-model-formats/structure/basic/coarse.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { CoarseHierarchy, CoarseConformation, CoarseElementData, CoarseSphereConformation, CoarseGaussianConformation } from '../../../mol-model/structure/model/properties/coarse' +import { CoarseHierarchy, CoarseConformation, CoarseElementData, CoarseSphereConformation, CoarseGaussianConformation } from '../../../mol-model/structure/model/properties/coarse'; import { Entities } from '../../../mol-model/structure/model/properties/common'; import { Column } from '../../../mol-data/db'; import { getCoarseKeys } from '../../../mol-model/structure/model/properties/utils/coarse-keys'; @@ -28,7 +28,7 @@ export interface CoarseData { ihm_gaussian_obj_site: IhmGaussianObjSite } -export const EmptyCoarse = { hierarchy: CoarseHierarchy.Empty, conformation: void 0 as any } +export const EmptyCoarse = { hierarchy: CoarseHierarchy.Empty, conformation: void 0 as any }; export function getCoarse(data: CoarseData, properties: Model['properties']): { hierarchy: CoarseHierarchy, conformation: CoarseConformation } { const { ihm_sphere_obj_site, ihm_gaussian_obj_site } = data; @@ -96,7 +96,7 @@ function getSegments(asym_id: Column<string>, seq_id_begin: Column<number>, seq_ return { chainElementSegments: Segmentation.ofOffsets<ElementIndex, ChainIndex>(chainOffsets, Interval.ofBounds(0, asym_id.rowCount)) - } + }; } function getData(data: IhmSphereObjSite | IhmGaussianObjSite): CoarseElementData { diff --git a/src/mol-model-formats/structure/basic/entities.ts b/src/mol-model-formats/structure/basic/entities.ts index 77d1468297bc84d448c8f22e7ca112fe8cb5be7b..ea547d074bb97d10e7390c7ce7377d30979a97e7 100644 --- a/src/mol-model-formats/structure/basic/entities.ts +++ b/src/mol-model-formats/structure/basic/entities.ts @@ -12,21 +12,21 @@ import { ElementIndex, EntityIndex } from '../../../mol-model/structure/model'; import { BasicData, BasicSchema, Entity } from './schema'; export function getEntities(data: BasicData): Entities { - let entityData: Entity + let entityData: Entity; if (!data.entity.id.isDefined) { - const entityIds = new Set<string>() + const entityIds = new Set<string>(); - const ids: ReturnType<Entity['id']['value']>[] = [] - const types: ReturnType<Entity['type']['value']>[] = [] + const ids: ReturnType<Entity['id']['value']>[] = []; + const types: ReturnType<Entity['type']['value']>[] = []; const { label_entity_id, label_comp_id } = data.atom_site; for (let i = 0 as ElementIndex, il = data.atom_site._rowCount; i < il; i++) { const entityId = label_entity_id.value(i); if (!entityIds.has(entityId)) { - ids.push(entityId) - types.push(getEntityType(label_comp_id.value(i))) - entityIds.add(entityId) + ids.push(entityId); + types.push(getEntityType(label_comp_id.value(i))); + entityIds.add(entityId); } } @@ -34,9 +34,9 @@ export function getEntities(data: BasicData): Entities { for (let i = 0 as ElementIndex, il = data.ihm_sphere_obj_site._rowCount; i < il; i++) { const entityId = sphere_entity_id.value(i); if (!entityIds.has(entityId)) { - ids.push(entityId) - types.push('polymer') - entityIds.add(entityId) + ids.push(entityId); + types.push('polymer'); + entityIds.add(entityId); } } @@ -44,58 +44,58 @@ export function getEntities(data: BasicData): Entities { for (let i = 0 as ElementIndex, il = data.ihm_gaussian_obj_site._rowCount; i < il; i++) { const entityId = gaussian_entity_id.value(i); if (!entityIds.has(entityId)) { - ids.push(entityId) - types.push('polymer') - entityIds.add(entityId) + ids.push(entityId); + types.push('polymer'); + entityIds.add(entityId); } } entityData = Table.ofPartialColumns(BasicSchema.entity, { id: Column.ofArray({ array: ids, schema: BasicSchema.entity.id }), type: Column.ofArray({ array: types, schema: BasicSchema.entity.type }), - }, ids.length) + }, ids.length); } else { entityData = data.entity; } - const getEntityIndex = Column.createIndexer<string, EntityIndex>(entityData.id) + const getEntityIndex = Column.createIndexer<string, EntityIndex>(entityData.id); // - const subtypes: EntitySubtype[] = new Array(entityData._rowCount) - subtypes.fill('other') + const subtypes: EntitySubtype[] = new Array(entityData._rowCount); + subtypes.fill('other'); - const entityIds = new Set<string>() - let assignSubtype = false + const entityIds = new Set<string>(); + let assignSubtype = false; if (data.entity_poly && data.entity_poly.type.isDefined) { - const { entity_id, type, _rowCount } = data.entity_poly + const { entity_id, type, _rowCount } = data.entity_poly; for (let i = 0; i < _rowCount; ++i) { - const entityId = entity_id.value(i) - subtypes[getEntityIndex(entityId)] = type.value(i) - entityIds.add(entityId) + const entityId = entity_id.value(i); + subtypes[getEntityIndex(entityId)] = type.value(i); + entityIds.add(entityId); } } else { - assignSubtype = true + assignSubtype = true; } if (data.pdbx_entity_branch && data.pdbx_entity_branch.entity_id.isDefined) { - const { entity_id, type, _rowCount } = data.pdbx_entity_branch + const { entity_id, type, _rowCount } = data.pdbx_entity_branch; for (let i = 0; i < _rowCount; ++i) { - const entityId = entity_id.value(i) - subtypes[getEntityIndex(entityId)] = type.value(i) - entityIds.add(entityId) + const entityId = entity_id.value(i); + subtypes[getEntityIndex(entityId)] = type.value(i); + entityIds.add(entityId); } } else { - assignSubtype = true + assignSubtype = true; } if (assignSubtype) { - const chemCompType = new Map<string, string>() + const chemCompType = new Map<string, string>(); if (data.chem_comp) { const { id, type } = data.chem_comp; for (let i = 0, il = data.chem_comp._rowCount; i < il; i++) { - chemCompType.set(id.value(i), type.value(i)) + chemCompType.set(id.value(i), type.value(i)); } } @@ -104,17 +104,17 @@ export function getEntities(data: BasicData): Entities { for (let i = 0 as ElementIndex, il = data.atom_site._rowCount; i < il; i++) { const entityId = label_entity_id.value(i); if (!entityIds.has(entityId)) { - const compId = label_comp_id.value(i) - const compType = chemCompType.get(compId) || '' - subtypes[getEntityIndex(entityId)] = getEntitySubtype(compId, compType) - entityIds.add(entityId) + const compId = label_comp_id.value(i); + const compType = chemCompType.get(compId) || ''; + subtypes[getEntityIndex(entityId)] = getEntitySubtype(compId, compType); + entityIds.add(entityId); } } } // TODO how to handle coarse? } - const subtypeColumn = Column.ofArray({ array: subtypes, schema: EntitySubtype }) + const subtypeColumn = Column.ofArray({ array: subtypes, schema: EntitySubtype }); // diff --git a/src/mol-model-formats/structure/basic/parser.ts b/src/mol-model-formats/structure/basic/parser.ts index 02eccb020b71114479220fd63353b7aad7eb9b3c..10273c258b9b61a34e49c3de4298cd93af352589 100644 --- a/src/mol-model-formats/structure/basic/parser.ts +++ b/src/mol-model-formats/structure/basic/parser.ts @@ -23,7 +23,7 @@ import { getEntities } from './entities'; import { getModelGroupName } from './util'; export async function createModels(data: BasicData, format: ModelFormat, ctx: RuntimeContext) { - const properties = getProperties(data) + const properties = getProperties(data); const models = data.ihm_model_list._rowCount > 0 ? await readIntegrative(ctx, data, properties, format) : await readStandard(ctx, data, properties, format); @@ -40,7 +40,7 @@ export async function createModels(data: BasicData, format: ModelFormat, ctx: Ru function createStandardModel(data: BasicData, atom_site: AtomSite, sourceIndex: Column<number>, entities: Entities, properties: Model['properties'], format: ModelFormat, previous?: Model): Model { const atomic = getAtomicHierarchyAndConformation(atom_site, sourceIndex, entities, properties.chemicalComponentMap, format, previous); - const modelNum = atom_site.pdbx_PDB_model_num.value(0) + const modelNum = atom_site.pdbx_PDB_model_num.value(0); if (previous && atomic.sameAsPrevious) { return { ...previous, @@ -52,15 +52,15 @@ function createStandardModel(data: BasicData, atom_site: AtomSite, sourceIndex: } const coarse = EmptyCoarse; - const sequence = getSequence(data, entities, atomic.hierarchy, coarse.hierarchy) - const atomicRanges = getAtomicRanges(atomic.hierarchy, entities, atomic.conformation, sequence) + const sequence = getSequence(data, entities, atomic.hierarchy, coarse.hierarchy); + const atomicRanges = getAtomicRanges(atomic.hierarchy, entities, atomic.conformation, sequence); const entry = data.entry.id.valueKind(0) === Column.ValueKind.Present ? data.entry.id.value(0) : format.name; - const label: string[] = [] - if (entry) label.push(entry) - if (data.struct.title.valueKind(0) === Column.ValueKind.Present) label.push(data.struct.title.value(0)) + const label: string[] = []; + if (entry) label.push(entry); + if (data.struct.title.valueKind(0) === Column.ValueKind.Present) label.push(data.struct.title.value(0)); return { id: UUID.create22(), @@ -89,17 +89,17 @@ function createStandardModel(data: BasicData, atom_site: AtomSite, sourceIndex: function createIntegrativeModel(data: BasicData, ihm: CoarseData, properties: Model['properties'], format: ModelFormat): Model { const atomic = getAtomicHierarchyAndConformation(ihm.atom_site, ihm.atom_site_sourceIndex, ihm.entities, properties.chemicalComponentMap, format); const coarse = getCoarse(ihm, properties); - const sequence = getSequence(data, ihm.entities, atomic.hierarchy, coarse.hierarchy) - const atomicRanges = getAtomicRanges(atomic.hierarchy, ihm.entities, atomic.conformation, sequence) + const sequence = getSequence(data, ihm.entities, atomic.hierarchy, coarse.hierarchy); + const atomicRanges = getAtomicRanges(atomic.hierarchy, ihm.entities, atomic.conformation, sequence); const entry = data.entry.id.valueKind(0) === Column.ValueKind.Present ? data.entry.id.value(0) : format.name; - const label: string[] = [] - if (entry) label.push(entry) - if (data.struct.title.valueKind(0) === Column.ValueKind.Present) label.push(data.struct.title.value(0)) - if (ihm.model_name) label.push(ihm.model_name) - if (ihm.model_group_name) label.push(ihm.model_group_name) + const label: string[] = []; + if (entry) label.push(entry); + if (data.struct.title.valueKind(0) === Column.ValueKind.Present) label.push(data.struct.title.value(0)); + if (ihm.model_name) label.push(ihm.model_name); + if (ihm.model_group_name) label.push(ihm.model_group_name); return { id: UUID.create22(), @@ -137,7 +137,7 @@ async function readStandard(ctx: RuntimeContext, data: BasicData, properties: Mo if (data.atom_site) { const atomCount = data.atom_site.id.rowCount; - const entities = getEntities(data) + const entities = getEntities(data); let modelStart = 0; while (modelStart < atomCount) { @@ -152,7 +152,7 @@ async function readStandard(ctx: RuntimeContext, data: BasicData, properties: Mo } function splitTable<T extends Table<any>>(table: T, col: Column<number>) { - const ret = new Map<number, { table: T, start: number, end: number }>() + const ret = new Map<number, { table: T, start: number, end: number }>(); const rowCount = table._rowCount; let modelStart = 0; while (modelStart < rowCount) { @@ -171,11 +171,11 @@ function splitTable<T extends Table<any>>(table: T, col: Column<number>) { async function readIntegrative(ctx: RuntimeContext, data: BasicData, properties: Model['properties'], format: ModelFormat) { - const entities = getEntities(data) + const entities = getEntities(data); // when `atom_site.ihm_model_id` is undefined fall back to `atom_site.pdbx_PDB_model_num` const atom_sites_modelColumn = data.atom_site.ihm_model_id.isDefined - ? data.atom_site.ihm_model_id : data.atom_site.pdbx_PDB_model_num - const atom_sites = splitTable(data.atom_site, atom_sites_modelColumn) + ? data.atom_site.ihm_model_id : data.atom_site.pdbx_PDB_model_num; + const atom_sites = splitTable(data.atom_site, atom_sites_modelColumn); // TODO: will coarse IHM records require sorting or will we trust it? // ==> Probably implement a sort as as well and store the sourceIndex same as with atomSite diff --git a/src/mol-model-formats/structure/basic/properties.ts b/src/mol-model-formats/structure/basic/properties.ts index 743c57c7f71b2565896b6a587cfecc9840afcbb0..8515a6722cde23cd835daeb5a5498ab43a30f651 100644 --- a/src/mol-model-formats/structure/basic/properties.ts +++ b/src/mol-model-formats/structure/basic/properties.ts @@ -16,33 +16,33 @@ import { Table } from '../../../mol-data/db'; function getMissingResidues(data: BasicData): Model['properties']['missingResidues'] { const map = new Map<string, MissingResidue>(); const getKey = (model_num: number, asym_id: string, seq_id: number) => { - return `${model_num}|${asym_id}|${seq_id}` - } + return `${model_num}|${asym_id}|${seq_id}`; + }; - const c = data.pdbx_unobs_or_zero_occ_residues + const c = data.pdbx_unobs_or_zero_occ_residues; for (let i = 0, il = c._rowCount; i < il; ++i) { - const key = getKey(c.PDB_model_num.value(i), c.label_asym_id.value(i), c.label_seq_id.value(i)) - map.set(key, { polymer_flag: c.polymer_flag.value(i), occupancy_flag: c.occupancy_flag.value(i) }) + const key = getKey(c.PDB_model_num.value(i), c.label_asym_id.value(i), c.label_seq_id.value(i)); + map.set(key, { polymer_flag: c.polymer_flag.value(i), occupancy_flag: c.occupancy_flag.value(i) }); } return { has: (model_num: number, asym_id: string, seq_id: number) => { - return map.has(getKey(model_num, asym_id, seq_id)) + return map.has(getKey(model_num, asym_id, seq_id)); }, get: (model_num: number, asym_id: string, seq_id: number) => { - return map.get(getKey(model_num, asym_id, seq_id)) + return map.get(getKey(model_num, asym_id, seq_id)); }, size: map.size - } + }; } function getChemicalComponentMap(data: BasicData): Model['properties']['chemicalComponentMap'] { const map = new Map<string, ChemicalComponent>(); if (data.chem_comp._rowCount > 0) { - const { id } = data.chem_comp + const { id } = data.chem_comp; for (let i = 0, il = id.rowCount; i < il; ++i) { - map.set(id.value(i), Table.getRow(data.chem_comp, i)) + map.set(id.value(i), Table.getRow(data.chem_comp, i)); } } else { const uniqueNames = getUniqueComponentNames(data); @@ -50,7 +50,7 @@ function getChemicalComponentMap(data: BasicData): Model['properties']['chemical map.set(n, getDefaultChemicalComponent(n)); }); } - return map + return map; } function getSaccharideComponentMap(data: BasicData): SaccharideComponentMap { @@ -60,83 +60,83 @@ function getSaccharideComponentMap(data: BasicData): SaccharideComponentMap { // note that `pdbx_chem_comp_identifier` does not contain // a 'SNFG CARBOHYDRATE SYMBOL' entry for 'Unknown' saccharide components // so we always need to check `chem_comp` for those - const { comp_id, type, identifier } = data.pdbx_chem_comp_identifier + const { comp_id, type, identifier } = data.pdbx_chem_comp_identifier; for (let i = 0, il = comp_id.rowCount; i < il; ++i) { if (type.value(i) === 'SNFG CARBOHYDRATE SYMBOL' || type.value(i) === 'SNFG CARB SYMBOL' // legacy, to be removed from mmCIF dictionary ) { - const snfgName = identifier.value(i) - const saccharideComp = SaccharidesSnfgMap.get(snfgName) + const snfgName = identifier.value(i); + const saccharideComp = SaccharidesSnfgMap.get(snfgName); if (saccharideComp) { - map.set(comp_id.value(i), saccharideComp) + map.set(comp_id.value(i), saccharideComp); } else { - console.warn(`Unknown SNFG name '${snfgName}'`) + console.warn(`Unknown SNFG name '${snfgName}'`); } } } } if (data.chem_comp._rowCount > 0) { - const { id, type } = data.chem_comp + const { id, type } = data.chem_comp; for (let i = 0, il = id.rowCount; i < il; ++i) { - const _id = id.value(i) - if (map.has(_id)) continue - const _type = type.value(i) + const _id = id.value(i); + if (map.has(_id)) continue; + const _type = type.value(i); if (SaccharideCompIdMap.has(_id)) { - map.set(_id, SaccharideCompIdMap.get(_id)!) + map.set(_id, SaccharideCompIdMap.get(_id)!); } else if (getMoleculeType(_type, _id) === MoleculeType.Saccharide) { - map.set(_id, UnknownSaccharideComponent) + map.set(_id, UnknownSaccharideComponent); } } } else { - const uniqueNames = getUniqueComponentNames(data) + const uniqueNames = getUniqueComponentNames(data); SaccharideCompIdMap.forEach((v, k) => { - if (!map.has(k) && uniqueNames.has(k)) map.set(k, v) - }) + if (!map.has(k) && uniqueNames.has(k)) map.set(k, v); + }); } - return map + return map; } const getUniqueComponentNames = memoize1((data: BasicData) => { - const uniqueNames = new Set<string>() - const { label_comp_id, auth_comp_id } = data.atom_site + const uniqueNames = new Set<string>(); + const { label_comp_id, auth_comp_id } = data.atom_site; const comp_id = label_comp_id.isDefined ? label_comp_id : auth_comp_id; for (let i = 0, il = comp_id.rowCount; i < il; ++i) { - uniqueNames.add(comp_id.value(i)) + uniqueNames.add(comp_id.value(i)); } - return uniqueNames -}) + return uniqueNames; +}); function getStructAsymMap(data: BasicData): Model['properties']['structAsymMap'] { const map = new Map<string, StructAsym>(); - const { label_asym_id, auth_asym_id, label_entity_id } = data.atom_site + const { label_asym_id, auth_asym_id, label_entity_id } = data.atom_site; for (let i = 0, il = label_asym_id.rowCount; i < il; ++i) { - const id = label_asym_id.value(i) + const id = label_asym_id.value(i); if (!map.has(id)) { map.set(id, { id, auth_id: auth_asym_id.value(i), entity_id: label_entity_id.value(i) - }) + }); } } if (data.struct_asym._rowCount > 0) { - const { id, entity_id } = data.struct_asym + const { id, entity_id } = data.struct_asym; for (let i = 0, il = id.rowCount; i < il; ++i) { - const _id = id.value(i) + const _id = id.value(i); if (!map.has(_id)) { map.set(_id, { id: _id, auth_id: '', entity_id: entity_id.value(i) - }) + }); } } } - return map + return map; } export function getProperties(data: BasicData): Model['properties'] { @@ -145,5 +145,5 @@ export function getProperties(data: BasicData): Model['properties'] { chemicalComponentMap: getChemicalComponentMap(data), saccharideComponentMap: getSaccharideComponentMap(data), structAsymMap: getStructAsymMap(data) - } + }; } \ No newline at end of file diff --git a/src/mol-model-formats/structure/basic/schema.ts b/src/mol-model-formats/structure/basic/schema.ts index 670432bc674935ecfb1cb8a1acdf473f4c049417..3673cd0f8e84de351a5790a93687aba047c1ec4b 100644 --- a/src/mol-model-formats/structure/basic/schema.ts +++ b/src/mol-model-formats/structure/basic/schema.ts @@ -43,7 +43,7 @@ export const BasicSchema = { ihm_sphere_obj_site: mmCIF_Schema.ihm_sphere_obj_site, ihm_gaussian_obj_site: mmCIF_Schema.ihm_gaussian_obj_site, pdbx_unobs_or_zero_occ_residues: mmCIF_Schema.pdbx_unobs_or_zero_occ_residues, -} +}; export interface BasicData { entry: Entry @@ -65,13 +65,13 @@ export interface BasicData { } export function createBasic(data: Partial<BasicData>): BasicData { - const basic = Object.create(null) + const basic = Object.create(null); for (const name of Object.keys(BasicSchema)) { if (name in data) { - basic[name] = data[name as keyof typeof BasicSchema] + basic[name] = data[name as keyof typeof BasicSchema]; } else { - basic[name] = Table.ofUndefinedColumns(BasicSchema[name as keyof typeof BasicSchema], 0) + basic[name] = Table.ofUndefinedColumns(BasicSchema[name as keyof typeof BasicSchema], 0); } } - return basic + return basic; } \ No newline at end of file diff --git a/src/mol-model-formats/structure/basic/sequence.ts b/src/mol-model-formats/structure/basic/sequence.ts index 8a3328d52ddfdb7e2d55876c72aa52c6fb84ffd8..07331de38f6578f828b25792cdc470ed5408ea70 100644 --- a/src/mol-model-formats/structure/basic/sequence.ts +++ b/src/mol-model-formats/structure/basic/sequence.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import StructureSequence from '../../../mol-model/structure/model/properties/sequence' +import StructureSequence from '../../../mol-model/structure/model/properties/sequence'; import { Column } from '../../../mol-data/db'; import { AtomicHierarchy } from '../../../mol-model/structure/model/properties/atomic'; import { Entities } from '../../../mol-model/structure/model/properties/common'; diff --git a/src/mol-model-formats/structure/basic/util.ts b/src/mol-model-formats/structure/basic/util.ts index daf0d3a8a3ebeaddf5e9c373843e602cc46bb2d7..2d3e9baeecaf13c2afdf921012a3689ddaf3bb6e 100644 --- a/src/mol-model-formats/structure/basic/util.ts +++ b/src/mol-model-formats/structure/basic/util.ts @@ -11,10 +11,10 @@ import { Table } from '../../../mol-data/db'; export function getModelGroupName(model_id: number, data: BasicData) { const { ihm_model_group, ihm_model_group_link } = data; - const link = Table.pickRow(ihm_model_group_link, i => ihm_model_group_link.model_id.value(i) === model_id) + const link = Table.pickRow(ihm_model_group_link, i => ihm_model_group_link.model_id.value(i) === model_id); if (link) { - const group = Table.pickRow(ihm_model_group, i => ihm_model_group.id.value(i) === link.group_id) - if (group) return group.name + const group = Table.pickRow(ihm_model_group, i => ihm_model_group.id.value(i) === link.group_id); + if (group) return group.name; } - return '' + return ''; } \ No newline at end of file diff --git a/src/mol-model-formats/structure/cif-core.ts b/src/mol-model-formats/structure/cif-core.ts index 539ff633834b16392be84f588de2f2f3ea8df563..b0985cd9334db0c7c5139bd9adbaf559444cf0b6 100644 --- a/src/mol-model-formats/structure/cif-core.ts +++ b/src/mol-model-formats/structure/cif-core.ts @@ -22,16 +22,16 @@ import { IndexPairBonds } from './property/bonds/index-pair'; import { AtomSiteAnisotrop } from './property/anisotropic'; function getSpacegroupNameOrNumber(space_group: CifCore_Database['space_group']) { - const groupNumber = space_group.IT_number.value(0) - const groupName = space_group['name_H-M_full'].value(0) - if (!space_group.IT_number.isDefined) return groupName - if (!space_group['name_H-M_full'].isDefined) return groupNumber - return groupNumber + const groupNumber = space_group.IT_number.value(0); + const groupName = space_group['name_H-M_full'].value(0); + if (!space_group.IT_number.isDefined) return groupName; + if (!space_group['name_H-M_full'].isDefined) return groupNumber; + return groupNumber; } function getSymmetry(db: CifCore_Database): Symmetry { - const { cell, space_group } = db - const nameOrNumber = getSpacegroupNameOrNumber(space_group) + const { cell, space_group } = db; + const nameOrNumber = getSpacegroupNameOrNumber(space_group); const spaceCell = SpacegroupCell.create(nameOrNumber, Vec3.create(cell.length_a.value(0), cell.length_b.value(0), cell.length_c.value(0)), Vec3.scale(Vec3.zero(), Vec3.create(cell.angle_alpha.value(0), cell.angle_beta.value(0), cell.angle_gamma.value(0)), Math.PI / 180)); @@ -41,28 +41,28 @@ function getSymmetry(db: CifCore_Database): Symmetry { assemblies : [], isNonStandardCrytalFrame: false, ncsOperators: [] - } + }; } async function getModels(db: CifCore_Database, format: CifCoreFormat, ctx: RuntimeContext): Promise<Model[]> { - const atomCount = db.atom_site._rowCount + const atomCount = db.atom_site._rowCount; const MOL = Column.ofConst('MOL', atomCount, Column.Schema.str); const A = Column.ofConst('A', atomCount, Column.Schema.str); const seq_id = Column.ofConst(1, atomCount, Column.Schema.int); - const symmetry = getSymmetry(db) - const m = symmetry.spacegroup.cell.fromFractional + const symmetry = getSymmetry(db); + const m = symmetry.spacegroup.cell.fromFractional; - const { fract_x, fract_y, fract_z } = db.atom_site - const x = new Float32Array(atomCount) - const y = new Float32Array(atomCount) - const z = new Float32Array(atomCount) - const v = Vec3() + const { fract_x, fract_y, fract_z } = db.atom_site; + const x = new Float32Array(atomCount); + const y = new Float32Array(atomCount); + const z = new Float32Array(atomCount); + const v = Vec3(); for (let i = 0; i < atomCount; ++i) { - Vec3.set(v, fract_x.value(i), fract_y.value(i), fract_z.value(i)) - Vec3.transformMat4(v, v, m) - x[i] = v[0], y[i] = v[1], z[i] = v[2] + Vec3.set(v, fract_x.value(i), fract_y.value(i), fract_z.value(i)); + Vec3.transformMat4(v, v, m); + x[i] = v[0], y[i] = v[1], z[i] = v[2]; } const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, { @@ -91,14 +91,14 @@ async function getModels(db: CifCore_Database, format: CifCoreFormat, ctx: Runti db.chemical.name_common.value(0) || db.chemical.name_systematic.value(0) || db.chemical_formula.sum.value(0) - ) + ); - const entityBuilder = new EntityBuilder() - entityBuilder.setNames([['MOL', name || 'Unknown Entity']]) + const entityBuilder = new EntityBuilder(); + entityBuilder.setNames([['MOL', name || 'Unknown Entity']]); entityBuilder.getEntityId('MOL', MoleculeType.Unknown, 'A'); const componentBuilder = new ComponentBuilder(seq_id, db.atom_site.type_symbol); - componentBuilder.setNames([['MOL', name || 'Unknown Molecule']]) + componentBuilder.setNames([['MOL', name || 'Unknown Molecule']]); componentBuilder.add('MOL', 0); const basics = createBasic({ @@ -110,30 +110,30 @@ async function getModels(db: CifCore_Database, format: CifCoreFormat, ctx: Runti const models = await createModels(basics, format, ctx); if (models.length > 0) { - ModelSymmetry.Provider.set(models[0], symmetry) + ModelSymmetry.Provider.set(models[0], symmetry); - const bondCount = db.geom_bond._rowCount + const bondCount = db.geom_bond._rowCount; if(bondCount > 0) { - const labelIndexMap: { [label: string]: number } = {} - const { label } = db.atom_site + const labelIndexMap: { [label: string]: number } = {}; + const { label } = db.atom_site; for (let i = 0, il = label.rowCount; i < il; ++i) { - labelIndexMap[label.value(i)] = i + labelIndexMap[label.value(i)] = i; } - const indexA: number[] = [] - const indexB: number[] = [] - const order: number[] = [] - const symmetryA: string[] = [] - const symmetryB: string[] = [] + const indexA: number[] = []; + const indexB: number[] = []; + const order: number[] = []; + const symmetryA: string[] = []; + const symmetryB: string[] = []; - const { atom_site_label_1, atom_site_label_2, valence, site_symmetry_1, site_symmetry_2 } = db.geom_bond + const { atom_site_label_1, atom_site_label_2, valence, site_symmetry_1, site_symmetry_2 } = db.geom_bond; for (let i = 0; i < bondCount; ++i) { - indexA[i] = labelIndexMap[atom_site_label_1.value(i)] - indexB[i] = labelIndexMap[atom_site_label_2.value(i)] + indexA[i] = labelIndexMap[atom_site_label_1.value(i)]; + indexB[i] = labelIndexMap[atom_site_label_2.value(i)]; // TODO derive order from bond length if undefined - order[i] = valence.isDefined ? valence.value(i) : 1 - symmetryA[i] = site_symmetry_1.value(i) || '1_555' - symmetryB[i] = site_symmetry_2.value(i) || '1_555' + order[i] = valence.isDefined ? valence.value(i) : 1; + symmetryA[i] = site_symmetry_1.value(i) || '1_555'; + symmetryB[i] = site_symmetry_2.value(i) || '1_555'; } IndexPairBonds.Provider.set(models[0], IndexPairBonds.fromData({ pairs: { @@ -151,19 +151,19 @@ async function getModels(db: CifCore_Database, format: CifCoreFormat, ctx: Runti function atomSiteAnisotropFromCifCore(model: Model) { if (!CifCoreFormat.is(model.sourceData)) return; - const { atom_site, atom_site_aniso } = model.sourceData.data.db + const { atom_site, atom_site_aniso } = model.sourceData.data.db; const data = Table.ofPartialColumns(AtomSiteAnisotrop.Schema, { U: atom_site_aniso.U, U_esd: atom_site_aniso.U_su }, atom_site_aniso._rowCount); - const elementToAnsiotrop = AtomSiteAnisotrop.getElementToAnsiotropFromLabel(atom_site.label, atom_site_aniso.label) - return { data, elementToAnsiotrop } + const elementToAnsiotrop = AtomSiteAnisotrop.getElementToAnsiotropFromLabel(atom_site.label, atom_site_aniso.label); + return { data, elementToAnsiotrop }; } function atomSiteAnisotropApplicableCifCore(model: Model) { if (!CifCoreFormat.is(model.sourceData)) return false; - return model.sourceData.data.db.atom_site_aniso.U.isDefined + return model.sourceData.data.db.atom_site_aniso.U.isDefined; } -AtomSiteAnisotrop.Provider.formatRegistry.add('cifCore', atomSiteAnisotropFromCifCore, atomSiteAnisotropApplicableCifCore) +AtomSiteAnisotrop.Provider.formatRegistry.add('cifCore', atomSiteAnisotropFromCifCore, atomSiteAnisotropApplicableCifCore); // @@ -174,11 +174,11 @@ type CifCoreFormat = ModelFormat<CifCoreFormat.Data> namespace CifCoreFormat { export type Data = { db: CifCore_Database, frame: CifFrame } export function is(x: ModelFormat): x is CifCoreFormat { - return x.kind === 'cifCore' + return x.kind === 'cifCore'; } export function fromFrame(frame: CifFrame, db?: CifCore_Database): CifCoreFormat { - if (!db) db = CIF.schema.cifCore(frame) + if (!db) db = CIF.schema.cifCore(frame); const name = ( db.database_code.depnum_ccdc_archive.value(0) || @@ -189,13 +189,13 @@ namespace CifCoreFormat { db.database_code.CSD.value(0) || db.database_code.COD.value(0) || db._name - ) + ); return { kind: 'cifCore', name, data: { db, frame } }; } } export function trajectoryFromCifCore(frame: CifFrame): Task<Model.Trajectory> { - const format = CifCoreFormat.fromFrame(frame) - return Task.create('Parse CIF Core', ctx => getModels(format.data.db, format, ctx)) + const format = CifCoreFormat.fromFrame(frame); + return Task.create('Parse CIF Core', ctx => getModels(format.data.db, format, ctx)); } diff --git a/src/mol-model-formats/structure/common/component.ts b/src/mol-model-formats/structure/common/component.ts index 7dbbfa176c7bcc7eb0907b04015d539ee67c13ff..f09418ccf2d46dd459bf7cc7e47be97c01ec5fa5 100644 --- a/src/mol-model-formats/structure/common/component.ts +++ b/src/mol-model-formats/structure/common/component.ts @@ -16,20 +16,20 @@ const ProteinAtomIdsList = [ new Set([ 'CA' ]), new Set([ 'C' ]), new Set([ 'N' ]) -] +]; const RnaAtomIdsList = [ new Set([ 'P', 'O3\'', 'O3*' ]), new Set([ 'C4\'', 'C4*' ]), new Set([ 'O2\'', 'O2*', 'F2\'', 'F2*' ]) -] +]; const DnaAtomIdsList = [ new Set([ 'P', 'O3\'', 'O3*' ]), new Set([ 'C3\'', 'C3*' ]), new Set([ 'O2\'', 'O2*', 'F2\'', 'F2*' ]) -] +]; const StandardComponents = (function() { - const map = new Map<string, Component>() + const map = new Map<string, Component>(); const components: Component[] = [ { id: 'HIS', name: 'HISTIDINE', type: 'L-peptide linking' }, { id: 'ARG', name: 'ARGININE', type: 'L-peptide linking' }, @@ -66,10 +66,10 @@ const StandardComponents = (function() { { id: 'DG', name: '2\'-DEOXYGUANOSINE-5\'-MONOPHOSPHATE', type: 'DNA linking' }, { id: 'DI', name: '2\'-DEOXYINOSINE-5\'-MONOPHOSPHATE', type: 'DNA linking' }, { id: 'DU', name: '2\'-DEOXYURIDINE-5\'-MONOPHOSPHATE', type: 'DNA linking' }, - ] - components.forEach(c => map.set(c.id, c)) - return map -})() + ]; + components.forEach(c => map.set(c.id, c)); + return map; +})(); export class ComponentBuilder { private namesMap = new Map<string, string>() @@ -80,62 +80,62 @@ export class ComponentBuilder { private mon_nstd_flags: mmCIF_Schema['chem_comp']['mon_nstd_flag']['T'][] = [] private set(c: Component) { - this.comps.set(c.id, c) - this.ids.push(c.id) - this.names.push(c.name) - this.types.push(c.type) - this.mon_nstd_flags.push(PolymerNames.has(c.id) ? 'y' : 'n') + this.comps.set(c.id, c); + this.ids.push(c.id); + this.names.push(c.name); + this.types.push(c.type); + this.mon_nstd_flags.push(PolymerNames.has(c.id) ? 'y' : 'n'); } private getAtomIds(index: number) { - const atomIds = new Set<string>() - let prevSeqId = this.seqId.value(index) + const atomIds = new Set<string>(); + let prevSeqId = this.seqId.value(index); while (index < this.seqId.rowCount) { - const seqId = this.seqId.value(index) - if (seqId !== prevSeqId) break - atomIds.add(this.atomId.value(index)) - prevSeqId - seqId - index += 1 + const seqId = this.seqId.value(index); + if (seqId !== prevSeqId) break; + atomIds.add(this.atomId.value(index)); + prevSeqId - seqId; + index += 1; } - return atomIds + return atomIds; } private hasAtomIds (atomIds: Set<string>, atomIdsList: Set<string>[]) { for (let i = 0, il = atomIdsList.length; i < il; ++i) { if (!SetUtils.areIntersecting(atomIds, atomIdsList[i])) { - return false + return false; } } - return true + return true; } private getType(atomIds: Set<string>): Component['type'] { if (this.hasAtomIds(atomIds, ProteinAtomIdsList)) { - return 'peptide linking' + return 'peptide linking'; } else if (this.hasAtomIds(atomIds, RnaAtomIdsList)) { - return 'RNA linking' + return 'RNA linking'; } else if (this.hasAtomIds(atomIds, DnaAtomIdsList)) { - return 'DNA linking' + return 'DNA linking'; } else { - return 'other' + return 'other'; } } - has(compId: string) { return this.comps.has(compId) } - get(compId: string) { return this.comps.get(compId) } + has(compId: string) { return this.comps.has(compId); } + get(compId: string) { return this.comps.get(compId); } add(compId: string, index: number) { if (!this.has(compId)) { if (StandardComponents.has(compId)) { - this.set(StandardComponents.get(compId)!) + this.set(StandardComponents.get(compId)!); } else if (WaterNames.has(compId)) { - this.set({ id: compId, name: 'WATER', type: 'non-polymer' }) + this.set({ id: compId, name: 'WATER', type: 'non-polymer' }); } else { - const type = this.getType(this.getAtomIds(index)) - this.set({ id: compId, name: this.namesMap.get(compId) || compId, type }) + const type = this.getType(this.getAtomIds(index)); + this.set({ id: compId, name: this.namesMap.get(compId) || compId, type }); } } - return this.get(compId)! + return this.get(compId)!; } getChemCompTable() { @@ -144,11 +144,11 @@ export class ComponentBuilder { name: Column.ofStringArray(this.names), type: Column.ofStringAliasArray(this.types), mon_nstd_flag: Column.ofStringAliasArray(this.mon_nstd_flags), - }, this.ids.length) + }, this.ids.length); } setNames(names: [string, string][]) { - names.forEach(n => this.namesMap.set(n[0], n[1])) + names.forEach(n => this.namesMap.set(n[0], n[1])); } constructor(private seqId: Column<number>, private atomId: Column<string>) { diff --git a/src/mol-model-formats/structure/common/entity.ts b/src/mol-model-formats/structure/common/entity.ts index 3de2bfefd7c42951082f68b0f654d059d2dba716..614223664650efb39387d766d37525bca5edc958 100644 --- a/src/mol-model-formats/structure/common/entity.ts +++ b/src/mol-model-formats/structure/common/entity.ts @@ -26,35 +26,35 @@ export class EntityBuilder { private waterId?: string private set(type: EntityType, description: string) { - this.count += 1 - this.ids.push(`${this.count}`) - this.types.push(type) - this.descriptions.push([description]) + this.count += 1; + this.ids.push(`${this.count}`); + this.types.push(type); + this.descriptions.push([description]); } getEntityId(compId: string, moleculeType: MoleculeType, chainId: string): string { if (moleculeType === MoleculeType.Water) { if (this.waterId === undefined) { - this.set('water', 'Water') - this.waterId = `${this.count}` + this.set('water', 'Water'); + this.waterId = `${this.count}`; } return this.waterId; } else if (isPolymer(moleculeType)) { if (this.compoundsMap.has(chainId)) { - return this.compoundsMap.get(chainId)! + return this.compoundsMap.get(chainId)!; } else { if (!this.chainMap.has(chainId)) { - this.set('polymer', `Polymer ${this.chainMap.size + 1}`) - this.chainMap.set(chainId, `${this.count}`) + this.set('polymer', `Polymer ${this.chainMap.size + 1}`); + this.chainMap.set(chainId, `${this.count}`); } - return this.chainMap.get(chainId)! + return this.chainMap.get(chainId)!; } } else { if (!this.heteroMap.has(compId)) { - this.set('non-polymer', this.namesMap.get(compId) || compId) - this.heteroMap.set(compId, `${this.count}`) + this.set('non-polymer', this.namesMap.get(compId) || compId); + this.heteroMap.set(compId, `${this.count}`); } - return this.heteroMap.get(compId)! + return this.heteroMap.get(compId)!; } } @@ -63,20 +63,20 @@ export class EntityBuilder { id: Column.ofStringArray(this.ids), type: Column.ofStringAliasArray(this.types), pdbx_description: Column.ofStringListArray(this.descriptions), - }, this.count) + }, this.count); } setCompounds(compounds: EntityCompound[]) { for (let i = 0, il = compounds.length; i < il; ++i) { - const { chains, description } = compounds[i] - this.set('polymer', description) + const { chains, description } = compounds[i]; + this.set('polymer', description); for (let j = 0, jl = chains.length; j < jl; ++j) { - this.compoundsMap.set(chains[j], `${this.count}`) + this.compoundsMap.set(chains[j], `${this.count}`); } } } setNames(names: [string, string][]) { - names.forEach(n => this.namesMap.set(n[0], n[1])) + names.forEach(n => this.namesMap.set(n[0], n[1])); } } \ No newline at end of file diff --git a/src/mol-model-formats/structure/common/property.ts b/src/mol-model-formats/structure/common/property.ts index eeb7c1685087afda73ad67d57f309eab2329f20c..c5f6b277e7bc7865f7a1d546ef45b8e16112c3fb 100644 --- a/src/mol-model-formats/structure/common/property.ts +++ b/src/mol-model-formats/structure/common/property.ts @@ -12,26 +12,26 @@ class FormatRegistry<T> { private applicable = new Map<ModelFormat['kind'], (model: Model) => boolean>() add(kind: ModelFormat['kind'], obtain: (model: Model) => T | undefined, applicable?: (model: Model) => boolean) { - this.map.set(kind, obtain) - if (applicable) this.applicable.set(kind, applicable) + this.map.set(kind, obtain); + if (applicable) this.applicable.set(kind, applicable); } remove(kind: ModelFormat['kind']) { - this.map.delete(kind) - this.applicable.delete(kind) + this.map.delete(kind); + this.applicable.delete(kind); } get(kind: ModelFormat['kind']) { - return this.map.get(kind) + return this.map.get(kind); } isApplicable(model: Model) { - const isApplicable = this.applicable.get(model.sourceData.kind) - return isApplicable ? isApplicable(model) : true + const isApplicable = this.applicable.get(model.sourceData.kind); + return isApplicable ? isApplicable(model) : true; } } -export { FormatPropertyProvider as FormatPropertyProvider } +export { FormatPropertyProvider as FormatPropertyProvider }; interface FormatPropertyProvider<T> { readonly descriptor: CustomPropertyDescriptor @@ -43,29 +43,29 @@ interface FormatPropertyProvider<T> { namespace FormatPropertyProvider { export function create<T>(descriptor: CustomPropertyDescriptor): FormatPropertyProvider<T> { - const { name } = descriptor - const formatRegistry = new FormatRegistry<T>() + const { name } = descriptor; + const formatRegistry = new FormatRegistry<T>(); return { descriptor, formatRegistry, isApplicable(model: Model) { - return formatRegistry.isApplicable(model) + return formatRegistry.isApplicable(model); }, get(model: Model): T | undefined { - if (model._staticPropertyData[name]) return model._staticPropertyData[name] - if (model.customProperties.has(descriptor)) return + if (model._staticPropertyData[name]) return model._staticPropertyData[name]; + if (model.customProperties.has(descriptor)) return; - const obtain = formatRegistry.get(model.sourceData.kind) - if (!obtain) return + const obtain = formatRegistry.get(model.sourceData.kind); + if (!obtain) return; - model._staticPropertyData[name] = obtain(model) - model.customProperties.add(descriptor) - return model._staticPropertyData[name] + model._staticPropertyData[name] = obtain(model); + model.customProperties.add(descriptor); + return model._staticPropertyData[name]; }, set(model: Model, value: T) { - model._staticPropertyData[name] = value + model._staticPropertyData[name] = value; } - } + }; } } \ No newline at end of file diff --git a/src/mol-model-formats/structure/common/util.ts b/src/mol-model-formats/structure/common/util.ts index 2f0c6b39d82f25609b26bd47f7c779d06335f837..788a1e8cbe50123ce60b1eb7ef029ddf514c55ff 100644 --- a/src/mol-model-formats/structure/common/util.ts +++ b/src/mol-model-formats/structure/common/util.ts @@ -6,22 +6,22 @@ import { memoize1 } from '../../../mol-util/memoize'; -const ChainIdAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +const ChainIdAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; function _getChainId (index: number) { - const n = ChainIdAlphabet.length - let j = index - let k = 0 - let chainId = ChainIdAlphabet[j % n] + const n = ChainIdAlphabet.length; + let j = index; + let k = 0; + let chainId = ChainIdAlphabet[j % n]; while (j >= n) { - j = Math.floor(j / n) - chainId += ChainIdAlphabet[j % n] - k += 1 + j = Math.floor(j / n); + chainId += ChainIdAlphabet[j % n]; + k += 1; } if (k >= 5) { - console.warn('getChainId overflow') + console.warn('getChainId overflow'); } - return chainId + return chainId; } -export const getChainId = memoize1(_getChainId) \ No newline at end of file +export const getChainId = memoize1(_getChainId); \ No newline at end of file diff --git a/src/mol-model-formats/structure/dcd.ts b/src/mol-model-formats/structure/dcd.ts index f2e02cd791c0404554fd7d50e8c0b4dd7856cb62..ebb78ee5d74d083c9b95545676b44f0e8bc27192 100644 --- a/src/mol-model-formats/structure/dcd.ts +++ b/src/mol-model-formats/structure/dcd.ts @@ -8,32 +8,32 @@ import { Task } from '../../mol-task'; import { DcdFile } from '../../mol-io/reader/dcd/parser'; import { Coordinates, Frame, Time } from '../../mol-model/structure/coordinates'; -const charmmTimeUnitFactor = 20.45482949774598 +const charmmTimeUnitFactor = 20.45482949774598; export function coordinatesFromDcd(dcdFile: DcdFile): Task<Coordinates> { return Task.create('Parse DCD', async ctx => { await ctx.update('Converting to coordinates'); - const { header } = dcdFile + const { header } = dcdFile; - let deltaTime = Time(1, 'step') + let deltaTime = Time(1, 'step'); if (header.DELTA) { - deltaTime = Time(header.DELTA * charmmTimeUnitFactor, 'ps') + deltaTime = Time(header.DELTA * charmmTimeUnitFactor, 'ps'); } - let offsetTime = Time(0, deltaTime.unit) + let offsetTime = Time(0, deltaTime.unit); if (header.ISTART >= 1) { - offsetTime = Time((header.ISTART - 1) * deltaTime.value, deltaTime.unit) + offsetTime = Time((header.ISTART - 1) * deltaTime.value, deltaTime.unit); } - const frames: Frame[] = [] + const frames: Frame[] = []; for (let i = 0, il = dcdFile.frames.length; i < il; ++i) { frames.push({ ...dcdFile.frames[i], time: Time(offsetTime.value + deltaTime.value * i, deltaTime.unit) - }) + }); } - return Coordinates.create(frames, deltaTime, offsetTime) - }) + return Coordinates.create(frames, deltaTime, offsetTime); + }); } diff --git a/src/mol-model-formats/structure/gro.ts b/src/mol-model-formats/structure/gro.ts index c38beca49164cb7d98d322036b10db9d83a2a316..88d699041d08f55c0c3a907dfb9f8aeea88912f0 100644 --- a/src/mol-model-formats/structure/gro.ts +++ b/src/mol-model-formats/structure/gro.ts @@ -20,29 +20,29 @@ import { createModels } from './basic/parser'; // TODO multi model files function getBasic(atoms: GroAtoms): BasicData { - const auth_atom_id = atoms.atomName - const auth_comp_id = atoms.residueName + const auth_atom_id = atoms.atomName; + const auth_comp_id = atoms.residueName; - const entityIds = new Array<string>(atoms.count) - const asymIds = new Array<string>(atoms.count) - const seqIds = new Uint32Array(atoms.count) - const ids = new Uint32Array(atoms.count) + const entityIds = new Array<string>(atoms.count); + const asymIds = new Array<string>(atoms.count); + const seqIds = new Uint32Array(atoms.count); + const ids = new Uint32Array(atoms.count); - const entityBuilder = new EntityBuilder() - const componentBuilder = new ComponentBuilder(atoms.residueNumber, atoms.atomName) + const entityBuilder = new EntityBuilder(); + const componentBuilder = new ComponentBuilder(atoms.residueNumber, atoms.atomName); - let currentEntityId = '' - let currentAsymIndex = 0 - let currentAsymId = '' - let currentSeqId = 0 - let prevMoleculeType = MoleculeType.Unknown - let prevResidueNumber = -1 + let currentEntityId = ''; + let currentAsymIndex = 0; + let currentAsymId = ''; + let currentSeqId = 0; + let prevMoleculeType = MoleculeType.Unknown; + let prevResidueNumber = -1; for (let i = 0, il = atoms.count; i < il; ++i) { - const residueNumber = atoms.residueNumber.value(i) + const residueNumber = atoms.residueNumber.value(i); if (residueNumber !== prevResidueNumber) { - const compId = atoms.residueName.value(i) - const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId) + const compId = atoms.residueName.value(i); + const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId); if (moleculeType !== prevMoleculeType || ( residueNumber !== prevResidueNumber + 1 && !( @@ -50,25 +50,25 @@ function getBasic(atoms: GroAtoms): BasicData { prevResidueNumber === 99999 && residueNumber === 0 ) )) { - currentAsymId = getChainId(currentAsymIndex) - currentAsymIndex += 1 - currentSeqId = 0 + currentAsymId = getChainId(currentAsymIndex); + currentAsymIndex += 1; + currentSeqId = 0; } - currentEntityId = entityBuilder.getEntityId(compId, moleculeType, currentAsymId) - currentSeqId += 1 + currentEntityId = entityBuilder.getEntityId(compId, moleculeType, currentAsymId); + currentSeqId += 1; - prevResidueNumber = residueNumber - prevMoleculeType = moleculeType + prevResidueNumber = residueNumber; + prevMoleculeType = moleculeType; } - entityIds[i] = currentEntityId - asymIds[i] = currentAsymId - seqIds[i] = currentSeqId - ids[i] = i + entityIds[i] = currentEntityId; + asymIds[i] = currentAsymId; + seqIds[i] = currentSeqId; + ids[i] = i; } - const auth_asym_id = Column.ofStringArray(asymIds) + const auth_asym_id = Column.ofStringArray(asymIds); const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, { auth_asym_id, @@ -90,24 +90,24 @@ function getBasic(atoms: GroAtoms): BasicData { type_symbol: Column.ofStringArray(Column.mapToArray(atoms.atomName, s => guessElementSymbolString(s))), pdbx_PDB_model_num: Column.ofConst(1, atoms.count, Column.Schema.int), - }, atoms.count) + }, atoms.count); return createBasic({ entity: entityBuilder.getEntityTable(), chem_comp: componentBuilder.getChemCompTable(), atom_site - }) + }); } // -export { GroFormat } +export { GroFormat }; type GroFormat = ModelFormat<GroFile> namespace GroFormat { export function is(x: ModelFormat): x is GroFormat { - return x.kind === 'gro' + return x.kind === 'gro'; } export function fromGro(gro: GroFile): GroFormat { @@ -118,7 +118,7 @@ namespace GroFormat { export function trajectoryFromGRO(gro: GroFile): Task<Model.Trajectory> { return Task.create('Parse GRO', async ctx => { const format = GroFormat.fromGro(gro); - const basic = getBasic(gro.structures[0].atoms) + const basic = getBasic(gro.structures[0].atoms); return createModels(basic, format, ctx); - }) + }); } diff --git a/src/mol-model-formats/structure/mmcif.ts b/src/mol-model-formats/structure/mmcif.ts index 70fc158950b14340b6819e826dd580de2584a2ed..d74f5be12c9d05e26895a401ab7e4739b8370f0e 100644 --- a/src/mol-model-formats/structure/mmcif.ts +++ b/src/mol-model-formats/structure/mmcif.ts @@ -20,29 +20,29 @@ import { StructConn } from './property/bonds/struct_conn'; function modelSymmetryFromMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return; - return ModelSymmetry.fromData(model.sourceData.data.db) + return ModelSymmetry.fromData(model.sourceData.data.db); } -ModelSymmetry.Provider.formatRegistry.add('mmCIF', modelSymmetryFromMmcif) +ModelSymmetry.Provider.formatRegistry.add('mmCIF', modelSymmetryFromMmcif); function secondaryStructureFromMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return; - const { struct_conf, struct_sheet_range } = model.sourceData.data.db - return ModelSecondaryStructure.fromStruct(struct_conf, struct_sheet_range, model.atomicHierarchy) + const { struct_conf, struct_sheet_range } = model.sourceData.data.db; + return ModelSecondaryStructure.fromStruct(struct_conf, struct_sheet_range, model.atomicHierarchy); } -ModelSecondaryStructure.Provider.formatRegistry.add('mmCIF', secondaryStructureFromMmcif) +ModelSecondaryStructure.Provider.formatRegistry.add('mmCIF', secondaryStructureFromMmcif); function atomSiteAnisotropFromMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return; - const { atom_site_anisotrop } = model.sourceData.data.db + const { atom_site_anisotrop } = model.sourceData.data.db; const data = Table.ofColumns(AtomSiteAnisotrop.Schema, atom_site_anisotrop); - const elementToAnsiotrop = AtomSiteAnisotrop.getElementToAnsiotrop(model.atomicConformation.atomId, atom_site_anisotrop.id) - return { data, elementToAnsiotrop } + const elementToAnsiotrop = AtomSiteAnisotrop.getElementToAnsiotrop(model.atomicConformation.atomId, atom_site_anisotrop.id); + return { data, elementToAnsiotrop }; } function atomSiteAnisotropApplicableMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return false; - return model.sourceData.data.db.atom_site_anisotrop.U.isDefined + return model.sourceData.data.db.atom_site_anisotrop.U.isDefined; } -AtomSiteAnisotrop.Provider.formatRegistry.add('mmCIF', atomSiteAnisotropFromMmcif, atomSiteAnisotropApplicableMmcif) +AtomSiteAnisotrop.Provider.formatRegistry.add('mmCIF', atomSiteAnisotropFromMmcif, atomSiteAnisotropApplicableMmcif); function componentBondFromMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return; @@ -51,42 +51,42 @@ function componentBondFromMmcif(model: Model) { return { data: chem_comp_bond, entries: ComponentBond.getEntriesFromChemCompBond(chem_comp_bond) - } + }; } -ComponentBond.Provider.formatRegistry.add('mmCIF', componentBondFromMmcif) +ComponentBond.Provider.formatRegistry.add('mmCIF', componentBondFromMmcif); function structConnFromMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return; const { struct_conn } = model.sourceData.data.db; if (struct_conn._rowCount === 0) return; - const entries = StructConn.getEntriesFromStructConn(struct_conn, model) + const entries = StructConn.getEntriesFromStructConn(struct_conn, model); return { data: struct_conn, byAtomIndex: StructConn.getAtomIndexFromEntries(entries), entries, - } + }; } -StructConn.Provider.formatRegistry.add('mmCIF', structConnFromMmcif) +StructConn.Provider.formatRegistry.add('mmCIF', structConnFromMmcif); // -export { MmcifFormat } +export { MmcifFormat }; type MmcifFormat = ModelFormat<MmcifFormat.Data> namespace MmcifFormat { export type Data = { db: mmCIF_Database, frame: CifFrame } export function is(x: ModelFormat): x is MmcifFormat { - return x.kind === 'mmCIF' + return x.kind === 'mmCIF'; } export function fromFrame(frame: CifFrame, db?: mmCIF_Database): MmcifFormat { - if (!db) db = CIF.schema.mmCIF(frame) + if (!db) db = CIF.schema.mmCIF(frame); return { kind: 'mmCIF', name: db._name, data: { db, frame } }; } } export function trajectoryFromMmCIF(frame: CifFrame): Task<Model.Trajectory> { - const format = MmcifFormat.fromFrame(frame) + const format = MmcifFormat.fromFrame(frame); return Task.create('Create mmCIF Model', ctx => createModels(format.data.db, format, ctx)); } \ No newline at end of file diff --git a/src/mol-model-formats/structure/mol.ts b/src/mol-model-formats/structure/mol.ts index ea99af2616ffe2cd8f627c025293b887b4fd01a8..c23612ee9ecd3cfaebdc40fd517e220eaf519c00 100644 --- a/src/mol-model-formats/structure/mol.ts +++ b/src/mol-model-formats/structure/mol.ts @@ -47,12 +47,12 @@ async function getModels(mol: MolFile, ctx: RuntimeContext): Promise<Model[]> { pdbx_PDB_model_num: Column.ofConst(1, atoms.count, Column.Schema.int), }, atoms.count); - const entityBuilder = new EntityBuilder() - entityBuilder.setNames([['MOL', 'Unknown Entity']]) + const entityBuilder = new EntityBuilder(); + entityBuilder.setNames([['MOL', 'Unknown Entity']]); entityBuilder.getEntityId('MOL', MoleculeType.Unknown, 'A'); const componentBuilder = new ComponentBuilder(seq_id, type_symbol); - componentBuilder.setNames([['MOL', 'Unknown Molecule']]) + componentBuilder.setNames([['MOL', 'Unknown Molecule']]); componentBuilder.add('MOL', 0); const basics = createBasic({ @@ -82,7 +82,7 @@ type MolFormat = ModelFormat<MolFile> namespace MolFormat { export function is(x: ModelFormat): x is MolFormat { - return x.kind === 'mol' + return x.kind === 'mol'; } export function create(mol: MolFile): MolFormat { @@ -91,5 +91,5 @@ namespace MolFormat { } export function trajectoryFromMol(mol: MolFile): Task<Model.Trajectory> { - return Task.create('Parse MOL', ctx => getModels(mol, ctx)) + return Task.create('Parse MOL', ctx => getModels(mol, ctx)); } diff --git a/src/mol-model-formats/structure/pdb.ts b/src/mol-model-formats/structure/pdb.ts index c77392ec26435bf213bec83521a7f74f95836c17..fece1202c6ef7d780e48ee9f1d1f3af72913d32b 100644 --- a/src/mol-model-formats/structure/pdb.ts +++ b/src/mol-model-formats/structure/pdb.ts @@ -16,7 +16,7 @@ export function trajectoryFromPDB(pdb: PdbFile): Task<Model.Trajectory> { return Task.create('Parse PDB', async ctx => { await ctx.update('Converting to mmCIF'); const cif = await pdbToMmCif(pdb); - const format = MmcifFormat.fromFrame(cif) - return createModels(format.data.db, format, ctx) - }) + const format = MmcifFormat.fromFrame(cif); + return createModels(format.data.db, format, ctx); + }); } diff --git a/src/mol-model-formats/structure/pdb/anisotropic.ts b/src/mol-model-formats/structure/pdb/anisotropic.ts index 869d59209eeb0416bc48cb4e8ab53d3bfa18887f..8126d99b21799dfd908332c6640017a1d58ad8cc 100644 --- a/src/mol-model-formats/structure/pdb/anisotropic.ts +++ b/src/mol-model-formats/structure/pdb/anisotropic.ts @@ -68,7 +68,7 @@ export function getAnisotropic(sites: AnisotropicTemplate): { [K in keyof mmCIF_ (fields as any)['U[1][3]'] = CifField.ofNumbers(sites['U[1][3]']); (fields as any)['U[2][3]'] = CifField.ofNumbers(sites['U[2][3]']); - return fields + return fields; } export function addAnisotropic(sites: AnisotropicTemplate, model: string, data: Tokenizer, s: number, e: number) { @@ -109,22 +109,22 @@ export function addAnisotropic(sites: AnisotropicTemplate, model: string, data: } // 29 - 35 Integer u[0][0] U(1,1) - sites['U[1][1]'][sites.index] = fastParseInt(str, s + 28, s + 35) / 10000 + sites['U[1][1]'][sites.index] = fastParseInt(str, s + 28, s + 35) / 10000; // 36 - 42 Integer u[1][1] U(2,2) - sites['U[2][2]'][sites.index] = fastParseInt(str, s + 35, s + 42) / 10000 + sites['U[2][2]'][sites.index] = fastParseInt(str, s + 35, s + 42) / 10000; // 43 - 49 Integer u[2][2] U(3,3) - sites['U[3][3]'][sites.index] = fastParseInt(str, s + 42, s + 49) / 10000 + sites['U[3][3]'][sites.index] = fastParseInt(str, s + 42, s + 49) / 10000; // 50 - 56 Integer u[0][1] U(1,2) - sites['U[1][2]'][sites.index] = fastParseInt(str, s + 49, s + 56) / 10000 + sites['U[1][2]'][sites.index] = fastParseInt(str, s + 49, s + 56) / 10000; // 57 - 63 Integer u[0][2] U(1,3) - sites['U[1][3]'][sites.index] = fastParseInt(str, s + 56, s + 63) / 10000 + sites['U[1][3]'][sites.index] = fastParseInt(str, s + 56, s + 63) / 10000; // 64 - 70 Integer u[1][2] U(2,3) - sites['U[2][3]'][sites.index] = fastParseInt(str, s + 63, s + 70) / 10000 + sites['U[2][3]'][sites.index] = fastParseInt(str, s + 63, s + 70) / 10000; // 77 - 78 LString(2) element Element symbol, right-justified. if (length >= 78) { @@ -133,10 +133,10 @@ export function addAnisotropic(sites: AnisotropicTemplate, model: string, data: if (data.tokenStart < data.tokenEnd) { TokenBuilder.addToken(sites.type_symbol, data); } else { - guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16) + guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16); } } else { - guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16) + guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16); } // 79 - 80 LString(2) charge Charge on the atom. diff --git a/src/mol-model-formats/structure/pdb/assembly.ts b/src/mol-model-formats/structure/pdb/assembly.ts index 23931f2714e99f1f737e129caef4c6dd88da42ff..64f2ac42c5a4e0cab8efb9e0874f382bd2fcc224 100644 --- a/src/mol-model-formats/structure/pdb/assembly.ts +++ b/src/mol-model-formats/structure/pdb/assembly.ts @@ -22,7 +22,7 @@ export function parseCryst1(id: string, record: string): CifCategory[] { // 56 - 66 LString Space group // 67 - 70 Integer Z value - const get = (s: number, l: number) => (record.substr(s, l) || '').trim() + const get = (s: number, l: number) => (record.substr(s, l) || '').trim(); const cell: CifCategory.Fields<mmCIF_Schema['cell']> = { entry_id: CifField.ofString(id), @@ -41,7 +41,7 @@ export function parseCryst1(id: string, record: string): CifCategory[] { Int_Tables_number: CifField.ofString('?'), cell_setting: CifField.ofString('?'), space_group_name_Hall: CifField.ofString('?') - } + }; return [CifCategory.ofFields('cell', cell), CifCategory.ofFields('symmetry', symmetry)]; } @@ -74,8 +74,8 @@ export function parseRemark350(lines: Tokens, lineStart: number, lineEnd: number current = PdbAssembly(id, details); assemblies.push(current); } else if (line.substr(13, 5) === 'BIOMT') { - const biomt = line.split(/\s+/) - const row = parseInt(line[18]) - 1 + const biomt = line.split(/\s+/); + const row = parseInt(line[18]) - 1; if (row === 0) { matrix = Mat4.identity(); diff --git a/src/mol-model-formats/structure/pdb/atom-site.ts b/src/mol-model-formats/structure/pdb/atom-site.ts index c47fa9d973e7c279194904063f08d0eb32a1f5bd..1ad9eb83109018481b424f273ce59efa2343d37f 100644 --- a/src/mol-model-formats/structure/pdb/atom-site.ts +++ b/src/mol-model-formats/structure/pdb/atom-site.ts @@ -142,10 +142,10 @@ export function addAtom(sites: AtomSiteTemplate, model: string, data: Tokenizer, if (data.tokenStart < data.tokenEnd) { TokenBuilder.addToken(sites.type_symbol, data); } else { - guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16) + guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16); } } else { - guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16) + guessElementSymbolTokens(sites.type_symbol, str, s + 12, s + 16); } // 79 - 80 LString(2) charge Charge on the atom. diff --git a/src/mol-model-formats/structure/pdb/entity.ts b/src/mol-model-formats/structure/pdb/entity.ts index 3402b32e960930964b157f8f28a955ddcdb53ffa..bce39351a57ffdda24d726c44f64a5b6b9d36b8f 100644 --- a/src/mol-model-formats/structure/pdb/entity.ts +++ b/src/mol-model-formats/structure/pdb/entity.ts @@ -17,18 +17,18 @@ const Spec = { 'ENGINEERED': '', 'MUTATION': '', 'OTHER_DETAILS': '' -} +}; type Spec = keyof typeof Spec export function parseCmpnd(lines: Tokens, lineStart: number, lineEnd: number) { - const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]) + const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]); - let currentSpec: Spec | undefined - let currentCompound: EntityCompound = { chains: [], description: '' } - const Compounds: EntityCompound[] = [] + let currentSpec: Spec | undefined; + let currentCompound: EntityCompound = { chains: [], description: '' }; + const Compounds: EntityCompound[] = []; for (let i = lineStart; i < lineEnd; i++) { - let line = getLine(i) + let line = getLine(i); // COLUMNS DATA TYPE FIELD DEFINITION // ---------------------------------------------------------------------------------- // 1 - 6 Record name "COMPND" @@ -36,44 +36,44 @@ export function parseCmpnd(lines: Tokens, lineStart: number, lineEnd: number) { // 11 - 80 Specification compound Description of the molecular components. // list - const cmpnd = line.substr(10, 70).trim() - const cmpndSpecEnd = cmpnd.indexOf(':') - const cmpndSpec = cmpnd.substring(0, cmpndSpecEnd) + const cmpnd = line.substr(10, 70).trim(); + const cmpndSpecEnd = cmpnd.indexOf(':'); + const cmpndSpec = cmpnd.substring(0, cmpndSpecEnd); - let value: string + let value: string; if (cmpndSpec in Spec) { - currentSpec = cmpndSpec as Spec - value = cmpnd.substring(cmpndSpecEnd + 2) + currentSpec = cmpndSpec as Spec; + value = cmpnd.substring(cmpndSpecEnd + 2); } else { - value = cmpnd + value = cmpnd; } - value = value.replace(/;$/, '') + value = value.replace(/;$/, ''); if (currentSpec === 'MOL_ID') { currentCompound = { chains: [], description: '' - } - Compounds.push(currentCompound) + }; + Compounds.push(currentCompound); } else if (currentSpec === 'MOLECULE') { - if (currentCompound.description) currentCompound.description += ' ' - currentCompound.description += value + if (currentCompound.description) currentCompound.description += ' '; + currentCompound.description += value; } else if (currentSpec === 'CHAIN') { - Array.prototype.push.apply(currentCompound.chains, value.split(/\s*,\s*/)) + Array.prototype.push.apply(currentCompound.chains, value.split(/\s*,\s*/)); } } - return Compounds + return Compounds; } export function parseHetnam(lines: Tokens, lineStart: number, lineEnd: number) { - const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]) + const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]); - const hetnams = new Map<string, string>() + const hetnams = new Map<string, string>(); for (let i = lineStart; i < lineEnd; i++) { - let line = getLine(i) + let line = getLine(i); // COLUMNS DATA TYPE FIELD DEFINITION // ---------------------------------------------------------------------------- // 1 - 6 Record name "HETNAM" @@ -81,15 +81,15 @@ export function parseHetnam(lines: Tokens, lineStart: number, lineEnd: number) { // 12 - 14 LString(3) hetID Het identifier, right-justified. // 16 - 70 String text Chemical name. - const het = line.substr(11, 3).trim() - const name = line.substr(15).trim() + const het = line.substr(11, 3).trim(); + const name = line.substr(15).trim(); if (hetnams.has(het)) { - hetnams.set(het, `${hetnams.get(het)!} ${name}`) + hetnams.set(het, `${hetnams.get(het)!} ${name}`); } else { - hetnams.set(het, name) + hetnams.set(het, name); } } - return hetnams + return hetnams; } \ No newline at end of file diff --git a/src/mol-model-formats/structure/pdb/secondary-structure.ts b/src/mol-model-formats/structure/pdb/secondary-structure.ts index 9045a2bfbe2331bb93f99cc46946e7b7695c2f22..f9b005ad2fc49909653aa2eeb79322dd1f31c370 100644 --- a/src/mol-model-formats/structure/pdb/secondary-structure.ts +++ b/src/mol-model-formats/structure/pdb/secondary-structure.ts @@ -32,9 +32,9 @@ const HelixTypes: {[k: string]: mmCIF_Schema['struct_conf']['conf_type_id']['T'] 8: 'HELX_LH_GA_P', 9: 'HELX_RH_27_P', // TODO or left-handed??? 10: 'HELX_RH_PP_P', // TODO or left-handed??? -} +}; function getStructConfTypeId(type: string): mmCIF_Schema['struct_conf']['conf_type_id']['T'] { - return HelixTypes[type] || 'HELX_P' + return HelixTypes[type] || 'HELX_P'; } interface PdbHelix { @@ -54,7 +54,7 @@ interface PdbHelix { } export function parseHelix(lines: Tokens, lineStart: number, lineEnd: number): CifCategory { - const helices: PdbHelix[] = [] + const helices: PdbHelix[] = []; const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]); for (let i = lineStart; i < lineEnd; i++) { @@ -94,16 +94,16 @@ export function parseHelix(lines: Tokens, lineStart: number, lineEnd: number): C helixClass: line.substr(38, 2).trim(), comment: line.substr(40, 30).trim(), length: line.substr(71, 5).trim() - }) + }); } - const beg_auth_asym_id = CifField.ofStrings(helices.map(h => h.initChainID)) - const beg_auth_comp_id = CifField.ofStrings(helices.map(h => h.initResName)) - const beg_auth_seq_id = CifField.ofStrings(helices.map(h => h.initSeqNum)) + const beg_auth_asym_id = CifField.ofStrings(helices.map(h => h.initChainID)); + const beg_auth_comp_id = CifField.ofStrings(helices.map(h => h.initResName)); + const beg_auth_seq_id = CifField.ofStrings(helices.map(h => h.initSeqNum)); - const end_auth_asym_id = CifField.ofStrings(helices.map(h => h.endChainID)) - const end_auth_comp_id = CifField.ofStrings(helices.map(h => h.endResName)) - const end_auth_seq_id = CifField.ofStrings(helices.map(h => h.endSeqNum)) + const end_auth_asym_id = CifField.ofStrings(helices.map(h => h.endChainID)); + const end_auth_comp_id = CifField.ofStrings(helices.map(h => h.endResName)); + const end_auth_seq_id = CifField.ofStrings(helices.map(h => h.endSeqNum)); const struct_conf: CifCategory.Fields<mmCIF_Schema['struct_conf']> = { beg_label_asym_id: beg_auth_asym_id, @@ -161,7 +161,7 @@ interface PdbSheet { } export function parseSheet(lines: Tokens, lineStart: number, lineEnd: number): CifCategory { - const sheets: PdbSheet[] = [] + const sheets: PdbSheet[] = []; const getLine = (n: number) => lines.data.substring(lines.indices[2 * n], lines.indices[2 * n + 1]); for (let i = lineStart; i < lineEnd; i++) { @@ -227,16 +227,16 @@ export function parseSheet(lines: Tokens, lineStart: number, lineEnd: number): C prevChainId: line.substr(64, 1).trim(), prevResSeq: line.substr(65, 4).trim(), prevICode: line.substr(69, 1).trim(), - }) + }); } - const beg_auth_asym_id = CifField.ofStrings(sheets.map(s => s.initChainID)) - const beg_auth_comp_id = CifField.ofStrings(sheets.map(s => s.initResName)) - const beg_auth_seq_id = CifField.ofStrings(sheets.map(s => s.initSeqNum)) + const beg_auth_asym_id = CifField.ofStrings(sheets.map(s => s.initChainID)); + const beg_auth_comp_id = CifField.ofStrings(sheets.map(s => s.initResName)); + const beg_auth_seq_id = CifField.ofStrings(sheets.map(s => s.initSeqNum)); - const end_auth_asym_id = CifField.ofStrings(sheets.map(s => s.endChainID)) - const end_auth_comp_id = CifField.ofStrings(sheets.map(s => s.endResName)) - const end_auth_seq_id = CifField.ofStrings(sheets.map(s => s.endSeqNum)) + const end_auth_asym_id = CifField.ofStrings(sheets.map(s => s.endChainID)); + const end_auth_comp_id = CifField.ofStrings(sheets.map(s => s.endResName)); + const end_auth_seq_id = CifField.ofStrings(sheets.map(s => s.endSeqNum)); const struct_sheet_range: CifCategory.Fields<mmCIF_Schema['struct_sheet_range']> = { beg_label_asym_id: beg_auth_asym_id, diff --git a/src/mol-model-formats/structure/pdb/to-cif.ts b/src/mol-model-formats/structure/pdb/to-cif.ts index 708ff61e5a57349b16f54777780ad08075cf8f03..8e2d1547d9cbbb2f3a920fae7813b6dffa1d30cb 100644 --- a/src/mol-model-formats/structure/pdb/to-cif.ts +++ b/src/mol-model-formats/structure/pdb/to-cif.ts @@ -56,7 +56,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> { if (!modelNum) { modelNum++; modelStr = '' + modelNum; } addAtom(atomSite, modelStr, tokenizer, s, e); } else if (substringStartsWith(data, s, e, 'ANISOU')) { - addAnisotropic(anisotropic, modelStr, tokenizer, s, e) + addAnisotropic(anisotropic, modelStr, tokenizer, s, e); } break; case 'C': @@ -71,7 +71,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> { if (!substringStartsWith(data, s, e, 'COMPND')) break; j++; } - entityBuilder.setCompounds(parseCmpnd(lines, i, j)) + entityBuilder.setCompounds(parseCmpnd(lines, i, j)); i = j - 1; } break; @@ -95,7 +95,7 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> { if (!substringStartsWith(data, s, e, 'HETNAM')) break; j++; } - heteroNames.push(...Array.from(parseHetnam(lines, i, j).entries())) + heteroNames.push(...Array.from(parseHetnam(lines, i, j).entries())); i = j - 1; } break; @@ -148,17 +148,17 @@ export async function pdbToMmCif(pdb: PdbFile): Promise<CifFrame> { } // build entity and chem_comp categories - const seqIds = Column.ofIntTokens(atomSite.auth_seq_id) - const atomIds = Column.ofStringTokens(atomSite.auth_atom_id) - const compIds = Column.ofStringTokens(atomSite.auth_comp_id) - const asymIds = Column.ofStringTokens(atomSite.auth_asym_id) - const componentBuilder = new ComponentBuilder(seqIds, atomIds) - componentBuilder.setNames(heteroNames) - entityBuilder.setNames(heteroNames) + const seqIds = Column.ofIntTokens(atomSite.auth_seq_id); + const atomIds = Column.ofStringTokens(atomSite.auth_atom_id); + const compIds = Column.ofStringTokens(atomSite.auth_comp_id); + const asymIds = Column.ofStringTokens(atomSite.auth_asym_id); + const componentBuilder = new ComponentBuilder(seqIds, atomIds); + componentBuilder.setNames(heteroNames); + entityBuilder.setNames(heteroNames); for (let i = 0, il = compIds.rowCount; i < il; ++i) { - const compId = compIds.value(i) - const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId) - atomSite.label_entity_id[i] = entityBuilder.getEntityId(compId, moleculeType, asymIds.value(i)) + const compId = compIds.value(i); + const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId); + atomSite.label_entity_id[i] = entityBuilder.getEntityId(compId, moleculeType, asymIds.value(i)); } const categories = { diff --git a/src/mol-model-formats/structure/property/anisotropic.ts b/src/mol-model-formats/structure/property/anisotropic.ts index 86db66428977fba9e1c7910f4af8524fb9488911..16cb3591e646ef9084ae255d4deeecc989bf3e5e 100644 --- a/src/mol-model-formats/structure/property/anisotropic.ts +++ b/src/mol-model-formats/structure/property/anisotropic.ts @@ -11,12 +11,12 @@ import { CifWriter } from '../../../mol-io/writer/cif'; import { FormatPropertyProvider } from '../common/property'; import { MmcifFormat } from '../mmcif'; -export { AtomSiteAnisotrop } +export { AtomSiteAnisotrop }; const Anisotrop = { U: mmCIF_Schema.atom_site_anisotrop.U, U_esd: mmCIF_Schema.atom_site_anisotrop.U_esd -} +}; type Anisotrop = Table<typeof Anisotrop> interface AtomSiteAnisotrop { @@ -26,7 +26,7 @@ interface AtomSiteAnisotrop { } namespace AtomSiteAnisotrop { - export const Schema = Anisotrop + export const Schema = Anisotrop; export const Descriptor: CustomPropertyDescriptor = { name: 'atom_site_anisotrop', @@ -45,38 +45,38 @@ namespace AtomSiteAnisotrop { } }; - export const Provider = FormatPropertyProvider.create<AtomSiteAnisotrop>(Descriptor) + export const Provider = FormatPropertyProvider.create<AtomSiteAnisotrop>(Descriptor); export function getElementToAnsiotrop(atomId: Column<number>, ansioId: Column<number>) { - const atomIdToElement = new Int32Array(atomId.rowCount) - atomIdToElement.fill(-1) + const atomIdToElement = new Int32Array(atomId.rowCount); + atomIdToElement.fill(-1); for (let i = 0, il = atomId.rowCount; i < il; i++) { - atomIdToElement[atomId.value(i)] = i + atomIdToElement[atomId.value(i)] = i; } - const elementToAnsiotrop = new Int32Array(atomId.rowCount) - elementToAnsiotrop.fill(-1) + const elementToAnsiotrop = new Int32Array(atomId.rowCount); + elementToAnsiotrop.fill(-1); for (let i = 0, il = ansioId.rowCount; i < il; ++i) { - const ei = atomIdToElement[ansioId.value(i)] - if (ei !== -1) elementToAnsiotrop[ei] = i + const ei = atomIdToElement[ansioId.value(i)]; + if (ei !== -1) elementToAnsiotrop[ei] = i; } - return elementToAnsiotrop + return elementToAnsiotrop; } export function getElementToAnsiotropFromLabel(atomLabel: Column<string>, ansioLabel: Column<string>) { - const atomLabelToElement: { [k: string]: number | undefined } = {} + const atomLabelToElement: { [k: string]: number | undefined } = {}; for (let i = 0, il = atomLabel.rowCount; i < il; i++) { - atomLabelToElement[atomLabel.value(i)] = i + atomLabelToElement[atomLabel.value(i)] = i; } - const elementToAnsiotrop = new Int32Array(atomLabel.rowCount) - elementToAnsiotrop.fill(-1) + const elementToAnsiotrop = new Int32Array(atomLabel.rowCount); + elementToAnsiotrop.fill(-1); for (let i = 0, il = ansioLabel.rowCount; i < il; ++i) { - const ei = atomLabelToElement[ansioLabel.value(i)] - if (ei !== undefined) elementToAnsiotrop[ei] = i + const ei = atomLabelToElement[ansioLabel.value(i)]; + if (ei !== undefined) elementToAnsiotrop[ei] = i; } - return elementToAnsiotrop + return elementToAnsiotrop; } } \ No newline at end of file diff --git a/src/mol-model-formats/structure/property/assembly.ts b/src/mol-model-formats/structure/property/assembly.ts index c6637ca3a481551b59d7823202df2a7226d52d8a..a82587d83f680904cbb26d2eb6c45dd31ef940d2 100644 --- a/src/mol-model-formats/structure/property/assembly.ts +++ b/src/mol-model-formats/structure/property/assembly.ts @@ -4,10 +4,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Mat4, Tensor, Vec3 } from '../../../mol-math/linear-algebra' -import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator' -import { Assembly, OperatorGroup, OperatorGroups } from '../../../mol-model/structure/model/properties/symmetry' -import { Queries as Q } from '../../../mol-model/structure' +import { Mat4, Tensor, Vec3 } from '../../../mol-math/linear-algebra'; +import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator'; +import { Assembly, OperatorGroup, OperatorGroups } from '../../../mol-model/structure/model/properties/symmetry'; +import { Queries as Q } from '../../../mol-model/structure'; import { StructureProperties } from '../../../mol-model/structure'; import { Table } from '../../../mol-data/db'; import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif'; @@ -68,7 +68,7 @@ function operatorGroupsProvider(generators: Generator[], matrices: Matrices): () } return groups; - } + }; } function getMatrices(pdbx_struct_oper_list: StructOperList): Matrices { @@ -116,7 +116,7 @@ function getAssemblyOperators(matrices: Matrices, operatorNames: string[][], sta for (let i = 0; i < op.length; i++) { Mat4.mul(m, m, matrices.get(op[i])!); } - index++ + index++; operators[operators.length] = SymmetryOperator.create(`ASM_${index}`, m, { assembly: { id: assemblyId, operId: index, operList: op } }); } diff --git a/src/mol-model-formats/structure/property/bonds/comp.ts b/src/mol-model-formats/structure/property/bonds/comp.ts index 21eafaa7f9f979a8aee88031e8d66a047a201015..ed510b10fa01f68e7efaf73a43e6720ef16dd331 100644 --- a/src/mol-model-formats/structure/property/bonds/comp.ts +++ b/src/mol-model-formats/structure/property/bonds/comp.ts @@ -5,11 +5,11 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Model } from '../../../../mol-model/structure/model/model' -import { BondType } from '../../../../mol-model/structure/model/types' +import { Model } from '../../../../mol-model/structure/model/model'; +import { BondType } from '../../../../mol-model/structure/model/types'; import { CustomPropertyDescriptor } from '../../../../mol-model/structure'; import { mmCIF_Schema } from '../../../../mol-io/reader/cif/schema/mmcif'; -import { CifWriter } from '../../../../mol-io/writer/cif' +import { CifWriter } from '../../../../mol-io/writer/cif'; import { Table } from '../../../../mol-data/db'; import { FormatPropertyProvider } from '../../common/property'; @@ -38,18 +38,18 @@ export namespace ComponentBond { if (comp_names.has(comp_id.value(i))) indices[indices.length] = i; } - return CifWriter.Category.ofTable(chem_comp_bond, indices) + return CifWriter.Category.ofTable(chem_comp_bond, indices); } }] } - } + }; - export const Provider = FormatPropertyProvider.create<ComponentBond>(Descriptor) + export const Provider = FormatPropertyProvider.create<ComponentBond>(Descriptor); export function chemCompBondFromTable(model: Model, table: Table<mmCIF_Schema['chem_comp_bond']>): Table<mmCIF_Schema['chem_comp_bond']> { return Table.pick(table, mmCIF_Schema.chem_comp_bond, (i: number) => { - return model.properties.chemicalComponentMap.has(table.comp_id.value(i)) - }) + return model.properties.chemicalComponentMap.has(table.comp_id.value(i)); + }); } export function getEntriesFromChemCompBond(data: Table<mmCIF_Schema['chem_comp_bond']>) { @@ -90,7 +90,7 @@ export namespace ComponentBond { entry.add(nameA, nameB, ord, flags); } - return entries + return entries; } export class Entry { diff --git a/src/mol-model-formats/structure/property/bonds/index-pair.ts b/src/mol-model-formats/structure/property/bonds/index-pair.ts index 98d48fabedbe7b8f45d31142ea66c08c657a8acc..7a09535eb37b4026a4055d0c7b7c7a91080528e1 100644 --- a/src/mol-model-formats/structure/property/bonds/index-pair.ts +++ b/src/mol-model-formats/structure/property/bonds/index-pair.ts @@ -34,9 +34,9 @@ function getGraph(indexA: ArrayLike<number>, indexB: ArrayLike<number>, props: P export namespace IndexPairBonds { export const Descriptor: CustomPropertyDescriptor = { name: 'index_pair_bonds', - } + }; - export const Provider = FormatPropertyProvider.create<IndexPairBonds>(Descriptor) + export const Provider = FormatPropertyProvider.create<IndexPairBonds>(Descriptor); export type Data = { pairs: { @@ -50,12 +50,12 @@ export namespace IndexPairBonds { } export function fromData(data: Data) { - const { pairs, count } = data - const indexA = pairs.indexA.toArray() - const indexB = pairs.indexB.toArray() - const order = pairs.order && pairs.order.toArray() - const symmetryA = pairs.symmetryA && pairs.symmetryA.toArray() - const symmetryB = pairs.symmetryB && pairs.symmetryB.toArray() + const { pairs, count } = data; + const indexA = pairs.indexA.toArray(); + const indexB = pairs.indexB.toArray(); + const order = pairs.order && pairs.order.toArray(); + const symmetryA = pairs.symmetryA && pairs.symmetryA.toArray(); + const symmetryB = pairs.symmetryB && pairs.symmetryB.toArray(); return getGraph(indexA, indexB, { order, symmetryA, symmetryB }, count); } } \ No newline at end of file diff --git a/src/mol-model-formats/structure/property/bonds/struct_conn.ts b/src/mol-model-formats/structure/property/bonds/struct_conn.ts index 4462ebe20da53b2081ef4ec4961a3e9f98832728..494ac4d2b6c0c62c28847de18753189b9730bbcf 100644 --- a/src/mol-model-formats/structure/property/bonds/struct_conn.ts +++ b/src/mol-model-formats/structure/property/bonds/struct_conn.ts @@ -5,14 +5,14 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Model } from '../../../../mol-model/structure/model/model' -import { Structure } from '../../../../mol-model/structure' -import { BondType } from '../../../../mol-model/structure/model/types' -import { Column, Table } from '../../../../mol-data/db' +import { Model } from '../../../../mol-model/structure/model/model'; +import { Structure } from '../../../../mol-model/structure'; +import { BondType } from '../../../../mol-model/structure/model/types'; +import { Column, Table } from '../../../../mol-data/db'; import { CustomPropertyDescriptor } from '../../../../mol-model/structure'; import { mmCIF_Schema } from '../../../../mol-io/reader/cif/schema/mmcif'; import { SortedArray } from '../../../../mol-data/int'; -import { CifWriter } from '../../../../mol-io/writer/cif' +import { CifWriter } from '../../../../mol-io/writer/cif'; import { ElementIndex, ResidueIndex } from '../../../../mol-model/structure/model/indexing'; import { getInterBondOrderFromTable } from '../../../../mol-model/structure/model/properties/atomic/bonds'; import { FormatPropertyProvider } from '../../common/property'; @@ -34,7 +34,7 @@ export namespace StructConn { const p = Provider.get(ctx.firstModel); if (!p || p.entries.length === 0) return CifWriter.Category.Empty; - const structure = ctx.structures[0] + const structure = ctx.structures[0]; const indices: number[] = []; for (const e of p.entries) { @@ -48,9 +48,9 @@ export namespace StructConn { } }] } - } + }; - export const Provider = FormatPropertyProvider.create<StructConn>(Descriptor) + export const Provider = FormatPropertyProvider.create<StructConn>(Descriptor); function hasAtom({ units }: Structure, element: ElementIndex) { for (let i = 0, _i = units.length; i < _i; i++) { @@ -120,15 +120,15 @@ export namespace StructConn { const atomIndex = model.atomicHierarchy.index.findAtomOnResidue(residueIndex, atomName, ps.label_alt_id.value(row)); if (atomIndex < 0) return void 0; return { residueIndex, atomIndex, symmetry: ps.symmetry.value(row) }; - } + }; const entries: StructConn.Entry[] = []; for (let i = 0; i < struct_conn._rowCount; i++) { - const partnerA = _p(i, p1) - const partnerB = _p(i, p2) + const partnerA = _p(i, p1); + const partnerB = _p(i, p2); if (partnerA === undefined || partnerB === undefined) continue; - const type = conn_type_id.value(i) + const type = conn_type_id.value(i); const orderType = (pdbx_value_order.value(i) || '').toLowerCase(); let flags = BondType.Flag.None; let order = 1; @@ -144,7 +144,7 @@ export namespace StructConn { struct_conn.ptnr1_label_atom_id.value(i), struct_conn.ptnr2_label_comp_id.value(i), struct_conn.ptnr2_label_atom_id.value(i) - ) + ); } switch (type) { diff --git a/src/mol-model-formats/structure/property/secondary-structure.ts b/src/mol-model-formats/structure/property/secondary-structure.ts index d1be73086b1cff12372e6ad2406aa78118fa593e..e79e9a321900da33f4def2872497d8a7b0d2b9f0 100644 --- a/src/mol-model-formats/structure/property/secondary-structure.ts +++ b/src/mol-model-formats/structure/property/secondary-structure.ts @@ -6,7 +6,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif' +import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif'; import { SecondaryStructureType } from '../../../mol-model/structure/model/types'; import { AtomicHierarchy } from '../../../mol-model/structure/model/properties/atomic'; import { SecondaryStructure } from '../../../mol-model/structure/model/properties/seconday-structure'; @@ -15,7 +15,7 @@ import { ChainIndex, ResidueIndex } from '../../../mol-model/structure/model/ind import { FormatPropertyProvider } from '../common/property'; import { CustomPropertyDescriptor } from '../../../mol-model/structure'; -export { ModelSecondaryStructure } +export { ModelSecondaryStructure }; type StructConf = Table<mmCIF_Schema['struct_conf']> type StructSheetRange = Table<mmCIF_Schema['struct_sheet_range']> @@ -25,7 +25,7 @@ namespace ModelSecondaryStructure { name: 'model_secondary_structure', }; - export const Provider = FormatPropertyProvider.create<SecondaryStructure>(Descriptor) + export const Provider = FormatPropertyProvider.create<SecondaryStructure>(Descriptor); export function fromStruct(conf: StructConf, sheetRange: StructSheetRange, hierarchy: AtomicHierarchy): SecondaryStructure { const map: SecondaryStructureMap = new Map(); @@ -34,8 +34,8 @@ namespace ModelSecondaryStructure { // must add Helices 1st because of 'key' value assignment. addSheets(sheetRange, map, conf._rowCount, elements); - const n = hierarchy.residues._rowCount - const getIndex = (rI: ResidueIndex) => rI + const n = hierarchy.residues._rowCount; + const getIndex = (rI: ResidueIndex) => rI; const secStruct: SecondaryStructureData = { type: new Int32Array(n) as any, @@ -93,9 +93,9 @@ function addHelices(cat: StructConf, map: SecondaryStructureMap, elements: Secon const asymId = beg_label_asym_id.value(i)!; if (map.has(asymId)) { - const entries = map.get(asymId)! + const entries = map.get(asymId)!; if (entries.has(entry.startSeqNumber)) { - entries.get(entry.startSeqNumber)!.push(entry) + entries.get(entry.startSeqNumber)!.push(entry); } else { entries.set(entry.startSeqNumber, [entry]); } @@ -130,7 +130,7 @@ function addSheets(cat: StructSheetRange, map: SecondaryStructureMap, sheetCount flags: type, sheet_id: id, symmetry: void 0 - } + }; const entry: SecondaryStructureEntry = { startSeqNumber: beg_label_seq_id.value(i), startInsCode: pdbx_beg_PDB_ins_code.value(i), @@ -144,9 +144,9 @@ function addSheets(cat: StructSheetRange, map: SecondaryStructureMap, sheetCount const asymId = beg_label_asym_id.value(i)!; if (map.has(asymId)) { - const entries = map.get(asymId)! + const entries = map.get(asymId)!; if (entries.has(entry.startSeqNumber)) { - entries.get(entry.startSeqNumber)!.push(entry) + entries.get(entry.startSeqNumber)!.push(entry); } else { entries.set(entry.startSeqNumber, [entry]); } diff --git a/src/mol-model-formats/structure/property/symmetry.ts b/src/mol-model-formats/structure/property/symmetry.ts index 8e3615079eafff748a161e731837ab6c15e91033..75330f6f657469b770f2345054864d98642d2f65 100644 --- a/src/mol-model-formats/structure/property/symmetry.ts +++ b/src/mol-model-formats/structure/property/symmetry.ts @@ -14,14 +14,14 @@ import { CustomPropertyDescriptor } from '../../../mol-model/structure'; import { FormatPropertyProvider } from '../common/property'; import { Table } from '../../../mol-data/db'; -export { ModelSymmetry } +export { ModelSymmetry }; namespace ModelSymmetry { export const Descriptor: CustomPropertyDescriptor = { name: 'model_symmetry', }; - export const Provider = FormatPropertyProvider.create<Symmetry>(Descriptor) + export const Provider = FormatPropertyProvider.create<Symmetry>(Descriptor); type Data = { symmetry: Table<mmCIF_Schema['symmetry']> @@ -50,14 +50,14 @@ function checkNonStandardCrystalFrame(atom_sites: Table<mmCIF_Schema['atom_sites function getSpacegroupNameOrNumber(symmetry: Table<mmCIF_Schema['symmetry']>) { const groupNumber = symmetry['Int_Tables_number'].value(0); const groupName = symmetry['space_group_name_H-M'].value(0); - if (!symmetry['Int_Tables_number'].isDefined) return groupName - if (!symmetry['space_group_name_H-M'].isDefined) return groupNumber - return groupName + if (!symmetry['Int_Tables_number'].isDefined) return groupName; + if (!symmetry['space_group_name_H-M'].isDefined) return groupNumber; + return groupName; } function getSpacegroup(symmetry: Table<mmCIF_Schema['symmetry']>, cell: Table<mmCIF_Schema['cell']>): Spacegroup { if (symmetry._rowCount === 0 || cell._rowCount === 0) return Spacegroup.ZeroP1; - const nameOrNumber = getSpacegroupNameOrNumber(symmetry) + const nameOrNumber = getSpacegroupNameOrNumber(symmetry); const spaceCell = SpacegroupCell.create(nameOrNumber, Vec3.create(cell.length_a.value(0), cell.length_b.value(0), cell.length_c.value(0)), Vec3.scale(Vec3.zero(), Vec3.create(cell.angle_alpha.value(0), cell.angle_beta.value(0), cell.angle_gamma.value(0)), Math.PI / 180)); @@ -78,7 +78,7 @@ function getNcsOperators(struct_ncs_oper: Table<mmCIF_Schema['struct_ncs_oper']> if (!SymmetryOperator.checkIfRotationAndTranslation(m, v)) continue; // ignore non-identity 'given' NCS operators if (struct_ncs_oper.code.value(i) === 'given' && !Mat3.isIdentity(m) && !Vec3.isZero(v)) continue; - const ncsId = id.value(i) + const ncsId = id.value(i); opers[opers.length] = SymmetryOperator.ofRotationAndOffset(`ncs_${ncsId}`, m, v, ncsId); } return opers; diff --git a/src/mol-model-formats/structure/psf.ts b/src/mol-model-formats/structure/psf.ts index 88e5a53d64a8e3f6dfdf798b15f8e61f580dccbf..73383d74524128dd1721ff04d2ee4dcb4064dc81 100644 --- a/src/mol-model-formats/structure/psf.ts +++ b/src/mol-model-formats/structure/psf.ts @@ -17,50 +17,50 @@ import { Topology } from '../../mol-model/structure/topology/topology'; import { createBasic, BasicSchema } from './basic/schema'; function getBasic(atoms: PsfFile['atoms']) { - const auth_atom_id = atoms.atomName - const auth_comp_id = atoms.residueName + const auth_atom_id = atoms.atomName; + const auth_comp_id = atoms.residueName; - const entityIds = new Array<string>(atoms.count) - const asymIds = new Array<string>(atoms.count) - const seqIds = new Uint32Array(atoms.count) - const ids = new Uint32Array(atoms.count) + const entityIds = new Array<string>(atoms.count); + const asymIds = new Array<string>(atoms.count); + const seqIds = new Uint32Array(atoms.count); + const ids = new Uint32Array(atoms.count); - const entityBuilder = new EntityBuilder() - const componentBuilder = new ComponentBuilder(atoms.residueId, atoms.atomName) + const entityBuilder = new EntityBuilder(); + const componentBuilder = new ComponentBuilder(atoms.residueId, atoms.atomName); - let currentEntityId = '' - let currentAsymIndex = 0 - let currentAsymId = '' - let currentSeqId = 0 - let prevMoleculeType = MoleculeType.Unknown - let prevResidueNumber = -1 + let currentEntityId = ''; + let currentAsymIndex = 0; + let currentAsymId = ''; + let currentSeqId = 0; + let prevMoleculeType = MoleculeType.Unknown; + let prevResidueNumber = -1; for (let i = 0, il = atoms.count; i < il; ++i) { - const residueNumber = atoms.residueId.value(i) + const residueNumber = atoms.residueId.value(i); if (residueNumber !== prevResidueNumber) { - const compId = atoms.residueName.value(i) - const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId) + const compId = atoms.residueName.value(i); + const moleculeType = getMoleculeType(componentBuilder.add(compId, i).type, compId); if (moleculeType !== prevMoleculeType || residueNumber !== prevResidueNumber + 1) { - currentAsymId = getChainId(currentAsymIndex) - currentAsymIndex += 1 - currentSeqId = 0 + currentAsymId = getChainId(currentAsymIndex); + currentAsymIndex += 1; + currentSeqId = 0; } - currentEntityId = entityBuilder.getEntityId(compId, moleculeType, currentAsymId) - currentSeqId += 1 + currentEntityId = entityBuilder.getEntityId(compId, moleculeType, currentAsymId); + currentSeqId += 1; - prevResidueNumber = residueNumber - prevMoleculeType = moleculeType + prevResidueNumber = residueNumber; + prevMoleculeType = moleculeType; } - entityIds[i] = currentEntityId - asymIds[i] = currentAsymId - seqIds[i] = currentSeqId - ids[i] = i + entityIds[i] = currentEntityId; + asymIds[i] = currentAsymId; + seqIds[i] = currentSeqId; + ids[i] = i; } - const auth_asym_id = Column.ofStringArray(asymIds) + const auth_asym_id = Column.ofStringArray(asymIds); const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, { auth_asym_id, @@ -79,24 +79,24 @@ function getBasic(atoms: PsfFile['atoms']) { type_symbol: Column.ofStringArray(Column.mapToArray(atoms.atomName, s => guessElementSymbolString(s))), pdbx_PDB_model_num: Column.ofConst(1, atoms.count, Column.Schema.int), - }, atoms.count) + }, atoms.count); return createBasic({ entity: entityBuilder.getEntityTable(), chem_comp: componentBuilder.getChemCompTable(), atom_site - }) + }); } // -export { PsfFormat } +export { PsfFormat }; type PsfFormat = ModelFormat<PsfFile> namespace PsfFormat { export function is(x: ModelFormat): x is PsfFormat { - return x.kind === 'psf' + return x.kind === 'psf'; } export function fromPsf(psf: PsfFile): PsfFormat { @@ -107,9 +107,9 @@ namespace PsfFormat { export function topologyFromPsf(psf: PsfFile): Task<Topology> { return Task.create('Parse PSF', async ctx => { const format = PsfFormat.fromPsf(psf); - const basic = getBasic(psf.atoms) + const basic = getBasic(psf.atoms); - const { atomIdA, atomIdB } = psf.bonds + const { atomIdA, atomIdB } = psf.bonds; const bonds = { indexA: Column.ofLambda({ @@ -123,8 +123,8 @@ export function topologyFromPsf(psf: PsfFile): Task<Topology> { schema: atomIdB.schema, }), order: Column.ofConst(1, psf.bonds.count, Column.Schema.int) - } + }; - return Topology.create(psf.id, basic, bonds, format) - }) + return Topology.create(psf.id, basic, bonds, format); + }); } \ No newline at end of file diff --git a/src/mol-model-formats/structure/util.ts b/src/mol-model-formats/structure/util.ts index 71959650bd411b465d47b4c8efc4b1fbe7e8e811..302dd417cd0c3d9141fc6c020b14ca373a2fe672 100644 --- a/src/mol-model-formats/structure/util.ts +++ b/src/mol-model-formats/structure/util.ts @@ -7,28 +7,28 @@ import { TokenBuilder, Tokens } from '../../mol-io/reader/common/text/tokenizer'; export function guessElementSymbolTokens(tokens: Tokens, str: string, start: number, end: number) { - let s = start, e = end - 1 + let s = start, e = end - 1; // trim spaces and numbers - let c = str.charCodeAt(s) - while ((c === 32 || (c >= 48 && c <= 57)) && s <= e) c = str.charCodeAt(++s) - c = str.charCodeAt(e) - while ((c === 32 || (c >= 48 && c <= 57)) && e >= s) c = str.charCodeAt(--e) + let c = str.charCodeAt(s); + while ((c === 32 || (c >= 48 && c <= 57)) && s <= e) c = str.charCodeAt(++s); + c = str.charCodeAt(e); + while ((c === 32 || (c >= 48 && c <= 57)) && e >= s) c = str.charCodeAt(--e); - ++e + ++e; - if (s === e) return TokenBuilder.add(tokens, s, e) // empty - if (s + 1 === e) return TokenBuilder.add(tokens, s, e) // one char + if (s === e) return TokenBuilder.add(tokens, s, e); // empty + if (s + 1 === e) return TokenBuilder.add(tokens, s, e); // one char - c = str.charCodeAt(s) + c = str.charCodeAt(s); if (s + 2 === e) { // two chars - const c2 = str.charCodeAt(s + 1) + const c2 = str.charCodeAt(s + 1); if ( ((c === 78 || c === 110) && (c2 === 65 || c2 === 97)) || // NA na Na nA ((c === 67 || c === 99) && (c2 === 76 || c2 === 108)) || // CL ((c === 70 || c === 102) && (c2 === 69 || c2 === 101)) // FE - ) return TokenBuilder.add(tokens, s, s + 2) + ) return TokenBuilder.add(tokens, s, s + 2); } if ( @@ -38,25 +38,25 @@ export function guessElementSymbolTokens(tokens: Tokens, str: string, start: num c === 79 || c === 111 || // O o c === 80 || c === 112 || // P p c === 83 || c === 115 // S s - ) return TokenBuilder.add(tokens, s, s + 1) + ) return TokenBuilder.add(tokens, s, s + 1); - TokenBuilder.add(tokens, s, s) // no reasonable guess, add empty token + TokenBuilder.add(tokens, s, s); // no reasonable guess, add empty token } export function guessElementSymbolString(str: string) { // trim spaces and numbers, convert to upper case - str = str.trim().toUpperCase() - const l = str.length + str = str.trim().toUpperCase(); + const l = str.length; - if (l === 0) return str // empty - if (l === 1) return str // one char + if (l === 0) return str; // empty + if (l === 1) return str; // one char if (l === 2) { // two chars - if (str === 'NA' || str === 'CL' || str === 'FE') return str + if (str === 'NA' || str === 'CL' || str === 'FE') return str; } - const c = str[0] - if (c === 'C' || c === 'H' || c === 'N' || c === 'O' || c === 'P' || c === 'S') return c + const c = str[0]; + if (c === 'C' || c === 'H' || c === 'N' || c === 'O' || c === 'P' || c === 'S') return c; - return '' // no reasonable guess, return empty string + return ''; // no reasonable guess, return empty string } \ No newline at end of file diff --git a/src/mol-model-formats/volume/ccp4.ts b/src/mol-model-formats/volume/ccp4.ts index 244dcc352a348f6e7a4c5c6c19d1ab56483e8e59..13714137edaf6b5560d603f3f926f31a39aa8715 100644 --- a/src/mol-model-formats/volume/ccp4.ts +++ b/src/mol-model-formats/volume/ccp4.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { VolumeData } from '../../mol-model/volume/data' +import { VolumeData } from '../../mol-model/volume/data'; import { Task } from '../../mol-task'; import { SpacegroupCell, Box3D } from '../../mol-math/geometry'; import { Tensor, Vec3 } from '../../mol-math/linear-algebra'; @@ -17,18 +17,18 @@ import { arrayMin, arrayRms, arrayMean, arrayMax } from '../../mol-util/array'; /** When available (e.g. in MRC files) use ORIGIN records instead of N[CRS]START */ export function getCcp4Origin(header: Ccp4Header): Vec3 { if (header.originX === 0.0 && header.originY === 0.0 && header.originZ === 0.0) { - return Vec3.create(header.NCSTART, header.NRSTART, header.NSSTART) + return Vec3.create(header.NCSTART, header.NRSTART, header.NSSTART); } else { return Vec3.create( header.originX / (header.xLength / header.NX), header.originY / (header.yLength / header.NY), header.originZ / (header.zLength / header.NZ) - ) + ); } } function getTypedArrayCtor(header: Ccp4Header) { - const valueType = getCcp4ValueType(header) + const valueType = getCcp4ValueType(header); switch (valueType) { case TypedArrayValueType.Float32: return Float32Array; case TypedArrayValueType.Int8: return Int8Array; @@ -41,10 +41,10 @@ function getTypedArrayCtor(header: Ccp4Header) { export function volumeFromCcp4(source: Ccp4File, params?: { voxelSize?: Vec3, offset?: Vec3 }): Task<VolumeData> { return Task.create<VolumeData>('Create Volume Data', async ctx => { const { header, values } = source; - const size = Vec3.create(header.xLength, header.yLength, header.zLength) - if (params && params.voxelSize) Vec3.mul(size, size, params.voxelSize) - const angles = Vec3.create(degToRad(header.alpha), degToRad(header.beta), degToRad(header.gamma)) - const spacegroup = header.ISPG > 65536 ? 0 : header.ISPG + const size = Vec3.create(header.xLength, header.yLength, header.zLength); + if (params && params.voxelSize) Vec3.mul(size, size, params.voxelSize); + const angles = Vec3.create(degToRad(header.alpha), degToRad(header.beta), degToRad(header.gamma)); + const spacegroup = header.ISPG > 65536 ? 0 : header.ISPG; const cell = SpacegroupCell.create(spacegroup || 'P 1', size, angles); const axis_order_fast_to_slow = Vec3.create(header.MAPC - 1, header.MAPR - 1, header.MAPS - 1); @@ -52,8 +52,8 @@ export function volumeFromCcp4(source: Ccp4File, params?: { voxelSize?: Vec3, of const grid = [header.NX, header.NY, header.NZ]; const extent = normalizeOrder([header.NC, header.NR, header.NS]); - const origin = getCcp4Origin(header) - if (params?.offset) Vec3.add(origin, origin, params.offset) + const origin = getCcp4Origin(header); + if (params?.offset) Vec3.add(origin, origin, params.offset); const gridOrigin = normalizeOrder(origin); const origin_frac = Vec3.create(gridOrigin[0] / grid[0], gridOrigin[1] / grid[1], gridOrigin[2] / grid[2]); diff --git a/src/mol-model-formats/volume/density-server.ts b/src/mol-model-formats/volume/density-server.ts index aefd8a3e7371bc69955b5b39e11a4d495798e79a..137d2dc1d7bc193a9202cab23e6c760e738feb2e 100644 --- a/src/mol-model-formats/volume/density-server.ts +++ b/src/mol-model-formats/volume/density-server.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { DensityServer_Data_Database } from '../../mol-io/reader/cif/schema/density-server' -import { VolumeData } from '../../mol-model/volume/data' +import { DensityServer_Data_Database } from '../../mol-io/reader/cif/schema/density-server'; +import { VolumeData } from '../../mol-model/volume/data'; import { Task } from '../../mol-task'; import { SpacegroupCell, Box3D } from '../../mol-math/geometry'; import { Tensor, Vec3 } from '../../mol-math/linear-algebra'; @@ -30,7 +30,7 @@ function volumeFromDensityServerData(source: DensityServer_Data_Database): Task< const data = Tensor.create(tensorSpace, Tensor.Data1(values.values.toArray({ array: Float32Array }))); // origin and dimensions are in "axis order" and need to be reordered - const origin = Vec3.ofArray(normalizeOrder(info.origin.value(0))) + const origin = Vec3.ofArray(normalizeOrder(info.origin.value(0))); const dimensions = Vec3.ofArray(normalizeOrder(info.dimensions.value(0))); return { @@ -47,4 +47,4 @@ function volumeFromDensityServerData(source: DensityServer_Data_Database): Task< }); } -export { volumeFromDensityServerData } \ No newline at end of file +export { volumeFromDensityServerData }; \ No newline at end of file diff --git a/src/mol-model-formats/volume/dsn6.ts b/src/mol-model-formats/volume/dsn6.ts index 30a83c2dd59ffddda29a68caefb950848a79315e..84b6ce107e18cb6b1721aff8121f172f81e18289 100644 --- a/src/mol-model-formats/volume/dsn6.ts +++ b/src/mol-model-formats/volume/dsn6.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { VolumeData } from '../../mol-model/volume/data' +import { VolumeData } from '../../mol-model/volume/data'; import { Task } from '../../mol-task'; import { SpacegroupCell, Box3D } from '../../mol-math/geometry'; import { Tensor, Vec3 } from '../../mol-math/linear-algebra'; @@ -15,10 +15,10 @@ import { arrayMin, arrayMax, arrayMean, arrayRms } from '../../mol-util/array'; function volumeFromDsn6(source: Dsn6File, params?: { voxelSize?: Vec3 }): Task<VolumeData> { return Task.create<VolumeData>('Create Volume Data', async ctx => { const { header, values } = source; - const size = Vec3.create(header.xlen, header.ylen, header.zlen) - if (params && params.voxelSize) Vec3.mul(size, size, params.voxelSize) - const angles = Vec3.create(degToRad(header.alpha), degToRad(header.beta), degToRad(header.gamma)) - const cell = SpacegroupCell.create('P 1', size, angles) + const size = Vec3.create(header.xlen, header.ylen, header.zlen); + if (params && params.voxelSize) Vec3.mul(size, size, params.voxelSize); + const angles = Vec3.create(degToRad(header.alpha), degToRad(header.beta), degToRad(header.gamma)); + const cell = SpacegroupCell.create('P 1', size, angles); const grid = [header.xRate, header.yRate, header.zRate]; const extent = [header.xExtent, header.yExtent, header.zExtent]; @@ -45,4 +45,4 @@ function volumeFromDsn6(source: Dsn6File, params?: { voxelSize?: Vec3 }): Task<V }); } -export { volumeFromDsn6 } \ No newline at end of file +export { volumeFromDsn6 }; \ No newline at end of file diff --git a/src/mol-model-props/common/custom-element-property.ts b/src/mol-model-props/common/custom-element-property.ts index 89c5581dec23f9ed45c66b1294d99771bbb92c41..74d9da21c0b7dbaf226d070517edbe1695e3a6e8 100644 --- a/src/mol-model-props/common/custom-element-property.ts +++ b/src/mol-model-props/common/custom-element-property.ts @@ -42,12 +42,12 @@ namespace CustomElementProperty { } export function create<T>(builder: Builder<T>): CustomElementProperty<T> { - const modelProperty = createModelProperty(builder) + const modelProperty = createModelProperty(builder); return { propertyProvider: modelProperty, colorThemeProvider: builder.coloring?.getColor && createColorThemeProvider(modelProperty, builder.coloring.getColor, builder.coloring.defaultColor), labelProvider: builder.getLabel && createLabelProvider(modelProperty, builder.getLabel) - } + }; } function createModelProperty<T>(builder: Builder<T>) { @@ -61,9 +61,9 @@ namespace CustomElementProperty { getParams: (data: Model) => ({}), isApplicable: (data: Model) => !!builder.isApplicable?.(data), obtain: async (ctx: CustomProperty.Context, data: Model) => { - return await builder.getData(data, ctx) + return await builder.getData(data, ctx); } - }) + }); } function createColorThemeProvider<T>(modelProperty: CustomModelProperty.Provider<{}, Value<T>>, getColor: (p: T) => Color, defaultColor: Color): ColorTheme.Provider<{}> { @@ -71,18 +71,18 @@ namespace CustomElementProperty { function Coloring(ctx: ThemeDataContext, props: {}): ColorTheme<{}> { let color: LocationColor; - const property = ctx.structure && modelProperty.get(ctx.structure.models[0]) - const contextHash = property?.version + const property = ctx.structure && modelProperty.get(ctx.structure.models[0]); + const contextHash = property?.version; if (property?.value && ctx.structure) { - const data = property.value + const data = property.value; color = (location: Location) => { if (StructureElement.Location.is(location)) { const e = data.get(location.element); if (typeof e !== 'undefined') return getColor(e); } return defaultColor; - } + }; } else { color = () => defaultColor; } @@ -109,7 +109,7 @@ namespace CustomElementProperty { attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? modelProperty.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(), detach: (data: ThemeDataContext) => data.structure && data.structure.models[0].customProperties.reference(modelProperty.descriptor, false) } - } + }; } function createLabelProvider<T>(modelProperty: CustomModelProperty.Provider<{}, Value<T>>, getLabel: (p: T) => string | undefined): LociLabelProvider { @@ -117,15 +117,15 @@ namespace CustomElementProperty { label: (loci: Loci) => { if (loci.kind === 'element-loci') { const e = loci.elements[0]; - if (!e || !e.unit.model.customProperties.hasReference(modelProperty.descriptor)) return - const data = modelProperty.get(e.unit.model).value - const element = e.unit.elements[OrderedSet.start(e.indices)] - const value = data?.get(element) - if (value === undefined) return + if (!e || !e.unit.model.customProperties.hasReference(modelProperty.descriptor)) return; + const data = modelProperty.get(e.unit.model).value; + const element = e.unit.elements[OrderedSet.start(e.indices)]; + const value = data?.get(element); + if (value === undefined) return; return getLabel(value); } - return + return; } - } + }; } } \ No newline at end of file diff --git a/src/mol-model-props/common/custom-model-property.ts b/src/mol-model-props/common/custom-model-property.ts index 70181907a06c1e1a0d9392488f9535b9290e35ca..eea8c387fc19f53d77056a109386cb06eb5a78ac 100644 --- a/src/mol-model-props/common/custom-model-property.ts +++ b/src/mol-model-props/common/custom-model-property.ts @@ -9,7 +9,7 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ValueBox } from '../../mol-util'; import { CustomProperty } from './custom-property'; -export { CustomModelProperty } +export { CustomModelProperty }; namespace CustomModelProperty { export interface Provider<Params extends PD.Params, Value> extends CustomProperty.Provider<Model, Params, Value> { } @@ -25,25 +25,25 @@ namespace CustomModelProperty { } export function createProvider<Params extends PD.Params, Value>(builder: ProviderBuilder<Params, Value>): CustomProperty.Provider<Model, Params, Value> { - const descriptorName = builder.descriptor.name - const propertyDataName = builder.type === 'static' ? '_staticPropertyData' : '_dynamicPropertyData' + const descriptorName = builder.descriptor.name; + const propertyDataName = builder.type === 'static' ? '_staticPropertyData' : '_dynamicPropertyData'; const get = (data: Model) => { if (!(descriptorName in data[propertyDataName])) { (data[propertyDataName][descriptorName] as CustomProperty.Container<PD.Values<Params>, Value>) = { props: { ...PD.getDefaultValues(builder.getParams(data)) }, data: ValueBox.create(undefined) - } + }; } return data[propertyDataName][descriptorName] as CustomProperty.Container<PD.Values<Params>, Value>; - } + }; const set = (data: Model, props: PD.Values<Params>, value: Value | undefined) => { const property = get(data); (data[propertyDataName][descriptorName] as CustomProperty.Container<PD.Values<Params>, Value>) = { props, data: ValueBox.withValue(property.data, value) }; - } + }; return { label: builder.label, @@ -53,24 +53,24 @@ namespace CustomModelProperty { isApplicable: builder.isApplicable, attach: async (ctx: CustomProperty.Context, data: Model, props: Partial<PD.Values<Params>> = {}, addRef) => { if (addRef) data.customProperties.reference(builder.descriptor, true); - const property = get(data) - const p = PD.merge(builder.defaultParams, property.props, props) - if (property.data.value && PD.areEqual(builder.defaultParams, property.props, p)) return - const value = await builder.obtain(ctx, data, p) + const property = get(data); + const p = PD.merge(builder.defaultParams, property.props, props); + if (property.data.value && PD.areEqual(builder.defaultParams, property.props, p)) return; + const value = await builder.obtain(ctx, data, p); data.customProperties.add(builder.descriptor); set(data, p, value); }, ref: (data: Model, add: boolean) => data.customProperties.reference(builder.descriptor, add), get: (data: Model) => get(data)?.data, set: (data: Model, props: Partial<PD.Values<Params>> = {}) => { - const property = get(data) - const p = PD.merge(builder.defaultParams, property.props, props) + const property = get(data); + const p = PD.merge(builder.defaultParams, property.props, props); if (!PD.areEqual(builder.defaultParams, property.props, p)) { // this invalidates property.value - set(data, p, undefined) + set(data, p, undefined); } }, props: (data: Model) => get(data).props, - } + }; } } \ No newline at end of file diff --git a/src/mol-model-props/common/custom-property.ts b/src/mol-model-props/common/custom-property.ts index 9f3c377716f2167817af3c995a981bbc94a9207f..80e40837d6fda912a4dde3c4ae94c2673a89bd95 100644 --- a/src/mol-model-props/common/custom-property.ts +++ b/src/mol-model-props/common/custom-property.ts @@ -12,7 +12,7 @@ import { OrderedMap } from 'immutable'; type AjaxTask = import('../../mol-util/data-source').AjaxTask -export { CustomProperty } +export { CustomProperty }; namespace CustomProperty { export interface Context { @@ -44,54 +44,54 @@ namespace CustomProperty { /** Get params for all applicable property providers */ getParams(data?: Data) { - const propertiesParams: PD.Params = {} - const autoAttachOptions: [string, string][] = [] - const autoAttachDefault: string[] = [] + const propertiesParams: PD.Params = {}; + const autoAttachOptions: [string, string][] = []; + const autoAttachDefault: string[] = []; if (data) { const values = this.providers.values(); while (true) { - const v = values.next() - if (v.done) break + const v = values.next(); + if (v.done) break; - const provider = v.value - if (!provider.isApplicable(data)) continue + const provider = v.value; + if (!provider.isApplicable(data)) continue; - autoAttachOptions.push([provider.descriptor.name, provider.label]) + autoAttachOptions.push([provider.descriptor.name, provider.label]); if (this.defaultAutoAttachValues.get(provider.descriptor.name)) { - autoAttachDefault.push(provider.descriptor.name) + autoAttachDefault.push(provider.descriptor.name); } propertiesParams[provider.descriptor.name] = PD.Group({ ...provider.getParams(data) - }, { label: provider.label }) + }, { label: provider.label }); } } return { autoAttach: PD.MultiSelect(autoAttachDefault, autoAttachOptions), properties: PD.Group(propertiesParams, { isFlat: true }) - } + }; } setDefaultAutoAttach(name: string, value: boolean) { - this.defaultAutoAttachValues.set(name, value) + this.defaultAutoAttachValues.set(name, value); } get(name: string) { const prop = this.providers.get(name); if (!prop) { - throw new Error(`Custom property '${name}' is not registered.`) + throw new Error(`Custom property '${name}' is not registered.`); } - return this.providers.get(name) + return this.providers.get(name); } register(provider: Provider<Data, any, any>, defaultAutoAttach: boolean) { - this.providers.set(provider.descriptor.name, provider) - this.defaultAutoAttachValues.set(provider.descriptor.name, defaultAutoAttach) + this.providers.set(provider.descriptor.name, provider); + this.defaultAutoAttachValues.set(provider.descriptor.name, defaultAutoAttach); } unregister(name: string) { - this.providers.delete(name) - this.defaultAutoAttachValues.delete(name) + this.providers.delete(name); + this.defaultAutoAttachValues.delete(name); } } } \ No newline at end of file diff --git a/src/mol-model-props/common/custom-structure-property.ts b/src/mol-model-props/common/custom-structure-property.ts index 8d5a40c027bed9388b5884cd3fff204bd0095e94..8a5adb84b7c19205502d603050fd9689784474a2 100644 --- a/src/mol-model-props/common/custom-structure-property.ts +++ b/src/mol-model-props/common/custom-structure-property.ts @@ -9,7 +9,7 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ValueBox } from '../../mol-util'; import { CustomProperty } from './custom-property'; -export { CustomStructureProperty } +export { CustomStructureProperty }; namespace CustomStructureProperty { export interface Provider<Params extends PD.Params, Value> extends CustomProperty.Provider<Structure, Params, Value> { } @@ -25,25 +25,25 @@ namespace CustomStructureProperty { } export function createProvider<Params extends PD.Params, Value>(builder: ProviderBuilder<Params, Value>): CustomProperty.Provider<Structure, Params, Value> { - const descriptorName = builder.descriptor.name - const propertyDataName = builder.type === 'root' ? 'inheritedPropertyData' : 'currentPropertyData' + const descriptorName = builder.descriptor.name; + const propertyDataName = builder.type === 'root' ? 'inheritedPropertyData' : 'currentPropertyData'; const get = (data: Structure) => { if (!(descriptorName in data[propertyDataName])) { (data[propertyDataName][descriptorName] as CustomProperty.Container<PD.Values<Params>, Value>) = { props: { ...PD.getDefaultValues(builder.getParams(data)) }, data: ValueBox.create(undefined) - } + }; } return data[propertyDataName][descriptorName] as CustomProperty.Container<PD.Values<Params>, Value>; - } + }; const set = (data: Structure, props: PD.Values<Params>, value: Value | undefined) => { const property = get(data); (data[propertyDataName][descriptorName] as CustomProperty.Container<PD.Values<Params>, Value>) = { props, data: ValueBox.withValue(property.data, value) }; - } + }; return { label: builder.label, @@ -53,27 +53,27 @@ namespace CustomStructureProperty { isApplicable: builder.isApplicable, attach: async (ctx: CustomProperty.Context, data: Structure, props: Partial<PD.Values<Params>> = {}, addRef) => { if (addRef) data.customPropertyDescriptors.reference(builder.descriptor, true); - if (builder.type === 'root') data = data.root - const rootProps = get(data.root).props - const property = get(data) - const p = PD.merge(builder.defaultParams, rootProps, props) - if (property.data.value && PD.areEqual(builder.defaultParams, property.props, p)) return - const value = await builder.obtain(ctx, data, p) + if (builder.type === 'root') data = data.root; + const rootProps = get(data.root).props; + const property = get(data); + const p = PD.merge(builder.defaultParams, rootProps, props); + if (property.data.value && PD.areEqual(builder.defaultParams, property.props, p)) return; + const value = await builder.obtain(ctx, data, p); data.customPropertyDescriptors.add(builder.descriptor); set(data, p, value); }, ref: (data: Structure, add: boolean) => data.customPropertyDescriptors.reference(builder.descriptor, add), get: (data: Structure) => get(data).data, set: (data: Structure, props: Partial<PD.Values<Params>> = {}, value?: Value) => { - if (builder.type === 'root') data = data.root - const property = get(data) - const p = PD.merge(builder.defaultParams, property.props, props) + if (builder.type === 'root') data = data.root; + const property = get(data); + const p = PD.merge(builder.defaultParams, property.props, props); if (!PD.areEqual(builder.defaultParams, property.props, p)) { // this invalidates property.value - set(data, p, value) + set(data, p, value); } }, props: (data: Structure) => get(data).props, - } + }; } } \ No newline at end of file diff --git a/src/mol-model-props/common/wrapper.ts b/src/mol-model-props/common/wrapper.ts index 7f3523515dbfc88602fe798e05c7a6c79328b8f0..5785a5fce81768920a103833a438794350e407c3 100644 --- a/src/mol-model-props/common/wrapper.ts +++ b/src/mol-model-props/common/wrapper.ts @@ -33,7 +33,7 @@ namespace PropertyWrapper { source: [{ data: info, rowCount: 1 }] }; } - } + }; } const _info_fields: CifWriter.Field<number, Info>[] = [ @@ -52,4 +52,4 @@ namespace PropertyWrapper { } } -export { PropertyWrapper } \ No newline at end of file +export { PropertyWrapper }; \ No newline at end of file diff --git a/src/mol-model-props/computed/accessible-surface-area.ts b/src/mol-model-props/computed/accessible-surface-area.ts index b3867ca743589cb6f1fd8d90be17510dce2e1715..f691387ea23d69f1213832fef5fb02d96e406d79 100644 --- a/src/mol-model-props/computed/accessible-surface-area.ts +++ b/src/mol-model-props/computed/accessible-surface-area.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ShrakeRupleyComputationParams, AccessibleSurfaceArea } from './accessible-surface-area/shrake-rupley'; import { Structure, CustomPropertyDescriptor, Unit } from '../../mol-model/structure'; import { CustomStructureProperty } from '../common/custom-structure-property'; @@ -16,28 +16,28 @@ import Type from '../../mol-script/language/type'; export const AccessibleSurfaceAreaParams = { ...ShrakeRupleyComputationParams -} +}; export type AccessibleSurfaceAreaParams = typeof AccessibleSurfaceAreaParams export type AccessibleSurfaceAreaProps = PD.Values<AccessibleSurfaceAreaParams> export const AccessibleSurfaceAreaSymbols = { isBuried: QuerySymbolRuntime.Dynamic(CustomPropSymbol('computed', 'accessible-surface-area.is-buried', Type.Bool), ctx => { - if (!Unit.isAtomic(ctx.element.unit)) return false - const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(ctx.element.structure).value - if (!accessibleSurfaceArea) return false - return AccessibleSurfaceArea.getFlag(ctx.element, accessibleSurfaceArea) === AccessibleSurfaceArea.Flag.Buried + if (!Unit.isAtomic(ctx.element.unit)) return false; + const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(ctx.element.structure).value; + if (!accessibleSurfaceArea) return false; + return AccessibleSurfaceArea.getFlag(ctx.element, accessibleSurfaceArea) === AccessibleSurfaceArea.Flag.Buried; } ), isAccessible: QuerySymbolRuntime.Dynamic(CustomPropSymbol('computed', 'accessible-surface-area.is-accessible', Type.Bool), ctx => { - if (!Unit.isAtomic(ctx.element.unit)) return false - const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(ctx.element.structure).value - if (!accessibleSurfaceArea) return false - return AccessibleSurfaceArea.getFlag(ctx.element, accessibleSurfaceArea) === AccessibleSurfaceArea.Flag.Accessible + if (!Unit.isAtomic(ctx.element.unit)) return false; + const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(ctx.element.structure).value; + if (!accessibleSurfaceArea) return false; + return AccessibleSurfaceArea.getFlag(ctx.element, accessibleSurfaceArea) === AccessibleSurfaceArea.Flag.Accessible; } ), -} +}; export type AccessibleSurfaceAreaValue = AccessibleSurfaceArea @@ -53,7 +53,7 @@ export const AccessibleSurfaceAreaProvider: CustomStructureProperty.Provider<Acc getParams: (data: Structure) => AccessibleSurfaceAreaParams, isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<AccessibleSurfaceAreaProps>) => { - const p = { ...PD.getDefaultValues(AccessibleSurfaceAreaParams), ...props } - return await AccessibleSurfaceArea.compute(data, p).runInContext(ctx.runtime) + const p = { ...PD.getDefaultValues(AccessibleSurfaceAreaParams), ...props }; + return await AccessibleSurfaceArea.compute(data, p).runInContext(ctx.runtime); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley.ts b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley.ts index b7b116061901f1357ffc613bcae58cb7070ac922..f854b833f2fd003b05746a3dc3e1b1ead1a6cd48 100644 --- a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley.ts +++ b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley.ts @@ -7,7 +7,7 @@ import { Task, RuntimeContext } from '../../../mol-task'; // import { BitFlags } from '../../../mol-util'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { Vec3 } from '../../../mol-math/linear-algebra'; import { Structure, StructureElement, StructureProperties } from '../../../mol-model/structure'; import { assignRadiusForHeavyAtoms } from './shrake-rupley/radii'; @@ -19,14 +19,14 @@ export const ShrakeRupleyComputationParams = { probeSize: PD.Numeric(1.4, { min: 0.1, max: 4, step: 0.01 }, { description: 'Corresponds to the size of a water molecule: 1.4 (original paper), 1.5 (occassionally used)' }), // buriedRasaThreshold: PD.Numeric(0.16, { min: 0.0, max: 1.0 }, { description: 'below this cutoff of relative accessible surface area a residue will be considered buried - see: Rost B, Sander C: Conservation and prediction of solvent accessibility in protein families. Proteins 1994.' }), nonPolymer: PD.Boolean(false, { description: 'Include non-polymer atoms as occluders.' }) -} +}; export type ShrakeRupleyComputationParams = typeof ShrakeRupleyComputationParams export type ShrakeRupleyComputationProps = PD.Values<ShrakeRupleyComputationParams> // TODO // - add back buried and relative asa -export { AccessibleSurfaceArea } +export { AccessibleSurfaceArea }; interface AccessibleSurfaceArea { readonly serialResidueIndex: ArrayLike<number> @@ -51,13 +51,13 @@ namespace AccessibleSurfaceArea { assignRadiusForHeavyAtoms(ctx); await computeArea(runtime, ctx); - const { area, serialResidueIndex } = ctx + const { area, serialResidueIndex } = ctx; return { area, serialResidueIndex }; } function initialize(structure: Structure, props: ShrakeRupleyComputationProps): ShrakeRupleyContext { const { elementCount, atomicResidueCount } = structure; - const { probeSize, nonPolymer, numberOfSpherePoints } = props + const { probeSize, nonPolymer, numberOfSpherePoints } = props; return { structure, @@ -69,7 +69,7 @@ namespace AccessibleSurfaceArea { atomRadiusType: new Int8Array(elementCount), serialResidueIndex: new Int32Array(elementCount), area: new Float32Array(atomicResidueCount) - } + }; } /** Creates a collection of points on a sphere by the Golden Section Spiral algorithm. */ @@ -95,26 +95,26 @@ namespace AccessibleSurfaceArea { /** Get relative area for a given component id */ export function normalize(compId: string, asa: number) { const maxAsa = MaxAsa[compId] || DefaultMaxAsa; - return asa / maxAsa + return asa / maxAsa; } export function getValue(location: StructureElement.Location, accessibleSurfaceArea: AccessibleSurfaceArea) { - const { getSerialIndex } = location.structure.root.serialMapping - const { area, serialResidueIndex } = accessibleSurfaceArea - const rSI = serialResidueIndex[getSerialIndex(location.unit, location.element)] - if (rSI === -1) return -1 - return area[rSI] + const { getSerialIndex } = location.structure.root.serialMapping; + const { area, serialResidueIndex } = accessibleSurfaceArea; + const rSI = serialResidueIndex[getSerialIndex(location.unit, location.element)]; + if (rSI === -1) return -1; + return area[rSI]; } export function getNormalizedValue(location: StructureElement.Location, accessibleSurfaceArea: AccessibleSurfaceArea) { - const value = getValue(location, accessibleSurfaceArea) - return value === -1 ? -1 : normalize(StructureProperties.residue.label_comp_id(location), value) + const value = getValue(location, accessibleSurfaceArea); + return value === -1 ? -1 : normalize(StructureProperties.residue.label_comp_id(location), value); } export function getFlag(location: StructureElement.Location, accessibleSurfaceArea: AccessibleSurfaceArea) { - const value = getNormalizedValue(location, accessibleSurfaceArea) + const value = getNormalizedValue(location, accessibleSurfaceArea); return value === -1 ? Flag.NA : value < 0.16 ? Flag.Buried : - Flag.Accessible + Flag.Accessible; } } \ No newline at end of file diff --git a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/area.ts b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/area.ts index fd93549b530d56b99679fc68644cab989513a5c6..7c01e6f6d928a08d7d506628ce4420cb90fe599a 100644 --- a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/area.ts +++ b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/area.ts @@ -16,7 +16,7 @@ import { StructureProperties, StructureElement, Structure } from '../../../../mo // - calculate atomRadiusType only for invariant units // - factor serialResidueIndex out -const updateChunk = 5000 +const updateChunk = 5000; export async function computeArea(runtime: RuntimeContext, ctx: ShrakeRupleyContext) { const { atomRadiusType: atomRadius } = ctx; for (let i = 0; i < atomRadius.length; i += updateChunk) { @@ -31,30 +31,30 @@ export async function computeArea(runtime: RuntimeContext, ctx: ShrakeRupleyCont const aPos = Vec3(); const bPos = Vec3(); const testPoint = Vec3(); -const aLoc = StructureElement.Location.create(void 0 as any) -const bLoc = StructureElement.Location.create(void 0 as any) +const aLoc = StructureElement.Location.create(void 0 as any); +const bLoc = StructureElement.Location.create(void 0 as any); function setLocation(l: StructureElement.Location, structure: Structure, serialIndex: number) { l.structure = structure; - l.unit = structure.units[structure.serialMapping.unitIndices[serialIndex]] - l.element = structure.serialMapping.elementIndices[serialIndex] - return l + l.unit = structure.units[structure.serialMapping.unitIndices[serialIndex]]; + l.element = structure.serialMapping.elementIndices[serialIndex]; + return l; } function computeRange(ctx: ShrakeRupleyContext, begin: number, end: number) { const { structure, atomRadiusType, serialResidueIndex, area, spherePoints, scalingConstant, maxLookupRadius, probeSize } = ctx; - const { x, y, z } = StructureProperties.atom + const { x, y, z } = StructureProperties.atom; const { lookup3d, serialMapping, unitIndexMap } = structure; - const { cumulativeUnitElementCount } = serialMapping + const { cumulativeUnitElementCount } = serialMapping; for (let aI = begin; aI < end; ++aI) { const radius1 = VdWLookup[atomRadiusType[aI]]; if (radius1 === VdWLookup[0]) continue; - setLocation(aLoc, structure, aI) - const aX = x(aLoc) - const aY = y(aLoc) - const aZ = z(aLoc) + setLocation(aLoc, structure, aI); + const aX = x(aLoc); + const aY = y(aLoc); + const aZ = z(aLoc); // pre-filter by lookup3d (provides >10x speed-up compared to naive evaluation) const { count, units, indices, squaredDistances } = lookup3d.find(aX, aY, aZ, maxLookupRadius); @@ -63,9 +63,9 @@ function computeRange(ctx: ShrakeRupleyContext, begin: number, end: number) { const cutoff1 = probeSize + probeSize + radius1; const neighbors = []; // TODO reuse for (let iI = 0; iI < count; ++iI) { - const bUnit = units[iI] - StructureElement.Location.set(bLoc, ctx.structure, bUnit, bUnit.elements[indices[iI]]) - const bI = cumulativeUnitElementCount[unitIndexMap.get(bUnit.id)] + indices[iI] + const bUnit = units[iI]; + StructureElement.Location.set(bLoc, ctx.structure, bUnit, bUnit.elements[indices[iI]]); + const bI = cumulativeUnitElementCount[unitIndexMap.get(bUnit.id)] + indices[iI]; const radius2 = VdWLookup[atomRadiusType[bI]]; if (StructureElement.Location.areEqual(aLoc, bLoc) || radius2 === VdWLookup[0]) continue; @@ -77,17 +77,17 @@ function computeRange(ctx: ShrakeRupleyContext, begin: number, end: number) { } // for all neighbors: test all sphere points - Vec3.set(aPos, aX, aY, aZ) + Vec3.set(aPos, aX, aY, aZ); const scale = probeSize + radius1; let accessiblePointCount = 0; for (let sI = 0; sI < spherePoints.length; ++sI) { - Vec3.scaleAndAdd(testPoint, aPos, spherePoints[sI], scale) + Vec3.scaleAndAdd(testPoint, aPos, spherePoints[sI], scale); let accessible = true; for (let _nI = 0; _nI < neighbors.length; ++_nI) { const nI = neighbors[_nI]; - setLocation(bLoc, structure, nI) - Vec3.set(bPos, x(bLoc), y(bLoc), z(bLoc)) + setLocation(bLoc, structure, nI); + Vec3.set(bPos, x(bLoc), y(bLoc), z(bLoc)); const radius3 = VdWLookup[atomRadiusType[nI]]; const cutoff3 = (radius3 + probeSize) * (radius3 + probeSize); if (Vec3.squaredDistance(testPoint, bPos) < cutoff3) { diff --git a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/common.ts b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/common.ts index 1bdaeb152b93c488ed20b3b3f100863f53eeb129..f91384826825ca2276c9e49b31e5e14d465ea898 100644 --- a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/common.ts +++ b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/common.ts @@ -32,7 +32,7 @@ export const VdWLookup = [ 1.80, // 7: C (nucleic) 1.60, // 8: N (nucleic) 1.40 // 9: P (nucleic) -] // can still be appended on-the-fly for rare elements like selenium +]; // can still be appended on-the-fly for rare elements like selenium /** Maximum accessible surface area observed for amino acids. Taken from: http://dx.doi.org/10.1371/journal.pone.0080635 */ export const MaxAsa: { [k: string]: number } = { @@ -56,5 +56,5 @@ export const MaxAsa: { [k: string]: number } = { 'TRP': 264.0, 'TYR': 255.0, 'VAL': 165.0 -} -export const DefaultMaxAsa = 121.0 \ No newline at end of file +}; +export const DefaultMaxAsa = 121.0; \ No newline at end of file diff --git a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/radii.ts b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/radii.ts index cc9ac3f5a0ad31f4d8f69b7769c9622636bbf0c7..09434674409db2f37a0cab6b033b6457bb34d1bb 100644 --- a/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/radii.ts +++ b/src/mol-model-props/computed/accessible-surface-area/shrake-rupley/radii.ts @@ -12,34 +12,34 @@ import { VdwRadius } from '../../../../mol-model/structure/model/properties/atom import { StructureElement, StructureProperties } from '../../../../mol-model/structure/structure'; import { getElementMoleculeType } from '../../../../mol-model/structure/util'; -const l = StructureElement.Location.create(void 0) +const l = StructureElement.Location.create(void 0); export function assignRadiusForHeavyAtoms(ctx: ShrakeRupleyContext) { - const { label_comp_id, key } = StructureProperties.residue - const { type_symbol, label_atom_id } = StructureProperties.atom + const { label_comp_id, key } = StructureProperties.residue; + const { type_symbol, label_atom_id } = StructureProperties.atom; const { structure, atomRadiusType, serialResidueIndex } = ctx; - let prevResidueIdx = 0 - let residueIdx = 0 - let serialResidueIdx = -1 + let prevResidueIdx = 0; + let residueIdx = 0; + let serialResidueIdx = -1; l.structure = structure; for (let i = 0, m = 0, il = structure.units.length; i < il; ++i) { - const unit = structure.units[i] - const { elements } = unit - l.unit = unit + const unit = structure.units[i]; + const { elements } = unit; + l.unit = unit; - prevResidueIdx = -1 + prevResidueIdx = -1; for (let j = 0, jl = elements.length; j < jl; ++j) { - const eI = elements[j] - const mj = m + j + const eI = elements[j]; + const mj = m + j; - l.element = eI - residueIdx = key(l) + l.element = eI; + residueIdx = key(l); - if (prevResidueIdx !== residueIdx) ++serialResidueIdx - prevResidueIdx = residueIdx + if (prevResidueIdx !== residueIdx) ++serialResidueIdx; + prevResidueIdx = residueIdx; const element = type_symbol(l); const elementIdx = getElementIdx(element); @@ -47,15 +47,15 @@ export function assignRadiusForHeavyAtoms(ctx: ShrakeRupleyContext) { // skip hydrogen atoms if (isHydrogen(elementIdx)) { atomRadiusType[mj] = VdWLookup[0]; - serialResidueIndex[mj] = -1 + serialResidueIndex[mj] = -1; continue; } - const moleculeType = getElementMoleculeType(unit, eI) + const moleculeType = getElementMoleculeType(unit, eI); // skip water and optionally non-polymer groups if (moleculeType === MoleculeType.Water || (!ctx.nonPolymer && !isPolymer(moleculeType))) { atomRadiusType[mj] = VdWLookup[0]; - serialResidueIndex[mj] = -1 + serialResidueIndex[mj] = -1; continue; } @@ -69,9 +69,9 @@ export function assignRadiusForHeavyAtoms(ctx: ShrakeRupleyContext) { } else { atomRadiusType[mj] = handleNonStandardCase(element); } - serialResidueIndex[mj] = serialResidueIdx + serialResidueIndex[mj] = serialResidueIdx; } - m += elements.length + m += elements.length; } } diff --git a/src/mol-model-props/computed/chemistry/functional-group.ts b/src/mol-model-props/computed/chemistry/functional-group.ts index 3d02749d88468954929f44c069653ce24759c4bb..b17420d1b15c43e88449dced29da41c78974a256 100644 --- a/src/mol-model-props/computed/chemistry/functional-group.ts +++ b/src/mol-model-props/computed/chemistry/functional-group.ts @@ -12,19 +12,19 @@ import { eachBondedAtom, bondCount, typeSymbol, bondToElementCount } from './uti function isAromatic(unit: Unit.Atomic, index: StructureElement.UnitIndex) { // TODO also extend unit.rings with geometry/composition-based aromaticity detection and use it here in addition - const { offset, edgeProps } = unit.bonds + const { offset, edgeProps } = unit.bonds; for (let i = offset[index], il = offset[index + 1]; i < il; ++i) { - if (BondType.is(BondType.Flag.Aromatic, edgeProps.flags[i])) return true + if (BondType.is(BondType.Flag.Aromatic, edgeProps.flags[i])) return true; } - return false + return false; } function bondToCarbonylCount(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let carbonylCount = 0 + let carbonylCount = 0; eachBondedAtom(structure, unit, index, (unit: Unit.Atomic, index: StructureElement.UnitIndex) => { - if (isCarbonyl(structure, unit, index)) carbonylCount += 1 - }) - return carbonylCount + if (isCarbonyl(structure, unit, index)) carbonylCount += 1; + }); + return carbonylCount; } // @@ -37,7 +37,7 @@ export function isQuaternaryAmine(structure: Structure, unit: Unit.Atomic, index typeSymbol(unit, index) === Elements.N && bondCount(structure, unit, index) === 4 && bondToElementCount(structure, unit, index, Elements.H) === 0 - ) + ); } /** @@ -48,33 +48,33 @@ export function isTertiaryAmine(structure: Structure, unit: Unit.Atomic, index: typeSymbol(unit, index) === Elements.N && bondCount(structure, unit, index) === 4 && idealValence === 3 - ) + ); } /** * Nitrogen in an imide */ export function isImide(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let flag = false + let flag = false; if (typeSymbol(unit, index) === Elements.N && (bondCount(structure, unit, index) - bondToElementCount(structure, unit, index, Elements.H)) === 2 ) { - flag = bondToCarbonylCount(structure, unit, index) === 2 + flag = bondToCarbonylCount(structure, unit, index) === 2; } - return flag + return flag; } /** * Nitrogen in an amide */ export function isAmide(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let flag = false + let flag = false; if (typeSymbol(unit, index) === Elements.N && (bondCount(structure, unit, index) - bondToElementCount(structure, unit, index, Elements.H)) === 2 ) { - flag = bondToCarbonylCount(structure, unit, index) === 1 + flag = bondToCarbonylCount(structure, unit, index) === 1; } - return flag + return flag; } /** @@ -85,7 +85,7 @@ export function isSulfonium(structure: Structure, unit: Unit.Atomic, index: Stru typeSymbol(unit, index) === Elements.S && bondCount(structure, unit, index) === 3 && bondToElementCount(structure, unit, index, Elements.H) === 0 - ) + ); } /** @@ -95,7 +95,7 @@ export function isSulfonicAcid(structure: Structure, unit: Unit.Atomic, index: S return ( typeSymbol(unit, index) === Elements.S && bondToElementCount(structure, unit, index, Elements.O) === 3 - ) + ); } /** @@ -105,7 +105,7 @@ export function isSulfate(structure: Structure, unit: Unit.Atomic, index: Struct return ( typeSymbol(unit, index) === Elements.S && bondToElementCount(structure, unit, index, Elements.O) === 4 - ) + ); } /** @@ -115,7 +115,7 @@ export function isPhosphate (structure: Structure, unit: Unit.Atomic, index: Str return ( typeSymbol(unit, index) === Elements.P && bondToElementCount(structure, unit, index, Elements.O) === bondCount(structure, unit, index) - ) + ); } /** @@ -126,7 +126,7 @@ export function isHalocarbon (structure: Structure, unit: Unit.Atomic, index: St isHalogen(typeSymbol(unit, index)) && bondCount(structure, unit, index) === 1 && bondToElementCount(structure, unit, index, Elements.C) === 1 - ) + ); } /** @@ -135,24 +135,24 @@ export function isHalocarbon (structure: Structure, unit: Unit.Atomic, index: St * TODO currently only checks intra bonds for group detection */ export function isCarbonyl(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let flag = false + let flag = false; if (typeSymbol(unit, index) === Elements.C) { - const { offset, edgeProps, b } = unit.bonds + const { offset, edgeProps, b } = unit.bonds; for (let i = offset[index], il = offset[index + 1]; i < il; ++i) { if (edgeProps.order[i] === 2 && typeSymbol(unit, b[i] as StructureElement.UnitIndex) === Elements.O) { - flag = true - break + flag = true; + break; } } } - return flag + return flag; } /** * Carbon in a carboxylate group */ export function isCarboxylate (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let terminalOxygenCount = 0 + let terminalOxygenCount = 0; if ( typeSymbol(unit, index) === Elements.C && bondToElementCount(structure, unit, index, Elements.O) === 2 && @@ -163,18 +163,18 @@ export function isCarboxylate (structure: Structure, unit: Unit.Atomic, index: S typeSymbol(unit, index) === Elements.O && bondCount(structure, unit, index) - bondToElementCount(structure, unit, index, Elements.H) === 1 ) { - terminalOxygenCount += 1 + terminalOxygenCount += 1; } - }) + }); } - return terminalOxygenCount === 2 + return terminalOxygenCount === 2; } /** * Carbon in a guanidine group */ export function isGuanidine (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let terminalNitrogenCount = 0 + let terminalNitrogenCount = 0; if ( typeSymbol(unit, index) === Elements.C && bondCount(structure, unit, index) === 3 && @@ -184,18 +184,18 @@ export function isGuanidine (structure: Structure, unit: Unit.Atomic, index: Str if ( bondCount(structure, unit, index) - bondToElementCount(structure, unit, index, Elements.H) === 1 ) { - terminalNitrogenCount += 1 + terminalNitrogenCount += 1; } - }) + }); } - return terminalNitrogenCount === 2 + return terminalNitrogenCount === 2; } /** * Carbon in a acetamidine group */ export function isAcetamidine (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let terminalNitrogenCount = 0 + let terminalNitrogenCount = 0; if ( typeSymbol(unit, index) === Elements.C && bondCount(structure, unit, index) === 3 && @@ -206,28 +206,28 @@ export function isAcetamidine (structure: Structure, unit: Unit.Atomic, index: S if ( bondCount(structure, unit, index) - bondToElementCount(structure, unit, index, Elements.H) === 1 ) { - terminalNitrogenCount += 1 + terminalNitrogenCount += 1; } - }) + }); } - return terminalNitrogenCount === 2 + return terminalNitrogenCount === 2; } -const PolarElements = new Set<ElementSymbol>([ 'N', 'O', 'S', 'F', 'CL', 'BR', 'I' ] as ElementSymbol[]) -export function isPolar(element: ElementSymbol) { return PolarElements.has(element) } +const PolarElements = new Set<ElementSymbol>([ 'N', 'O', 'S', 'F', 'CL', 'BR', 'I' ] as ElementSymbol[]); +export function isPolar(element: ElementSymbol) { return PolarElements.has(element); } export function hasPolarNeighbour (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let flag = false + let flag = false; eachBondedAtom(structure, unit, index, (unit: Unit.Atomic, index: StructureElement.UnitIndex) => { - if (isPolar(typeSymbol(unit, index))) flag = true - }) - return flag + if (isPolar(typeSymbol(unit, index))) flag = true; + }); + return flag; } export function hasAromaticNeighbour (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let flag = false + let flag = false; eachBondedAtom(structure, unit, index, (unit: Unit.Atomic, index: StructureElement.UnitIndex) => { - if (isAromatic(unit, index)) flag = true - }) - return flag + if (isAromatic(unit, index)) flag = true; + }); + return flag; } diff --git a/src/mol-model-props/computed/chemistry/geometry.ts b/src/mol-model-props/computed/chemistry/geometry.ts index 67b5a17e60bf70e723ba9c3a3b55ac466f7eca11..6862f513ac3c38af95aee8786105458c5f96b7e9 100644 --- a/src/mol-model-props/computed/chemistry/geometry.ts +++ b/src/mol-model-props/computed/chemistry/geometry.ts @@ -30,34 +30,34 @@ export const enum AtomGeometry { export function geometryLabel(geometry: AtomGeometry): string { switch (geometry) { case AtomGeometry.Spherical: - return 'Spherical' + return 'Spherical'; case AtomGeometry.Terminal: - return 'Terminal' + return 'Terminal'; case AtomGeometry.Linear: - return 'Linear' + return 'Linear'; case AtomGeometry.Trigonal: - return 'Trigonal' + return 'Trigonal'; case AtomGeometry.Tetrahedral: - return 'Tetrahedral' + return 'Tetrahedral'; case AtomGeometry.TrigonalBiPyramidal: - return 'Trigonal Bi-Pyramidal' + return 'Trigonal Bi-Pyramidal'; case AtomGeometry.Octahedral: - return 'Octahedral' + return 'Octahedral'; case AtomGeometry.SquarePlanar: - return 'Square Planar' + return 'Square Planar'; case AtomGeometry.Unknown: - return 'Unknown' + return 'Unknown'; } } export function assignGeometry (totalCoordination: number): AtomGeometry { switch (totalCoordination) { - case 0: return AtomGeometry.Spherical - case 1: return AtomGeometry.Terminal - case 2: return AtomGeometry.Linear - case 3: return AtomGeometry.Trigonal - case 4: return AtomGeometry.Tetrahedral - default: return AtomGeometry.Unknown + case 0: return AtomGeometry.Spherical; + case 1: return AtomGeometry.Terminal; + case 2: return AtomGeometry.Linear; + case 3: return AtomGeometry.Trigonal; + case 4: return AtomGeometry.Tetrahedral; + default: return AtomGeometry.Unknown; } } @@ -67,32 +67,32 @@ export const AtomGeometryAngles = new Map<AtomGeometry, number>([ [ AtomGeometry.Trigonal, degToRad(120) ], [ AtomGeometry.Tetrahedral, degToRad(109.4721) ], [ AtomGeometry.Octahedral, degToRad(90) ] -]) +]); // tmp objects for `calcAngles` and `calcPlaneAngle` -const tmpDir1 = Vec3() -const tmpDir2 = Vec3() -const tmpPosA = Vec3() -const tmpPosB = Vec3() -const tmpPosX = Vec3() +const tmpDir1 = Vec3(); +const tmpDir2 = Vec3(); +const tmpPosA = Vec3(); +const tmpPosB = Vec3(); +const tmpPosX = Vec3(); /** * Calculate the angles x-a1-a2 for all x where x is a heavy atom (not H) bonded to ap1. */ export function calcAngles (structure: Structure, unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex): number[] { - const angles: number[] = [] - unitA.conformation.position(unitA.elements[indexA], tmpPosA) - unitB.conformation.position(unitB.elements[indexB], tmpPosB) - Vec3.sub(tmpDir1, tmpPosB, tmpPosA) + const angles: number[] = []; + unitA.conformation.position(unitA.elements[indexA], tmpPosA); + unitB.conformation.position(unitB.elements[indexB], tmpPosB); + Vec3.sub(tmpDir1, tmpPosB, tmpPosA); eachBondedAtom(structure, unitA, indexA, (unitX: Unit.Atomic, indexX: StructureElement.UnitIndex) => { if (typeSymbol(unitX, indexX) !== Elements.H) { - unitX.conformation.position(unitX.elements[indexX], tmpPosX) - Vec3.sub(tmpDir2, tmpPosX, tmpPosA) - angles.push(Vec3.angle(tmpDir1, tmpDir2)) + unitX.conformation.position(unitX.elements[indexX], tmpPosX); + Vec3.sub(tmpDir2, tmpPosX, tmpPosA); + angles.push(Vec3.angle(tmpDir1, tmpDir2)); } - }) - return angles + }); + return angles; } /** @@ -103,38 +103,38 @@ export function calcAngles (structure: Structure, unitA: Unit.Atomic, indexA: St * @return {number} Angle from plane to second atom */ export function calcPlaneAngle (structure: Structure, unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex): number | undefined { - unitA.conformation.position(unitA.elements[indexA], tmpPosA) - unitB.conformation.position(unitB.elements[indexB], tmpPosB) - Vec3.sub(tmpDir1, tmpPosB, tmpPosA) + unitA.conformation.position(unitA.elements[indexA], tmpPosA); + unitB.conformation.position(unitB.elements[indexB], tmpPosB); + Vec3.sub(tmpDir1, tmpPosB, tmpPosA); - const neighbours = [Vec3(), Vec3()] - let ni = 0 - let unitX1: Unit.Atomic | undefined - let indexX1: StructureElement.UnitIndex | undefined + const neighbours = [Vec3(), Vec3()]; + let ni = 0; + let unitX1: Unit.Atomic | undefined; + let indexX1: StructureElement.UnitIndex | undefined; eachBondedAtom(structure, unitA, indexA, (unitX: Unit.Atomic, indexX: StructureElement.UnitIndex) => { - if (ni > 1) return + if (ni > 1) return; if (typeSymbol(unitX, indexX) !== Elements.H) { - unitX1 = unitX - indexX1 = indexX - unitX.conformation.position(unitX.elements[indexX], tmpPosX) - Vec3.sub(neighbours[ni++], tmpPosX, tmpPosA) + unitX1 = unitX; + indexX1 = indexX; + unitX.conformation.position(unitX.elements[indexX], tmpPosX); + Vec3.sub(neighbours[ni++], tmpPosX, tmpPosA); } - }) + }); if (ni === 1 && unitX1 && indexX1) { eachBondedAtom(structure, unitX1, indexX1, (unitX: Unit.Atomic, indexX: StructureElement.UnitIndex) => { - if (ni > 1) return - if (unitX === unitA && indexX === indexA) return + if (ni > 1) return; + if (unitX === unitA && indexX === indexA) return; if (typeSymbol(unitX, indexX) !== Elements.H) { - unitX.conformation.position(unitX.elements[indexX], tmpPosX) - Vec3.sub(neighbours[ni++], tmpPosX, tmpPosA) + unitX.conformation.position(unitX.elements[indexX], tmpPosX); + Vec3.sub(neighbours[ni++], tmpPosX, tmpPosA); } - }) + }); } if (ni !== 2) { - return + return; } - Vec3.cross(tmpDir2, neighbours[0], neighbours[1]) - return Math.abs((Math.PI / 2) - Vec3.angle(tmpDir2, tmpDir1)) + Vec3.cross(tmpDir2, neighbours[0], neighbours[1]); + return Math.abs((Math.PI / 2) - Vec3.angle(tmpDir2, tmpDir1)); } \ No newline at end of file diff --git a/src/mol-model-props/computed/chemistry/util.ts b/src/mol-model-props/computed/chemistry/util.ts index dfe201f839c65cb87a86f81067fec2893f156b51..2f76f64fa482c3853e0ff5ce3205e6022d88113c 100644 --- a/src/mol-model-props/computed/chemistry/util.ts +++ b/src/mol-model-props/computed/chemistry/util.ts @@ -11,108 +11,108 @@ import { BondType } from '../../../mol-model/structure/model/types'; import { SortedArray } from '../../../mol-data/int'; export function typeSymbol(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.model.atomicHierarchy.atoms.type_symbol.value(unit.elements[index]) + return unit.model.atomicHierarchy.atoms.type_symbol.value(unit.elements[index]); } export function formalCharge(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.model.atomicHierarchy.atoms.pdbx_formal_charge.value(unit.elements[index]) + return unit.model.atomicHierarchy.atoms.pdbx_formal_charge.value(unit.elements[index]); } export function atomId(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.model.atomicHierarchy.atoms.label_atom_id.value(unit.elements[index]) + return unit.model.atomicHierarchy.atoms.label_atom_id.value(unit.elements[index]); } export function altLoc(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.model.atomicHierarchy.atoms.label_alt_id.value(unit.elements[index]) + return unit.model.atomicHierarchy.atoms.label_alt_id.value(unit.elements[index]); } export function compId(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.getResidueIndex(index)) + return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.getResidueIndex(index)); } // export function interBondCount(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex): number { - let count = 0 - const indices = structure.interUnitBonds.getEdgeIndices(index, unit) + let count = 0; + const indices = structure.interUnitBonds.getEdgeIndices(index, unit); for (let i = 0, il = indices.length; i < il; ++i) { - const b = structure.interUnitBonds.edges[indices[i]] - if (BondType.isCovalent(b.props.flag)) count += 1 + const b = structure.interUnitBonds.edges[indices[i]]; + if (BondType.isCovalent(b.props.flag)) count += 1; } - return count + return count; } export function intraBondCount(unit: Unit.Atomic, index: StructureElement.UnitIndex): number { - let count = 0 - const { offset, edgeProps: { flags } } = unit.bonds + let count = 0; + const { offset, edgeProps: { flags } } = unit.bonds; for (let i = offset[index], il = offset[index + 1]; i < il; ++i) { - if (BondType.isCovalent(flags[i])) count += 1 + if (BondType.isCovalent(flags[i])) count += 1; } - return count + return count; } export function bondCount(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex): number { - return interBondCount(structure, unit, index) + intraBondCount(unit, index) + return interBondCount(structure, unit, index) + intraBondCount(unit, index); } export function bondToElementCount(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex, element: Elements): number { - let count = 0 + let count = 0; eachBondedAtom(structure, unit, index, (unit: Unit.Atomic, index: StructureElement.UnitIndex) => { - if (typeSymbol(unit, index) === element) count += 1 - }) - return count + if (typeSymbol(unit, index) === element) count += 1; + }); + return count; } // export function intraConnectedTo(unit: Unit.Atomic, indexA: StructureElement.UnitIndex, indexB: StructureElement.UnitIndex) { - const { offset, b, edgeProps: { flags } } = unit.bonds - BondType.is + const { offset, b, edgeProps: { flags } } = unit.bonds; + BondType.is; for (let i = offset[indexA], il = offset[indexA + 1]; i < il; ++i) { - if (b[i] === indexB && BondType.isCovalent(flags[i])) return true + if (b[i] === indexB && BondType.isCovalent(flags[i])) return true; } - return false + return false; } export function interConnectedTo(structure: Structure, unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex) { - const b = structure.interUnitBonds.getEdge(indexA, unitA, indexB, unitB) - return b && BondType.isCovalent(b.props.flag) + const b = structure.interUnitBonds.getEdge(indexA, unitA, indexB, unitB); + return b && BondType.isCovalent(b.props.flag); } export function connectedTo(structure: Structure, unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex) { - return unitA === unitB ? intraConnectedTo(unitA, indexA, indexB) : interConnectedTo(structure, unitA, indexA, unitB, indexB) + return unitA === unitB ? intraConnectedTo(unitA, indexA, indexB) : interConnectedTo(structure, unitA, indexA, unitB, indexB); } // export function eachInterBondedAtom(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex, cb: (unit: Unit.Atomic, index: StructureElement.UnitIndex) => void): void { - const indices = structure.interUnitBonds.getEdgeIndices(index, unit) + const indices = structure.interUnitBonds.getEdgeIndices(index, unit); for (let i = 0, il = indices.length; i < il; ++i) { - const b = structure.interUnitBonds.edges[indices[i]] - if (BondType.isCovalent(b.props.flag)) cb(b.unitB, b.indexB) + const b = structure.interUnitBonds.edges[indices[i]]; + if (BondType.isCovalent(b.props.flag)) cb(b.unitB, b.indexB); } } export function eachIntraBondedAtom(unit: Unit.Atomic, index: StructureElement.UnitIndex, cb: (unit: Unit.Atomic, index: StructureElement.UnitIndex) => void): void { - const { offset, b, edgeProps: { flags } } = unit.bonds + const { offset, b, edgeProps: { flags } } = unit.bonds; for (let i = offset[index], il = offset[index + 1]; i < il; ++i) { - if (BondType.isCovalent(flags[i])) cb(unit, b[i] as StructureElement.UnitIndex) + if (BondType.isCovalent(flags[i])) cb(unit, b[i] as StructureElement.UnitIndex); } } export function eachBondedAtom(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex, cb: (unit: Unit.Atomic, index: StructureElement.UnitIndex) => void): void { - eachInterBondedAtom(structure, unit, index, cb) - eachIntraBondedAtom(unit, index, cb) + eachInterBondedAtom(structure, unit, index, cb); + eachIntraBondedAtom(unit, index, cb); } // export function eachResidueAtom(unit: Unit.Atomic, index: StructureElement.UnitIndex, cb: (index: StructureElement.UnitIndex) => void): void { - const { offsets } = unit.model.atomicHierarchy.residueAtomSegments - const rI = unit.getResidueIndex(index) + const { offsets } = unit.model.atomicHierarchy.residueAtomSegments; + const rI = unit.getResidueIndex(index); for (let i = offsets[rI], il = offsets[rI + 1]; i < il; ++i) { // TODO optimize, avoid search with .indexOf - const idx = SortedArray.indexOf(unit.elements, i) - if (idx !== -1) cb(idx as StructureElement.UnitIndex) + const idx = SortedArray.indexOf(unit.elements, i); + if (idx !== -1) cb(idx as StructureElement.UnitIndex); } } \ No newline at end of file diff --git a/src/mol-model-props/computed/chemistry/valence-model.ts b/src/mol-model-props/computed/chemistry/valence-model.ts index 484ff82358e8807caae50c70603e1a26aa33172e..ee6dc942f88fc10b0a8795d74687893e765c865e 100644 --- a/src/mol-model-props/computed/chemistry/valence-model.ts +++ b/src/mol-model-props/computed/chemistry/valence-model.ts @@ -26,8 +26,8 @@ import { BondType } from '../../../mol-model/structure/model/types'; * */ -const tmpConjBondItA = new Bond.ElementBondIterator() -const tmpConjBondItB = new Bond.ElementBondIterator() +const tmpConjBondItA = new Bond.ElementBondIterator(); +const tmpConjBondItB = new Bond.ElementBondIterator(); /** * Are we involved in some kind of pi system. Either explicitly forming @@ -37,51 +37,51 @@ const tmpConjBondItB = new Bond.ElementBondIterator() * N,O adjacent to P=O or S=O do not qualify (keeps sulfonamide N sp3 geom) */ function isConjugated (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - const element = typeSymbol(unit, index) - const hetero = element === Elements.O || element === Elements.N + const element = typeSymbol(unit, index); + const hetero = element === Elements.O || element === Elements.N; - if (hetero && bondCount(structure, unit, index) === 4) return false + if (hetero && bondCount(structure, unit, index) === 4) return false; - tmpConjBondItA.setElement(structure, unit, index) + tmpConjBondItA.setElement(structure, unit, index); while (tmpConjBondItA.hasNext) { - const bA = tmpConjBondItA.move() - if (bA.order > 1) return true + const bA = tmpConjBondItA.move(); + if (bA.order > 1) return true; if (hetero) { - const elementB = typeSymbol(bA.otherUnit, bA.otherIndex) - tmpConjBondItB.setElement(structure, bA.otherUnit, bA.otherIndex) + const elementB = typeSymbol(bA.otherUnit, bA.otherIndex); + tmpConjBondItB.setElement(structure, bA.otherUnit, bA.otherIndex); while (tmpConjBondItB.hasNext) { - const bB = tmpConjBondItB.move() + const bB = tmpConjBondItB.move(); if (bB.order > 1) { if ((elementB === Elements.P || elementB === Elements.S) && typeSymbol(bB.otherUnit, bB.otherIndex) === Elements.O) { - continue + continue; } - return true + return true; } } } } - return false + return false; } export function explicitValence (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - let v = 0 + let v = 0; // intra-unit bonds - const { offset, edgeProps: { flags, order } } = unit.bonds + const { offset, edgeProps: { flags, order } } = unit.bonds; for (let i = offset[index], il = offset[index + 1]; i < il; ++i) { - if (BondType.isCovalent(flags[i])) v += order[i] + if (BondType.isCovalent(flags[i])) v += order[i]; } // inter-unit bonds structure.interUnitBonds.getEdgeIndices(index, unit).forEach(i => { - const b = structure.interUnitBonds.edges[i] - if (BondType.isCovalent(b.props.flag)) v += b.props.order - }) - return v + const b = structure.interUnitBonds.edges[i]; + if (BondType.isCovalent(b.props.flag)) v += b.props.order; + }); + return v; } -const tmpChargeBondItA = new Bond.ElementBondIterator() -const tmpChargeBondItB = new Bond.ElementBondIterator() +const tmpChargeBondItA = new Bond.ElementBondIterator(); +const tmpChargeBondItB = new Bond.ElementBondIterator(); /** * Attempts to produce a consistent charge and implicit @@ -95,72 +95,72 @@ const tmpChargeBondItB = new Bond.ElementBondIterator() * a much simpler view and deduces one from the other */ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex, props: ValenceModelProps) { - const hydrogenCount = bondToElementCount(structure, unit, index, Elements.H) - const element = typeSymbol(unit, index) - let charge = formalCharge(unit, index) + const hydrogenCount = bondToElementCount(structure, unit, index, Elements.H); + const element = typeSymbol(unit, index); + let charge = formalCharge(unit, index); - const assignCharge = (props.assignCharge === 'always' || (props.assignCharge === 'auto' && charge === 0)) - const assignH = (props.assignH === 'always' || (props.assignH === 'auto' && hydrogenCount === 0)) + const assignCharge = (props.assignCharge === 'always' || (props.assignCharge === 'auto' && charge === 0)); + const assignH = (props.assignH === 'always' || (props.assignH === 'auto' && hydrogenCount === 0)); - const degree = bondCount(structure, unit, index) - const valence = explicitValence(structure, unit, index) + const degree = bondCount(structure, unit, index); + const valence = explicitValence(structure, unit, index); - const conjugated = isConjugated(structure, unit, index) - const multiBond = (valence - degree > 0) + const conjugated = isConjugated(structure, unit, index); + const multiBond = (valence - degree > 0); - let implicitHCount = 0 - let geom = AtomGeometry.Unknown + let implicitHCount = 0; + let geom = AtomGeometry.Unknown; switch (element) { case Elements.H: if (assignCharge) { if (degree === 0) { - charge = 1 - geom = AtomGeometry.Spherical + charge = 1; + geom = AtomGeometry.Spherical; } else if (degree === 1) { - charge = 0 - geom = AtomGeometry.Terminal + charge = 0; + geom = AtomGeometry.Terminal; } } - break + break; case Elements.C: // TODO: Isocyanide? if (assignCharge) { - charge = 0 // Assume carbon always neutral + charge = 0; // Assume carbon always neutral } if (assignH) { // Carbocation/carbanion are 3-valent - implicitHCount = Math.max(0, 4 - valence - Math.abs(charge)) + implicitHCount = Math.max(0, 4 - valence - Math.abs(charge)); } // Carbocation is planar, carbanion is tetrahedral - geom = assignGeometry(degree + implicitHCount + Math.max(0, -charge)) - break + geom = assignGeometry(degree + implicitHCount + Math.max(0, -charge)); + break; case Elements.N: if (assignCharge) { if (!assignH) { // Trust input H explicitly: - charge = valence - 3 + charge = valence - 3; } else if (conjugated && valence < 4) { // Neutral unless amidine/guanidine double-bonded N: if (degree - hydrogenCount === 1 && valence - hydrogenCount === 2) { - charge = 1 + charge = 1; } else { - charge = 0 + charge = 0; } } else { // Sulfonamide nitrogen and classed as sp3 in conjugation model but // they won't be charged // Don't assign charge to nitrogens bound to metals - tmpChargeBondItA.setElement(structure, unit, index) + tmpChargeBondItA.setElement(structure, unit, index); while (tmpChargeBondItA.hasNext) { - const b = tmpChargeBondItA.move() - const elementB = typeSymbol(b.otherUnit, b.otherIndex) + const b = tmpChargeBondItA.move(); + const elementB = typeSymbol(b.otherUnit, b.otherIndex); if (elementB === Elements.S || isMetal(elementB)) { - charge = 0 - break + charge = 0; + break; } else { - charge = 1 + charge = 1; } } // TODO: Planarity sanity check? @@ -170,39 +170,39 @@ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomi if (assignH) { // NH4+ -> 4, 1' amide -> 2, nitro N/N+ depiction -> 0 - implicitHCount = Math.max(0, 3 - valence + charge) + implicitHCount = Math.max(0, 3 - valence + charge); } if (conjugated && !multiBond) { // Amide, anilinic N etc. cannot consider lone-pair for geometry purposes // Anilinic N geometry is depenent on ring electronics, for our purposes we // assume it's trigonal! - geom = assignGeometry(degree + implicitHCount - charge) + geom = assignGeometry(degree + implicitHCount - charge); } else { // Everything else, pyridine, amine, nitrile, lp plays normal role: - geom = assignGeometry(degree + implicitHCount + 1 - charge) + geom = assignGeometry(degree + implicitHCount + 1 - charge); } - break + break; case Elements.O: if (assignCharge) { if (!assignH) { - charge = valence - 2 + charge = valence - 2; } if (valence === 1) { - tmpChargeBondItA.setElement(structure, unit, index) + tmpChargeBondItA.setElement(structure, unit, index); b1: while (tmpChargeBondItA.hasNext) { - const bA = tmpChargeBondItA.move() - tmpChargeBondItB.setElement(structure, bA.otherUnit, bA.otherIndex) + const bA = tmpChargeBondItA.move(); + tmpChargeBondItB.setElement(structure, bA.otherUnit, bA.otherIndex); while (tmpChargeBondItB.hasNext) { - const bB = tmpChargeBondItB.move() + const bB = tmpChargeBondItB.move(); if ( !(bB.otherUnit === unit && bB.otherIndex === index) && typeSymbol(bB.otherUnit, bB.otherIndex) === Elements.O && bB.order === 2 ) { - charge = -1 - break b1 + charge = -1; + break b1; } } } @@ -210,16 +210,16 @@ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomi } if (assignH) { // ethanol -> 1, carboxylate -> -1 - implicitHCount = Math.max(0, 2 - valence + charge) + implicitHCount = Math.max(0, 2 - valence + charge); } if (conjugated && !multiBond) { // carboxylate OH, phenol OH, one lone-pair taken up with conjugation - geom = assignGeometry(degree + implicitHCount - charge + 1) + geom = assignGeometry(degree + implicitHCount - charge + 1); } else { // Carbonyl (trigonal) - geom = assignGeometry(degree + implicitHCount - charge + 2) + geom = assignGeometry(degree + implicitHCount - charge + 2); } - break + break; // Only handles thiols/thiolates/thioether/sulfonium. Sulfoxides and higher // oxidiation states are assumed neutral S (charge carried on O if required) @@ -227,22 +227,22 @@ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomi if (assignCharge) { if (!assignH) { if (valence <= 3 && bondToElementCount(structure, unit, index, Elements.O) === 0) { - charge = valence - 2 // e.g. explicitly deprotonated thiol + charge = valence - 2; // e.g. explicitly deprotonated thiol } else { - charge = 0 + charge = 0; } } } if (assignH) { if (valence < 2) { - implicitHCount = Math.max(0, 2 - valence + charge) + implicitHCount = Math.max(0, 2 - valence + charge); } } if (valence <= 3) { // Thiol, thiolate, tioether -> tetrahedral - geom = assignGeometry(degree + implicitHCount - charge + 2) + geom = assignGeometry(degree + implicitHCount - charge + 2); } - break + break; case Elements.F: case Elements.CL: @@ -251,9 +251,9 @@ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomi case Elements.AT: // Never implicitly protonate halides if (assignCharge) { - charge = valence - 1 + charge = valence - 1; } - break + break; case Elements.LI: case Elements.NA: @@ -262,9 +262,9 @@ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomi case Elements.CS: case Elements.FR: if (assignCharge) { - charge = 1 - valence + charge = 1 - valence; } - break + break; case Elements.BE: case Elements.MG: @@ -273,50 +273,50 @@ export function calculateHydrogensCharge (structure: Structure, unit: Unit.Atomi case Elements.BA: case Elements.RA: if (assignCharge) { - charge = 2 - valence + charge = 2 - valence; } - break + break; default: if (isDebugMode) { - console.warn('Requested charge, protonation for an unhandled element', element) + console.warn('Requested charge, protonation for an unhandled element', element); } } - return [ charge, implicitHCount, implicitHCount + hydrogenCount, geom ] + return [ charge, implicitHCount, implicitHCount + hydrogenCount, geom ]; } function calcUnitValenceModel(structure: Structure, unit: Unit.Atomic, props: ValenceModelProps) { - const n = unit.elements.length + const n = unit.elements.length; - const charge = new Int8Array(n) - const implicitH = new Int8Array(n) - const totalH = new Int8Array(n) - const idealGeometry = new Int8Array(n) + const charge = new Int8Array(n); + const implicitH = new Int8Array(n); + const totalH = new Int8Array(n); + const idealGeometry = new Int8Array(n); // always use root UnitIndex to take the topology of the whole structure in account - const hasParent = !!structure.parent - let mapping: SortedArray + const hasParent = !!structure.parent; + let mapping: SortedArray; if (hasParent) { - const rootUnit = structure.root.unitMap.get(unit.id) as Unit.Atomic - mapping = SortedArray.indicesOf(rootUnit.elements, unit.elements) + const rootUnit = structure.root.unitMap.get(unit.id) as Unit.Atomic; + mapping = SortedArray.indicesOf(rootUnit.elements, unit.elements); if (mapping.length !== unit.elements.length) { - throw new Error('expected to find an index for every element') + throw new Error('expected to find an index for every element'); } - unit = rootUnit - structure = structure.root + unit = rootUnit; + structure = structure.root; } for (let i = 0; i < n; ++i) { - const j = (hasParent ? mapping![i] : i) as StructureElement.UnitIndex - const [ chg, implH, totH, geom ] = calculateHydrogensCharge(structure, unit, j, props) - charge[i] = chg - implicitH[i] = implH - totalH[i] = totH - idealGeometry[i] = geom + const j = (hasParent ? mapping![i] : i) as StructureElement.UnitIndex; + const [ chg, implH, totH, geom ] = calculateHydrogensCharge(structure, unit, j, props); + charge[i] = chg; + implicitH[i] = implH; + totalH[i] = totH; + idealGeometry[i] = geom; } - return { charge, implicitH, totalH, idealGeometry } + return { charge, implicitH, totalH, idealGeometry }; } export interface ValenceModel { @@ -329,19 +329,19 @@ export interface ValenceModel { export const ValenceModelParams = { assignCharge: PD.Select('auto', [['always', 'always'], ['auto', 'auto'], ['never', 'never']]), assignH: PD.Select('auto', [['always', 'always'], ['auto', 'auto'], ['never', 'never']]), -} +}; export type ValenceModelParams = typeof ValenceModelParams export type ValenceModelProps = PD.Values<ValenceModelParams> export async function calcValenceModel(ctx: RuntimeContext, structure: Structure, props: Partial<ValenceModelProps>) { - const p = { ...PD.getDefaultValues(ValenceModelParams), ...props } - const map = new Map<number, ValenceModel>() + const p = { ...PD.getDefaultValues(ValenceModelParams), ...props }; + const map = new Map<number, ValenceModel>(); for (let i = 0, il = structure.units.length; i < il; ++i) { - const u = structure.units[i] + const u = structure.units[i]; if (Unit.isAtomic(u)) { - const valenceModel = calcUnitValenceModel(structure, u, p) - map.set(u.id, valenceModel) + const valenceModel = calcUnitValenceModel(structure, u, p); + map.set(u.id, valenceModel); } } - return map + return map; } \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions.ts b/src/mol-model-props/computed/interactions.ts index 5284d866a18cfa2240ad9288e258fad1b98998f7..88d67d898197181b718919218b870bcd97af9798 100644 --- a/src/mol-model-props/computed/interactions.ts +++ b/src/mol-model-props/computed/interactions.ts @@ -12,7 +12,7 @@ import { CustomProperty } from '../common/custom-property'; export const InteractionsParams = { ..._InteractionsParams -} +}; export type InteractionsParams = typeof InteractionsParams export type InteractionsProps = PD.Values<InteractionsParams> @@ -29,7 +29,7 @@ export const InteractionsProvider: CustomStructureProperty.Provider<Interactions getParams: (data: Structure) => InteractionsParams, isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<InteractionsProps>) => { - const p = { ...PD.getDefaultValues(InteractionsParams), ...props } - return await computeInteractions(ctx, data, p) + const p = { ...PD.getDefaultValues(InteractionsParams), ...props }; + return await computeInteractions(ctx, data, p); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/charged.ts b/src/mol-model-props/computed/interactions/charged.ts index b60b79d814f9a0dbbbaf94b453ade1882a58ef8a..91b11d9e62fd94f5c648b616880e5963f1eb43db 100644 --- a/src/mol-model-props/computed/interactions/charged.ts +++ b/src/mol-model-props/computed/interactions/charged.ts @@ -23,7 +23,7 @@ import { Vec3 } from '../../../mol-math/linear-algebra'; const IonicParams = { distanceMax: PD.Numeric(5.0, { min: 0, max: 8, step: 0.1 }), -} +}; type IonicParams = typeof IonicParams type IonicProps = PD.Values<IonicParams> @@ -31,77 +31,77 @@ const PiStackingParams = { distanceMax: PD.Numeric(5.5, { min: 1, max: 8, step: 0.1 }), offsetMax: PD.Numeric(2.0, { min: 0, max: 4, step: 0.1 }), angleDevMax: PD.Numeric(30, { min: 0, max: 180, step: 1 }), -} +}; type PiStackingParams = typeof PiStackingParams type PiStackingProps = PD.Values<PiStackingParams> const CationPiParams = { distanceMax: PD.Numeric(6.0, { min: 1, max: 8, step: 0.1 }), offsetMax: PD.Numeric(2.0, { min: 0, max: 4, step: 0.1 }), -} +}; type CationPiParams = typeof CationPiParams type CationPiProps = PD.Values<CationPiParams> // -const PositvelyCharged = ['ARG', 'HIS', 'LYS'] -const NegativelyCharged = ['GLU', 'ASP'] +const PositvelyCharged = ['ARG', 'HIS', 'LYS']; +const NegativelyCharged = ['GLU', 'ASP']; function getUnitValenceModel(structure: Structure, unit: Unit.Atomic) { - const valenceModel = ValenceModelProvider.get(structure).value - if (!valenceModel) throw Error('expected valence model to be available') - const unitValenceModel = valenceModel.get(unit.id) - if (!unitValenceModel) throw Error('expected valence model for unit to be available') - return unitValenceModel + const valenceModel = ValenceModelProvider.get(structure).value; + if (!valenceModel) throw Error('expected valence model to be available'); + const unitValenceModel = valenceModel.get(unit.id); + if (!unitValenceModel) throw Error('expected valence model for unit to be available'); + return unitValenceModel; } function addUnitPositiveCharges(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { charge } = getUnitValenceModel(structure, unit) - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { charge } = getUnitValenceModel(structure, unit); + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; - const addedElements = new Set<StructureElement.UnitIndex>() + const addedElements = new Set<StructureElement.UnitIndex>(); - const { label_comp_id } = unit.model.atomicHierarchy.residues - const residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements) + const { label_comp_id } = unit.model.atomicHierarchy.residues; + const residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements); while (residueIt.hasNext) { const { index: residueIndex, start, end } = residueIt.move(); - const compId = label_comp_id.value(residueIndex) + const compId = label_comp_id.value(residueIndex); if (PositvelyCharged.includes(compId)) { - builder.startState() + builder.startState(); for (let j = start as StructureElement.UnitIndex; j < end; ++j) { if (typeSymbol(unit, j) === Elements.N && !ProteinBackboneAtoms.has(atomId(unit, j))) { - builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j) + builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j); } } - builder.finishState(FeatureType.PositiveCharge, FeatureGroup.None) + builder.finishState(FeatureType.PositiveCharge, FeatureGroup.None); } else if (!PolymerNames.has(compId)) { - addedElements.clear() + addedElements.clear(); for (let j = start as StructureElement.UnitIndex; j < end; ++j) { - let group = FeatureGroup.None + let group = FeatureGroup.None; if (isGuanidine(structure, unit, j)) { - group = FeatureGroup.Guanidine + group = FeatureGroup.Guanidine; } else if (isAcetamidine(structure, unit, j)) { - group = FeatureGroup.Acetamidine + group = FeatureGroup.Acetamidine; } if (group) { - builder.startState() + builder.startState(); eachBondedAtom(structure, unit, j, (_, k) => { if (typeSymbol(unit, k) === Elements.N) { - addedElements.add(k) - builder.pushMember(x[elements[k]], y[elements[k]], z[elements[k]], k) + addedElements.add(k); + builder.pushMember(x[elements[k]], y[elements[k]], z[elements[k]], k); } - }) - builder.finishState(FeatureType.PositiveCharge, group) + }); + builder.finishState(FeatureType.PositiveCharge, group); } } for (let j = start as StructureElement.UnitIndex; j < end; ++j) { if (charge[j] > 0 && !addedElements.has(j)) { - builder.add(FeatureType.PositiveCharge, FeatureGroup.None, x[elements[j]], y[elements[j]], z[elements[j]], j) + builder.add(FeatureType.PositiveCharge, FeatureGroup.None, x[elements[j]], y[elements[j]], z[elements[j]], j); } } } @@ -109,72 +109,72 @@ function addUnitPositiveCharges(structure: Structure, unit: Unit.Atomic, builder } function addUnitNegativeCharges(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { charge } = getUnitValenceModel(structure, unit) - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { charge } = getUnitValenceModel(structure, unit); + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; - const addedElements = new Set<StructureElement.UnitIndex>() + const addedElements = new Set<StructureElement.UnitIndex>(); - const { label_comp_id } = unit.model.atomicHierarchy.residues - const residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements) + const { label_comp_id } = unit.model.atomicHierarchy.residues; + const residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, elements); while (residueIt.hasNext) { const { index: residueIndex, start, end } = residueIt.move(); - const compId = label_comp_id.value(residueIndex) + const compId = label_comp_id.value(residueIndex); if (NegativelyCharged.includes(compId)) { - builder.startState() + builder.startState(); for (let j = start as StructureElement.UnitIndex; j < end; ++j) { if (typeSymbol(unit, j) === Elements.O && !ProteinBackboneAtoms.has(atomId(unit, j))) { - builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j) + builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j); } } - builder.finishState(FeatureType.NegativeCharge, FeatureGroup.None) + builder.finishState(FeatureType.NegativeCharge, FeatureGroup.None); } else if (BaseNames.has(compId)) { for (let j = start as StructureElement.UnitIndex; j < end; ++j) { if (isPhosphate(structure, unit, j)) { - builder.startState() + builder.startState(); eachBondedAtom(structure, unit, j, (_, k) => { if (typeSymbol(unit, k) === Elements.O) { - builder.pushMember(x[elements[k]], y[elements[k]], z[elements[k]], k) + builder.pushMember(x[elements[k]], y[elements[k]], z[elements[k]], k); } - }) - builder.finishState(FeatureType.NegativeCharge, FeatureGroup.Phosphate) + }); + builder.finishState(FeatureType.NegativeCharge, FeatureGroup.Phosphate); } } } else if (!PolymerNames.has(compId)) { for (let j = start as StructureElement.UnitIndex; j < end; ++j) { - builder.startState() + builder.startState(); if (typeSymbol(unit, j) === Elements.N && !ProteinBackboneAtoms.has(atomId(unit, j))) { - builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j) + builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j); } - builder.finishState(FeatureType.NegativeCharge, FeatureGroup.None) + builder.finishState(FeatureType.NegativeCharge, FeatureGroup.None); - let group = FeatureGroup.None + let group = FeatureGroup.None; if (isSulfonicAcid(structure, unit, j)) { - group = FeatureGroup.SulfonicAcid + group = FeatureGroup.SulfonicAcid; } else if (isPhosphate(structure, unit, j)) { - group = FeatureGroup.Phosphate + group = FeatureGroup.Phosphate; } else if (isSulfate(structure, unit, j)) { - group = FeatureGroup.Sulfate + group = FeatureGroup.Sulfate; } else if (isCarboxylate(structure, unit, j)) { - group = FeatureGroup.Carboxylate + group = FeatureGroup.Carboxylate; } if (group) { - builder.startState() + builder.startState(); eachBondedAtom(structure, unit, j, (_, k) => { if (typeSymbol(unit, k) === Elements.O) { - addedElements.add(k) - builder.pushMember(x[elements[k]], y[elements[k]], z[elements[k]], k) + addedElements.add(k); + builder.pushMember(x[elements[k]], y[elements[k]], z[elements[k]], k); } - }) - builder.finishState(FeatureType.NegativeCharge, group) + }); + builder.finishState(FeatureType.NegativeCharge, group); } } for (let j = start as StructureElement.UnitIndex; j < end; ++j) { if (charge[j] < 0 && !addedElements.has(j)) { - builder.add(FeatureType.NegativeCharge, FeatureGroup.None, x[elements[j]], y[elements[j]], z[elements[j]], j) + builder.add(FeatureType.NegativeCharge, FeatureGroup.None, x[elements[j]], y[elements[j]], z[elements[j]], j); } } } @@ -182,17 +182,17 @@ function addUnitNegativeCharges(structure: Structure, unit: Unit.Atomic, builder } function addUnitAromaticRings(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (const ringIndex of unit.rings.aromaticRings) { - const ring = unit.rings.all[ringIndex] - builder.startState() + const ring = unit.rings.all[ringIndex]; + builder.startState(); for (let i = 0, il = ring.length; i < il; ++i) { - const j = ring[i] - builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j) + const j = ring[i]; + builder.pushMember(x[elements[j]], y[elements[j]], z[elements[j]], j); } - builder.finishState(FeatureType.AromaticRing, FeatureGroup.None) + builder.finishState(FeatureType.AromaticRing, FeatureGroup.None); } } @@ -200,70 +200,70 @@ function isIonic(ti: FeatureType, tj: FeatureType) { return ( (ti === FeatureType.NegativeCharge && tj === FeatureType.PositiveCharge) || (ti === FeatureType.PositiveCharge && tj === FeatureType.NegativeCharge) - ) + ); } function isPiStacking(ti: FeatureType, tj: FeatureType) { - return ti === FeatureType.AromaticRing && tj === FeatureType.AromaticRing + return ti === FeatureType.AromaticRing && tj === FeatureType.AromaticRing; } function isCationPi(ti: FeatureType, tj: FeatureType) { return ( (ti === FeatureType.AromaticRing && tj === FeatureType.PositiveCharge) || (ti === FeatureType.PositiveCharge && tj === FeatureType.AromaticRing) - ) + ); } -const tmpPointA = Vec3() -const tmpPointB = Vec3() +const tmpPointA = Vec3(); +const tmpPointB = Vec3(); function areFeaturesWithinDistanceSq(infoA: Features.Info, infoB: Features.Info, distanceSq: number): boolean { - const { feature: featureA, offsets: offsetsA, members: membersA } = infoA - const { feature: featureB, offsets: offsetsB, members: membersB } = infoB + const { feature: featureA, offsets: offsetsA, members: membersA } = infoA; + const { feature: featureB, offsets: offsetsB, members: membersB } = infoB; for (let i = offsetsA[featureA], il = offsetsA[featureA + 1]; i < il; ++i) { - const elementA = membersA[i] - infoA.unit.conformation.position(infoA.unit.elements[elementA], tmpPointA) + const elementA = membersA[i]; + infoA.unit.conformation.position(infoA.unit.elements[elementA], tmpPointA); for (let j = offsetsB[featureB], jl = offsetsB[featureB + 1]; j < jl; ++j) { - const elementB = membersB[j] - infoB.unit.conformation.position(infoB.unit.elements[elementB], tmpPointB) - if (Vec3.squaredDistance(tmpPointA, tmpPointB) < distanceSq) return true + const elementB = membersB[j]; + infoB.unit.conformation.position(infoB.unit.elements[elementB], tmpPointB); + if (Vec3.squaredDistance(tmpPointA, tmpPointB) < distanceSq) return true; } } - return false + return false; } -const tmpVecA = Vec3() -const tmpVecB = Vec3() -const tmpVecC = Vec3() -const tmpVecD = Vec3() +const tmpVecA = Vec3(); +const tmpVecB = Vec3(); +const tmpVecC = Vec3(); +const tmpVecD = Vec3(); function getNormal(out: Vec3, info: Features.Info) { - const { unit, feature, offsets, members } = info - const { elements } = unit + const { unit, feature, offsets, members } = info; + const { elements } = unit; - const i = offsets[feature] - info.unit.conformation.position(elements[members[i]], tmpVecA) - info.unit.conformation.position(elements[members[i + 1]], tmpVecB) - info.unit.conformation.position(elements[members[i + 2]], tmpVecC) + const i = offsets[feature]; + info.unit.conformation.position(elements[members[i]], tmpVecA); + info.unit.conformation.position(elements[members[i + 1]], tmpVecB); + info.unit.conformation.position(elements[members[i + 2]], tmpVecC); - return Vec3.triangleNormal(out, tmpVecA, tmpVecB, tmpVecC) + return Vec3.triangleNormal(out, tmpVecA, tmpVecB, tmpVecC); } const getOffset = function (infoA: Features.Info, infoB: Features.Info, normal: Vec3) { - Features.position(tmpVecA, infoA) - Features.position(tmpVecB, infoB) + Features.position(tmpVecA, infoA); + Features.position(tmpVecB, infoB); - Vec3.sub(tmpVecC, tmpVecA, tmpVecB) + Vec3.sub(tmpVecC, tmpVecA, tmpVecB); - Vec3.projectOnPlane(tmpVecD, tmpVecC, normal) - Vec3.add(tmpVecD, tmpVecD, tmpVecB) - return Vec3.distance(tmpVecD, tmpVecB) -} + Vec3.projectOnPlane(tmpVecD, tmpVecC, normal); + Vec3.add(tmpVecD, tmpVecD, tmpVecB); + return Vec3.distance(tmpVecD, tmpVecB); +}; function getIonicOptions(props: IonicProps) { return { distanceMaxSq: props.distanceMax * props.distanceMax, - } + }; } type IonicOptions = ReturnType<typeof getIonicOptions> @@ -271,110 +271,110 @@ function getPiStackingOptions(props: PiStackingProps) { return { offsetMax: props.offsetMax, angleDevMax: degToRad(props.angleDevMax), - } + }; } type PiStackingOptions = ReturnType<typeof getPiStackingOptions> function getCationPiOptions(props: CationPiProps) { return { offsetMax: props.offsetMax - } + }; } type CationPiOptions = ReturnType<typeof getCationPiOptions> -const deg180InRad = degToRad(180) -const deg90InRad = degToRad(90) +const deg180InRad = degToRad(180); +const deg90InRad = degToRad(90); -const tmpNormalA = Vec3() -const tmpNormalB = Vec3() +const tmpNormalA = Vec3(); +const tmpNormalB = Vec3(); function testIonic(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number, opts: IonicOptions): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; if (isIonic(typeA, typeB)) { if (areFeaturesWithinDistanceSq(infoA, infoB, opts.distanceMaxSq)) { - return InteractionType.Ionic + return InteractionType.Ionic; } } } function testPiStacking(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number, opts: PiStackingOptions): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; if (isPiStacking(typeA, typeB)) { - getNormal(tmpNormalA, infoA) - getNormal(tmpNormalB, infoB) + getNormal(tmpNormalA, infoA); + getNormal(tmpNormalB, infoB); - const angle = Vec3.angle(tmpNormalA, tmpNormalB) - const offset = Math.min(getOffset(infoA, infoB, tmpNormalB), getOffset(infoB, infoA, tmpNormalA)) + const angle = Vec3.angle(tmpNormalA, tmpNormalB); + const offset = Math.min(getOffset(infoA, infoB, tmpNormalB), getOffset(infoB, infoA, tmpNormalA)); if (offset <= opts.offsetMax) { if (angle <= opts.angleDevMax || angle >= deg180InRad - opts.angleDevMax) { - return InteractionType.PiStacking // parallel + return InteractionType.PiStacking; // parallel } else if (angle <= opts.angleDevMax + deg90InRad && angle >= deg90InRad - opts.angleDevMax) { - return InteractionType.PiStacking // t-shaped + return InteractionType.PiStacking; // t-shaped } } } } function testCationPi(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number, opts: CationPiOptions): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; if (isCationPi(typeA, typeB)) { - const [infoR, infoC] = typeA === FeatureType.AromaticRing ? [infoA, infoB] : [infoB, infoA] + const [infoR, infoC] = typeA === FeatureType.AromaticRing ? [infoA, infoB] : [infoB, infoA]; - getNormal(tmpNormalA, infoR) - const offset = getOffset(infoC, infoR, tmpNormalA) + getNormal(tmpNormalA, infoR); + const offset = getOffset(infoC, infoR, tmpNormalA); if (offset <= opts.offsetMax) { - return InteractionType.CationPi + return InteractionType.CationPi; } } } // -export const NegativChargeProvider = Features.Provider([FeatureType.NegativeCharge], addUnitNegativeCharges) -export const PositiveChargeProvider = Features.Provider([FeatureType.PositiveCharge], addUnitPositiveCharges) -export const AromaticRingProvider = Features.Provider([FeatureType.AromaticRing], addUnitAromaticRings) +export const NegativChargeProvider = Features.Provider([FeatureType.NegativeCharge], addUnitNegativeCharges); +export const PositiveChargeProvider = Features.Provider([FeatureType.PositiveCharge], addUnitPositiveCharges); +export const AromaticRingProvider = Features.Provider([FeatureType.AromaticRing], addUnitAromaticRings); export const IonicProvider: ContactProvider<IonicParams> = { name: 'ionic', params: IonicParams, createTester: (props: IonicProps) => { - const opts = getIonicOptions(props) + const opts = getIonicOptions(props); return { maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.NegativeCharge, FeatureType.PositiveCharge]), getType: (structure, infoA, infoB, distanceSq) => testIonic(structure, infoA, infoB, distanceSq, opts) - } + }; } -} +}; export const PiStackingProvider: ContactProvider<PiStackingParams> = { name: 'pi-stacking', params: PiStackingParams, createTester: (props: PiStackingProps) => { - const opts = getPiStackingOptions(props) + const opts = getPiStackingOptions(props); return { maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.AromaticRing]), getType: (structure, infoA, infoB, distanceSq) => testPiStacking(structure, infoA, infoB, distanceSq, opts) - } + }; } -} +}; export const CationPiProvider: ContactProvider<CationPiParams> = { name: 'cation-pi', params: CationPiParams, createTester: (props: CationPiProps) => { - const opts = getCationPiOptions(props) + const opts = getCationPiOptions(props); return { maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.AromaticRing, FeatureType.PositiveCharge]), getType: (structure, infoA, infoB, distanceSq) => testCationPi(structure, infoA, infoB, distanceSq, opts) - } + }; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/common.ts b/src/mol-model-props/computed/interactions/common.ts index 552d47641c0ee996f9a8af8c46ac86d13b5871ea..b62fb461229bfd8b0f295099843df1fc931ce6b5 100644 --- a/src/mol-model-props/computed/interactions/common.ts +++ b/src/mol-model-props/computed/interactions/common.ts @@ -4,15 +4,15 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { IntAdjacencyGraph } from '../../../mol-math/graph' -import { InterUnitGraph } from '../../../mol-math/graph/inter-unit-graph' -import { Unit } from '../../../mol-model/structure' -import { AssignableArrayLike } from '../../../mol-util/type-helpers' -import { Features } from './features' -import { StructureElement } from '../../../mol-model/structure/structure' -import { IntMap } from '../../../mol-data/int' +import { IntAdjacencyGraph } from '../../../mol-math/graph'; +import { InterUnitGraph } from '../../../mol-math/graph/inter-unit-graph'; +import { Unit } from '../../../mol-model/structure'; +import { AssignableArrayLike } from '../../../mol-util/type-helpers'; +import { Features } from './features'; +import { StructureElement } from '../../../mol-model/structure/structure'; +import { IntMap } from '../../../mol-data/int'; -export { InteractionsIntraContacts } +export { InteractionsIntraContacts }; interface InteractionsIntraContacts extends IntAdjacencyGraph<Features.FeatureIndex, InteractionsIntraContacts.Props> { readonly elementsIndex: InteractionsIntraContacts.ElementsIndex } @@ -34,104 +34,104 @@ namespace InteractionsIntraContacts { * Note: assumes that feature members of a contact are non-overlapping */ export function createElementsIndex(contacts: IntAdjacencyGraph<Features.FeatureIndex, Props>, features: Features, elementsCount: number) { - const offsets = new Int32Array(elementsCount + 1) - const bucketFill = new Int32Array(elementsCount) - const bucketSizes = new Int32Array(elementsCount) - const { members, offsets: featureOffsets } = features + const offsets = new Int32Array(elementsCount + 1); + const bucketFill = new Int32Array(elementsCount); + const bucketSizes = new Int32Array(elementsCount); + const { members, offsets: featureOffsets } = features; for (let i = 0, il = contacts.edgeCount * 2; i < il; ++i) { - const aI = contacts.a[i] - const bI = contacts.b[i] - if (aI > bI) continue + const aI = contacts.a[i]; + const bI = contacts.b[i]; + if (aI > bI) continue; for (let j = featureOffsets[aI], jl = featureOffsets[aI + 1]; j < jl; ++j) { - ++bucketSizes[members[j]] + ++bucketSizes[members[j]]; } for (let j = featureOffsets[bI], jl = featureOffsets[bI + 1]; j < jl; ++j) { - ++bucketSizes[members[j]] + ++bucketSizes[members[j]]; } } - let offset = 0 + let offset = 0; for (let i = 0; i < elementsCount; i++) { - offsets[i] = offset - offset += bucketSizes[i] + offsets[i] = offset; + offset += bucketSizes[i]; } - offsets[elementsCount] = offset + offsets[elementsCount] = offset; - const indices = new Int32Array(offset) + const indices = new Int32Array(offset); for (let i = 0, il = contacts.edgeCount * 2; i < il; ++i) { - const aI = contacts.a[i] - const bI = contacts.b[i] - if (aI > bI) continue + const aI = contacts.a[i]; + const bI = contacts.b[i]; + if (aI > bI) continue; for (let j = featureOffsets[aI], jl = featureOffsets[aI + 1]; j < jl; ++j) { - const m = members[j] - const om = offsets[m] + bucketFill[m] - indices[om] = i - ++bucketFill[m] + const m = members[j]; + const om = offsets[m] + bucketFill[m]; + indices[om] = i; + ++bucketFill[m]; } for (let j = featureOffsets[bI], jl = featureOffsets[bI + 1]; j < jl; ++j) { - const m = members[j] - const om = offsets[m] + bucketFill[m] - indices[om] = i - ++bucketFill[m] + const m = members[j]; + const om = offsets[m] + bucketFill[m]; + indices[om] = i; + ++bucketFill[m]; } } - return { indices, offsets } + return { indices, offsets }; } } -export { InteractionsInterContacts } +export { InteractionsInterContacts }; class InteractionsInterContacts extends InterUnitGraph<Unit, Features.FeatureIndex, InteractionsInterContacts.Props> { private readonly elementKeyIndex: Map<string, number[]> getContactIndicesForElement(index: StructureElement.UnitIndex, unit: Unit): ReadonlyArray<number> { - return this.elementKeyIndex.get(this.getElementKey(index, unit)) || [] + return this.elementKeyIndex.get(this.getElementKey(index, unit)) || []; } private getElementKey(index: StructureElement.UnitIndex, unit: Unit): string { - return `${index}|${unit.id}` + return `${index}|${unit.id}`; } constructor(map: Map<number, InterUnitGraph.UnitPairEdges<Unit, Features.FeatureIndex, InteractionsInterContacts.Props>[]>, unitsFeatures: IntMap<Features>) { - super(map) + super(map); - let count = 0 - const elementKeyIndex = new Map<string, number[]>() + let count = 0; + const elementKeyIndex = new Map<string, number[]>(); const add = (index: StructureElement.UnitIndex, unit: Unit) => { - const vertexKey = this.getElementKey(index, unit) - const e = elementKeyIndex.get(vertexKey) - if (e === undefined) elementKeyIndex.set(vertexKey, [count]) - else e.push(count) - } + const vertexKey = this.getElementKey(index, unit); + const e = elementKeyIndex.get(vertexKey); + if (e === undefined) elementKeyIndex.set(vertexKey, [count]); + else e.push(count); + }; this.map.forEach(pairEdgesArray => { pairEdgesArray.forEach(pairEdges => { pairEdges.connectedIndices.forEach(indexA => { pairEdges.getEdges(indexA).forEach(edgeInfo => { - const { unitA, unitB } = pairEdges + const { unitA, unitB } = pairEdges; - const { offsets: offsetsA, members: membersA } = unitsFeatures.get(unitA.id) + const { offsets: offsetsA, members: membersA } = unitsFeatures.get(unitA.id); for (let j = offsetsA[indexA], jl = offsetsA[indexA + 1]; j < jl; ++j) { - add(membersA[j], unitA) + add(membersA[j], unitA); } - const { indexB } = edgeInfo - const { offsets: offsetsB, members: membersB } = unitsFeatures.get(unitB.id) + const { indexB } = edgeInfo; + const { offsets: offsetsB, members: membersB } = unitsFeatures.get(unitB.id); for (let j = offsetsB[indexB], jl = offsetsB[indexB + 1]; j < jl; ++j) { - add(membersB[j], unitB) + add(membersB[j], unitB); } - count += 1 - }) - }) - }) - }) + count += 1; + }); + }); + }); + }); - this.elementKeyIndex = elementKeyIndex + this.elementKeyIndex = elementKeyIndex; } } namespace InteractionsInterContacts { @@ -158,23 +158,23 @@ export const enum InteractionType { export function interactionTypeLabel(type: InteractionType): string { switch (type) { case InteractionType.HydrogenBond: - return 'Hydrogen Bond' + return 'Hydrogen Bond'; case InteractionType.Hydrophobic: - return 'Hydrophobic Contact' + return 'Hydrophobic Contact'; case InteractionType.HalogenBond: - return 'Halogen Bond' + return 'Halogen Bond'; case InteractionType.Ionic: - return 'Ionic Interaction' + return 'Ionic Interaction'; case InteractionType.MetalCoordination: - return 'Metal Coordination' + return 'Metal Coordination'; case InteractionType.CationPi: - return 'Cation-Pi Interaction' + return 'Cation-Pi Interaction'; case InteractionType.PiStacking: - return 'Pi Stacking' + return 'Pi Stacking'; case InteractionType.WeakHydrogenBond: - return 'Weak Hydrogen Bond' + return 'Weak Hydrogen Bond'; case InteractionType.Unknown: - return 'Unknown Interaction' + return 'Unknown Interaction'; } } @@ -198,33 +198,33 @@ export const enum FeatureType { export function featureTypeLabel(type: FeatureType): string { switch (type) { case FeatureType.None: - return 'None' + return 'None'; case FeatureType.PositiveCharge: - return 'Positive Charge' + return 'Positive Charge'; case FeatureType.NegativeCharge: - return 'Negative Charge' + return 'Negative Charge'; case FeatureType.AromaticRing: - return 'Aromatic Ring' + return 'Aromatic Ring'; case FeatureType.HydrogenDonor: - return 'Hydrogen Donor' + return 'Hydrogen Donor'; case FeatureType.HydrogenAcceptor: - return 'Hydrogen Acceptor' + return 'Hydrogen Acceptor'; case FeatureType.HalogenDonor: - return 'Halogen Donor' + return 'Halogen Donor'; case FeatureType.HalogenAcceptor: - return 'Halogen Acceptor' + return 'Halogen Acceptor'; case FeatureType.HydrophobicAtom: - return 'HydrophobicAtom' + return 'HydrophobicAtom'; case FeatureType.WeakHydrogenDonor: - return 'Weak Hydrogen Donor' + return 'Weak Hydrogen Donor'; case FeatureType.IonicTypePartner: - return 'Ionic Type Partner' + return 'Ionic Type Partner'; case FeatureType.DativeBondPartner: - return 'Dative Bond Partner' + return 'Dative Bond Partner'; case FeatureType.TransitionMetal: - return 'Transition Metal' + return 'Transition Metal'; case FeatureType.IonicTypeMetal: - return 'Ionic Type Metal' + return 'Ionic Type Metal'; } } @@ -245,26 +245,26 @@ export const enum FeatureGroup { export function featureGroupLabel(group: FeatureGroup): string { switch (group) { case FeatureGroup.None: - return 'None' + return 'None'; case FeatureGroup.QuaternaryAmine: - return 'Quaternary Amine' + return 'Quaternary Amine'; case FeatureGroup.TertiaryAmine: - return 'Tertiary Amine' + return 'Tertiary Amine'; case FeatureGroup.Sulfonium: - return 'Sulfonium' + return 'Sulfonium'; case FeatureGroup.SulfonicAcid: - return 'Sulfonic Acid' + return 'Sulfonic Acid'; case FeatureGroup.Sulfate: - return 'Sulfate' + return 'Sulfate'; case FeatureGroup.Phosphate: - return 'Phosphate' + return 'Phosphate'; case FeatureGroup.Halocarbon: - return 'Halocarbon' + return 'Halocarbon'; case FeatureGroup.Guanidine: - return 'Guanidine' + return 'Guanidine'; case FeatureGroup.Acetamidine: - return 'Acetamidine' + return 'Acetamidine'; case FeatureGroup.Carboxylate: - return 'Carboxylate' + return 'Carboxylate'; } } \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/contacts-builder.ts b/src/mol-model-props/computed/interactions/contacts-builder.ts index 93ab4ef52435d7bea010810218e293d57e94e0f4..046fb652b1c9fbe54005323e24c1b4e4c85b6431 100644 --- a/src/mol-model-props/computed/interactions/contacts-builder.ts +++ b/src/mol-model-props/computed/interactions/contacts-builder.ts @@ -12,7 +12,7 @@ import { NumberArray } from '../../../mol-util/type-helpers'; import { IntMap } from '../../../mol-data/int'; import { InterUnitGraph } from '../../../mol-math/graph/inter-unit-graph'; -export { IntraContactsBuilder } +export { IntraContactsBuilder }; interface IntraContactsBuilder { add: (indexA: Features.FeatureIndex, indexB: Features.FeatureIndex, type: InteractionType) => void @@ -21,39 +21,39 @@ interface IntraContactsBuilder { namespace IntraContactsBuilder { export function create(features: Features, elementsCount: number): IntraContactsBuilder { - const aIndices: Features.FeatureIndex[] = [] - const bIndices: Features.FeatureIndex[] = [] - const types: number[] = [] + const aIndices: Features.FeatureIndex[] = []; + const bIndices: Features.FeatureIndex[] = []; + const types: number[] = []; return { add(indexA: Features.FeatureIndex, indexB: Features.FeatureIndex, type: InteractionType) { - aIndices[aIndices.length] = indexA - bIndices[bIndices.length] = indexB - types[types.length] = type + aIndices[aIndices.length] = indexA; + bIndices[bIndices.length] = indexB; + types[types.length] = type; }, getContacts() { - const builder = new IntAdjacencyGraph.EdgeBuilder(features.count, aIndices, bIndices) - const type = new Int8Array(builder.slotCount) as ArrayLike<InteractionType> - const flag = new Int8Array(builder.slotCount) as NumberArray + const builder = new IntAdjacencyGraph.EdgeBuilder(features.count, aIndices, bIndices); + const type = new Int8Array(builder.slotCount) as ArrayLike<InteractionType>; + const flag = new Int8Array(builder.slotCount) as NumberArray; for (let i = 0, _i = builder.edgeCount; i < _i; i++) { - builder.addNextEdge() - builder.assignProperty(type, types[i]) + builder.addNextEdge(); + builder.assignProperty(type, types[i]); } - const graph = builder.createGraph({ type, flag }) + const graph = builder.createGraph({ type, flag }); - let elementsIndex: InteractionsIntraContacts.ElementsIndex + let elementsIndex: InteractionsIntraContacts.ElementsIndex; const contacts: InteractionsIntraContacts = Object.defineProperty(graph, 'elementsIndex', { get: () => { - return elementsIndex || (elementsIndex = InteractionsIntraContacts.createElementsIndex(graph, features, elementsCount)) + return elementsIndex || (elementsIndex = InteractionsIntraContacts.createElementsIndex(graph, features, elementsCount)); } - }) - return contacts + }); + return contacts; } - } + }; } } -export { InterContactsBuilder } +export { InterContactsBuilder }; interface InterContactsBuilder { startUnitPair: (unitA: Unit, unitB: Unit) => void @@ -64,21 +64,21 @@ interface InterContactsBuilder { namespace InterContactsBuilder { export function create(): InterContactsBuilder { - const builder = new InterUnitGraph.Builder<Unit, Features.FeatureIndex, InteractionsInterContacts.Props>() + const builder = new InterUnitGraph.Builder<Unit, Features.FeatureIndex, InteractionsInterContacts.Props>(); return { startUnitPair(unitA: Unit, unitB: Unit) { - builder.startUnitPair(unitA, unitB) + builder.startUnitPair(unitA, unitB); }, finishUnitPair() { - builder.finishUnitPair() + builder.finishUnitPair(); }, add(indexA: Features.FeatureIndex, indexB: Features.FeatureIndex, type: InteractionType) { - builder.add(indexA, indexB, { type, flag: InteractionFlag.None }) + builder.add(indexA, indexB, { type, flag: InteractionFlag.None }); }, getContacts(unitsFeatures: IntMap<Features>) { return new InteractionsInterContacts(builder.getMap(), unitsFeatures); } - } + }; } } \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/contacts.ts b/src/mol-model-props/computed/interactions/contacts.ts index 57967b0c19e8210b4ed905fa52162ad76a6d7287..efa26d4641f1ecb1e06da16bca749213546def38 100644 --- a/src/mol-model-props/computed/interactions/contacts.ts +++ b/src/mol-model-props/computed/interactions/contacts.ts @@ -17,11 +17,11 @@ import { Elements } from '../../../mol-model/structure/model/properties/atomic/t export const ContactsParams = { lineOfSightDistFactor: PD.Numeric(1.0, { min: 0, max: 3, step: 0.1 }), -} +}; export type ContactsParams = typeof ContactsParams export type ContactsProps = PD.Values<ContactsParams> -const MAX_LINE_OF_SIGHT_DISTANCE = 3 +const MAX_LINE_OF_SIGHT_DISTANCE = 3; export interface ContactProvider<P extends PD.Params> { readonly name: string @@ -36,81 +36,81 @@ export interface ContactTester { } function validPair(structure: Structure, infoA: Features.Info, infoB: Features.Info): boolean { - const indexA = infoA.members[infoA.offsets[infoA.feature]] - const indexB = infoB.members[infoB.offsets[infoB.feature]] - if (indexA === indexB) return false // no self interaction - const altA = altLoc(infoA.unit, indexA) - const altB = altLoc(infoB.unit, indexB) - if (altA && altB && altA !== altB) return false // incompatible alternate location id - if (infoA.unit.residueIndex[infoA.unit.elements[indexA]] === infoB.unit.residueIndex[infoB.unit.elements[indexB]]) return false // same residue + const indexA = infoA.members[infoA.offsets[infoA.feature]]; + const indexB = infoB.members[infoB.offsets[infoB.feature]]; + if (indexA === indexB) return false; // no self interaction + const altA = altLoc(infoA.unit, indexA); + const altB = altLoc(infoB.unit, indexB); + if (altA && altB && altA !== altB) return false; // incompatible alternate location id + if (infoA.unit.residueIndex[infoA.unit.elements[indexA]] === infoB.unit.residueIndex[infoB.unit.elements[indexB]]) return false; // same residue // e.g. no hbond if donor and acceptor are bonded - if (connectedTo(structure, infoA.unit, indexA, infoB.unit, indexB)) return false + if (connectedTo(structure, infoA.unit, indexA, infoB.unit, indexB)) return false; - return true + return true; } // function invalidAltLoc (unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex) { - const altA = altLoc(unitA, indexA) - const altB = altLoc(unitB, indexB) - return altA && altB && altA !== altB + const altA = altLoc(unitA, indexA); + const altB = altLoc(unitB, indexB); + return altA && altB && altA !== altB; } function isMember(element: StructureElement.UnitIndex, info: Features.Info) { - const { feature, offsets, members } = info + const { feature, offsets, members } = info; for (let i = offsets[feature], il = offsets[feature + 1]; i < il; ++i) { - if (members[i] === element) return true + if (members[i] === element) return true; } - return false + return false; } -const tmpVec = Vec3() -const tmpVecA = Vec3() -const tmpVecB = Vec3() +const tmpVec = Vec3(); +const tmpVecA = Vec3(); +const tmpVecB = Vec3(); function checkLineOfSight(structure: Structure, infoA: Features.Info, infoB: Features.Info, distFactor: number) { - const featureA = infoA.feature - const featureB = infoB.feature - const indexA = infoA.members[infoA.offsets[featureA]] - const indexB = infoB.members[infoB.offsets[featureB]] + const featureA = infoA.feature; + const featureB = infoB.feature; + const indexA = infoA.members[infoA.offsets[featureA]]; + const indexB = infoB.members[infoB.offsets[featureB]]; - Features.position(tmpVecA, infoA) - Features.position(tmpVecB, infoB) - Vec3.scale(tmpVec, Vec3.add(tmpVec, tmpVecA, tmpVecB), 0.5) + Features.position(tmpVecA, infoA); + Features.position(tmpVecB, infoB); + Vec3.scale(tmpVec, Vec3.add(tmpVec, tmpVecA, tmpVecB), 0.5); - const distMax = distFactor * MAX_LINE_OF_SIGHT_DISTANCE + const distMax = distFactor * MAX_LINE_OF_SIGHT_DISTANCE; - const { count, indices, units, squaredDistances } = structure.lookup3d.find(tmpVec[0], tmpVec[1], tmpVec[2], distMax) - if (count === 0) return true + const { count, indices, units, squaredDistances } = structure.lookup3d.find(tmpVec[0], tmpVec[1], tmpVec[2], distMax); + if (count === 0) return true; for (let r = 0; r < count; ++r) { - const i = indices[r] - const unit = units[r] - if (!Unit.isAtomic(unit)) continue + const i = indices[r]; + const unit = units[r]; + if (!Unit.isAtomic(unit)) continue; - const element = typeSymbol(unit, i) + const element = typeSymbol(unit, i); // allow hydrogens - if (element === Elements.H) continue + if (element === Elements.H) continue; - const vdw = VdwRadius(element) + const vdw = VdwRadius(element); // check distance - if (vdw * vdw * distFactor * distFactor <= squaredDistances[r]) continue + if (vdw * vdw * distFactor * distFactor <= squaredDistances[r]) continue; // allow different altlocs - if (invalidAltLoc(unit, i, infoA.unit, indexA) || invalidAltLoc(unit, i, infoB.unit, indexB)) continue + if (invalidAltLoc(unit, i, infoA.unit, indexA) || invalidAltLoc(unit, i, infoB.unit, indexB)) continue; // allow member atoms - if ((infoA.unit === unit && isMember(i, infoA)) || (infoB.unit === unit && isMember(i, infoB))) continue + if ((infoA.unit === unit && isMember(i, infoA)) || (infoB.unit === unit && isMember(i, infoB))) continue; - unit.conformation.position(unit.elements[i], tmpVec) + unit.conformation.position(unit.elements[i], tmpVec); // allow atoms at the center of functional groups - if (Vec3.squaredDistance(tmpVec, tmpVecA) < 1 || Vec3.squaredDistance(tmpVec, tmpVecB) < 1) continue + if (Vec3.squaredDistance(tmpVec, tmpVecA) < 1 || Vec3.squaredDistance(tmpVec, tmpVecB) < 1) continue; - return false + return false; } - return true + return true; } /** @@ -118,42 +118,42 @@ function checkLineOfSight(structure: Structure, infoA: Features.Info, infoB: Fea */ export function addUnitContacts(structure: Structure, unit: Unit.Atomic, features: Features, builder: IntraContactsBuilder, testers: ReadonlyArray<ContactTester>, props: ContactsProps) { for (const tester of testers) { - _addUnitContacts(structure, unit, features, builder, tester, props) + _addUnitContacts(structure, unit, features, builder, tester, props); } } function _addUnitContacts(structure: Structure, unit: Unit.Atomic, features: Features, builder: IntraContactsBuilder, tester: ContactTester, props: ContactsProps) { - const { x, y, z } = features - const { lookup3d, indices: subsetIndices } = features.subset(tester.requiredFeatures) + const { x, y, z } = features; + const { lookup3d, indices: subsetIndices } = features.subset(tester.requiredFeatures); - const infoA = Features.Info(structure, unit, features) - const infoB = { ...infoA } + const infoA = Features.Info(structure, unit, features); + const infoB = { ...infoA }; - const distFactor = props.lineOfSightDistFactor + const distFactor = props.lineOfSightDistFactor; for (let t = 0, tl = OrderedSet.size(subsetIndices); t < tl; ++t) { - const i = OrderedSet.getAt(subsetIndices, t) - const { count, indices, squaredDistances } = lookup3d.find(x[i], y[i], z[i], tester.maxDistance) - if (count === 0) continue + const i = OrderedSet.getAt(subsetIndices, t); + const { count, indices, squaredDistances } = lookup3d.find(x[i], y[i], z[i], tester.maxDistance); + if (count === 0) continue; - infoA.feature = i + infoA.feature = i; for (let r = 0; r < count; ++r) { - const j = OrderedSet.getAt(subsetIndices, indices[r]) - if (j <= i) continue + const j = OrderedSet.getAt(subsetIndices, indices[r]); + if (j <= i) continue; - infoB.feature = j - if (!validPair(structure, infoA, infoB)) continue + infoB.feature = j; + if (!validPair(structure, infoA, infoB)) continue; - const type = tester.getType(structure, infoA, infoB, squaredDistances[r]) + const type = tester.getType(structure, infoA, infoB, squaredDistances[r]); if (type && checkLineOfSight(structure, infoA, infoB, distFactor)) { - builder.add(i, j, type) + builder.add(i, j, type); } } } } -const _imageTransform = Mat4() +const _imageTransform = Mat4(); /** * Add all inter-unit contacts, i.e. pairs of features @@ -164,48 +164,48 @@ export function addStructureContacts(structure: Structure, unitA: Unit.Atomic, f // the lookup queries need to happen in the "unitB space". // that means imageA = inverseOperB(operA(i)) - const imageTransform = Mat4.mul(_imageTransform, unitB.conformation.operator.inverse, unitA.conformation.operator.matrix) - const isNotIdentity = !Mat4.isIdentity(imageTransform) - const imageA = Vec3() + const imageTransform = Mat4.mul(_imageTransform, unitB.conformation.operator.inverse, unitA.conformation.operator.matrix); + const isNotIdentity = !Mat4.isIdentity(imageTransform); + const imageA = Vec3(); - const maxDistance = Math.max(...testers.map(t => t.maxDistance)) + const maxDistance = Math.max(...testers.map(t => t.maxDistance)); const { center, radius } = lookup3d.boundary.sphere; const testDistanceSq = (radius + maxDistance) * (radius + maxDistance); - const distFactor = props.lineOfSightDistFactor + const distFactor = props.lineOfSightDistFactor; - const infoA = Features.Info(structure, unitA, featuresA) - const infoB = Features.Info(structure, unitB, featuresB) + const infoA = Features.Info(structure, unitA, featuresA); + const infoB = Features.Info(structure, unitB, featuresB); - builder.startUnitPair(unitA, unitB) + builder.startUnitPair(unitA, unitB); for (let i = 0 as Features.FeatureIndex; i < countA; ++i) { - Vec3.set(imageA, xA[i], yA[i], zA[i]) - if (isNotIdentity) Vec3.transformMat4(imageA, imageA, imageTransform) - if (Vec3.squaredDistance(imageA, center) > testDistanceSq) continue + Vec3.set(imageA, xA[i], yA[i], zA[i]); + if (isNotIdentity) Vec3.transformMat4(imageA, imageA, imageTransform); + if (Vec3.squaredDistance(imageA, center) > testDistanceSq) continue; - const { indices, count, squaredDistances } = lookup3d.find(imageA[0], imageA[1], imageA[2], maxDistance) - if (count === 0) continue + const { indices, count, squaredDistances } = lookup3d.find(imageA[0], imageA[1], imageA[2], maxDistance); + if (count === 0) continue; - infoA.feature = i + infoA.feature = i; for (let r = 0; r < count; ++r) { - const j = indices[r] - infoB.feature = j - if (!validPair(structure, infoA, infoB)) continue + const j = indices[r]; + infoB.feature = j; + if (!validPair(structure, infoA, infoB)) continue; - const distanceSq = squaredDistances[r] + const distanceSq = squaredDistances[r]; for (const tester of testers) { if (distanceSq < tester.maxDistance * tester.maxDistance) { - const type = tester.getType(structure, infoA, infoB, distanceSq) + const type = tester.getType(structure, infoA, infoB, distanceSq); if (type && checkLineOfSight(structure, infoA, infoB, distFactor)) { - builder.add(i, j, type) - break + builder.add(i, j, type); + break; } } } } } - builder.finishUnitPair() + builder.finishUnitPair(); } \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/features.ts b/src/mol-model-props/computed/interactions/features.ts index befc1431a3299975e7fccd2117cd452ed6cdebf6..0a6f552a74003501c5dbb76fb1762f2538239595 100644 --- a/src/mol-model-props/computed/interactions/features.ts +++ b/src/mol-model-props/computed/interactions/features.ts @@ -13,7 +13,7 @@ import { ValenceModelProvider } from '../valence-model'; import { Vec3 } from '../../../mol-math/linear-algebra'; import { getBoundary } from '../../../mol-math/geometry/boundary'; -export { Features } +export { Features }; interface Features { /** number of features */ @@ -43,9 +43,9 @@ namespace Features { export type FeatureIndex = { readonly '@type': 'feature-index' } & number export function setPosition(out: Vec3, unit: Unit, index: FeatureIndex, features: Features) { - Vec3.set(out, features.x[index], features.y[index], features.z[index]) - Vec3.transformMat4(out, out, unit.conformation.operator.matrix) - return out + Vec3.set(out, features.x[index], features.y[index], features.z[index]); + Vec3.transformMat4(out, out, unit.conformation.operator.matrix); + return out; } /** maps unit elements to features, range for unit element i is offsets[i] to offsets[i + 1] */ @@ -73,73 +73,73 @@ namespace Features { } export function createElementsIndex(data: Data, elementsCount: number): ElementsIndex { - const offsets = new Int32Array(elementsCount + 1) - const bucketFill = new Int32Array(elementsCount) - const bucketSizes = new Int32Array(elementsCount) - const { members, count, offsets: featureOffsets } = data - for (let i = 0, il = featureOffsets[count]; i < il; ++i) ++bucketSizes[members[i]] + const offsets = new Int32Array(elementsCount + 1); + const bucketFill = new Int32Array(elementsCount); + const bucketSizes = new Int32Array(elementsCount); + const { members, count, offsets: featureOffsets } = data; + for (let i = 0, il = featureOffsets[count]; i < il; ++i) ++bucketSizes[members[i]]; - let offset = 0 + let offset = 0; for (let i = 0; i < elementsCount; i++) { - offsets[i] = offset - offset += bucketSizes[i] + offsets[i] = offset; + offset += bucketSizes[i]; } - offsets[elementsCount] = offset + offsets[elementsCount] = offset; - const indices = new Int32Array(offset) + const indices = new Int32Array(offset); for (let i = 0; i < count; ++i) { for (let j = featureOffsets[i], jl = featureOffsets[i + 1]; j < jl; ++j) { - const a = members[j] - const oa = offsets[a] + bucketFill[a] - indices[oa] = i - ++bucketFill[a] + const a = members[j]; + const oa = offsets[a] + bucketFill[a]; + indices[oa] = i; + ++bucketFill[a]; } } - return { indices: indices as unknown as ArrayLike<FeatureIndex>, offsets } + return { indices: indices as unknown as ArrayLike<FeatureIndex>, offsets }; } export function create(elementsCount: number, data: Data): Features { - let lookup3d: GridLookup3D<FeatureIndex> - let elementsIndex: ElementsIndex + let lookup3d: GridLookup3D<FeatureIndex>; + let elementsIndex: ElementsIndex; return { ...data, get lookup3d() { if (!lookup3d) { - const position = { x: data.x, y: data.y, z: data.z, indices: OrderedSet.ofBounds(0 as FeatureIndex, data.count as FeatureIndex) } - lookup3d = GridLookup3D(position, getBoundary(position)) + const position = { x: data.x, y: data.y, z: data.z, indices: OrderedSet.ofBounds(0 as FeatureIndex, data.count as FeatureIndex) }; + lookup3d = GridLookup3D(position, getBoundary(position)); } - return lookup3d + return lookup3d; }, get elementsIndex() { - return elementsIndex || (elementsIndex = createElementsIndex(data, elementsCount)) + return elementsIndex || (elementsIndex = createElementsIndex(data, elementsCount)); }, subset: (types: Set<FeatureType>) => createSubset(data, types) - } + }; } export function createSubset(data: Data, types: ReadonlySet<FeatureType>): Subset { - let lookup3d: GridLookup3D + let lookup3d: GridLookup3D; - const { count, types: _types } = data - const _indices = [] + const { count, types: _types } = data; + const _indices = []; for (let i = 0; i < count; ++i) { - if (types.has(_types[i])) _indices.push(i) + if (types.has(_types[i])) _indices.push(i); } - const indices = SortedArray.ofSortedArray<FeatureIndex>(_indices) + const indices = SortedArray.ofSortedArray<FeatureIndex>(_indices); return { indices, get lookup3d() { if (!lookup3d) { - const position = { x: data.x, y: data.y, z: data.z, indices } - lookup3d = GridLookup3D(position, getBoundary(position)) + const position = { x: data.x, y: data.y, z: data.z, indices }; + lookup3d = GridLookup3D(position, getBoundary(position)); } - return lookup3d + return lookup3d; } - } + }; } export interface Info { @@ -154,8 +154,8 @@ namespace Features { idealGeometry: Int8Array } export function Info(structure: Structure, unit: Unit.Atomic, features: Features): Info { - const valenceModel = ValenceModelProvider.get(structure).value - if (!valenceModel || !valenceModel.has(unit.id)) throw new Error('valence model required') + const valenceModel = ValenceModelProvider.get(structure).value; + if (!valenceModel || !valenceModel.has(unit.id)) throw new Error('valence model required'); return { unit, @@ -167,23 +167,23 @@ namespace Features { members: features.members, offsets: features.offsets, idealGeometry: valenceModel.get(unit.id)!.idealGeometry - } + }; } export function position(out: Vec3, info: Info) { - Vec3.set(out, info.x[info.feature], info.y[info.feature], info.z[info.feature]) - Vec3.transformMat4(out, out, info.unit.conformation.operator.matrix) - return out + Vec3.set(out, info.x[info.feature], info.y[info.feature], info.z[info.feature]); + Vec3.transformMat4(out, out, info.unit.conformation.operator.matrix); + return out; } - const tmpVecA = Vec3() - const tmpVecB = Vec3() + const tmpVecA = Vec3(); + const tmpVecB = Vec3(); export function distance(infoA: Info, infoB: Info) { - const elementA = infoA.members[infoA.offsets[infoA.feature]] - const elementB = infoB.members[infoB.offsets[infoB.feature]] - infoA.unit.conformation.position(infoA.unit.elements[elementA], tmpVecA) - infoB.unit.conformation.position(infoB.unit.elements[elementB], tmpVecB) - return Vec3.distance(tmpVecA, tmpVecB) + const elementA = infoA.members[infoA.offsets[infoA.feature]]; + const elementB = infoB.members[infoB.offsets[infoB.feature]]; + infoA.unit.conformation.position(infoA.unit.elements[elementA], tmpVecA); + infoB.unit.conformation.position(infoB.unit.elements[elementB], tmpVecB); + return Vec3.distance(tmpVecA, tmpVecB); } export interface Provider { @@ -191,11 +191,11 @@ namespace Features { add: (structure: Structure, unit: Unit.Atomic, featuresBuilder: FeaturesBuilder) => void } export function Provider(types: FeatureType[], add: Provider['add']): Provider { - return { types: new Set(types), add } + return { types: new Set(types), add }; } } -export { FeaturesBuilder } +export { FeaturesBuilder }; interface FeaturesBuilder { startState: () => void @@ -209,64 +209,64 @@ namespace FeaturesBuilder { interface State { x: number, y: number, z: number, offset: number, count: number } export function create(initialCount = 2048, chunkSize = 1024, features?: Features): FeaturesBuilder { - const xCenters = ChunkedArray.create(Float32Array, 1, chunkSize, features ? features.x : initialCount) - const yCenters = ChunkedArray.create(Float32Array, 1, chunkSize, features ? features.y : initialCount) - const zCenters = ChunkedArray.create(Float32Array, 1, chunkSize, features ? features.z : initialCount) - const types = ChunkedArray.create(Uint8Array, 1, chunkSize, features ? features.types : initialCount) - const groups = ChunkedArray.create(Uint8Array, 1, chunkSize, features ? features.groups : initialCount) - const offsets = ChunkedArray.create(Uint32Array, 1, chunkSize, features ? features.offsets : initialCount) - const members = ChunkedArray.create(Uint32Array, 1, chunkSize, features ? features.members : initialCount) + const xCenters = ChunkedArray.create(Float32Array, 1, chunkSize, features ? features.x : initialCount); + const yCenters = ChunkedArray.create(Float32Array, 1, chunkSize, features ? features.y : initialCount); + const zCenters = ChunkedArray.create(Float32Array, 1, chunkSize, features ? features.z : initialCount); + const types = ChunkedArray.create(Uint8Array, 1, chunkSize, features ? features.types : initialCount); + const groups = ChunkedArray.create(Uint8Array, 1, chunkSize, features ? features.groups : initialCount); + const offsets = ChunkedArray.create(Uint32Array, 1, chunkSize, features ? features.offsets : initialCount); + const members = ChunkedArray.create(Uint32Array, 1, chunkSize, features ? features.members : initialCount); - const state: State = { x: 0, y: 0, z: 0, offset: 0, count: 0 } + const state: State = { x: 0, y: 0, z: 0, offset: 0, count: 0 }; return { startState: () => { - state.x = 0 - state.y = 0 - state.z = 0 - state.offset = members.elementCount - state.count = 0 + state.x = 0; + state.y = 0; + state.z = 0; + state.offset = members.elementCount; + state.count = 0; }, pushMember: (x: number, y: number, z: number, member: StructureElement.UnitIndex) => { - ChunkedArray.add(members, member) - state.x += x - state.y += y - state.z += z - state.count += 1 + ChunkedArray.add(members, member); + state.x += x; + state.y += y; + state.z += z; + state.count += 1; }, finishState: (type: FeatureType, group: FeatureGroup) => { - const { count } = state - if (count === 0) return - ChunkedArray.add(types, type) - ChunkedArray.add(groups, group) - ChunkedArray.add(xCenters, state.x / count) - ChunkedArray.add(yCenters, state.y / count) - ChunkedArray.add(zCenters, state.z / count) - ChunkedArray.add(offsets, state.offset) + const { count } = state; + if (count === 0) return; + ChunkedArray.add(types, type); + ChunkedArray.add(groups, group); + ChunkedArray.add(xCenters, state.x / count); + ChunkedArray.add(yCenters, state.y / count); + ChunkedArray.add(zCenters, state.z / count); + ChunkedArray.add(offsets, state.offset); }, add: (type: FeatureType, group: FeatureGroup, x: number, y: number, z: number, member: StructureElement.UnitIndex) => { - ChunkedArray.add(types, type) - ChunkedArray.add(groups, group) - ChunkedArray.add(xCenters, x) - ChunkedArray.add(yCenters, y) - ChunkedArray.add(zCenters, z) - ChunkedArray.add(offsets, members.elementCount) - ChunkedArray.add(members, member) + ChunkedArray.add(types, type); + ChunkedArray.add(groups, group); + ChunkedArray.add(xCenters, x); + ChunkedArray.add(yCenters, y); + ChunkedArray.add(zCenters, z); + ChunkedArray.add(offsets, members.elementCount); + ChunkedArray.add(members, member); }, getFeatures: (elementsCount: number) => { - ChunkedArray.add(offsets, members.elementCount) - const x = ChunkedArray.compact(xCenters, true) as ArrayLike<number> - const y = ChunkedArray.compact(yCenters, true) as ArrayLike<number> - const z = ChunkedArray.compact(zCenters, true) as ArrayLike<number> - const count = xCenters.elementCount + ChunkedArray.add(offsets, members.elementCount); + const x = ChunkedArray.compact(xCenters, true) as ArrayLike<number>; + const y = ChunkedArray.compact(yCenters, true) as ArrayLike<number>; + const z = ChunkedArray.compact(zCenters, true) as ArrayLike<number>; + const count = xCenters.elementCount; return Features.create(elementsCount, { x, y, z, count, types: ChunkedArray.compact(types, true) as ArrayLike<FeatureType>, groups: ChunkedArray.compact(groups, true) as ArrayLike<FeatureGroup>, offsets: ChunkedArray.compact(offsets, true) as ArrayLike<number>, members: ChunkedArray.compact(members, true) as ArrayLike<StructureElement.UnitIndex>, - }) + }); } - } + }; } } \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/halogen-bonds.ts b/src/mol-model-props/computed/interactions/halogen-bonds.ts index 8c4633d92966ec672ed808461fa7394b4187b16e..52f5b494176e6fe2d80e3f02ca5319d45b0091a9 100644 --- a/src/mol-model-props/computed/interactions/halogen-bonds.ts +++ b/src/mol-model-props/computed/interactions/halogen-bonds.ts @@ -21,48 +21,48 @@ import { ContactProvider } from './contacts'; const HalogenBondsParams = { distanceMax: PD.Numeric(4.0, { min: 1, max: 5, step: 0.1 }), angleMax: PD.Numeric(30, { min: 0, max: 60, step: 1 }), -} +}; type HalogenBondsParams = typeof HalogenBondsParams type HalogenBondsProps = PD.Values<HalogenBondsParams> -const halBondElements = [Elements.CL, Elements.BR, Elements.I, Elements.AT] as ElementSymbol[] +const halBondElements = [Elements.CL, Elements.BR, Elements.I, Elements.AT] as ElementSymbol[]; /** * Halogen bond donors (X-C, with X one of Cl, Br, I or At) not F! */ function addUnitHalogenDonors(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { - const element = typeSymbol(unit, i) + const element = typeSymbol(unit, i); if (halBondElements.includes(element)) { - builder.add(FeatureType.HalogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.HalogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } -const X = [Elements.N, Elements.O, Elements.S] as ElementSymbol[] -const Y = [Elements.C, Elements.N, Elements.P, Elements.S] as ElementSymbol[] +const X = [Elements.N, Elements.O, Elements.S] as ElementSymbol[]; +const Y = [Elements.C, Elements.N, Elements.P, Elements.S] as ElementSymbol[]; /** * Halogen bond acceptors (Y-{O|N|S}, with Y=C,P,N,S) */ function addUnitHalogenAcceptors(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { - const element = typeSymbol(unit, i) + const element = typeSymbol(unit, i); if (X.includes(element)) { - let flag = false + let flag = false; eachBondedAtom(structure, unit, i, (unitB, indexB) => { if (Y.includes(typeSymbol(unitB, indexB))) { - flag = true + flag = true; } - }) + }); if (flag) { - builder.add(FeatureType.HalogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.HalogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } @@ -72,58 +72,58 @@ function isHalogenBond(ti: FeatureType, tj: FeatureType) { return ( (ti === FeatureType.HalogenAcceptor && tj === FeatureType.HalogenDonor) || (ti === FeatureType.HalogenDonor && tj === FeatureType.HalogenAcceptor) - ) + ); } // http://www.pnas.org/content/101/48/16789.full -const OptimalHalogenAngle = degToRad(180) // adjusted from 165 to account for spherical statistics -const OptimalAcceptorAngle = degToRad(120) +const OptimalHalogenAngle = degToRad(180); // adjusted from 165 to account for spherical statistics +const OptimalAcceptorAngle = degToRad(120); function getOptions(props: HalogenBondsProps) { return { angleMax: degToRad(props.angleMax), - } + }; } type Options = ReturnType<typeof getOptions> function testHalogenBond(structure: Structure, infoA: Features.Info, infoB: Features.Info, opts: Options): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; - if (!isHalogenBond(typeA, typeB)) return + if (!isHalogenBond(typeA, typeB)) return; - const [don, acc] = typeA === FeatureType.HalogenDonor ? [infoA, infoB] : [infoB, infoA] + const [don, acc] = typeA === FeatureType.HalogenDonor ? [infoA, infoB] : [infoB, infoA]; - const donIndex = don.members[don.offsets[don.feature]] - const accIndex = acc.members[acc.offsets[acc.feature]] + const donIndex = don.members[don.offsets[don.feature]]; + const accIndex = acc.members[acc.offsets[acc.feature]]; - const halogenAngles = calcAngles(structure, don.unit, donIndex, acc.unit, accIndex) + const halogenAngles = calcAngles(structure, don.unit, donIndex, acc.unit, accIndex); // Singly bonded halogen only (not bromide ion for example) - if (halogenAngles.length !== 1) return - if (OptimalHalogenAngle - halogenAngles[0] > opts.angleMax) return + if (halogenAngles.length !== 1) return; + if (OptimalHalogenAngle - halogenAngles[0] > opts.angleMax) return; - const acceptorAngles = calcAngles(structure, acc.unit, accIndex, don.unit, donIndex) + const acceptorAngles = calcAngles(structure, acc.unit, accIndex, don.unit, donIndex); // Angle must be defined. Excludes water as acceptor. Debatable - if (acceptorAngles.length === 0) return - if (acceptorAngles.some(acceptorAngle => OptimalAcceptorAngle - acceptorAngle > opts.angleMax)) return + if (acceptorAngles.length === 0) return; + if (acceptorAngles.some(acceptorAngle => OptimalAcceptorAngle - acceptorAngle > opts.angleMax)) return; - return InteractionType.HalogenBond + return InteractionType.HalogenBond; } // -export const HalogenDonorProvider = Features.Provider([FeatureType.HalogenDonor], addUnitHalogenDonors) -export const HalogenAcceptorProvider = Features.Provider([FeatureType.HalogenAcceptor], addUnitHalogenAcceptors) +export const HalogenDonorProvider = Features.Provider([FeatureType.HalogenDonor], addUnitHalogenDonors); +export const HalogenAcceptorProvider = Features.Provider([FeatureType.HalogenAcceptor], addUnitHalogenAcceptors); export const HalogenBondsProvider: ContactProvider<HalogenBondsParams> = { name: 'halogen-bonds', params: HalogenBondsParams, createTester: (props: HalogenBondsProps) => { - const opts = getOptions(props) + const opts = getOptions(props); return { maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.HalogenDonor, FeatureType.HalogenAcceptor]), getType: (structure, infoA, infoB) => testHalogenBond(structure, infoA, infoB, opts) - } + }; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/hydrogen-bonds.ts b/src/mol-model-props/computed/interactions/hydrogen-bonds.ts index a47f444e04823e1dfdfd2103cbe7639f9e38a4f3..1f0ef8c037c5a2a38405ea7bf5d46ccf54d64ff7 100644 --- a/src/mol-model-props/computed/interactions/hydrogen-bonds.ts +++ b/src/mol-model-props/computed/interactions/hydrogen-bonds.ts @@ -26,7 +26,7 @@ const GeometryParams = { donAngleDevMax: PD.Numeric(45, { min: 0, max: 180, step: 1 }, { description: 'Max deviation from ideal donor angle' }), accOutOfPlaneAngleMax: PD.Numeric(90, { min: 0, max: 180, step: 1 }), donOutOfPlaneAngleMax: PD.Numeric(45, { min: 0, max: 180, step: 1 }), -} +}; type GeometryParams = typeof GeometryParams type GeometryProps = PD.Values<GeometryParams> @@ -34,13 +34,13 @@ const HydrogenBondsParams = { ...GeometryParams, water: PD.Boolean(false, { description: 'Include water-to-water hydrogen bonds' }), sulfurDistanceMax: PD.Numeric(4.1, { min: 1, max: 5, step: 0.1 }), -} +}; type HydrogenBondsParams = typeof HydrogenBondsParams type HydrogenBondsProps = PD.Values<HydrogenBondsParams> const WeakHydrogenBondsParams = { ...GeometryParams, -} +}; type WeakHydrogenBondsParams = typeof WeakHydrogenBondsParams type WeakHydrogenBondsProps = PD.Values<WeakHydrogenBondsParams> @@ -54,26 +54,26 @@ type WeakHydrogenBondsProps = PD.Values<WeakHydrogenBondsParams> // http://www.csb.yale.edu/userguides/datamanip/hbplus/hbplus_descrip.html function getUnitValenceModel(structure: Structure, unit: Unit.Atomic) { - const valenceModel = ValenceModelProvider.get(structure).value - if (!valenceModel) throw Error('expected valence model to be available') - const unitValenceModel = valenceModel.get(unit.id) - if (!unitValenceModel) throw Error('expected valence model for unit to be available') - return unitValenceModel + const valenceModel = ValenceModelProvider.get(structure).value; + if (!valenceModel) throw Error('expected valence model to be available'); + const unitValenceModel = valenceModel.get(unit.id); + if (!unitValenceModel) throw Error('expected valence model for unit to be available'); + return unitValenceModel; } /** * Potential hydrogen donor */ function addUnitHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { totalH } = getUnitValenceModel(structure, unit) - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation - const { elementAromaticRingIndices } = unit.rings + const { totalH } = getUnitValenceModel(structure, unit); + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; + const { elementAromaticRingIndices } = unit.rings; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { if (elementAromaticRingIndices.has(i)) continue; - const element = typeSymbol(unit, i) + const element = typeSymbol(unit, i); if (( // include both nitrogen atoms in histidine due to // their often ambiguous protonation assignment @@ -82,7 +82,7 @@ function addUnitHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder: totalH[i] > 0 && (element === Elements.N || element === Elements.O || element === Elements.S) )) { - builder.add(FeatureType.HydrogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.HydrogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } @@ -91,9 +91,9 @@ function addUnitHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder: * Weak hydrogen donor. */ function addUnitWeakHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { totalH } = getUnitValenceModel(structure, unit) - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { totalH } = getUnitValenceModel(structure, unit); + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { if ( @@ -105,111 +105,111 @@ function addUnitWeakHydrogenDonors(structure: Structure, unit: Unit.Atomic, buil inAromaticRingWithElectronNegativeElement(unit, i) ) ) { - builder.add(FeatureType.WeakHydrogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.WeakHydrogenDonor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } function inAromaticRingWithElectronNegativeElement(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - const { elementAromaticRingIndices, all } = unit.rings - const ringIndices = elementAromaticRingIndices.get(index) - if (ringIndices === undefined) return false + const { elementAromaticRingIndices, all } = unit.rings; + const ringIndices = elementAromaticRingIndices.get(index); + if (ringIndices === undefined) return false; for (let i = 0, il = ringIndices.length; i < il; ++i) { - const ring = all[ringIndices[i]] + const ring = all[ringIndices[i]]; for (let j = 0, jl = ring.length; j < jl; ++j) { - const element = typeSymbol(unit, ring[j]) + const element = typeSymbol(unit, ring[j]); if (element === Elements.N || element === Elements.O) { - return true + return true; } } } - return false + return false; } /** * Potential hydrogen acceptor */ function addUnitHydrogenAcceptors(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { charge, implicitH, idealGeometry } = getUnitValenceModel(structure, unit) - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation - const { elementAromaticRingIndices } = unit.rings + const { charge, implicitH, idealGeometry } = getUnitValenceModel(structure, unit); + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; + const { elementAromaticRingIndices } = unit.rings; const add = (i: StructureElement.UnitIndex) => { - builder.add(FeatureType.HydrogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) - } + builder.add(FeatureType.HydrogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); + }; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { if (elementAromaticRingIndices.has(i)) continue; - const element = typeSymbol(unit, i) + const element = typeSymbol(unit, i); if (element === Elements.O) { // Basically assume all oxygen atoms are acceptors! - add(i) + add(i); } else if (element === Elements.N) { if (isHistidineNitrogen(unit, i)) { // include both nitrogen atoms in histidine due to // their often ambiguous protonation assignment - add(i) + add(i); } else if (charge[i] < 1) { // Neutral nitrogen might be an acceptor // It must have at least one lone pair not conjugated - const totalBonds = bondCount(structure, unit, i) + implicitH[i] - const ig = idealGeometry[i] + const totalBonds = bondCount(structure, unit, i) + implicitH[i]; + const ig = idealGeometry[i]; if ( (ig === AtomGeometry.Tetrahedral && totalBonds < 4) || (ig === AtomGeometry.Trigonal && totalBonds < 3) || (ig === AtomGeometry.Linear && totalBonds < 2) ) { - add(i) + add(i); } } } else if (element === Elements.S) { - const resname = compId(unit, i) + const resname = compId(unit, i); if (resname === 'CYS' || resname === 'MET' || formalCharge(unit, i) === -1) { - add(i) + add(i); } } } } function isWater(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.model.atomicHierarchy.derived.residue.moleculeType[unit.residueIndex[unit.elements[index]]] === MoleculeType.Water + return unit.model.atomicHierarchy.derived.residue.moleculeType[unit.residueIndex[unit.elements[index]]] === MoleculeType.Water; } function isBackbone(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return ProteinBackboneAtoms.has(atomId(unit, index)) + return ProteinBackboneAtoms.has(atomId(unit, index)); } function isRing(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return unit.rings.elementRingIndices.has(index) + return unit.rings.elementRingIndices.has(index); } function isHistidineNitrogen(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return compId(unit, index) === 'HIS' && typeSymbol(unit, index) === Elements.N && isRing(unit, index) + return compId(unit, index) === 'HIS' && typeSymbol(unit, index) === Elements.N && isRing(unit, index); } function isBackboneHydrogenBond(unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex) { - return isBackbone(unitA, indexA) && isBackbone(unitB, indexB) + return isBackbone(unitA, indexA) && isBackbone(unitB, indexB); } function isWaterHydrogenBond(unitA: Unit.Atomic, indexA: StructureElement.UnitIndex, unitB: Unit.Atomic, indexB: StructureElement.UnitIndex) { - return isWater(unitA, indexA) && isWater(unitB, indexB) + return isWater(unitA, indexA) && isWater(unitB, indexB); } function isHydrogenBond(ti: FeatureType, tj: FeatureType) { return ( (ti === FeatureType.HydrogenAcceptor && tj === FeatureType.HydrogenDonor) || (ti === FeatureType.HydrogenDonor && tj === FeatureType.HydrogenAcceptor) - ) + ); } function isWeakHydrogenBond(ti: FeatureType, tj: FeatureType) { return ( (ti === FeatureType.WeakHydrogenDonor && tj === FeatureType.HydrogenAcceptor) || (ti === FeatureType.HydrogenAcceptor && tj === FeatureType.WeakHydrogenDonor) - ) + ); } function getGeometryOptions(props: GeometryProps) { @@ -219,7 +219,7 @@ function getGeometryOptions(props: GeometryProps) { maxDonAngleDev: degToRad(props.donAngleDevMax), maxAccOutOfPlaneAngle: degToRad(props.accOutOfPlaneAngleMax), maxDonOutOfPlaneAngle: degToRad(props.donOutOfPlaneAngleMax), - } + }; } type GeometryOptions = ReturnType<typeof getGeometryOptions> @@ -229,106 +229,106 @@ function getHydrogenBondsOptions(props: HydrogenBondsProps) { includeWater: props.water, maxSulfurDistSq: props.sulfurDistanceMax * props.sulfurDistanceMax, maxDistSq: props.distanceMax * props.distanceMax - } + }; } type HydrogenBondsOptions = ReturnType<typeof getHydrogenBondsOptions> -const deg120InRad = degToRad(120) +const deg120InRad = degToRad(120); function checkGeometry(structure: Structure, don: Features.Info, acc: Features.Info, opts: GeometryOptions): true | undefined { - const donIndex = don.members[don.offsets[don.feature]] - const accIndex = acc.members[acc.offsets[acc.feature]] + const donIndex = don.members[don.offsets[don.feature]]; + const accIndex = acc.members[acc.offsets[acc.feature]]; - if (!opts.includeBackbone && isBackboneHydrogenBond(don.unit, donIndex, acc.unit, accIndex)) return + if (!opts.includeBackbone && isBackboneHydrogenBond(don.unit, donIndex, acc.unit, accIndex)) return; - const donAngles = calcAngles(structure, don.unit, donIndex, acc.unit, accIndex) - const idealDonAngle = AtomGeometryAngles.get(don.idealGeometry[donIndex]) || deg120InRad - if (donAngles.some(donAngle => Math.abs(idealDonAngle - donAngle) > opts.maxDonAngleDev)) return + const donAngles = calcAngles(structure, don.unit, donIndex, acc.unit, accIndex); + const idealDonAngle = AtomGeometryAngles.get(don.idealGeometry[donIndex]) || deg120InRad; + if (donAngles.some(donAngle => Math.abs(idealDonAngle - donAngle) > opts.maxDonAngleDev)) return; if (don.idealGeometry[donIndex] === AtomGeometry.Trigonal) { - const outOfPlane = calcPlaneAngle(structure, don.unit, donIndex, acc.unit, accIndex) - if (outOfPlane !== undefined && outOfPlane > opts.maxDonOutOfPlaneAngle) return + const outOfPlane = calcPlaneAngle(structure, don.unit, donIndex, acc.unit, accIndex); + if (outOfPlane !== undefined && outOfPlane > opts.maxDonOutOfPlaneAngle) return; } - const accAngles = calcAngles(structure, acc.unit, accIndex, don.unit, donIndex) - const idealAccAngle = AtomGeometryAngles.get(acc.idealGeometry[accIndex]) || deg120InRad + const accAngles = calcAngles(structure, acc.unit, accIndex, don.unit, donIndex); + const idealAccAngle = AtomGeometryAngles.get(acc.idealGeometry[accIndex]) || deg120InRad; // Do not limit large acceptor angles - if (accAngles.some(accAngle => idealAccAngle - accAngle > opts.maxAccAngleDev)) return + if (accAngles.some(accAngle => idealAccAngle - accAngle > opts.maxAccAngleDev)) return; if (acc.idealGeometry[accIndex] === AtomGeometry.Trigonal) { - const outOfPlane = calcPlaneAngle(structure, acc.unit, accIndex, don.unit, donIndex) - if (outOfPlane !== undefined && outOfPlane > opts.maxAccOutOfPlaneAngle) return + const outOfPlane = calcPlaneAngle(structure, acc.unit, accIndex, don.unit, donIndex); + if (outOfPlane !== undefined && outOfPlane > opts.maxAccOutOfPlaneAngle) return; } - return true + return true; } function testHydrogenBond(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number, opts: HydrogenBondsOptions): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; - if (!isHydrogenBond(typeA, typeB)) return + if (!isHydrogenBond(typeA, typeB)) return; - const [don, acc] = typeB === FeatureType.HydrogenAcceptor ? [infoA, infoB] : [infoB, infoA] + const [don, acc] = typeB === FeatureType.HydrogenAcceptor ? [infoA, infoB] : [infoB, infoA]; - const donIndex = don.members[don.offsets[don.feature]] - const accIndex = acc.members[acc.offsets[acc.feature]] + const donIndex = don.members[don.offsets[don.feature]]; + const accIndex = acc.members[acc.offsets[acc.feature]]; // check if distance is ok depending on non-sulfur-containing hbond - const maxDistSq = typeSymbol(don.unit, donIndex) === Elements.S || typeSymbol(acc.unit, accIndex) === Elements.S ? opts.maxSulfurDistSq : opts.maxDistSq - if (distanceSq > maxDistSq) return + const maxDistSq = typeSymbol(don.unit, donIndex) === Elements.S || typeSymbol(acc.unit, accIndex) === Elements.S ? opts.maxSulfurDistSq : opts.maxDistSq; + if (distanceSq > maxDistSq) return; - if (!opts.includeWater && isWaterHydrogenBond(don.unit, donIndex, acc.unit, accIndex)) return + if (!opts.includeWater && isWaterHydrogenBond(don.unit, donIndex, acc.unit, accIndex)) return; - if (!checkGeometry(structure, don, acc, opts)) return + if (!checkGeometry(structure, don, acc, opts)) return; - return InteractionType.HydrogenBond + return InteractionType.HydrogenBond; } function testWeakHydrogenBond(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number, opts: GeometryOptions): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; - if (!isWeakHydrogenBond(typeA, typeB)) return + if (!isWeakHydrogenBond(typeA, typeB)) return; - const [don, acc] = typeB === FeatureType.HydrogenAcceptor ? [infoA, infoB] : [infoB, infoA] + const [don, acc] = typeB === FeatureType.HydrogenAcceptor ? [infoA, infoB] : [infoB, infoA]; - if (!checkGeometry(structure, don, acc, opts)) return + if (!checkGeometry(structure, don, acc, opts)) return; - return InteractionType.WeakHydrogenBond + return InteractionType.WeakHydrogenBond; } // -export const HydrogenDonorProvider = Features.Provider([FeatureType.HydrogenDonor], addUnitHydrogenDonors) -export const WeakHydrogenDonorProvider = Features.Provider([FeatureType.WeakHydrogenDonor], addUnitWeakHydrogenDonors) -export const HydrogenAcceptorProvider = Features.Provider([FeatureType.HydrogenAcceptor], addUnitHydrogenAcceptors) +export const HydrogenDonorProvider = Features.Provider([FeatureType.HydrogenDonor], addUnitHydrogenDonors); +export const WeakHydrogenDonorProvider = Features.Provider([FeatureType.WeakHydrogenDonor], addUnitWeakHydrogenDonors); +export const HydrogenAcceptorProvider = Features.Provider([FeatureType.HydrogenAcceptor], addUnitHydrogenAcceptors); export const HydrogenBondsProvider: ContactProvider<HydrogenBondsParams> = { name: 'hydrogen-bonds', params: HydrogenBondsParams, createTester: (props: HydrogenBondsProps) => { - const maxDistance = Math.max(props.distanceMax, props.sulfurDistanceMax) - const opts = getHydrogenBondsOptions(props) + const maxDistance = Math.max(props.distanceMax, props.sulfurDistanceMax); + const opts = getHydrogenBondsOptions(props); return { maxDistance, requiredFeatures: new Set([FeatureType.HydrogenDonor, FeatureType.HydrogenAcceptor]), getType: (structure, infoA, infoB, distanceSq) => testHydrogenBond(structure, infoA, infoB, distanceSq, opts) - } + }; } -} +}; export const WeakHydrogenBondsProvider: ContactProvider<WeakHydrogenBondsParams> = { name: 'weak-hydrogen-bonds', params: WeakHydrogenBondsParams, createTester: (props: WeakHydrogenBondsProps) => { - const opts = getGeometryOptions(props) + const opts = getGeometryOptions(props); return { maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.WeakHydrogenDonor, FeatureType.HydrogenAcceptor]), getType: (structure, infoA, infoB, distanceSq) => testWeakHydrogenBond(structure, infoA, infoB, distanceSq, opts) - } + }; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/hydrophobic.ts b/src/mol-model-props/computed/interactions/hydrophobic.ts index 47f8a90ea7df1a8b144c143f39caed27089f7df0..6c9f77a3bac077b2ace7cd608c3ccf9849ab92a4 100644 --- a/src/mol-model-props/computed/interactions/hydrophobic.ts +++ b/src/mol-model-props/computed/interactions/hydrophobic.ts @@ -17,7 +17,7 @@ import { ContactProvider } from './contacts'; const HydrophobicParams = { distanceMax: PD.Numeric(4.0, { min: 1, max: 5, step: 0.1 }), -} +}; type HydrophobicParams = typeof HydrophobicParams type HydrophobicProps = PD.Values<HydrophobicParams> @@ -27,48 +27,48 @@ type HydrophobicProps = PD.Values<HydrophobicParams> * - Fluorine */ function addHydrophobicAtom(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { - const element = typeSymbol(unit, i) - let flag = false + const element = typeSymbol(unit, i); + let flag = false; if (element === Elements.C) { - flag = true + flag = true; eachBondedAtom(structure, unit, i, (unitB, indexB) => { - const elementB = typeSymbol(unitB, indexB) - if (elementB !== Elements.C && elementB !== Elements.H) flag = false - }) + const elementB = typeSymbol(unitB, indexB); + if (elementB !== Elements.C && elementB !== Elements.H) flag = false; + }); } else if (element === Elements.F) { - flag = true + flag = true; } if (flag) { - builder.add(FeatureType.HydrophobicAtom, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.HydrophobicAtom, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } function isHydrophobicContact(ti: FeatureType, tj: FeatureType) { - return ti === FeatureType.HydrophobicAtom && tj === FeatureType.HydrophobicAtom + return ti === FeatureType.HydrophobicAtom && tj === FeatureType.HydrophobicAtom; } function testHydrophobic(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; - if (!isHydrophobicContact(typeA, typeB)) return + if (!isHydrophobicContact(typeA, typeB)) return; - const indexA = infoA.members[infoA.offsets[infoA.feature]] - const indexB = infoB.members[infoB.offsets[infoB.feature]] - if (typeSymbol(infoA.unit, indexA) === Elements.F && typeSymbol(infoB.unit, indexB) === Elements.F) return + const indexA = infoA.members[infoA.offsets[infoA.feature]]; + const indexB = infoB.members[infoB.offsets[infoB.feature]]; + if (typeSymbol(infoA.unit, indexA) === Elements.F && typeSymbol(infoB.unit, indexB) === Elements.F) return; - return InteractionType.Hydrophobic + return InteractionType.Hydrophobic; } // -export const HydrophobicAtomProvider = Features.Provider([FeatureType.HydrophobicAtom], addHydrophobicAtom) +export const HydrophobicAtomProvider = Features.Provider([FeatureType.HydrophobicAtom], addHydrophobicAtom); export const HydrophobicProvider: ContactProvider<HydrophobicParams> = { name: 'hydrophobic', @@ -78,6 +78,6 @@ export const HydrophobicProvider: ContactProvider<HydrophobicParams> = { maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.HydrophobicAtom]), getType: (structure, infoA, infoB, distanceSq) => testHydrophobic(structure, infoA, infoB, distanceSq) - } + }; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/interactions.ts b/src/mol-model-props/computed/interactions/interactions.ts index 3d9295e20132a9184ae714d53969313eac4034b0..8d69bbcc20cb99e6a909488151fdc0bd3e240d07 100644 --- a/src/mol-model-props/computed/interactions/interactions.ts +++ b/src/mol-model-props/computed/interactions/interactions.ts @@ -27,7 +27,7 @@ import { DataLoci } from '../../../mol-model/loci'; import { bondLabel, LabelGranularity } from '../../../mol-theme/label'; import { ObjectKeys } from '../../../mol-util/type-helpers'; -export { Interactions } +export { Interactions }; interface Interactions { /** Features of each unit */ @@ -69,24 +69,24 @@ namespace Interactions { locA.element.indexB === locB.element.indexB && locA.element.unitA === locB.element.unitA && locA.element.unitB === locB.element.unitB - ) + ); } function _label(interactions: Interactions, element: Element): string { - const { unitA, indexA, unitB, indexB } = element - const { contacts, unitsContacts } = interactions + const { unitA, indexA, unitB, indexB } = element; + const { contacts, unitsContacts } = interactions; if (unitA === unitB) { - const contacts = unitsContacts.get(unitA.id) - const idx = contacts.getDirectedEdgeIndex(indexA, indexB) - return interactionTypeLabel(contacts.edgeProps.type[idx]) + const contacts = unitsContacts.get(unitA.id); + const idx = contacts.getDirectedEdgeIndex(indexA, indexB); + return interactionTypeLabel(contacts.edgeProps.type[idx]); } else { - const idx = contacts.getEdgeIndex(indexA, unitA, indexB, unitB) - return interactionTypeLabel(contacts.edges[idx].props.type) + const idx = contacts.getEdgeIndex(indexA, unitA, indexB, unitB); + return interactionTypeLabel(contacts.edges[idx].props.type); } } export function locationLabel(location: Location): string { - return _label(location.data.interactions, location.element) + return _label(location.data.interactions, location.element); } export interface Loci extends DataLoci<StructureInteractions, Element> { } @@ -102,29 +102,29 @@ namespace Interactions { } export function getBoundingSphere(interactions: Interactions, elements: ReadonlyArray<Element>, boundingSphere: Sphere3D) { - const { unitsFeatures } = interactions + const { unitsFeatures } = interactions; return CentroidHelper.fromPairProvider(elements.length, (i, pA, pB) => { - const e = elements[i] - Features.setPosition(pA, e.unitA, e.indexA, unitsFeatures.get(e.unitA.id)) - Features.setPosition(pB, e.unitB, e.indexB, unitsFeatures.get(e.unitB.id)) - }, boundingSphere) + const e = elements[i]; + Features.setPosition(pA, e.unitA, e.indexA, unitsFeatures.get(e.unitA.id)); + Features.setPosition(pB, e.unitB, e.indexB, unitsFeatures.get(e.unitB.id)); + }, boundingSphere); } export function getLabel(structure: Structure, interactions: Interactions, elements: ReadonlyArray<Element>) { - const element = elements[0] - if (element === undefined) return '' - const { unitA, indexA, unitB, indexB } = element - const { unitsFeatures } = interactions - const { members: mA, offsets: oA } = unitsFeatures.get(unitA.id) - const { members: mB, offsets: oB } = unitsFeatures.get(unitB.id) - const options = { granularity: 'element' as LabelGranularity } + const element = elements[0]; + if (element === undefined) return ''; + const { unitA, indexA, unitB, indexB } = element; + const { unitsFeatures } = interactions; + const { members: mA, offsets: oA } = unitsFeatures.get(unitA.id); + const { members: mB, offsets: oB } = unitsFeatures.get(unitB.id); + const options = { granularity: 'element' as LabelGranularity }; if (oA[indexA + 1] - oA[indexA] > 1 || oB[indexB + 1] - oB[indexB] > 1) { - options.granularity = 'residue' + options.granularity = 'residue'; } return [ _label(interactions, element), bondLabel(Bond.Location(structure, unitA, mA[oA[indexA]], structure, unitB, mB[oB[indexB]]), options) - ].join('</br>') + ].join('</br>'); } } @@ -134,7 +134,7 @@ const FeatureProviders = [ HalogenDonorProvider, HalogenAcceptorProvider, HydrophobicAtomProvider, MetalProvider, MetalBindingProvider, -] +]; const ContactProviders = { 'ionic': IonicProvider, @@ -145,22 +145,22 @@ const ContactProviders = { 'weak-hydrogen-bonds': WeakHydrogenBondsProvider, 'hydrophobic': HydrophobicProvider, 'metal-coordination': MetalCoordinationProvider, -} +}; type ContactProviders = typeof ContactProviders function getProvidersParams(defaultOn: string[] = []) { const params: { [k in keyof ContactProviders]: PD.Mapped<PD.NamedParamUnion<{ on: PD.Group<ContactProviders[k]['params']> off: PD.Group<{}> - }>> } = Object.create(null) + }>> } = Object.create(null); Object.keys(ContactProviders).forEach(k => { (params as any)[k] = PD.MappedStatic(defaultOn.includes(k) ? 'on' : 'off', { on: PD.Group(ContactProviders[k as keyof ContactProviders].params), off: PD.Group({}) - }, { cycle: true }) - }) - return params + }, { cycle: true }); + }); + return params; } export const ContactProviderParams = getProvidersParams([ // 'ionic', @@ -171,86 +171,86 @@ export const ContactProviderParams = getProvidersParams([ // 'hydrophobic', 'metal-coordination', // 'weak-hydrogen-bonds', -]) +]); export const InteractionsParams = { providers: PD.Group(ContactProviderParams, { isFlat: true }), contacts: PD.Group(ContactsParams, { label: 'Advanced Options' }), -} +}; export type InteractionsParams = typeof InteractionsParams export type InteractionsProps = PD.Values<InteractionsParams> export async function computeInteractions(ctx: CustomProperty.Context, structure: Structure, props: Partial<InteractionsProps>): Promise<Interactions> { - const p = { ...PD.getDefaultValues(InteractionsParams), ...props } - await ValenceModelProvider.attach(ctx, structure) + const p = { ...PD.getDefaultValues(InteractionsParams), ...props }; + await ValenceModelProvider.attach(ctx, structure); const contactTesters: ContactTester[] = []; ObjectKeys(ContactProviders).forEach(k => { - const { name, params } = p.providers[k] + const { name, params } = p.providers[k]; if (name === 'on') { - contactTesters.push(ContactProviders[k].createTester(params as any)) + contactTesters.push(ContactProviders[k].createTester(params as any)); } - }) + }); - const requiredFeatures = new Set<FeatureType>() - contactTesters.forEach(l => SetUtils.add(requiredFeatures, l.requiredFeatures)) - const featureProviders = FeatureProviders.filter(f => SetUtils.areIntersecting(requiredFeatures, f.types)) + const requiredFeatures = new Set<FeatureType>(); + contactTesters.forEach(l => SetUtils.add(requiredFeatures, l.requiredFeatures)); + const featureProviders = FeatureProviders.filter(f => SetUtils.areIntersecting(requiredFeatures, f.types)); - const unitsFeatures = IntMap.Mutable<Features>() - const unitsContacts = IntMap.Mutable<InteractionsIntraContacts>() + const unitsFeatures = IntMap.Mutable<Features>(); + const unitsContacts = IntMap.Mutable<InteractionsIntraContacts>(); for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const group = structure.unitSymmetryGroups[i] + const group = structure.unitSymmetryGroups[i]; if (ctx.runtime.shouldUpdate) { - await ctx.runtime.update({ message: 'computing interactions', current: i, max: il }) + await ctx.runtime.update({ message: 'computing interactions', current: i, max: il }); } - const features = findUnitFeatures(structure, group.units[0], featureProviders) - const intraUnitContacts = findIntraUnitContacts(structure, group.units[0], features, contactTesters, p.contacts) + const features = findUnitFeatures(structure, group.units[0], featureProviders); + const intraUnitContacts = findIntraUnitContacts(structure, group.units[0], features, contactTesters, p.contacts); for (let j = 0, jl = group.units.length; j < jl; ++j) { - const u = group.units[j] - unitsFeatures.set(u.id, features) - unitsContacts.set(u.id, intraUnitContacts) + const u = group.units[j]; + unitsFeatures.set(u.id, features); + unitsContacts.set(u.id, intraUnitContacts); } } - const contacts = findInterUnitContacts(structure, unitsFeatures, contactTesters, p.contacts) + const contacts = findInterUnitContacts(structure, unitsFeatures, contactTesters, p.contacts); - const interactions = { unitsFeatures, unitsContacts, contacts } - refineInteractions(structure, interactions) - return interactions + const interactions = { unitsFeatures, unitsContacts, contacts }; + refineInteractions(structure, interactions); + return interactions; } function findUnitFeatures(structure: Structure, unit: Unit, featureProviders: Features.Provider[]) { - const count = unit.elements.length - const featuresBuilder = FeaturesBuilder.create(count, count / 2) + const count = unit.elements.length; + const featuresBuilder = FeaturesBuilder.create(count, count / 2); if (Unit.isAtomic(unit)) { for (const fp of featureProviders) { - fp.add(structure, unit, featuresBuilder) + fp.add(structure, unit, featuresBuilder); } } - return featuresBuilder.getFeatures(count) + return featuresBuilder.getFeatures(count); } function findIntraUnitContacts(structure: Structure, unit: Unit, features: Features, contactTesters: ReadonlyArray<ContactTester>, props: ContactsProps) { - const builder = IntraContactsBuilder.create(features, unit.elements.length) + const builder = IntraContactsBuilder.create(features, unit.elements.length); if (Unit.isAtomic(unit)) { - addUnitContacts(structure, unit, features, builder, contactTesters, props) + addUnitContacts(structure, unit, features, builder, contactTesters, props); } - return builder.getContacts() + return builder.getContacts(); } function findInterUnitContacts(structure: Structure, unitsFeatures: IntMap<Features>, contactTesters: ReadonlyArray<ContactTester>, props: ContactsProps) { - const builder = InterContactsBuilder.create() + const builder = InterContactsBuilder.create(); Structure.eachUnitPair(structure, (unitA: Unit, unitB: Unit) => { - const featuresA = unitsFeatures.get(unitA.id) - const featuresB = unitsFeatures.get(unitB.id) - addStructureContacts(structure, unitA as Unit.Atomic, featuresA, unitB as Unit.Atomic, featuresB, builder, contactTesters, props) + const featuresA = unitsFeatures.get(unitA.id); + const featuresB = unitsFeatures.get(unitB.id); + addStructureContacts(structure, unitA as Unit.Atomic, featuresA, unitB as Unit.Atomic, featuresB, builder, contactTesters, props); }, { maxRadius: Math.max(...contactTesters.map(t => t.maxDistance)), validUnit: (unit: Unit) => Unit.isAtomic(unit), validUnitPair: (unitA: Unit, unitB: Unit) => Structure.validUnitPair(structure, unitA, unitB) - }) + }); - return builder.getContacts(unitsFeatures) + return builder.getContacts(unitsFeatures); } \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/metal.ts b/src/mol-model-props/computed/interactions/metal.ts index 80d7881c716e7582d3cdb1474543748dd1f9af05..5dd135342f40404d51a3f79b4bdf7990be08650c 100644 --- a/src/mol-model-props/computed/interactions/metal.ts +++ b/src/mol-model-props/computed/interactions/metal.ts @@ -17,7 +17,7 @@ import { ElementSymbol, AminoAcidNames, BaseNames, ProteinBackboneAtoms, Nucleic export const MetalCoordinationParams = { distanceMax: PD.Numeric(3.0, { min: 1, max: 5, step: 0.1 }), -} +}; export type MetalCoordinationParams = typeof MetalCoordinationParams export type MetalCoordinationProps = PD.Values<MetalCoordinationParams> @@ -26,101 +26,101 @@ const IonicTypeMetals = [ Elements.MG, Elements.CA, Elements.SR, Elements.BA, Elements.AL, Elements.GA, Elements.IN, Elements.TL, Elements.SC, Elements.SN, Elements.PB, Elements.BI, Elements.SB, Elements.HG -] as ElementSymbol[] +] as ElementSymbol[]; function addMetal(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { - const element = typeSymbol(unit, i) + const element = typeSymbol(unit, i); - let type = FeatureType.None + let type = FeatureType.None; if (IonicTypeMetals.includes(element)) { - type = FeatureType.IonicTypeMetal + type = FeatureType.IonicTypeMetal; } else if (isTransitionMetal(element) || element === Elements.ZN || element === Elements.CD) { - type = FeatureType.TransitionMetal + type = FeatureType.TransitionMetal; } if (type) { - builder.add(type, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(type, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } function isProteinSidechain(atomname: string) { - return !ProteinBackboneAtoms.has(atomname) + return !ProteinBackboneAtoms.has(atomname); } function isProteinBackbone(atomname: string) { - return ProteinBackboneAtoms.has(atomname) + return ProteinBackboneAtoms.has(atomname); } function isNucleicBackbone(atomname: string) { - return NucleicBackboneAtoms.has(atomname) + return NucleicBackboneAtoms.has(atomname); } /** * Metal binding partners (dative bond or ionic-type interaction) */ function addMetalBinding(structure: Structure, unit: Unit.Atomic, builder: FeaturesBuilder) { - const { elements } = unit - const { x, y, z } = unit.model.atomicConformation + const { elements } = unit; + const { x, y, z } = unit.model.atomicConformation; for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) { - const element = typeSymbol(unit, i) - const resname = compId(unit, i) - const atomname = atomId(unit, i) - let dative = false - let ionic = false + const element = typeSymbol(unit, i); + const resname = compId(unit, i); + const atomname = atomId(unit, i); + let dative = false; + let ionic = false; - const isStandardAminoacid = AminoAcidNames.has(resname) - const isStandardBase = BaseNames.has(resname) + const isStandardAminoacid = AminoAcidNames.has(resname); + const isStandardBase = BaseNames.has(resname); if (!isStandardAminoacid && !isStandardBase) { if (isHalogen(element) || element === Elements.O || element === Elements.S) { - dative = true - ionic = true + dative = true; + ionic = true; } else if (element === Elements.N) { - dative = true + dative = true; } } else if (isStandardAminoacid) { // main chain oxygen atom or oxygen, nitrogen and sulfur from specific amino acids if (element === Elements.O) { if (['ASP', 'GLU', 'SER', 'THR', 'TYR', 'ASN', 'GLN'].includes(resname) && isProteinSidechain(atomname)) { - dative = true - ionic = true + dative = true; + ionic = true; } else if (isProteinBackbone(atomname)) { - dative = true - ionic = true + dative = true; + ionic = true; } } else if (element === Elements.S && (resname === 'CYS' || resname === 'MET')) { - dative = true - ionic = true + dative = true; + ionic = true; } else if (element === Elements.N) { if (resname === 'HIS' && isProteinSidechain(atomname)) { - dative = true + dative = true; } } } else if (isStandardBase) { // http://pubs.acs.org/doi/pdf/10.1021/acs.accounts.6b00253 // http://onlinelibrary.wiley.com/doi/10.1002/anie.200900399/full if (element === Elements.O && isNucleicBackbone(atomname)) { - dative = true - ionic = true + dative = true; + ionic = true; } else if (['N3', 'N4', 'N7'].includes(atomname)) { - dative = true + dative = true; } else if (['O2', 'O4', 'O6'].includes(atomname)) { - dative = true - ionic = true + dative = true; + ionic = true; } } if (dative) { - builder.add(FeatureType.DativeBondPartner, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.DativeBondPartner, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } if (ionic) { - builder.add(FeatureType.IonicTypePartner, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i) + builder.add(FeatureType.IonicTypePartner, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i); } } } @@ -130,27 +130,27 @@ function isMetalCoordination(ti: FeatureType, tj: FeatureType) { return ( tj === FeatureType.DativeBondPartner || tj === FeatureType.TransitionMetal - ) + ); } else if (ti === FeatureType.IonicTypeMetal) { return ( tj === FeatureType.IonicTypePartner - ) + ); } } function testMetalCoordination(structure: Structure, infoA: Features.Info, infoB: Features.Info, distanceSq: number): InteractionType | undefined { - const typeA = infoA.types[infoA.feature] - const typeB = infoB.types[infoB.feature] + const typeA = infoA.types[infoA.feature]; + const typeB = infoB.types[infoB.feature]; - if (!isMetalCoordination(typeA, typeB) && !isMetalCoordination(typeB, typeA)) return + if (!isMetalCoordination(typeA, typeB) && !isMetalCoordination(typeB, typeA)) return; - return InteractionType.MetalCoordination + return InteractionType.MetalCoordination; } // -export const MetalProvider = Features.Provider([FeatureType.IonicTypeMetal, FeatureType.TransitionMetal], addMetal) -export const MetalBindingProvider = Features.Provider([FeatureType.IonicTypePartner, FeatureType.DativeBondPartner], addMetalBinding) +export const MetalProvider = Features.Provider([FeatureType.IonicTypeMetal, FeatureType.TransitionMetal], addMetal); +export const MetalBindingProvider = Features.Provider([FeatureType.IonicTypePartner, FeatureType.DativeBondPartner], addMetalBinding); export const MetalCoordinationProvider: ContactProvider<MetalCoordinationParams> = { name: 'metal-coordination', @@ -160,6 +160,6 @@ export const MetalCoordinationProvider: ContactProvider<MetalCoordinationParams> maxDistance: props.distanceMax, requiredFeatures: new Set([FeatureType.IonicTypeMetal, FeatureType.TransitionMetal, FeatureType.IonicTypePartner, FeatureType.DativeBondPartner]), getType: (structure, infoA, infoB, distanceSq) => testMetalCoordination(structure, infoA, infoB, distanceSq) - } + }; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/interactions/refine.ts b/src/mol-model-props/computed/interactions/refine.ts index 2bda57a2279625f5a044a14b0c9b103b90f15378..8b65fe083e69298dbee7d2da7c66ff85ed094dff 100644 --- a/src/mol-model-props/computed/interactions/refine.ts +++ b/src/mol-model-props/computed/interactions/refine.ts @@ -19,7 +19,7 @@ interface ContactRefiner { } export function refineInteractions(structure: Structure, interactions: Interactions) { - const { contacts, unitsContacts, unitsFeatures } = interactions + const { contacts, unitsContacts, unitsFeatures } = interactions; const contactRefiners: ContactRefiner[] = [ hydrophobicRefiner(structure, interactions), @@ -27,46 +27,46 @@ export function refineInteractions(structure: Structure, interactions: Interacti saltBridgeRefiner(structure, interactions), piStackingRefiner(structure, interactions), metalCoordinationRefiner(structure, interactions), - ] + ]; for (let i = 0, il = contacts.edgeCount; i < il; ++i) { - const e = contacts.edges[i] + const e = contacts.edges[i]; - const infoA = Features.Info(structure, e.unitA as Unit.Atomic, unitsFeatures.get(e.unitA.id)) - infoA.feature = e.indexA - const infoB = Features.Info(structure, e.unitB as Unit.Atomic, unitsFeatures.get(e.unitB.id)) - infoB.feature = e.indexB + const infoA = Features.Info(structure, e.unitA as Unit.Atomic, unitsFeatures.get(e.unitA.id)); + infoA.feature = e.indexA; + const infoB = Features.Info(structure, e.unitB as Unit.Atomic, unitsFeatures.get(e.unitB.id)); + infoB.feature = e.indexB; for (const refiner of contactRefiners) { - if (refiner.isApplicable(e.props.type)) refiner.handleInterContact(i, infoA, infoB) + if (refiner.isApplicable(e.props.type)) refiner.handleInterContact(i, infoA, infoB); } } // - const ucKeys = unitsContacts.keys() + const ucKeys = unitsContacts.keys(); while (true) { const { done, value } = ucKeys.next(); if (done) break; - const contacts = unitsContacts.get(value) - const features = unitsFeatures.get(value) - const unit = structure.unitMap.get(value) - if (!Unit.isAtomic(unit)) continue + const contacts = unitsContacts.get(value); + const features = unitsFeatures.get(value); + const unit = structure.unitMap.get(value); + if (!Unit.isAtomic(unit)) continue; - const infoA = Features.Info(structure, unit, features) - const infoB = Features.Info(structure, unit, features) + const infoA = Features.Info(structure, unit, features); + const infoB = Features.Info(structure, unit, features); - for (const refiner of contactRefiners) refiner.startUnit(unit, contacts, features) + for (const refiner of contactRefiners) refiner.startUnit(unit, contacts, features); for (let i = 0, il = contacts.edgeCount * 2; i < il; ++i) { - infoA.feature = contacts.a[i] - infoB.feature = contacts.b[i] + infoA.feature = contacts.a[i]; + infoB.feature = contacts.b[i]; // console.log(i, contacts.a[i], contacts.b[i]) for (const refiner of contactRefiners) { - if (refiner.isApplicable(contacts.edgeProps.type[i])) refiner.handleIntraContact(i, infoA, infoB) + if (refiner.isApplicable(contacts.edgeProps.type[i])) refiner.handleIntraContact(i, infoA, infoB); } } } @@ -77,53 +77,53 @@ export function refineInteractions(structure: Structure, interactions: Interacti * only the one with the closest distance is kept. */ function hydrophobicRefiner(structure: Structure, interactions: Interactions): ContactRefiner { - const { contacts } = interactions + const { contacts } = interactions; /* keep only closest contact between residues */ const handleResidueContact = function (dist: number, edge: number, key: string, map: Map<string, [number, number]>, set: (i: number) => void) { - const [minDist, minIndex] = map.get(key) || [Infinity, -1] + const [minDist, minIndex] = map.get(key) || [Infinity, -1]; if (dist < minDist) { - if (minIndex !== -1) set(minIndex) - map.set(key, [dist, edge]) + if (minIndex !== -1) set(minIndex); + map.set(key, [dist, edge]); } else { - set(edge) + set(edge); } - } + }; function handleEdge(edge: number, infoA: Features.Info, infoB: Features.Info, map: Map<string, [number, number]>, set: (i: number) => void) { - const elementA = infoA.members[infoA.offsets[infoA.feature]] - const elementB = infoB.members[infoB.offsets[infoB.feature]] - const residueA = infoA.unit.getResidueIndex(elementA) - const residueB = infoB.unit.getResidueIndex(elementB) + const elementA = infoA.members[infoA.offsets[infoA.feature]]; + const elementB = infoB.members[infoB.offsets[infoB.feature]]; + const residueA = infoA.unit.getResidueIndex(elementA); + const residueB = infoB.unit.getResidueIndex(elementB); - const keyA = `${elementA}|${infoA.unit.id}|${residueB}|${infoB.unit.id}|A` - const keyB = `${elementB}|${infoB.unit.id}|${residueA}|${infoA.unit.id}|B` + const keyA = `${elementA}|${infoA.unit.id}|${residueB}|${infoB.unit.id}|A`; + const keyB = `${elementB}|${infoB.unit.id}|${residueA}|${infoA.unit.id}|B`; - const dist = Features.distance(infoA, infoB) + const dist = Features.distance(infoA, infoB); - handleResidueContact(dist, edge, keyA, map, set) - handleResidueContact(dist, edge, keyB, map, set) + handleResidueContact(dist, edge, keyA, map, set); + handleResidueContact(dist, edge, keyB, map, set); } - const residueInterMap = new Map<string, [number, number]>() - const setInterFiltered = (i: number) => contacts.edges[i].props.flag = InteractionFlag.Filtered + const residueInterMap = new Map<string, [number, number]>(); + const setInterFiltered = (i: number) => contacts.edges[i].props.flag = InteractionFlag.Filtered; - let residueIntraMap: Map<string, [number, number]> - let setIntraFiltered: (i: number) => void + let residueIntraMap: Map<string, [number, number]>; + let setIntraFiltered: (i: number) => void; return { isApplicable: (type: InteractionType) => type === InteractionType.Hydrophobic, handleInterContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - handleEdge(index, infoA, infoB, residueInterMap, setInterFiltered) + handleEdge(index, infoA, infoB, residueInterMap, setInterFiltered); }, startUnit: (unit: Unit.Atomic, contacts: InteractionsIntraContacts, features: Features) => { - residueIntraMap = new Map<string, [number, number]>() - setIntraFiltered = (i: number) => contacts.edgeProps.flag[i] = InteractionFlag.Filtered + residueIntraMap = new Map<string, [number, number]>(); + setIntraFiltered = (i: number) => contacts.edgeProps.flag[i] = InteractionFlag.Filtered; }, handleIntraContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - handleEdge(index, infoA, infoB, residueIntraMap, setIntraFiltered) + handleEdge(index, infoA, infoB, residueIntraMap, setIntraFiltered); } - } + }; } /** @@ -131,62 +131,62 @@ function hydrophobicRefiner(structure: Structure, interactions: Interactions): C * a normal/strong hydrogen bond */ function weakHydrogenBondsRefiner(structure: Structure, interactions: Interactions): ContactRefiner { - const { contacts } = interactions + const { contacts } = interactions; const hasHydrogenBond = (infoA: Features.Info, infoB: Features.Info) => { - const acc = infoA.types[infoA.feature] === FeatureType.WeakHydrogenDonor ? infoB : infoA + const acc = infoA.types[infoA.feature] === FeatureType.WeakHydrogenDonor ? infoB : infoA; // check intra - const eI = acc.members[acc.offsets[acc.feature]] - const { edgeProps: { type }, elementsIndex: { offsets, indices } } = interactions.unitsContacts.get(acc.unit.id) + const eI = acc.members[acc.offsets[acc.feature]]; + const { edgeProps: { type }, elementsIndex: { offsets, indices } } = interactions.unitsContacts.get(acc.unit.id); for (let i = offsets[eI], il = offsets[eI + 1]; i < il; ++i) { - if (type[indices[i]] === InteractionType.HydrogenBond) return true + if (type[indices[i]] === InteractionType.HydrogenBond) return true; } // check inter - const interIndices = contacts.getEdgeIndices(acc.feature, acc.unit) + const interIndices = contacts.getEdgeIndices(acc.feature, acc.unit); for (let i = 0, il = interIndices.length; i < il; ++i) { - if (contacts.edges[interIndices[i]].props.type === InteractionType.HydrogenBond) return true + if (contacts.edges[interIndices[i]].props.type === InteractionType.HydrogenBond) return true; } - return false - } + return false; + }; return { isApplicable: (type: InteractionType) => type === InteractionType.WeakHydrogenBond, handleInterContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { if (hasHydrogenBond(infoA, infoB)) { - contacts.edges[index].props.flag = InteractionFlag.Filtered + contacts.edges[index].props.flag = InteractionFlag.Filtered; } }, startUnit: () => {}, handleIntraContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { if (hasHydrogenBond(infoA, infoB)) { - const { flag } = interactions.unitsContacts.get(infoA.unit.id).edgeProps - flag[index] = InteractionFlag.Filtered + const { flag } = interactions.unitsContacts.get(infoA.unit.id).edgeProps; + flag[index] = InteractionFlag.Filtered; } } - } + }; } /** * Filter inter-unit contact `index` if there is a contact of `types` between its members */ function filterInter(types: InteractionType[], index: number, infoA: Features.Info, infoB: Features.Info, contacts: InteractionsInterContacts) { - const { offsets: offsetsA, feature: featureA } = infoA - const { offsets: offsetsB, feature: featureB } = infoB + const { offsets: offsetsA, feature: featureA } = infoA; + const { offsets: offsetsB, feature: featureB } = infoB; for (let i = offsetsA[featureA], il = offsetsA[featureA + 1]; i < il; ++i) { - const aI = infoA.members[i] - const indices = contacts.getContactIndicesForElement(aI, infoA.unit) + const aI = infoA.members[i]; + const indices = contacts.getContactIndicesForElement(aI, infoA.unit); for (let k = 0, kl = indices.length; k < kl; ++k) { - const cI = indices[k] + const cI = indices[k]; if (types.includes(contacts.edges[cI].props.type)) { for (let j = offsetsB[featureB], jl = offsetsB[featureB + 1]; j < jl; ++j) { - const bI = infoB.members[j] + const bI = infoB.members[j]; if (contacts.getContactIndicesForElement(bI, infoB.unit).includes(cI)) { - contacts.edges[index].props.flag = InteractionFlag.Filtered - return + contacts.edges[index].props.flag = InteractionFlag.Filtered; + return; } } } @@ -198,21 +198,21 @@ function filterInter(types: InteractionType[], index: number, infoA: Features.In * Filter intra-unit contact `index` if there is a contact of `types` between its members */ function filterIntra(types: InteractionType[], index: number, infoA: Features.Info, infoB: Features.Info, contacts: InteractionsIntraContacts) { - const { edgeProps: { type, flag }, elementsIndex: { offsets, indices } } = contacts - const { offsets: offsetsA, feature: featureA } = infoA - const { offsets: offsetsB, feature: featureB } = infoB + const { edgeProps: { type, flag }, elementsIndex: { offsets, indices } } = contacts; + const { offsets: offsetsA, feature: featureA } = infoA; + const { offsets: offsetsB, feature: featureB } = infoB; for (let i = offsetsA[featureA], il = offsetsA[featureA + 1]; i < il; ++i) { - const aI = infoA.members[i] + const aI = infoA.members[i]; for (let k = offsets[aI], kl = offsets[aI + 1]; k < kl; ++k) { - const cI = indices[k] + const cI = indices[k]; if (types.includes(type[cI])) { for (let j = offsetsB[featureB], jl = offsetsB[featureB + 1]; j < jl; ++j) { - const bI = infoB.members[j] + const bI = infoB.members[j]; for (let l = offsets[bI], ll = offsets[bI + 1]; l < ll; ++l) { if (cI === indices[l]) { - flag[index] = InteractionFlag.Filtered - return + flag[index] = InteractionFlag.Filtered; + return; } } } @@ -226,18 +226,18 @@ function filterIntra(types: InteractionType[], index: number, infoA: Features.In * an ionic interaction between each other */ function saltBridgeRefiner(structure: Structure, interactions: Interactions): ContactRefiner { - const { contacts } = interactions + const { contacts } = interactions; return { isApplicable: (type: InteractionType) => type === InteractionType.Ionic, handleInterContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - filterInter([InteractionType.HydrogenBond, InteractionType.WeakHydrogenBond], index, infoA, infoB, contacts) + filterInter([InteractionType.HydrogenBond, InteractionType.WeakHydrogenBond], index, infoA, infoB, contacts); }, startUnit: () => {}, handleIntraContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - filterIntra([InteractionType.HydrogenBond, InteractionType.WeakHydrogenBond], index, infoA, infoB, interactions.unitsContacts.get(infoA.unit.id)) + filterIntra([InteractionType.HydrogenBond, InteractionType.WeakHydrogenBond], index, infoA, infoB, interactions.unitsContacts.get(infoA.unit.id)); } - } + }; } /** @@ -245,18 +245,18 @@ function saltBridgeRefiner(structure: Structure, interactions: Interactions): Co * a pi-stacking interaction between each other */ function piStackingRefiner(structure: Structure, interactions: Interactions): ContactRefiner { - const { contacts } = interactions + const { contacts } = interactions; return { isApplicable: (type: InteractionType) => type === InteractionType.Hydrophobic || type === InteractionType.CationPi, handleInterContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - filterInter([InteractionType.PiStacking], index, infoA, infoB, contacts) + filterInter([InteractionType.PiStacking], index, infoA, infoB, contacts); }, startUnit: () => {}, handleIntraContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - filterIntra([InteractionType.PiStacking], index, infoA, infoB, interactions.unitsContacts.get(infoA.unit.id)) + filterIntra([InteractionType.PiStacking], index, infoA, infoB, interactions.unitsContacts.get(infoA.unit.id)); } - } + }; } /** @@ -264,16 +264,16 @@ function piStackingRefiner(structure: Structure, interactions: Interactions): Co * a metal coordination between each other */ function metalCoordinationRefiner(structure: Structure, interactions: Interactions): ContactRefiner { - const { contacts } = interactions + const { contacts } = interactions; return { isApplicable: (type: InteractionType) => type === InteractionType.Ionic, handleInterContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - filterInter([InteractionType.MetalCoordination], index, infoA, infoB, contacts) + filterInter([InteractionType.MetalCoordination], index, infoA, infoB, contacts); }, startUnit: () => {}, handleIntraContact: (index: number, infoA: Features.Info, infoB: Features.Info) => { - filterIntra([InteractionType.MetalCoordination], index, infoA, infoB, interactions.unitsContacts.get(infoA.unit.id)) + filterIntra([InteractionType.MetalCoordination], index, infoA, infoB, interactions.unitsContacts.get(infoA.unit.id)); } - } + }; } \ No newline at end of file diff --git a/src/mol-model-props/computed/representations/interactions-inter-unit-cylinder.ts b/src/mol-model-props/computed/representations/interactions-inter-unit-cylinder.ts index 1895d5e5536bcc212138f0ec3fda1c01c2ae6d68..ac32e740d142d3fd77ce5432558b06287919d84a 100644 --- a/src/mol-model-props/computed/representations/interactions-inter-unit-cylinder.ts +++ b/src/mol-model-props/computed/representations/interactions-inter-unit-cylinder.ts @@ -21,55 +21,55 @@ import { InteractionsProvider } from '../interactions'; import { LocationIterator } from '../../../mol-geo/util/location-iterator'; import { InteractionFlag } from '../interactions/common'; -const tmpLoc = StructureElement.Location.create(void 0) +const tmpLoc = StructureElement.Location.create(void 0); function createInterUnitInteractionCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<InteractionsInterUnitParams>, mesh?: Mesh) { - if (!structure.hasAtomic) return Mesh.createEmpty(mesh) + if (!structure.hasAtomic) return Mesh.createEmpty(mesh); - const interactions = InteractionsProvider.get(structure).value! - const { contacts, unitsFeatures } = interactions + const interactions = InteractionsProvider.get(structure).value!; + const { contacts, unitsFeatures } = interactions; - const { edgeCount, edges } = contacts - const { sizeFactor } = props + const { edgeCount, edges } = contacts; + const { sizeFactor } = props; - if (!edgeCount) return Mesh.createEmpty(mesh) + if (!edgeCount) return Mesh.createEmpty(mesh); const builderProps = { linkCount: edgeCount, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - const { unitA, indexA, unitB, indexB } = edges[edgeIndex] - const fA = unitsFeatures.get(unitA.id) - const fB = unitsFeatures.get(unitB.id) - Vec3.set(posA, fA.x[indexA], fA.y[indexA], fA.z[indexA]) - Vec3.transformMat4(posA, posA, unitA.conformation.operator.matrix) - Vec3.set(posB, fB.x[indexB], fB.y[indexB], fB.z[indexB]) - Vec3.transformMat4(posB, posB, unitB.conformation.operator.matrix) + const { unitA, indexA, unitB, indexB } = edges[edgeIndex]; + const fA = unitsFeatures.get(unitA.id); + const fB = unitsFeatures.get(unitB.id); + Vec3.set(posA, fA.x[indexA], fA.y[indexA], fA.z[indexA]); + Vec3.transformMat4(posA, posA, unitA.conformation.operator.matrix); + Vec3.set(posB, fB.x[indexB], fB.y[indexB], fB.z[indexB]); + Vec3.transformMat4(posB, posB, unitB.conformation.operator.matrix); }, style: (edgeIndex: number) => LinkCylinderStyle.Dashed, radius: (edgeIndex: number) => { - const b = edges[edgeIndex] - const fA = unitsFeatures.get(b.unitA.id) + const b = edges[edgeIndex]; + const fA = unitsFeatures.get(b.unitA.id); tmpLoc.structure = structure; - tmpLoc.unit = b.unitA - tmpLoc.element = b.unitA.elements[fA.members[fA.offsets[b.indexA]]] - const sizeA = theme.size.size(tmpLoc) - const fB = unitsFeatures.get(b.unitB.id) - tmpLoc.unit = b.unitB - tmpLoc.element = b.unitB.elements[fB.members[fB.offsets[b.indexB]]] - const sizeB = theme.size.size(tmpLoc) - return Math.min(sizeA, sizeB) * sizeFactor + tmpLoc.unit = b.unitA; + tmpLoc.element = b.unitA.elements[fA.members[fA.offsets[b.indexA]]]; + const sizeA = theme.size.size(tmpLoc); + const fB = unitsFeatures.get(b.unitB.id); + tmpLoc.unit = b.unitB; + tmpLoc.element = b.unitB.elements[fB.members[fB.offsets[b.indexB]]]; + const sizeB = theme.size.size(tmpLoc); + return Math.min(sizeA, sizeB) * sizeFactor; }, ignore: (edgeIndex: number) => edges[edgeIndex].props.flag === InteractionFlag.Filtered - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const InteractionsInterUnitParams = { ...ComplexMeshParams, ...LinkCylinderParams, sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }), -} +}; export type InteractionsInterUnitParams = typeof InteractionsInterUnitParams export function InteractionsInterUnitVisual(materialId: number): ComplexVisual<InteractionsInterUnitParams> { @@ -83,63 +83,63 @@ export function InteractionsInterUnitVisual(materialId: number): ComplexVisual<I state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments - ) + ); - const interactionsHash = InteractionsProvider.get(newStructure).version + const interactionsHash = InteractionsProvider.get(newStructure).version; if ((state.info.interactionsHash as number) !== interactionsHash) { - state.createGeometry = true - state.updateTransform = true - state.info.interactionsHash = interactionsHash + state.createGeometry = true; + state.updateTransform = true; + state.info.interactionsHash = interactionsHash; } } - }, materialId) + }, materialId); } function getInteractionLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const interactions = InteractionsProvider.get(structure).value! - const c = interactions.contacts.edges[groupId] + const interactions = InteractionsProvider.get(structure).value!; + const c = interactions.contacts.edges[groupId]; return Interactions.Loci(structure, interactions, [ { unitA: c.unitA, indexA: c.indexA, unitB: c.unitB, indexB: c.indexB }, { unitA: c.unitB, indexA: c.indexB, unitB: c.unitA, indexB: c.indexA }, - ]) + ]); } - return EmptyLoci + return EmptyLoci; } function eachInteraction(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; if (Interactions.isLoci(loci)) { - if (!Structure.areEquivalent(loci.data.structure, structure)) return false - const interactions = InteractionsProvider.get(structure).value! - if (loci.data.interactions !== interactions) return false - const { contacts } = interactions + if (!Structure.areEquivalent(loci.data.structure, structure)) return false; + const interactions = InteractionsProvider.get(structure).value!; + if (loci.data.interactions !== interactions) return false; + const { contacts } = interactions; for (const c of loci.elements) { - const idx = contacts.getEdgeIndex(c.indexA, c.unitA, c.indexB, c.unitB) + const idx = contacts.getEdgeIndex(c.indexA, c.unitA, c.indexB, c.unitB); if (idx !== -1) { - if (apply(Interval.ofSingleton(idx))) changed = true + if (apply(Interval.ofSingleton(idx))) changed = true; } } } - return changed + return changed; } function createInteractionsIterator(structure: Structure): LocationIterator { - const interactions = InteractionsProvider.get(structure).value! - const { contacts } = interactions - const groupCount = contacts.edgeCount - const instanceCount = 1 - const location = Interactions.Location(interactions, structure) - const { element } = location + const interactions = InteractionsProvider.get(structure).value!; + const { contacts } = interactions; + const groupCount = contacts.edgeCount; + const instanceCount = 1; + const location = Interactions.Location(interactions, structure); + const { element } = location; const getLocation = (groupIndex: number) => { - const c = contacts.edges[groupIndex] - element.unitA = c.unitA - element.indexA = c.indexA - element.unitB = c.unitB - element.indexB = c.indexB - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + const c = contacts.edges[groupIndex]; + element.unitA = c.unitA; + element.indexA = c.indexA; + element.unitB = c.unitB; + element.indexB = c.indexB; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } \ No newline at end of file diff --git a/src/mol-model-props/computed/representations/interactions-intra-unit-cylinder.ts b/src/mol-model-props/computed/representations/interactions-intra-unit-cylinder.ts index 3e0b864a7bfb1718587e070f2b68718fbda39d95..cc6677b50a68f0bcd857fed0d6a64528a202805f 100644 --- a/src/mol-model-props/computed/representations/interactions-intra-unit-cylinder.ts +++ b/src/mol-model-props/computed/representations/interactions-intra-unit-cylinder.ts @@ -22,48 +22,48 @@ import { Interactions } from '../interactions/interactions'; import { InteractionFlag } from '../interactions/common'; async function createIntraUnitInteractionsCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<InteractionsIntraUnitParams>, mesh?: Mesh) { - if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) + if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh); - const location = StructureElement.Location.create(structure, unit) + const location = StructureElement.Location.create(structure, unit); - const interactions = InteractionsProvider.get(structure).value! - const features = interactions.unitsFeatures.get(unit.id) - const contacts = interactions.unitsContacts.get(unit.id) + const interactions = InteractionsProvider.get(structure).value!; + const features = interactions.unitsFeatures.get(unit.id); + const contacts = interactions.unitsContacts.get(unit.id); - const { x, y, z, members, offsets } = features - const { edgeCount, a, b, edgeProps: { flag } } = contacts - const { sizeFactor } = props - const { matrix } = unit.conformation.operator + const { x, y, z, members, offsets } = features; + const { edgeCount, a, b, edgeProps: { flag } } = contacts; + const { sizeFactor } = props; + const { matrix } = unit.conformation.operator; - if (!edgeCount) return Mesh.createEmpty(mesh) + if (!edgeCount) return Mesh.createEmpty(mesh); const builderProps = { linkCount: edgeCount * 2, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - Vec3.set(posA, x[a[edgeIndex]], y[a[edgeIndex]], z[a[edgeIndex]]) - Vec3.transformMat4(posA, posA, matrix) - Vec3.set(posB, x[b[edgeIndex]], y[b[edgeIndex]], z[b[edgeIndex]]) - Vec3.transformMat4(posB, posB, matrix) + Vec3.set(posA, x[a[edgeIndex]], y[a[edgeIndex]], z[a[edgeIndex]]); + Vec3.transformMat4(posA, posA, matrix); + Vec3.set(posB, x[b[edgeIndex]], y[b[edgeIndex]], z[b[edgeIndex]]); + Vec3.transformMat4(posB, posB, matrix); }, style: (edgeIndex: number) => LinkCylinderStyle.Dashed, radius: (edgeIndex: number) => { - location.element = unit.elements[members[offsets[a[edgeIndex]]]] - const sizeA = theme.size.size(location) - location.element = unit.elements[members[offsets[b[edgeIndex]]]] - const sizeB = theme.size.size(location) - return Math.min(sizeA, sizeB) * sizeFactor + location.element = unit.elements[members[offsets[a[edgeIndex]]]]; + const sizeA = theme.size.size(location); + location.element = unit.elements[members[offsets[b[edgeIndex]]]]; + const sizeB = theme.size.size(location); + return Math.min(sizeA, sizeB) * sizeFactor; }, ignore: (edgeIndex: number) => flag[edgeIndex] === InteractionFlag.Filtered - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const InteractionsIntraUnitParams = { ...UnitsMeshParams, ...LinkCylinderParams, sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }), -} +}; export type InteractionsIntraUnitParams = typeof InteractionsIntraUnitParams export function InteractionsIntraUnitVisual(materialId: number): UnitsVisual<InteractionsIntraUnitParams> { @@ -77,72 +77,72 @@ export function InteractionsIntraUnitVisual(materialId: number): UnitsVisual<Int state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments - ) + ); - const interactionsHash = InteractionsProvider.get(newStructureGroup.structure).version + const interactionsHash = InteractionsProvider.get(newStructureGroup.structure).version; if ((state.info.interactionsHash as number) !== interactionsHash) { - state.createGeometry = true - state.updateTransform = true - state.info.interactionsHash = interactionsHash + state.createGeometry = true; + state.updateTransform = true; + state.info.interactionsHash = interactionsHash; } } - }, materialId) + }, materialId); } function getInteractionLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = structure.unitMap.get(group.units[instanceId].id) - const interactions = InteractionsProvider.get(structure).value! - const { a, b } = interactions.unitsContacts.get(unit.id) + const { structure, group } = structureGroup; + const unit = structure.unitMap.get(group.units[instanceId].id); + const interactions = InteractionsProvider.get(structure).value!; + const { a, b } = interactions.unitsContacts.get(unit.id); return Interactions.Loci(structure, interactions, [ { unitA: unit, indexA: a[groupId], unitB: unit, indexB: b[groupId] }, { unitA: unit, indexA: b[groupId], unitB: unit, indexB: a[groupId] }, - ]) + ]); } - return EmptyLoci + return EmptyLoci; } function eachInteraction(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; if (Interactions.isLoci(loci)) { - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.data.structure, structure)) return false - const interactions = InteractionsProvider.get(structure).value! - if (loci.data.interactions !== interactions) return false - const unit = group.units[0] - const contacts = interactions.unitsContacts.get(unit.id) - const groupCount = contacts.edgeCount * 2 + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.data.structure, structure)) return false; + const interactions = InteractionsProvider.get(structure).value!; + if (loci.data.interactions !== interactions) return false; + const unit = group.units[0]; + const contacts = interactions.unitsContacts.get(unit.id); + const groupCount = contacts.edgeCount * 2; for (const e of loci.elements) { - const unitIdx = group.unitIndexMap.get(e.unitA.id) + const unitIdx = group.unitIndexMap.get(e.unitA.id); if (unitIdx !== undefined) { - const idx = contacts.getDirectedEdgeIndex(e.indexA, e.indexB) + const idx = contacts.getDirectedEdgeIndex(e.indexA, e.indexB); if (idx !== -1) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true + if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true; } } } } - return changed + return changed; } function createInteractionsIterator(structureGroup: StructureGroup): LocationIterator { - const { structure, group } = structureGroup - const unit = group.units[0] - const interactions = InteractionsProvider.get(structure).value! - const contacts = interactions.unitsContacts.get(unit.id) - const groupCount = contacts.edgeCount * 2 - const instanceCount = group.units.length - const location = Interactions.Location(interactions, structure) - const { element } = location + const { structure, group } = structureGroup; + const unit = group.units[0]; + const interactions = InteractionsProvider.get(structure).value!; + const contacts = interactions.unitsContacts.get(unit.id); + const groupCount = contacts.edgeCount * 2; + const instanceCount = group.units.length; + const location = Interactions.Location(interactions, structure); + const { element } = location; const getLocation = (groupIndex: number, instanceIndex: number) => { - const instanceUnit = group.units[instanceIndex] - element.unitA = instanceUnit - element.indexA = contacts.a[groupIndex] - element.unitB = instanceUnit - element.indexB = contacts.b[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const instanceUnit = group.units[instanceIndex]; + element.unitA = instanceUnit; + element.indexA = contacts.a[groupIndex]; + element.unitB = instanceUnit; + element.indexB = contacts.b[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } \ No newline at end of file diff --git a/src/mol-model-props/computed/representations/interactions.ts b/src/mol-model-props/computed/representations/interactions.ts index a77f08af3024f8f49519110e202569e09dda65ba..d8dcc7477ae6543865cc5fcf13eed184c3249fd4 100644 --- a/src/mol-model-props/computed/representations/interactions.ts +++ b/src/mol-model-props/computed/representations/interactions.ts @@ -18,7 +18,7 @@ import { getUnitKindsParam } from '../../../mol-repr/structure/params'; const InteractionsVisuals = { 'intra-unit': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InteractionsIntraUnitParams>) => UnitsRepresentation('Intra-unit interactions cylinder', ctx, getParams, InteractionsIntraUnitVisual), 'inter-unit': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InteractionsInterUnitParams>) => ComplexRepresentation('Inter-unit interactions cylinder', ctx, getParams, InteractionsInterUnitVisual), -} +}; export const InteractionsParams = { ...InteractionsIntraUnitParams, @@ -26,15 +26,15 @@ export const InteractionsParams = { unitKinds: getUnitKindsParam(['atomic']), sizeFactor: PD.Numeric(0.2, { min: 0.01, max: 1, step: 0.01 }), visuals: PD.MultiSelect(['intra-unit', 'inter-unit'], PD.objectToOptions(InteractionsVisuals)), -} +}; export type InteractionsParams = typeof InteractionsParams export function getInteractionParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(InteractionsParams) + return PD.clone(InteractionsParams); } export type InteractionRepresentation = StructureRepresentation<InteractionsParams> export function InteractionRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InteractionsParams>): InteractionRepresentation { - return Representation.createMulti('Interactions', ctx, getParams, StructureRepresentationStateBuilder, InteractionsVisuals as unknown as Representation.Def<Structure, InteractionsParams>) + return Representation.createMulti('Interactions', ctx, getParams, StructureRepresentationStateBuilder, InteractionsVisuals as unknown as Representation.Def<Structure, InteractionsParams>); } export const InteractionsRepresentationProvider = StructureRepresentationProvider({ @@ -51,4 +51,4 @@ export const InteractionsRepresentationProvider = StructureRepresentationProvide attach: (ctx: CustomProperty.Context, structure: Structure) => InteractionsProvider.attach(ctx, structure, void 0, true), detach: (data) => InteractionsProvider.ref(data, false) } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure.ts b/src/mol-model-props/computed/secondary-structure.ts index 5b6f9dc10d49de380a21404958ed778e7519163f..4ca57c396cd45b5a2ab30049c3e21242594aa402 100644 --- a/src/mol-model-props/computed/secondary-structure.ts +++ b/src/mol-model-props/computed/secondary-structure.ts @@ -16,16 +16,16 @@ import { CustomPropertyDescriptor } from '../../mol-model/structure/common/custo import { Model } from '../../mol-model/structure/model'; function getSecondaryStructureParams(data?: Structure) { - let defaultType = 'model' as 'model' | 'dssp' + let defaultType = 'model' as 'model' | 'dssp'; if (data) { - defaultType = 'dssp' + defaultType = 'dssp'; for (let i = 0, il = data.models.length; i < il; ++i) { - const m = data.models[i] + const m = data.models[i]; if (Model.isFromPdbArchive(m) || Model.hasSecondaryStructure(m)) { // if there is any secondary structure definition given or if there is // an archival model, don't calculate dssp by default - defaultType = 'model' - break + defaultType = 'model'; + break; } } } @@ -34,10 +34,10 @@ function getSecondaryStructureParams(data?: Structure) { 'model': PD.EmptyGroup({ label: 'Model' }), 'dssp': PD.Group(DSSPComputationParams, { label: 'DSSP', isFlat: true }) }, { options: [['model', 'Model'], ['dssp', 'DSSP']] }) - } + }; } -export const SecondaryStructureParams = getSecondaryStructureParams() +export const SecondaryStructureParams = getSecondaryStructureParams(); export type SecondaryStructureParams = typeof SecondaryStructureParams export type SecondaryStructureProps = PD.Values<SecondaryStructureParams> @@ -55,38 +55,38 @@ export const SecondaryStructureProvider: CustomStructureProperty.Provider<Second getParams: getSecondaryStructureParams, isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<SecondaryStructureProps>) => { - const p = { ...PD.getDefaultValues(SecondaryStructureParams), ...props } + const p = { ...PD.getDefaultValues(SecondaryStructureParams), ...props }; switch (p.type.name) { - case 'dssp': return await computeDssp(data, p.type.params) - case 'model': return await computeModel(data) + case 'dssp': return await computeDssp(data, p.type.params); + case 'model': return await computeModel(data); } } -}) +}); async function computeDssp(structure: Structure, props: DSSPComputationProps): Promise<SecondaryStructureValue> { // TODO take inter-unit hbonds into account for bridge, ladder, sheet assignment // TODO use Zhang-Skolnik for CA alpha only parts or for coarse parts with per-residue elements - const map = new Map<number, SecondaryStructure>() + const map = new Map<number, SecondaryStructure>(); for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const u = structure.unitSymmetryGroups[i].units[0] + const u = structure.unitSymmetryGroups[i].units[0]; if (Unit.isAtomic(u)) { - const secondaryStructure = await computeUnitDSSP(u, props) - map.set(u.invariantId, secondaryStructure) + const secondaryStructure = await computeUnitDSSP(u, props); + map.set(u.invariantId, secondaryStructure); } } - return map + return map; } async function computeModel(structure: Structure): Promise<SecondaryStructureValue> { - const map = new Map<number, SecondaryStructure>() + const map = new Map<number, SecondaryStructure>(); for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const u = structure.unitSymmetryGroups[i].units[0] + const u = structure.unitSymmetryGroups[i].units[0]; if (Unit.isAtomic(u)) { - const secondaryStructure = ModelSecondaryStructure.Provider.get(u.model) + const secondaryStructure = ModelSecondaryStructure.Provider.get(u.model); if (secondaryStructure) { - map.set(u.invariantId, secondaryStructure) + map.set(u.invariantId, secondaryStructure); } } } - return map + return map; } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp.ts b/src/mol-model-props/computed/secondary-structure/dssp.ts index 171c8b01ec344fd2b290cd407fa7386833f18089..459654b7c97956027cd921730350092680d859ce 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp.ts @@ -7,7 +7,7 @@ import { SecondaryStructure } from '../../../mol-model/structure/model/properties/seconday-structure'; import { SecondaryStructureType } from '../../../mol-model/structure/model/types'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { assignBends } from './dssp/bends'; import { calcUnitBackboneHbonds } from './dssp/backbone-hbonds'; import { Ladder, Bridge, DSSPContext, DSSPType } from './dssp/common'; @@ -34,29 +34,29 @@ import { SortedArray } from '../../../mol-data/int'; export const DSSPComputationParams = { oldDefinition: PD.Boolean(true, { description: 'Whether to use the old DSSP convention for the annotation of turns and helices, causes them to be two residues shorter' }), oldOrdering: PD.Boolean(true, { description: 'Alpha-helices are preferred over 3-10 helices' }) -} +}; export type DSSPComputationParams = typeof DSSPComputationParams export type DSSPComputationProps = PD.Values<DSSPComputationParams> export async function computeUnitDSSP(unit: Unit.Atomic, params: DSSPComputationProps): Promise<SecondaryStructure> { - const proteinInfo = getUnitProteinInfo(unit) - const { residueIndices } = proteinInfo - const lookup3d = calcUnitProteinTraceLookup3D(unit, residueIndices) + const proteinInfo = getUnitProteinInfo(unit); + const { residueIndices } = proteinInfo; + const lookup3d = calcUnitProteinTraceLookup3D(unit, residueIndices); - const hbonds = calcUnitBackboneHbonds(unit, proteinInfo, lookup3d) + const hbonds = calcUnitBackboneHbonds(unit, proteinInfo, lookup3d); - const residueCount = residueIndices.length - const flags = new Uint32Array(residueCount) + const residueCount = residueIndices.length; + const flags = new Uint32Array(residueCount); // console.log(`calculating secondary structure elements using ${ params.oldDefinition ? 'old' : 'revised'} definition and ${ params.oldOrdering ? 'old' : 'revised'} ordering of secondary structure elements`) - const torsionAngles = calculateUnitDihedralAngles(unit, proteinInfo) + const torsionAngles = calculateUnitDihedralAngles(unit, proteinInfo); - const ladders: Ladder[] = [] - const bridges: Bridge[] = [] + const ladders: Ladder[] = []; + const bridges: Bridge[] = []; - const getResidueFlag = params.oldDefinition ? getOriginalResidueFlag : getUpdatedResidueFlag - const getFlagName = params.oldOrdering ? getOriginalFlagName : getUpdatedFlagName + const getResidueFlag = params.oldDefinition ? getOriginalResidueFlag : getUpdatedResidueFlag; + const getFlagName = params.oldOrdering ? getOriginalFlagName : getUpdatedFlagName; const ctx: DSSPContext = { params, @@ -71,33 +71,33 @@ export async function computeUnitDSSP(unit: Unit.Atomic, params: DSSPComputation torsionAngles, ladders, bridges - } + }; - assignTurns(ctx) - assignHelices(ctx) - assignBends(ctx) - assignBridges(ctx) - assignLadders(ctx) - assignSheets(ctx) + assignTurns(ctx); + assignHelices(ctx); + assignBends(ctx); + assignBridges(ctx); + assignLadders(ctx); + assignSheets(ctx); - const assignment = getDSSPAssignment(flags, getResidueFlag) - const type = new Uint32Array(residueCount) as unknown as SecondaryStructureType[] - const keys: number[] = [] - const elements: SecondaryStructure.Element[] = [] - const getIndex = (rI: ResidueIndex) => SortedArray.indexOf(residueIndices, rI) + const assignment = getDSSPAssignment(flags, getResidueFlag); + const type = new Uint32Array(residueCount) as unknown as SecondaryStructureType[]; + const keys: number[] = []; + const elements: SecondaryStructure.Element[] = []; + const getIndex = (rI: ResidueIndex) => SortedArray.indexOf(residueIndices, rI); for (let i = 0, il = residueIndices.length; i < il; ++i) { - const assign = assignment[i] - type[i] = assign - const flag = getResidueFlag(flags[i]) + const assign = assignment[i]; + type[i] = assign; + const flag = getResidueFlag(flags[i]); // console.log(i, SortedArray.indexOf(residueIndices, i), getFlagName(flags[i])) // TODO is this expected behavior? elements will be strictly split depending on 'winning' flag if (elements.length === 0 /* would fail at very start */ || flag !== (elements[elements.length - 1] as SecondaryStructure.Helix | SecondaryStructure.Sheet | SecondaryStructure.Turn).flags /* flag changed */) { - elements[elements.length] = createElement(mapToKind(assign), flags[i], getResidueFlag) + elements[elements.length] = createElement(mapToKind(assign), flags[i], getResidueFlag); } - keys[i] = elements.length - 1 + keys[i] = elements.length - 1; } - return SecondaryStructure(type, keys, elements, getIndex) + return SecondaryStructure(type, keys, elements, getIndex); } function createElement(kind: string, flag: DSSPType.Flag, getResidueFlag: (f: DSSPType) => SecondaryStructureType): SecondaryStructure.Element { @@ -106,90 +106,90 @@ function createElement(kind: string, flag: DSSPType.Flag, getResidueFlag: (f: DS return { kind: 'helix', flags: getResidueFlag(flag) - } as SecondaryStructure.Helix + } as SecondaryStructure.Helix; } else if (kind === 'sheet') { return { kind: 'sheet', flags: getResidueFlag(flag) - } as SecondaryStructure.Sheet + } as SecondaryStructure.Sheet; } else if (kind === 'turn' || kind === 'bend') { return { kind: 'turn', flags: getResidueFlag(flag) - } + }; } else { return { kind: 'none' - } + }; } } function mapToKind(assignment: SecondaryStructureType.Flag) { if (assignment === SecondaryStructureType.SecondaryStructureDssp.H || assignment === SecondaryStructureType.SecondaryStructureDssp.G || assignment === SecondaryStructureType.SecondaryStructureDssp.I) { - return 'helix' + return 'helix'; } else if (assignment === SecondaryStructureType.SecondaryStructureDssp.B || assignment === SecondaryStructureType.SecondaryStructureDssp.E) { - return 'sheet' + return 'sheet'; } else if (assignment === SecondaryStructureType.SecondaryStructureDssp.T) { - return 'turn' + return 'turn'; } else if (assignment === SecondaryStructureType.SecondaryStructureDssp.S) { - return 'bend' + return 'bend'; } else { - return 'none' + return 'none'; } } /** Original priority: H,B,E,G,I,T,S */ function getOriginalResidueFlag(f: DSSPType) { - if (DSSPType.is(f, DSSPType.Flag.H)) return SecondaryStructureType.SecondaryStructureDssp.H - if (DSSPType.is(f, DSSPType.Flag.E)) return SecondaryStructureType.SecondaryStructureDssp.E - if (DSSPType.is(f, DSSPType.Flag.B)) return SecondaryStructureType.SecondaryStructureDssp.B - if (DSSPType.is(f, DSSPType.Flag.G)) return SecondaryStructureType.SecondaryStructureDssp.G - if (DSSPType.is(f, DSSPType.Flag.I)) return SecondaryStructureType.SecondaryStructureDssp.I - if (DSSPType.is(f, DSSPType.Flag.T)) return SecondaryStructureType.SecondaryStructureDssp.T - if (DSSPType.is(f, DSSPType.Flag.S)) return SecondaryStructureType.SecondaryStructureDssp.S - return SecondaryStructureType.Flag.None + if (DSSPType.is(f, DSSPType.Flag.H)) return SecondaryStructureType.SecondaryStructureDssp.H; + if (DSSPType.is(f, DSSPType.Flag.E)) return SecondaryStructureType.SecondaryStructureDssp.E; + if (DSSPType.is(f, DSSPType.Flag.B)) return SecondaryStructureType.SecondaryStructureDssp.B; + if (DSSPType.is(f, DSSPType.Flag.G)) return SecondaryStructureType.SecondaryStructureDssp.G; + if (DSSPType.is(f, DSSPType.Flag.I)) return SecondaryStructureType.SecondaryStructureDssp.I; + if (DSSPType.is(f, DSSPType.Flag.T)) return SecondaryStructureType.SecondaryStructureDssp.T; + if (DSSPType.is(f, DSSPType.Flag.S)) return SecondaryStructureType.SecondaryStructureDssp.S; + return SecondaryStructureType.Flag.None; } function getOriginalFlagName(f: DSSPType) { - if (DSSPType.is(f, DSSPType.Flag.H)) return 'H' - if (DSSPType.is(f, DSSPType.Flag.E)) return 'E' - if (DSSPType.is(f, DSSPType.Flag.B)) return 'B' - if (DSSPType.is(f, DSSPType.Flag.G)) return 'G' - if (DSSPType.is(f, DSSPType.Flag.I)) return 'I' - if (DSSPType.is(f, DSSPType.Flag.T)) return 'T' - if (DSSPType.is(f, DSSPType.Flag.S)) return 'S' - return '-' + if (DSSPType.is(f, DSSPType.Flag.H)) return 'H'; + if (DSSPType.is(f, DSSPType.Flag.E)) return 'E'; + if (DSSPType.is(f, DSSPType.Flag.B)) return 'B'; + if (DSSPType.is(f, DSSPType.Flag.G)) return 'G'; + if (DSSPType.is(f, DSSPType.Flag.I)) return 'I'; + if (DSSPType.is(f, DSSPType.Flag.T)) return 'T'; + if (DSSPType.is(f, DSSPType.Flag.S)) return 'S'; + return '-'; } /** Version 2.1.0 priority: I,H,B,E,G,T,S */ function getUpdatedResidueFlag(f: DSSPType) { - if (DSSPType.is(f, DSSPType.Flag.I)) return SecondaryStructureType.SecondaryStructureDssp.I - if (DSSPType.is(f, DSSPType.Flag.H)) return SecondaryStructureType.SecondaryStructureDssp.H - if (DSSPType.is(f, DSSPType.Flag.E)) return SecondaryStructureType.SecondaryStructureDssp.E - if (DSSPType.is(f, DSSPType.Flag.B)) return SecondaryStructureType.SecondaryStructureDssp.B - if (DSSPType.is(f, DSSPType.Flag.G)) return SecondaryStructureType.SecondaryStructureDssp.G - if (DSSPType.is(f, DSSPType.Flag.T)) return SecondaryStructureType.SecondaryStructureDssp.T - if (DSSPType.is(f, DSSPType.Flag.S)) return SecondaryStructureType.SecondaryStructureDssp.S - return SecondaryStructureType.Flag.None + if (DSSPType.is(f, DSSPType.Flag.I)) return SecondaryStructureType.SecondaryStructureDssp.I; + if (DSSPType.is(f, DSSPType.Flag.H)) return SecondaryStructureType.SecondaryStructureDssp.H; + if (DSSPType.is(f, DSSPType.Flag.E)) return SecondaryStructureType.SecondaryStructureDssp.E; + if (DSSPType.is(f, DSSPType.Flag.B)) return SecondaryStructureType.SecondaryStructureDssp.B; + if (DSSPType.is(f, DSSPType.Flag.G)) return SecondaryStructureType.SecondaryStructureDssp.G; + if (DSSPType.is(f, DSSPType.Flag.T)) return SecondaryStructureType.SecondaryStructureDssp.T; + if (DSSPType.is(f, DSSPType.Flag.S)) return SecondaryStructureType.SecondaryStructureDssp.S; + return SecondaryStructureType.Flag.None; } function getUpdatedFlagName(f: DSSPType) { - if (DSSPType.is(f, DSSPType.Flag.I)) return 'I' - if (DSSPType.is(f, DSSPType.Flag.H)) return 'H' - if (DSSPType.is(f, DSSPType.Flag.E)) return 'E' - if (DSSPType.is(f, DSSPType.Flag.B)) return 'B' - if (DSSPType.is(f, DSSPType.Flag.G)) return 'G' - if (DSSPType.is(f, DSSPType.Flag.T)) return 'T' - if (DSSPType.is(f, DSSPType.Flag.S)) return 'S' - return '-' + if (DSSPType.is(f, DSSPType.Flag.I)) return 'I'; + if (DSSPType.is(f, DSSPType.Flag.H)) return 'H'; + if (DSSPType.is(f, DSSPType.Flag.E)) return 'E'; + if (DSSPType.is(f, DSSPType.Flag.B)) return 'B'; + if (DSSPType.is(f, DSSPType.Flag.G)) return 'G'; + if (DSSPType.is(f, DSSPType.Flag.T)) return 'T'; + if (DSSPType.is(f, DSSPType.Flag.S)) return 'S'; + return '-'; } function getDSSPAssignment(flags: Uint32Array, getResidueFlag: (f: DSSPType) => SecondaryStructureType) { - const type = new Uint32Array(flags.length) + const type = new Uint32Array(flags.length); for (let i = 0, il = flags.length; i < il; ++i) { - const f = DSSPType.create(flags[i]) - type[i] = getResidueFlag(f) + const f = DSSPType.create(flags[i]); + type[i] = getResidueFlag(f); } - return type as unknown as ArrayLike<SecondaryStructureType> + return type as unknown as ArrayLike<SecondaryStructureType>; } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp/backbone-hbonds.ts b/src/mol-model-props/computed/secondary-structure/dssp/backbone-hbonds.ts index 6ed04cfccc82135c9295ef56af4f60ac7aca9e9b..fe118f183763ddae414338e9b0f8427462541833 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/backbone-hbonds.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/backbone-hbonds.ts @@ -26,112 +26,112 @@ const caMaxDist = 9.0; * q1 and q2 are partial charges which are placed on the C,O * (+q1,-q1) and N,H (-q2,+q2) */ -const Q = -27.888 +const Q = -27.888; /** cutoff for hbonds in kcal/mol, must be lower to be consider as an hbond */ -const hbondEnergyCutoff = -0.5 +const hbondEnergyCutoff = -0.5; /** prevent extremely low hbond energies */ -const hbondEnergyMinimal = -9.9 +const hbondEnergyMinimal = -9.9; /** * E = Q * (1/r(ON) + l/r(CH) - l/r(OH) - l/r(CN)) */ function calcHbondEnergy(oPos: Vec3, cPos: Vec3, nPos: Vec3, hPos: Vec3) { - const distOH = Vec3.distance(oPos, hPos) - const distCH = Vec3.distance(cPos, hPos) - const distCN = Vec3.distance(cPos, nPos) - const distON = Vec3.distance(oPos, nPos) + const distOH = Vec3.distance(oPos, hPos); + const distCH = Vec3.distance(cPos, hPos); + const distCN = Vec3.distance(cPos, nPos); + const distON = Vec3.distance(oPos, nPos); - const e1 = Q / distOH - Q / distCH - const e2 = Q / distCN - Q / distON - const e = e1 + e2 + const e1 = Q / distOH - Q / distCH; + const e2 = Q / distCN - Q / distON; + const e = e1 + e2; // cap lowest possible energy if (e < hbondEnergyMinimal) - return hbondEnergyMinimal + return hbondEnergyMinimal; - return e + return e; } export function calcUnitBackboneHbonds(unit: Unit.Atomic, proteinInfo: ProteinInfo, lookup3d: GridLookup3D): DsspHbonds { - const { residueIndices, cIndices, hIndices, nIndices, oIndices } = proteinInfo + const { residueIndices, cIndices, hIndices, nIndices, oIndices } = proteinInfo; - const { index } = unit.model.atomicHierarchy - const { invariantPosition } = unit.conformation - const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue + const { index } = unit.model.atomicHierarchy; + const { invariantPosition } = unit.conformation; + const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue; - const residueCount = residueIndices.length + const residueCount = residueIndices.length; const oAtomResidues: number[] = []; const nAtomResidues: number[] = []; const energies: number[] = []; - const oPos = Vec3() - const cPos = Vec3() - const caPos = Vec3() - const nPos = Vec3() - const hPos = Vec3() + const oPos = Vec3(); + const cPos = Vec3(); + const caPos = Vec3(); + const nPos = Vec3(); + const hPos = Vec3(); - const cPosPrev = Vec3() - const oPosPrev = Vec3() + const cPosPrev = Vec3(); + const oPosPrev = Vec3(); for (let i = 0, il = residueIndices.length; i < il; ++i) { - const oPI = i - const oRI = residueIndices[i] + const oPI = i; + const oRI = residueIndices[i]; - const oAtom = oIndices[oPI] - const cAtom = cIndices[oPI] - const caAtom = traceElementIndex[oRI] + const oAtom = oIndices[oPI]; + const cAtom = cIndices[oPI]; + const caAtom = traceElementIndex[oRI]; // continue if residue is missing O or C atom - if (oAtom === -1 || cAtom === -1) continue + if (oAtom === -1 || cAtom === -1) continue; // ignore C-terminal residue as acceptor - if (index.findAtomOnResidue(oRI, 'OXT') !== -1) continue + if (index.findAtomOnResidue(oRI, 'OXT') !== -1) continue; - invariantPosition(oAtom, oPos) - invariantPosition(cAtom, cPos) - invariantPosition(caAtom as ElementIndex, caPos) + invariantPosition(oAtom, oPos); + invariantPosition(cAtom, cPos); + invariantPosition(caAtom as ElementIndex, caPos); - const { indices, count } = lookup3d.find(caPos[0], caPos[1], caPos[2], caMaxDist) + const { indices, count } = lookup3d.find(caPos[0], caPos[1], caPos[2], caMaxDist); for (let j = 0; j < count; ++j) { - const nPI = indices[j] + const nPI = indices[j]; // ignore bonds within a residue or to prev or next residue - if (nPI === oPI || nPI - 1 === oPI || nPI + 1 === oPI) continue + if (nPI === oPI || nPI - 1 === oPI || nPI + 1 === oPI) continue; - const nAtom = nIndices[nPI] - if (nAtom === -1) continue + const nAtom = nIndices[nPI]; + if (nAtom === -1) continue; - invariantPosition(nAtom, nPos) + invariantPosition(nAtom, nPos); - const hAtom = hIndices[nPI] + const hAtom = hIndices[nPI]; if (hAtom === -1) { // approximate calculation of H position, TODO factor out - if (nPI === 0) continue - const nPIprev = nPI - 1 + if (nPI === 0) continue; + const nPIprev = nPI - 1; - const oAtomPrev = oIndices[nPIprev] - const cAtomPrev = cIndices[nPIprev] - if (oAtomPrev === -1 || cAtomPrev === -1) continue + const oAtomPrev = oIndices[nPIprev]; + const cAtomPrev = cIndices[nPIprev]; + if (oAtomPrev === -1 || cAtomPrev === -1) continue; - invariantPosition(oAtomPrev, oPosPrev) - invariantPosition(cAtomPrev, cPosPrev) + invariantPosition(oAtomPrev, oPosPrev); + invariantPosition(cAtomPrev, cPosPrev); - Vec3.sub(hPos, cPosPrev, oPosPrev) - const dist = Vec3.distance(oPosPrev, cPosPrev) - Vec3.scaleAndAdd(hPos, nPos, hPos, 1 / dist) + Vec3.sub(hPos, cPosPrev, oPosPrev); + const dist = Vec3.distance(oPosPrev, cPosPrev); + Vec3.scaleAndAdd(hPos, nPos, hPos, 1 / dist); } else { - invariantPosition(hAtom, hPos) + invariantPosition(hAtom, hPos); } - const e = calcHbondEnergy(oPos, cPos, nPos, hPos) - if (e > hbondEnergyCutoff) continue + const e = calcHbondEnergy(oPos, cPos, nPos, hPos); + if (e > hbondEnergyCutoff) continue; - oAtomResidues[oAtomResidues.length] = oPI - nAtomResidues[nAtomResidues.length] = nPI - energies[energies.length] = e + oAtomResidues[oAtomResidues.length] = oPI; + nAtomResidues[nAtomResidues.length] = nPI; + energies[energies.length] = e; } } diff --git a/src/mol-model-props/computed/secondary-structure/dssp/bends.ts b/src/mol-model-props/computed/secondary-structure/dssp/bends.ts index 250c644ca5755c9c01f65e40180549a878b95a9f..ccb91a53753b37c744e298127a0f55fd366302dd 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/bends.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/bends.ts @@ -16,55 +16,55 @@ import { ElementIndex } from '../../../../mol-model/structure'; * Type: S */ export function assignBends(ctx: DSSPContext) { - const { unit, flags, proteinInfo } = ctx - const { position } = unit.conformation - const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue + const { unit, flags, proteinInfo } = ctx; + const { position } = unit.conformation; + const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue; - const { residueIndices, nIndices } = proteinInfo - const residueCount = residueIndices.length + const { residueIndices, nIndices } = proteinInfo; + const residueCount = residueIndices.length; // const position = (i: number, v: Vec3) => Vec3.set(v, x[i], y[i], z[i]) - const p = (i: ElementIndex | -1, v: Vec3) => i === -1 ? Vec3.setNaN(v) : position(i, v) + const p = (i: ElementIndex | -1, v: Vec3) => i === -1 ? Vec3.setNaN(v) : position(i, v); - const caPosPrev2 = Vec3() - const caPos = Vec3() - const caPosNext2 = Vec3() + const caPosPrev2 = Vec3(); + const caPos = Vec3(); + const caPosNext2 = Vec3(); - const cPos = Vec3() - const nPosNext = Vec3() + const cPos = Vec3(); + const nPosNext = Vec3(); - const caMinus2 = Vec3() - const caPlus2 = Vec3() + const caMinus2 = Vec3(); + const caPlus2 = Vec3(); f1: for (let i = 2; i < residueCount - 2; i++) { // check for peptide bond for (let k = 0; k < 4; k++) { - let index = i + k - 2 - p(traceElementIndex[index], cPos) - p(nIndices[index + 1], nPosNext) + let index = i + k - 2; + p(traceElementIndex[index], cPos); + p(nIndices[index + 1], nPosNext); if (Vec3.squaredDistance(cPos, nPosNext) > 6.25 /* max squared peptide bond distance allowed */) { - continue f1 + continue f1; } } - const oRIprev2 = residueIndices[i - 2] - const oRI = residueIndices[i] - const oRInext2 = residueIndices[i + 2] + const oRIprev2 = residueIndices[i - 2]; + const oRI = residueIndices[i]; + const oRInext2 = residueIndices[i + 2]; - const caAtomPrev2 = traceElementIndex[oRIprev2] - const caAtom = traceElementIndex[oRI] - const caAtomNext2 = traceElementIndex[oRInext2] + const caAtomPrev2 = traceElementIndex[oRIprev2]; + const caAtom = traceElementIndex[oRI]; + const caAtomNext2 = traceElementIndex[oRInext2]; - p(caAtomPrev2, caPosPrev2) - p(caAtom, caPos) - p(caAtomNext2, caPosNext2) + p(caAtomPrev2, caPosPrev2); + p(caAtom, caPos); + p(caAtomNext2, caPosNext2); - Vec3.sub(caMinus2, caPosPrev2, caPos) - Vec3.sub(caPlus2, caPos, caPosNext2) + Vec3.sub(caMinus2, caPosPrev2, caPos); + Vec3.sub(caPlus2, caPos, caPosNext2); - const angle = radToDeg(Vec3.angle(caMinus2, caPlus2)) + const angle = radToDeg(Vec3.angle(caMinus2, caPlus2)); if (angle && angle > 70.00) { - flags[i] |= DSSPType.Flag.S + flags[i] |= DSSPType.Flag.S; } } } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp/bridges.ts b/src/mol-model-props/computed/secondary-structure/dssp/bridges.ts index d2c351c5aa333a296e3df92e8c117f8f3ea6af4f..9dc1e6dedbc0a2996e7b96fc3dda3f34f5fd8991 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/bridges.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/bridges.ts @@ -24,54 +24,54 @@ import { DSSPContext, DSSPType, BridgeType, Bridge } from './common'; * Type: B */ export function assignBridges(ctx: DSSPContext) { - const { proteinInfo, hbonds, flags, bridges } = ctx + const { proteinInfo, hbonds, flags, bridges } = ctx; - const { offset, b } = hbonds - let i: number, j: number + const { offset, b } = hbonds; + let i: number, j: number; for (let k = 0, kl = proteinInfo.residueIndices.length; k < kl; ++k) { for (let t = offset[k], _t = offset[k + 1]; t < _t; t++) { - const l = b[t] - if (k > l) continue + const l = b[t]; + if (k > l) continue; // Parallel Bridge(i, j) =: [Hbond(i - 1, j) and Hbond(j, i + 1)] - i = k + 1 // k is i - 1 - j = l + i = k + 1; // k is i - 1 + j = l; if (i !== j && hbonds.getDirectedEdgeIndex(j, i + 1) !== -1) { - flags[i] |= DSSPType.Flag.B - flags[j] |= DSSPType.Flag.B + flags[i] |= DSSPType.Flag.B; + flags[j] |= DSSPType.Flag.B; // TODO move to constructor, actually omit object all together - bridges[bridges.length] = new Bridge(i, j, BridgeType.PARALLEL) + bridges[bridges.length] = new Bridge(i, j, BridgeType.PARALLEL); } // Parallel Bridge(i, j) =: [Hbond(j - 1, i) and Hbond(i, j + 1)] - i = k - j = l - 1 // l is j + 1 + i = k; + j = l - 1; // l is j + 1 if (i !== j && hbonds.getDirectedEdgeIndex(j - 1, i) !== -1) { - flags[i] |= DSSPType.Flag.B - flags[j] |= DSSPType.Flag.B - bridges[bridges.length] = new Bridge(j, i, BridgeType.PARALLEL) + flags[i] |= DSSPType.Flag.B; + flags[j] |= DSSPType.Flag.B; + bridges[bridges.length] = new Bridge(j, i, BridgeType.PARALLEL); } // Antiparallel Bridge(i, j) =: [Hbond(i, j) and Hbond(j, i)] - i = k - j = l + i = k; + j = l; if (i !== j && hbonds.getDirectedEdgeIndex(j, i) !== -1) { - flags[i] |= DSSPType.Flag.B - flags[j] |= DSSPType.Flag.B - bridges[bridges.length] = new Bridge(j, i, BridgeType.ANTI_PARALLEL) + flags[i] |= DSSPType.Flag.B; + flags[j] |= DSSPType.Flag.B; + bridges[bridges.length] = new Bridge(j, i, BridgeType.ANTI_PARALLEL); } // Antiparallel Bridge(i, j) =: [Hbond(i - 1, j + 1) and Hbond(j - 1, i + l)] - i = k + 1 - j = l - 1 + i = k + 1; + j = l - 1; if (i !== j && hbonds.getDirectedEdgeIndex(j - 1, i + 1) !== -1) { - flags[i] |= DSSPType.Flag.B - flags[j] |= DSSPType.Flag.B - bridges[bridges.length] = new Bridge(j, i, BridgeType.ANTI_PARALLEL) + flags[i] |= DSSPType.Flag.B; + flags[j] |= DSSPType.Flag.B; + bridges[bridges.length] = new Bridge(j, i, BridgeType.ANTI_PARALLEL); } } } - bridges.sort((a, b) => a.partner1 > b.partner1 ? 1 : a.partner1 < b.partner1 ? -1 : 0) + bridges.sort((a, b) => a.partner1 > b.partner1 ? 1 : a.partner1 < b.partner1 ? -1 : 0); } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp/common.ts b/src/mol-model-props/computed/secondary-structure/dssp/common.ts index 8d7d588f0c3ef204167d039812772cfeff82c4f3..7de24a1f3bf90fb73ce2ca1f4813836a095e93a5 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/common.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/common.ts @@ -30,11 +30,11 @@ export interface DSSPContext { bridges: Bridge[] } -export { DSSPType } +export { DSSPType }; type DSSPType = BitFlags<DSSPType.Flag> namespace DSSPType { - export const is: (t: DSSPType, f: Flag) => boolean = BitFlags.has - export const create: (f: Flag) => DSSPType = BitFlags.create + export const is: (t: DSSPType, f: Flag) => boolean = BitFlags.has; + export const create: (f: Flag) => DSSPType = BitFlags.create; export const enum Flag { _ = 0x0, H = 0x1, @@ -76,8 +76,8 @@ export class Bridge { type: BridgeType; constructor(p1: number, p2: number, type: BridgeType) { - this.partner1 = Math.min(p1, p2) - this.partner2 = Math.max(p1, p2) - this.type = type + this.partner1 = Math.min(p1, p2); + this.partner2 = Math.max(p1, p2); + this.type = type; } } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp/dihedral-angles.ts b/src/mol-model-props/computed/secondary-structure/dssp/dihedral-angles.ts index b08dcda29d202437e3a4fbde8b5e18d2c077c90c..b861ac5278a75a514ae5e75755c1a305c0e362ed 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/dihedral-angles.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/dihedral-angles.ts @@ -17,49 +17,49 @@ export interface DihedralAngles { } export function calculateUnitDihedralAngles(unit: Unit.Atomic, proteinInfo: ProteinInfo): DihedralAngles { - const { cIndices, nIndices, residueIndices } = proteinInfo - const { position } = unit.conformation - const { index } = unit.model.atomicHierarchy - const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue + const { cIndices, nIndices, residueIndices } = proteinInfo; + const { position } = unit.conformation; + const { index } = unit.model.atomicHierarchy; + const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue; - const residueCount = residueIndices.length - const p = (i: ElementIndex | -1, v: Vec3) => i === -1 ? Vec3.setNaN(v) : position(i, v) + const residueCount = residueIndices.length; + const p = (i: ElementIndex | -1, v: Vec3) => i === -1 ? Vec3.setNaN(v) : position(i, v); - let cPosPrev = Vec3(), caPosPrev = Vec3(), nPosPrev = Vec3() - let cPos = Vec3(), caPos = Vec3(), nPos = Vec3() - let cPosNext = Vec3(), caPosNext = Vec3(), nPosNext = Vec3() + let cPosPrev = Vec3(), caPosPrev = Vec3(), nPosPrev = Vec3(); + let cPos = Vec3(), caPos = Vec3(), nPos = Vec3(); + let cPosNext = Vec3(), caPosNext = Vec3(), nPosNext = Vec3(); - if (residueCount === 0) return { phi: new Float32Array(0), psi: new Float32Array(0) } + if (residueCount === 0) return { phi: new Float32Array(0), psi: new Float32Array(0) }; - const phi: Float32Array = new Float32Array(residueCount - 1) - const psi: Float32Array = new Float32Array(residueCount - 1) + const phi: Float32Array = new Float32Array(residueCount - 1); + const psi: Float32Array = new Float32Array(residueCount - 1); - p(-1, cPosPrev) - p(-1, caPosPrev) - p(-1, nPosPrev) + p(-1, cPosPrev); + p(-1, caPosPrev); + p(-1, nPosPrev); - p(cIndices[0], cPos) - p(traceElementIndex[residueIndices[0]], caPos) - p(nIndices[0], nPos) + p(cIndices[0], cPos); + p(traceElementIndex[residueIndices[0]], caPos); + p(nIndices[0], nPos); - p(cIndices[1], cPosNext) - p(traceElementIndex[residueIndices[1]], caPosNext) - p(nIndices[1], nPosNext) + p(cIndices[1], cPosNext); + p(traceElementIndex[residueIndices[1]], caPosNext); + p(nIndices[1], nPosNext); for (let i = 0; i < residueCount - 1; ++i) { // ignore C-terminal residue as acceptor - if (index.findAtomOnResidue(residueIndices[i], 'OXT') !== -1) continue + if (index.findAtomOnResidue(residueIndices[i], 'OXT') !== -1) continue; // returns NaN for missing atoms - phi[i] = radToDeg(Vec3.dihedralAngle(cPosPrev, nPos, caPos, cPos)) - psi[i] = radToDeg(Vec3.dihedralAngle(nPos, caPos, cPos, nPosNext)) + phi[i] = radToDeg(Vec3.dihedralAngle(cPosPrev, nPos, caPos, cPos)); + psi[i] = radToDeg(Vec3.dihedralAngle(nPos, caPos, cPos, nPosNext)); - cPosPrev = cPos, caPosPrev = caPos, nPosPrev = nPos - cPos = cPosNext, caPos = caPosNext, nPos = nPosNext + cPosPrev = cPos, caPosPrev = caPos, nPosPrev = nPos; + cPos = cPosNext, caPos = caPosNext, nPos = nPosNext; - p(cIndices[i + 1], cPosNext) - p(traceElementIndex[residueIndices[i + 1]], caPosNext) - p(nIndices[i + 1], nPosNext) + p(cIndices[i + 1], cPosNext); + p(traceElementIndex[residueIndices[i + 1]], caPosNext); + p(nIndices[i + 1], nPosNext); } return { phi, psi }; diff --git a/src/mol-model-props/computed/secondary-structure/dssp/helices.ts b/src/mol-model-props/computed/secondary-structure/dssp/helices.ts index 62317112f135b5e06bdf79b0db33f2f20ddde5f4..cb53f7e5d2f447e4972d882a70906719dc2dcd20 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/helices.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/helices.ts @@ -19,31 +19,31 @@ import { DSSPContext, DSSPType } from './common'; * Type: G (n=3), H (n=4), I (n=5) */ export function assignHelices(ctx: DSSPContext) { - const { proteinInfo, flags } = ctx - const residueCount = proteinInfo.residueIndices.length + const { proteinInfo, flags } = ctx; + const residueCount = proteinInfo.residueIndices.length; - const turnFlag = [DSSPType.Flag.T3S, DSSPType.Flag.T4S, DSSPType.Flag.T5S, DSSPType.Flag.T3, DSSPType.Flag.T4, DSSPType.Flag.T5] - const helixFlag = [0, 0, 0, DSSPType.Flag.G, DSSPType.Flag.H, DSSPType.Flag.I] + const turnFlag = [DSSPType.Flag.T3S, DSSPType.Flag.T4S, DSSPType.Flag.T5S, DSSPType.Flag.T3, DSSPType.Flag.T4, DSSPType.Flag.T5]; + const helixFlag = [0, 0, 0, DSSPType.Flag.G, DSSPType.Flag.H, DSSPType.Flag.I]; - const helixCheckOrder = ctx.params.oldOrdering ? [4, 3, 5] : [3, 4, 5] + const helixCheckOrder = ctx.params.oldOrdering ? [4, 3, 5] : [3, 4, 5]; for (let ni = 0; ni < helixCheckOrder.length; ni++) { - const n = helixCheckOrder[ni] + const n = helixCheckOrder[ni]; for (let i = 1, il = residueCount - n; i < il; i++) { - const fI = DSSPType.create(flags[i]) - const fI1 = DSSPType.create(flags[i - 1]) - const fI2 = DSSPType.create(flags[i + 1]) + const fI = DSSPType.create(flags[i]); + const fI1 = DSSPType.create(flags[i - 1]); + const fI2 = DSSPType.create(flags[i + 1]); // TODO rework to elegant solution which will not break instantly if (ctx.params.oldOrdering) { if ((n === 3 && (DSSPType.is(fI, DSSPType.Flag.H) || DSSPType.is(fI2, DSSPType.Flag.H)) || // for 3-10 yield to alpha helix (n === 5 && ((DSSPType.is(fI, DSSPType.Flag.H) || DSSPType.is(fI, DSSPType.Flag.G)) || (DSSPType.is(fI2, DSSPType.Flag.H) || DSSPType.is(fI2, DSSPType.Flag.G)))))) { // for pi yield to all other helices - continue + continue; } } else { if ((n === 4 && (DSSPType.is(fI, DSSPType.Flag.G) || DSSPType.is(fI2, DSSPType.Flag.G)) || // for alpha helix yield to 3-10 (n === 5 && ((DSSPType.is(fI, DSSPType.Flag.H) || DSSPType.is(fI, DSSPType.Flag.G)) || (DSSPType.is(fI2, DSSPType.Flag.H) || DSSPType.is(fI2, DSSPType.Flag.G)))))) { // for pi yield to all other helices - continue + continue; } } @@ -51,11 +51,11 @@ export function assignHelices(ctx: DSSPContext) { DSSPType.is(fI1, turnFlag[n]) && DSSPType.is(fI1, turnFlag[n - 3])) { // check fI1 accordingly if (ctx.params.oldDefinition) { for (let k = 0; k < n; k++) { - flags[i + k] |= helixFlag[n] + flags[i + k] |= helixFlag[n]; } } else { for (let k = -1; k <= n; k++) { - flags[i + k] |= helixFlag[n] + flags[i + k] |= helixFlag[n]; } } } diff --git a/src/mol-model-props/computed/secondary-structure/dssp/ladders.ts b/src/mol-model-props/computed/secondary-structure/dssp/ladders.ts index 57a5c2ceb0047297c82707a37f6da9bf647e0bbc..346a4c818c15eb01afe054336b7fdbb45aaa290e 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/ladders.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/ladders.ts @@ -9,22 +9,22 @@ import { DSSPContext, Ladder, BridgeType, Bridge } from './common'; function shouldExtendLadder(ladder: Ladder, bridge: Bridge): boolean { // in order to extend ladders, same type must be present - if (bridge.type !== ladder.type) return false + if (bridge.type !== ladder.type) return false; // only extend if residue 1 is sequence neighbor with regard to ladder - if (bridge.partner1 !== ladder.firstEnd + 1) return false + if (bridge.partner1 !== ladder.firstEnd + 1) return false; if (bridge.type === BridgeType.PARALLEL) { if (bridge.partner2 === ladder.secondEnd + 1) { - return true + return true; } } else { if (bridge.partner2 === ladder.secondStart - 1) { - return true + return true; } } - return false + return false; } /** @@ -34,18 +34,18 @@ function shouldExtendLadder(ladder: Ladder, bridge: Bridge): boolean { */ function resemblesBulge(ladder1: Ladder, ladder2: Ladder) { if (!(ladder1.type === ladder2.type && ladder2.firstStart - ladder1.firstEnd < 6 && - ladder1.firstStart < ladder2.firstStart && ladder2.nextLadder === 0)) return false + ladder1.firstStart < ladder2.firstStart && ladder2.nextLadder === 0)) return false; if (ladder1.type === BridgeType.PARALLEL) { - return bulgeCriterion2(ladder1, ladder2) + return bulgeCriterion2(ladder1, ladder2); } else { - return bulgeCriterion2(ladder2, ladder1) + return bulgeCriterion2(ladder2, ladder1); } } function bulgeCriterion2(ladder1: Ladder, ladder2: Ladder) { return ladder2.secondStart - ladder1.secondEnd > 0 && ((ladder2.secondStart - ladder1.secondEnd < 6 && - ladder2.firstStart - ladder1.firstEnd < 3) || ladder2.secondStart - ladder1.secondEnd < 3) + ladder2.firstStart - ladder1.firstEnd < 3) || ladder2.secondStart - ladder1.secondEnd < 3); } /** @@ -54,21 +54,21 @@ function bulgeCriterion2(ladder1: Ladder, ladder2: Ladder) { * Type: E */ export function assignLadders(ctx: DSSPContext) { - const { bridges, ladders } = ctx + const { bridges, ladders } = ctx; // create ladders for (let bridgeIndex = 0; bridgeIndex < bridges.length; bridgeIndex++) { - const bridge = bridges[bridgeIndex] - let found = false + const bridge = bridges[bridgeIndex]; + let found = false; for (let ladderIndex = 0; ladderIndex < ladders.length; ladderIndex++) { - const ladder = ladders[ladderIndex] + const ladder = ladders[ladderIndex]; if (shouldExtendLadder(ladder, bridge)) { - found = true - ladder.firstEnd++ + found = true; + ladder.firstEnd++; if (bridge.type === BridgeType.PARALLEL) { - ladder.secondEnd++ + ladder.secondEnd++; } else { - ladder.secondStart-- + ladder.secondStart--; } } } @@ -83,18 +83,18 @@ export function assignLadders(ctx: DSSPContext) { secondStart: bridge.partner2, secondEnd: bridge.partner2, type: bridge.type - } + }; } } // connect ladders for (let ladderIndex1 = 0; ladderIndex1 < ladders.length; ladderIndex1++) { - const ladder1 = ladders[ladderIndex1] + const ladder1 = ladders[ladderIndex1]; for (let ladderIndex2 = ladderIndex1; ladderIndex2 < ladders.length; ladderIndex2++) { - const ladder2 = ladders[ladderIndex2] + const ladder2 = ladders[ladderIndex2]; if (resemblesBulge(ladder1, ladder2)) { - ladder1.nextLadder = ladderIndex2 - ladder2.previousLadder = ladderIndex1 + ladder1.nextLadder = ladderIndex2; + ladder2.previousLadder = ladderIndex1; } } } diff --git a/src/mol-model-props/computed/secondary-structure/dssp/protein-info.ts b/src/mol-model-props/computed/secondary-structure/dssp/protein-info.ts index b4f3c9344bb4d3ee89e6be3872f5b2a3c7aa3542..c37c863c45d0c18c2ac079779a43e941f8cd1bd8 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/protein-info.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/protein-info.ts @@ -17,23 +17,23 @@ export interface ProteinInfo { } export function getUnitProteinInfo(unit: Unit.Atomic): ProteinInfo { - const { index } = unit.model.atomicHierarchy - const { proteinElements, residueIndex } = unit - const residueCount = proteinElements.length + const { index } = unit.model.atomicHierarchy; + const { proteinElements, residueIndex } = unit; + const residueCount = proteinElements.length; - const unitProteinResidues = new Uint32Array(residueCount) - const c = new Int32Array(residueCount) - const h = new Int32Array(residueCount) - const o = new Int32Array(residueCount) - const n = new Int32Array(residueCount) + const unitProteinResidues = new Uint32Array(residueCount); + const c = new Int32Array(residueCount); + const h = new Int32Array(residueCount); + const o = new Int32Array(residueCount); + const n = new Int32Array(residueCount); for (let i = 0; i < residueCount; ++i) { - const rI = residueIndex[proteinElements[i]] - unitProteinResidues[i] = rI - c[i] = index.findAtomOnResidue(rI, 'C') - h[i] = index.findAtomOnResidue(rI, 'H') - o[i] = index.findAtomOnResidue(rI, 'O') - n[i] = index.findAtomOnResidue(rI, 'N') + const rI = residueIndex[proteinElements[i]]; + unitProteinResidues[i] = rI; + c[i] = index.findAtomOnResidue(rI, 'C'); + h[i] = index.findAtomOnResidue(rI, 'H'); + o[i] = index.findAtomOnResidue(rI, 'O'); + n[i] = index.findAtomOnResidue(rI, 'N'); } return { @@ -42,5 +42,5 @@ export function getUnitProteinInfo(unit: Unit.Atomic): ProteinInfo { hIndices: h as unknown as ArrayLike<ElementIndex | -1>, oIndices: o as unknown as ArrayLike<ElementIndex | -1>, nIndices: n as unknown as ArrayLike<ElementIndex | -1>, - } + }; } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp/sheets.ts b/src/mol-model-props/computed/secondary-structure/dssp/sheets.ts index ebd80b3d8d104704f1796dcf20240b1544deedca..1b4c1d822a634da5ed022e0979198a5811ceb146 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/sheets.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/sheets.ts @@ -8,7 +8,7 @@ import { DSSPContext, DSSPType, BridgeType } from './common'; function isHelixType(f: DSSPType) { - return DSSPType.is(f, DSSPType.Flag.G) || DSSPType.is(f, DSSPType.Flag.H) || DSSPType.is(f, DSSPType.Flag.I) + return DSSPType.is(f, DSSPType.Flag.G) || DSSPType.is(f, DSSPType.Flag.H) || DSSPType.is(f, DSSPType.Flag.I); } /** @@ -17,39 +17,39 @@ function isHelixType(f: DSSPType) { * Type: E */ export function assignSheets(ctx: DSSPContext) { - const { ladders, flags } = ctx + const { ladders, flags } = ctx; for (let ladderIndex = 0; ladderIndex < ladders.length; ladderIndex++) { - const ladder = ladders[ladderIndex] + const ladder = ladders[ladderIndex]; for (let lcount = ladder.firstStart; lcount <= ladder.firstEnd; lcount++) { - const diff = ladder.firstStart - lcount - const l2count = ladder.secondStart - diff + const diff = ladder.firstStart - lcount; + const l2count = ladder.secondStart - diff; if (ladder.firstStart !== ladder.firstEnd) { - flags[lcount] |= DSSPType.Flag.E - flags[l2count] |= DSSPType.Flag.E + flags[lcount] |= DSSPType.Flag.E; + flags[l2count] |= DSSPType.Flag.E; } else { if (!isHelixType(flags[lcount]) && DSSPType.is(flags[lcount], DSSPType.Flag.E)) { - flags[lcount] |= DSSPType.Flag.B + flags[lcount] |= DSSPType.Flag.B; } if (!isHelixType(flags[l2count]) && DSSPType.is(flags[l2count], DSSPType.Flag.E)) { - flags[l2count] |= DSSPType.Flag.B + flags[l2count] |= DSSPType.Flag.B; } } } - if (ladder.nextLadder === 0) continue + if (ladder.nextLadder === 0) continue; - const conladder = ladders[ladder.nextLadder] + const conladder = ladders[ladder.nextLadder]; for (let lcount = ladder.firstStart; lcount <= conladder.firstEnd; lcount++) { - flags[lcount] |= DSSPType.Flag.E + flags[lcount] |= DSSPType.Flag.E; } if (ladder.type === BridgeType.PARALLEL) { for (let lcount = ladder.secondStart; lcount <= conladder.secondEnd; lcount++) { - flags[lcount] |= DSSPType.Flag.E + flags[lcount] |= DSSPType.Flag.E; } } else { for (let lcount = conladder.secondEnd; lcount <= ladder.secondStart; lcount++) { - flags[lcount] |= DSSPType.Flag.E + flags[lcount] |= DSSPType.Flag.E; } } } diff --git a/src/mol-model-props/computed/secondary-structure/dssp/trace-lookup.ts b/src/mol-model-props/computed/secondary-structure/dssp/trace-lookup.ts index 24965665776fa3082f115e8156915556f861a05a..8cd5fcc5db2d4fa0335af6c905f67a220cad4678 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/trace-lookup.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/trace-lookup.ts @@ -12,11 +12,11 @@ import { getBoundary } from '../../../../mol-math/geometry/boundary'; export function calcUnitProteinTraceLookup3D(unit: Unit.Atomic, unitProteinResidues: SortedArray<ResidueIndex>): GridLookup3D { const { x, y, z } = unit.model.atomicConformation; - const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue - const indices = new Uint32Array(unitProteinResidues.length) + const { traceElementIndex } = unit.model.atomicHierarchy.derived.residue; + const indices = new Uint32Array(unitProteinResidues.length); for (let i = 0, il = unitProteinResidues.length; i < il; ++i) { - indices[i] = traceElementIndex[unitProteinResidues[i]] + indices[i] = traceElementIndex[unitProteinResidues[i]]; } - const position = { x, y, z, indices: SortedArray.ofSortedArray(indices) } + const position = { x, y, z, indices: SortedArray.ofSortedArray(indices) }; return GridLookup3D(position, getBoundary(position)); } \ No newline at end of file diff --git a/src/mol-model-props/computed/secondary-structure/dssp/turns.ts b/src/mol-model-props/computed/secondary-structure/dssp/turns.ts index f613fabbd529c99a96ed9c1e5f73e5d96d3f8a3e..fe96d3cb853673ba2c6b428a21ca3932f9a41d22 100644 --- a/src/mol-model-props/computed/secondary-structure/dssp/turns.ts +++ b/src/mol-model-props/computed/secondary-structure/dssp/turns.ts @@ -16,23 +16,23 @@ import { DSSPContext, DSSPType } from './common'; * Type: T */ export function assignTurns(ctx: DSSPContext) { - const { proteinInfo, hbonds, flags } = ctx + const { proteinInfo, hbonds, flags } = ctx; - const turnFlag = [DSSPType.Flag.T3S, DSSPType.Flag.T4S, DSSPType.Flag.T5S, DSSPType.Flag.T3, DSSPType.Flag.T4, DSSPType.Flag.T5] + const turnFlag = [DSSPType.Flag.T3S, DSSPType.Flag.T4S, DSSPType.Flag.T5S, DSSPType.Flag.T3, DSSPType.Flag.T4, DSSPType.Flag.T5]; for (let idx = 0; idx < 3; idx++) { for (let i = 0, il = proteinInfo.residueIndices.length - 1; i < il; ++i) { // check if hbond exists if (hbonds.getDirectedEdgeIndex(i, i + idx + 3) !== -1) { - flags[i] |= turnFlag[idx + 3] | turnFlag[idx] + flags[i] |= turnFlag[idx + 3] | turnFlag[idx]; if (ctx.params.oldDefinition) { for (let k = 1; k < idx + 3; ++k) { - flags[i + k] |= turnFlag[idx + 3] | DSSPType.Flag.T + flags[i + k] |= turnFlag[idx + 3] | DSSPType.Flag.T; } } else { for (let k = 0; k <= idx + 3; ++k) { - flags[i + k] |= turnFlag[idx + 3] | DSSPType.Flag.T + flags[i + k] |= turnFlag[idx + 3] | DSSPType.Flag.T; } } } diff --git a/src/mol-model-props/computed/themes/accessible-surface-area.ts b/src/mol-model-props/computed/themes/accessible-surface-area.ts index 0834fb9d0e7d0a16c8a73a40efbb926ed79fee92..4cd678435b222be97459700146f58f35550cf0a6 100644 --- a/src/mol-model-props/computed/themes/accessible-surface-area.ts +++ b/src/mol-model-props/computed/themes/accessible-surface-area.ts @@ -5,51 +5,51 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ParamDefinition as PD } from '../../../mol-util/param-definition' -import { Color, ColorScale } from '../../../mol-util/color' -import { ThemeDataContext } from '../../../mol-theme/theme' -import { ColorTheme, LocationColor } from '../../../mol-theme/color' -import { StructureElement, Unit } from '../../../mol-model/structure' -import { AccessibleSurfaceAreaProvider } from '../accessible-surface-area' -import { AccessibleSurfaceArea } from '../accessible-surface-area/shrake-rupley' -import { CustomProperty } from '../../common/custom-property' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; +import { Color, ColorScale } from '../../../mol-util/color'; +import { ThemeDataContext } from '../../../mol-theme/theme'; +import { ColorTheme, LocationColor } from '../../../mol-theme/color'; +import { StructureElement, Unit } from '../../../mol-model/structure'; +import { AccessibleSurfaceAreaProvider } from '../accessible-surface-area'; +import { AccessibleSurfaceArea } from '../accessible-surface-area/shrake-rupley'; +import { CustomProperty } from '../../common/custom-property'; import { Location } from '../../../mol-model/location'; -const DefaultColor = Color(0xFAFAFA) -const Description = 'Assigns a color based on the relative accessible surface area of a residue.' +const DefaultColor = Color(0xFAFAFA); +const Description = 'Assigns a color based on the relative accessible surface area of a residue.'; export const AccessibleSurfaceAreaColorThemeParams = { list: PD.ColorList('rainbow', { presetKind: 'scale' }) -} +}; export type AccessibleSurfaceAreaColorThemeParams = typeof AccessibleSurfaceAreaColorThemeParams export function getAccessibleSurfaceAreaColorThemeParams(ctx: ThemeDataContext) { - return AccessibleSurfaceAreaColorThemeParams // TODO return copy + return AccessibleSurfaceAreaColorThemeParams; // TODO return copy } export function AccessibleSurfaceAreaColorTheme(ctx: ThemeDataContext, props: PD.Values<AccessibleSurfaceAreaColorThemeParams>): ColorTheme<AccessibleSurfaceAreaColorThemeParams> { - let color: LocationColor + let color: LocationColor; const scale = ColorScale.create({ listOrName: props.list.colors, minLabel: 'buried', maxLabel: 'exposed', domain: [0.0, 1.0] - }) + }); - const accessibleSurfaceArea = ctx.structure && AccessibleSurfaceAreaProvider.get(ctx.structure) - const contextHash = accessibleSurfaceArea?.version + const accessibleSurfaceArea = ctx.structure && AccessibleSurfaceAreaProvider.get(ctx.structure); + const contextHash = accessibleSurfaceArea?.version; if (accessibleSurfaceArea?.value && ctx.structure) { - const asa = accessibleSurfaceArea.value + const asa = accessibleSurfaceArea.value; color = (location: Location): Color => { if (StructureElement.Location.is(location) && Unit.isAtomic(location.unit)) { - const value = AccessibleSurfaceArea.getNormalizedValue(location, asa) - return value === -1 ? DefaultColor : scale.color(value) + const value = AccessibleSurfaceArea.getNormalizedValue(location, asa); + return value === -1 ? DefaultColor : scale.color(value); } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -60,7 +60,7 @@ export function AccessibleSurfaceAreaColorTheme(ctx: ThemeDataContext, props: PD contextHash, description: Description, legend: scale ? scale.legend : undefined - } + }; } export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<AccessibleSurfaceAreaColorThemeParams, 'accessible-surface-area'> = { @@ -75,4 +75,4 @@ export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<Access attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? AccessibleSurfaceAreaProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(AccessibleSurfaceAreaProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/themes/interaction-type.ts b/src/mol-model-props/computed/themes/interaction-type.ts index a5cb1028a38a4d9d7bf26abadcd546a2a1ff7665..6718dd574668d27b794e7e4edb95e60d72874384 100644 --- a/src/mol-model-props/computed/themes/interaction-type.ts +++ b/src/mol-model-props/computed/themes/interaction-type.ts @@ -6,7 +6,7 @@ import { Location } from '../../../mol-model/location'; import { Color, ColorMap } from '../../../mol-util/color'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { InteractionsProvider } from '../interactions'; import { ThemeDataContext } from '../../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; @@ -15,8 +15,8 @@ import { TableLegend } from '../../../mol-util/legend'; import { Interactions } from '../interactions/interactions'; import { CustomProperty } from '../../common/custom-property'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Assigns colors according the interaction type of a link.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Assigns colors according the interaction type of a link.'; const InteractionTypeColors = ColorMap({ HydrogenBond: 0x2B83BA, @@ -27,7 +27,7 @@ const InteractionTypeColors = ColorMap({ CationPi: 0xFF8000, PiStacking: 0x8CB366, WeakHydrogenBond: 0xC5DDEC, -}) +}); const InteractionTypeColorTable: [string, Color][] = [ ['Hydrogen Bond', InteractionTypeColors.HydrogenBond], @@ -38,61 +38,61 @@ const InteractionTypeColorTable: [string, Color][] = [ ['Cation Pi', InteractionTypeColors.CationPi], ['Pi Stacking', InteractionTypeColors.PiStacking], ['Weak HydrogenBond', InteractionTypeColors.WeakHydrogenBond], -] +]; function typeColor(type: InteractionType): Color { switch (type) { case InteractionType.HydrogenBond: - return InteractionTypeColors.HydrogenBond + return InteractionTypeColors.HydrogenBond; case InteractionType.Hydrophobic: - return InteractionTypeColors.Hydrophobic + return InteractionTypeColors.Hydrophobic; case InteractionType.HalogenBond: - return InteractionTypeColors.HalogenBond + return InteractionTypeColors.HalogenBond; case InteractionType.Ionic: - return InteractionTypeColors.Ionic + return InteractionTypeColors.Ionic; case InteractionType.MetalCoordination: - return InteractionTypeColors.MetalCoordination + return InteractionTypeColors.MetalCoordination; case InteractionType.CationPi: - return InteractionTypeColors.CationPi + return InteractionTypeColors.CationPi; case InteractionType.PiStacking: - return InteractionTypeColors.PiStacking + return InteractionTypeColors.PiStacking; case InteractionType.WeakHydrogenBond: - return InteractionTypeColors.WeakHydrogenBond + return InteractionTypeColors.WeakHydrogenBond; case InteractionType.Unknown: - return DefaultColor + return DefaultColor; } } -export const InteractionTypeColorThemeParams = { } +export const InteractionTypeColorThemeParams = { }; export type InteractionTypeColorThemeParams = typeof InteractionTypeColorThemeParams export function getInteractionTypeColorThemeParams(ctx: ThemeDataContext) { - return InteractionTypeColorThemeParams // TODO return copy + return InteractionTypeColorThemeParams; // TODO return copy } export function InteractionTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<InteractionTypeColorThemeParams>): ColorTheme<InteractionTypeColorThemeParams> { - let color: LocationColor + let color: LocationColor; - const interactions = ctx.structure ? InteractionsProvider.get(ctx.structure) : undefined - const contextHash = interactions?.version + const interactions = ctx.structure ? InteractionsProvider.get(ctx.structure) : undefined; + const contextHash = interactions?.version; if (interactions && interactions.value) { color = (location: Location) => { if (Interactions.isLocation(location)) { - const { unitsContacts, contacts } = location.data.interactions - const { unitA, unitB, indexA, indexB } = location.element + const { unitsContacts, contacts } = location.data.interactions; + const { unitA, unitB, indexA, indexB } = location.element; if (unitA === unitB) { - const links = unitsContacts.get(unitA.id) - const idx = links.getDirectedEdgeIndex(indexA, indexB) - return typeColor(links.edgeProps.type[idx]) + const links = unitsContacts.get(unitA.id); + const idx = links.getDirectedEdgeIndex(indexA, indexB); + return typeColor(links.edgeProps.type[idx]); } else { - const idx = contacts.getEdgeIndex(indexA, unitA, indexB, unitB) - return typeColor(contacts.edges[idx].props.type) + const idx = contacts.getEdgeIndex(indexA, unitA, indexB, unitB); + return typeColor(contacts.edges[idx].props.type); } } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -103,7 +103,7 @@ export function InteractionTypeColorTheme(ctx: ThemeDataContext, props: PD.Value contextHash, description: Description, legend: TableLegend(InteractionTypeColorTable) - } + }; } export const InteractionTypeColorThemeProvider: ColorTheme.Provider<InteractionTypeColorThemeParams, 'interaction-type'> = { @@ -118,4 +118,4 @@ export const InteractionTypeColorThemeProvider: ColorTheme.Provider<InteractionT attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? InteractionsProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(InteractionsProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/computed/valence-model.ts b/src/mol-model-props/computed/valence-model.ts index 48d49036a2779583c7f51742d6f0a5c61dd3b5f5..d2994f593857b433db9c2fc8292d36c8939f32bd 100644 --- a/src/mol-model-props/computed/valence-model.ts +++ b/src/mol-model-props/computed/valence-model.ts @@ -12,7 +12,7 @@ import { CustomProperty } from '../common/custom-property'; export const ValenceModelParams = { ..._ValenceModelParams -} +}; export type ValenceModelParams = typeof ValenceModelParams export type ValenceModelProps = PD.Values<ValenceModelParams> @@ -29,7 +29,7 @@ export const ValenceModelProvider: CustomStructureProperty.Provider<ValenceModel getParams: (data: Structure) => ValenceModelParams, isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<ValenceModelProps>) => { - const p = { ...PD.getDefaultValues(ValenceModelParams), ...props } - return await calcValenceModel(ctx.runtime, data, p) + const p = { ...PD.getDefaultValues(ValenceModelParams), ...props }; + return await calcValenceModel(ctx.runtime, data, p); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/integrative/cross-link-restraint/color.ts b/src/mol-model-props/integrative/cross-link-restraint/color.ts index 62958cd04bb8d59fbf5477b0b50983122083b0fb..7fad48e5c2e10f27d02f3132629489f95b1b46a5 100644 --- a/src/mol-model-props/integrative/cross-link-restraint/color.ts +++ b/src/mol-model-props/integrative/cross-link-restraint/color.ts @@ -6,48 +6,48 @@ import { Color, ColorScale } from '../../../mol-util/color'; import { Location } from '../../../mol-model/location'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { ThemeDataContext } from '../../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; import { CustomProperty } from '../../common/custom-property'; import { CrossLinkRestraintProvider, CrossLinkRestraint } from './property'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Colors cross-links by the deviation of the observed distance versus the modeled distance (e.g. modeled / `ihm_cross_link_restraint.distance_threshold`).' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Colors cross-links by the deviation of the observed distance versus the modeled distance (e.g. modeled / `ihm_cross_link_restraint.distance_threshold`).'; export const CrossLinkColorThemeParams = { domain: PD.Interval([0.5, 1.5], { step: 0.01 }), list: PD.ColorList('red-grey', { presetKind: 'scale' }), -} +}; export type CrossLinkColorThemeParams = typeof CrossLinkColorThemeParams export function getCrossLinkColorThemeParams(ctx: ThemeDataContext) { - return CrossLinkColorThemeParams // TODO return copy + return CrossLinkColorThemeParams; // TODO return copy } export function CrossLinkColorTheme(ctx: ThemeDataContext, props: PD.Values<CrossLinkColorThemeParams>): ColorTheme<CrossLinkColorThemeParams> { - let color: LocationColor - let scale: ColorScale | undefined = undefined + let color: LocationColor; + let scale: ColorScale | undefined = undefined; - const crossLinkRestraints = ctx.structure && CrossLinkRestraintProvider.get(ctx.structure).value + const crossLinkRestraints = ctx.structure && CrossLinkRestraintProvider.get(ctx.structure).value; if (crossLinkRestraints) { scale = ColorScale.create({ domain: props.domain, listOrName: props.list.colors - }) - const scaleColor = scale.color + }); + const scaleColor = scale.color; color = (location: Location): Color => { if (CrossLinkRestraint.isLocation(location)) { - const pair = crossLinkRestraints.pairs[location.element] + const pair = crossLinkRestraints.pairs[location.element]; if (pair) { - return scaleColor(CrossLinkRestraint.distance(pair) / pair.distanceThreshold) + return scaleColor(CrossLinkRestraint.distance(pair) / pair.distanceThreshold); } } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -57,7 +57,7 @@ export function CrossLinkColorTheme(ctx: ThemeDataContext, props: PD.Values<Cros props, description: Description, legend: scale ? scale.legend : undefined - } + }; } export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThemeParams, 'cross-link'> = { @@ -72,4 +72,4 @@ export const CrossLinkColorThemeProvider: ColorTheme.Provider<CrossLinkColorThem attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? CrossLinkRestraintProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(CrossLinkRestraintProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/integrative/cross-link-restraint/format.ts b/src/mol-model-props/integrative/cross-link-restraint/format.ts index a4e9c0c738a9aaaace9628f3fcb4497e54892b43..b4e2704e3323abd4f22744d14fb5e3ae1f9eba08 100644 --- a/src/mol-model-props/integrative/cross-link-restraint/format.ts +++ b/src/mol-model-props/integrative/cross-link-restraint/format.ts @@ -4,14 +4,14 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Model } from '../../../mol-model/structure/model/model' -import { Table } from '../../../mol-data/db' +import { Model } from '../../../mol-model/structure/model/model'; +import { Table } from '../../../mol-data/db'; import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif'; import { Unit, CustomPropertyDescriptor } from '../../../mol-model/structure'; import { ElementIndex } from '../../../mol-model/structure/model/indexing'; import { FormatPropertyProvider } from '../../../mol-model-formats/structure/common/property'; -export { ModelCrossLinkRestraint } +export { ModelCrossLinkRestraint }; interface ModelCrossLinkRestraint { getIndicesByElement: (element: ElementIndex, kind: Unit.Kind) => number[] @@ -22,9 +22,9 @@ namespace ModelCrossLinkRestraint { export const Descriptor: CustomPropertyDescriptor = { name: 'ihm_cross_link_restraint', // TODO cifExport - } + }; - export const Provider = FormatPropertyProvider.create<ModelCrossLinkRestraint>(Descriptor) + export const Provider = FormatPropertyProvider.create<ModelCrossLinkRestraint>(Descriptor); export function fromTable(table: Table<mmCIF_Schema['ihm_cross_link_restraint']>, model: Model): ModelCrossLinkRestraint { @@ -33,25 +33,25 @@ namespace ModelCrossLinkRestraint { asym_id: table.asym_id_1, seq_id: table.seq_id_1, atom_id: table.atom_id_1, - } + }; const p2: typeof p1 = { entity_id: table.entity_id_2, asym_id: table.asym_id_2, seq_id: table.seq_id_2, atom_id: table.atom_id_2, - } + }; function _add(map: Map<ElementIndex, number[]>, element: ElementIndex, row: number) { - const indices = map.get(element) - if (indices) indices.push(row) - else map.set(element, [ row ]) + const indices = map.get(element); + if (indices) indices.push(row); + else map.set(element, [ row ]); } function add(row: number, ps: typeof p1) { - const entityId = ps.entity_id.value(row) - const asymId = ps.asym_id.value(row) - const seqId = ps.seq_id.value(row) + const entityId = ps.entity_id.value(row); + const asymId = ps.asym_id.value(row); + const seqId = ps.seq_id.value(row); if (table.model_granularity.value(row) === 'by-atom') { const atomicElement = model.atomicHierarchy.index.findAtom({ @@ -59,15 +59,15 @@ namespace ModelCrossLinkRestraint { label_asym_id: asymId, label_atom_id: ps.atom_id.value(row), label_entity_id: entityId, - }) - if (atomicElement >= 0) _add(atomicElementMap, atomicElement as ElementIndex, row) + }); + if (atomicElement >= 0) _add(atomicElementMap, atomicElement as ElementIndex, row); } else if (model.coarseHierarchy.isDefined) { - const sphereElement = model.coarseHierarchy.spheres.findSequenceKey(entityId, asymId, seqId) + const sphereElement = model.coarseHierarchy.spheres.findSequenceKey(entityId, asymId, seqId); if (sphereElement >= 0) { - _add(sphereElementMap, sphereElement, row) + _add(sphereElementMap, sphereElement, row); } else { - const gaussianElement = model.coarseHierarchy.gaussians.findSequenceKey(entityId, asymId, seqId) - if (gaussianElement >= 0) _add(gaussianElementMap, gaussianElement, row) + const gaussianElement = model.coarseHierarchy.gaussians.findSequenceKey(entityId, asymId, seqId); + if (gaussianElement >= 0) _add(gaussianElementMap, gaussianElement, row); } } } @@ -81,26 +81,26 @@ namespace ModelCrossLinkRestraint { } /** map from atomic element to cross link indices */ - const atomicElementMap: Map<ElementIndex, number[]> = new Map() + const atomicElementMap: Map<ElementIndex, number[]> = new Map(); /** map from sphere element to cross link indices */ - const sphereElementMap: Map<ElementIndex, number[]> = new Map() + const sphereElementMap: Map<ElementIndex, number[]> = new Map(); /** map from gaussian element to cross link indices */ - const gaussianElementMap: Map<ElementIndex, number[]> = new Map() + const gaussianElementMap: Map<ElementIndex, number[]> = new Map(); const emptyIndexArray: number[] = []; for (let i = 0; i < table._rowCount; ++i) { - add(i, p1) - add(i, p2) + add(i, p1); + add(i, p2); } return { getIndicesByElement: (element: ElementIndex, kind: Unit.Kind) => { - const map = getMapByKind(kind) - const idx = map.get(element) - return idx !== undefined ? idx : emptyIndexArray + const map = getMapByKind(kind); + const idx = map.get(element); + return idx !== undefined ? idx : emptyIndexArray; }, data: table - } + }; } } \ No newline at end of file diff --git a/src/mol-model-props/integrative/cross-link-restraint/property.ts b/src/mol-model-props/integrative/cross-link-restraint/property.ts index 5deb93896a949af60ea84b5774a24e7ccb183bb4..d68d94af5cf72126377f5813c4f579fd35fa2c99 100644 --- a/src/mol-model-props/integrative/cross-link-restraint/property.ts +++ b/src/mol-model-props/integrative/cross-link-restraint/property.ts @@ -29,11 +29,11 @@ export const CrossLinkRestraintProvider: CustomStructureProperty.Provider<{}, Cr getParams: (data: Structure) => ({}), isApplicable: (data: Structure) => data.models.some(m => !!ModelCrossLinkRestraint.Provider.get(m)), obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<{}>) => { - return extractCrossLinkRestraints(data) + return extractCrossLinkRestraints(data); } -}) +}); -export { CrossLinkRestraint } +export { CrossLinkRestraint }; interface CrossLinkRestraint extends PairRestraint { readonly restraintType: 'harmonic' | 'upper bound' | 'lower bound' @@ -49,14 +49,14 @@ namespace CrossLinkRestraint { } export function isApplicable(structure: Structure) { - return structure.models.some(m => !!ModelCrossLinkRestraint.Provider.get(m)) + return structure.models.some(m => !!ModelCrossLinkRestraint.Provider.get(m)); } - const distVecA = Vec3(), distVecB = Vec3() + const distVecA = Vec3(), distVecB = Vec3(); export function distance(pair: CrossLinkRestraint) { - pair.unitA.conformation.position(pair.unitA.elements[pair.indexA], distVecA) - pair.unitB.conformation.position(pair.unitB.elements[pair.indexB], distVecB) - return Vec3.distance(distVecA, distVecB) + pair.unitA.conformation.position(pair.unitA.elements[pair.indexA], distVecA); + pair.unitB.conformation.position(pair.unitB.elements[pair.indexB], distVecB); + return Vec3.distance(distVecA, distVecB); } type StructureCrossLinkRestraints = { readonly structure: Structure, readonly crossLinkRestraints: CrossLinkRestraintValue } @@ -77,16 +77,16 @@ namespace CrossLinkRestraint { locA.data.structure === locB.data.structure && locA.data.crossLinkRestraints === locB.data.crossLinkRestraints && locA.element === locB.element - ) + ); } function _label(crossLinkRestraints: CrossLinkRestraintValue, element: Element): string { - const p = crossLinkRestraints.pairs[element] - return `Cross Link Restraint | Type: ${p.restraintType} | Threshold: ${p.distanceThreshold} \u212B | Psi: ${p.psi} | Sigma 1: ${p.sigma1} | Sigma 2: ${p.sigma2} | Distance: ${distance(p).toFixed(2)} \u212B` + const p = crossLinkRestraints.pairs[element]; + return `Cross Link Restraint | Type: ${p.restraintType} | Threshold: ${p.distanceThreshold} \u212B | Psi: ${p.psi} | Sigma 1: ${p.sigma1} | Sigma 2: ${p.sigma2} | Distance: ${distance(p).toFixed(2)} \u212B`; } export function locationLabel(location: Location): string { - return _label(location.data.crossLinkRestraints, location.element) + return _label(location.data.crossLinkRestraints, location.element); } export interface Loci extends DataLoci<StructureCrossLinkRestraints, Element> { } @@ -103,20 +103,20 @@ namespace CrossLinkRestraint { export function getBoundingSphere(crossLinkRestraints: CrossLinkRestraintValue, elements: ReadonlyArray<Element>, boundingSphere: Sphere3D) { return CentroidHelper.fromPairProvider(elements.length, (i, pA, pB) => { - const p = crossLinkRestraints.pairs[elements[i]] - p.unitA.conformation.position(p.unitA.elements[p.indexA], pA) - p.unitB.conformation.position(p.unitB.elements[p.indexB], pB) - }, boundingSphere) + const p = crossLinkRestraints.pairs[elements[i]]; + p.unitA.conformation.position(p.unitA.elements[p.indexA], pA); + p.unitB.conformation.position(p.unitB.elements[p.indexB], pB); + }, boundingSphere); } export function getLabel(structure: Structure, crossLinkRestraints: CrossLinkRestraintValue, elements: ReadonlyArray<Element>) { - const element = elements[0] - if (element === undefined) return '' - const p = crossLinkRestraints.pairs[element] + const element = elements[0]; + if (element === undefined) return ''; + const p = crossLinkRestraints.pairs[element]; return [ _label(crossLinkRestraints, element), bondLabel(Bond.Location(structure, p.unitA, p.indexA, structure, p.unitB, p.indexB)) - ].join('</br>') + ].join('</br>'); } } @@ -125,66 +125,66 @@ namespace CrossLinkRestraint { function _addRestraints(map: Map<number, number>, unit: Unit, restraints: ModelCrossLinkRestraint) { const { elements } = unit; const elementCount = elements.length; - const kind = unit.kind + const kind = unit.kind; for (let i = 0; i < elementCount; i++) { const e = elements[i]; - restraints.getIndicesByElement(e, kind).forEach(ri => map.set(ri, i)) + restraints.getIndicesByElement(e, kind).forEach(ri => map.set(ri, i)); } } function extractInter(pairs: CrossLinkRestraint[], unitA: Unit, unitB: Unit) { - if (unitA.model !== unitB.model) return - if (unitA.model.sourceData.kind !== 'mmCIF') return + if (unitA.model !== unitB.model) return; + if (unitA.model.sourceData.kind !== 'mmCIF') return; - const restraints = ModelCrossLinkRestraint.Provider.get(unitA.model) - if (!restraints) return + const restraints = ModelCrossLinkRestraint.Provider.get(unitA.model); + if (!restraints) return; const rA = new Map<number, StructureElement.UnitIndex>(); const rB = new Map<number, StructureElement.UnitIndex>(); - _addRestraints(rA, unitA, restraints) - _addRestraints(rB, unitB, restraints) + _addRestraints(rA, unitA, restraints); + _addRestraints(rB, unitB, restraints); rA.forEach((indexA, ri) => { - const indexB = rB.get(ri) + const indexB = rB.get(ri); if (indexB !== undefined) { pairs.push( createCrossLinkRestraint(unitA, indexA, unitB, indexB, restraints, ri), createCrossLinkRestraint(unitB, indexB, unitA, indexA, restraints, ri) - ) + ); } - }) + }); } function extractIntra(pairs: CrossLinkRestraint[], unit: Unit) { - if (unit.model.sourceData.kind !== 'mmCIF') return + if (unit.model.sourceData.kind !== 'mmCIF') return; - const restraints = ModelCrossLinkRestraint.Provider.get(unit.model) - if (!restraints) return + const restraints = ModelCrossLinkRestraint.Provider.get(unit.model); + if (!restraints) return; const { elements } = unit; const elementCount = elements.length; - const kind = unit.kind + const kind = unit.kind; const r = new Map<number, StructureElement.UnitIndex[]>(); for (let i = 0; i < elementCount; i++) { const e = elements[i]; restraints.getIndicesByElement(e, kind).forEach(ri => { - const il = r.get(ri) - if (il) il.push(i as StructureElement.UnitIndex) - else r.set(ri, [i as StructureElement.UnitIndex]) - }) + const il = r.get(ri); + if (il) il.push(i as StructureElement.UnitIndex); + else r.set(ri, [i as StructureElement.UnitIndex]); + }); } r.forEach((il, ri) => { - if (il.length < 2) return - const [ indexA, indexB ] = il + if (il.length < 2) return; + const [ indexA, indexB ] = il; pairs.push( createCrossLinkRestraint(unit, indexA, unit, indexB, restraints, ri), createCrossLinkRestraint(unit, indexB, unit, indexA, restraints, ri) - ) - }) + ); + }); } function createCrossLinkRestraint(unitA: Unit, indexA: StructureElement.UnitIndex, unitB: Unit, indexB: StructureElement.UnitIndex, restraints: ModelCrossLinkRestraint, row: number): CrossLinkRestraint { @@ -196,26 +196,26 @@ function createCrossLinkRestraint(unitA: Unit, indexA: StructureElement.UnitInde psi: restraints.data.psi.value(row), sigma1: restraints.data.sigma_1.value(row), sigma2: restraints.data.sigma_2.value(row), - } + }; } function extractCrossLinkRestraints(structure: Structure): PairRestraints<CrossLinkRestraint> { - const pairs: CrossLinkRestraint[] = [] + const pairs: CrossLinkRestraint[] = []; if (!structure.models.some(m => ModelCrossLinkRestraint.Provider.get(m))) { - return new PairRestraints(pairs) + return new PairRestraints(pairs); } - const n = structure.units.length + const n = structure.units.length; for (let i = 0; i < n; ++i) { - const unitA = structure.units[i] - extractIntra(pairs, unitA) + const unitA = structure.units[i]; + extractIntra(pairs, unitA); for (let j = i + 1; j < n; ++j) { - const unitB = structure.units[j] + const unitB = structure.units[j]; if (unitA.model === unitB.model) { - extractInter(pairs, unitA, unitB) + extractInter(pairs, unitA, unitB); } } } - return new PairRestraints(pairs) + return new PairRestraints(pairs); } \ No newline at end of file diff --git a/src/mol-model-props/integrative/cross-link-restraint/representation.ts b/src/mol-model-props/integrative/cross-link-restraint/representation.ts index 12cdbbfefb61672b49d030f91e58c5aab1f074a1..d3a890e9ec01a8c16abcbcef983e6cdb38c9c454 100644 --- a/src/mol-model-props/integrative/cross-link-restraint/representation.ts +++ b/src/mol-model-props/integrative/cross-link-restraint/representation.ts @@ -25,36 +25,36 @@ import { CrossLinkRestraintProvider, CrossLinkRestraint } from './property'; function createCrossLinkRestraintCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CrossLinkRestraintCylinderParams>, mesh?: Mesh) { - const crossLinks = CrossLinkRestraintProvider.get(structure).value! - if (!crossLinks.count) return Mesh.createEmpty(mesh) - const { sizeFactor } = props + const crossLinks = CrossLinkRestraintProvider.get(structure).value!; + if (!crossLinks.count) return Mesh.createEmpty(mesh); + const { sizeFactor } = props; - const location = StructureElement.Location.create(structure) + const location = StructureElement.Location.create(structure); const builderProps = { linkCount: crossLinks.count, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - const b = crossLinks.pairs[edgeIndex] - const uA = b.unitA, uB = b.unitB - uA.conformation.position(uA.elements[b.indexA], posA) - uB.conformation.position(uB.elements[b.indexB], posB) + const b = crossLinks.pairs[edgeIndex]; + const uA = b.unitA, uB = b.unitB; + uA.conformation.position(uA.elements[b.indexA], posA); + uB.conformation.position(uB.elements[b.indexB], posB); }, radius: (edgeIndex: number) => { - const b = crossLinks.pairs[edgeIndex] - location.unit = b.unitA - location.element = b.unitA.elements[b.indexA] - return theme.size.size(location) * sizeFactor + const b = crossLinks.pairs[edgeIndex]; + location.unit = b.unitA; + location.element = b.unitA.elements[b.indexA]; + return theme.size.size(location) * sizeFactor; }, - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const CrossLinkRestraintCylinderParams = { ...ComplexMeshParams, ...LinkCylinderParams, sizeFactor: PD.Numeric(0.5, { min: 0, max: 10, step: 0.1 }), -} +}; export type CrossLinkRestraintCylinderParams = typeof CrossLinkRestraintCylinderParams export function CrossLinkRestraintVisual(materialId: number): ComplexVisual<CrossLinkRestraintCylinderParams> { @@ -69,67 +69,67 @@ export function CrossLinkRestraintVisual(materialId: number): ComplexVisual<Cros newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments || newProps.linkCap !== currentProps.linkCap - ) + ); } - }, materialId) + }, materialId); } function createCrossLinkRestraintIterator(structure: Structure): LocationIterator { - const crossLinkRestraints = CrossLinkRestraintProvider.get(structure).value! - const { pairs } = crossLinkRestraints - const groupCount = pairs.length - const instanceCount = 1 - const location = CrossLinkRestraint.Location(crossLinkRestraints, structure) + const crossLinkRestraints = CrossLinkRestraintProvider.get(structure).value!; + const { pairs } = crossLinkRestraints; + const groupCount = pairs.length; + const instanceCount = 1; + const location = CrossLinkRestraint.Location(crossLinkRestraints, structure); const getLocation = (groupIndex: number) => { - location.element = groupIndex - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + location.element = groupIndex; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const crossLinkRestraints = CrossLinkRestraintProvider.get(structure).value! - const pair = crossLinkRestraints.pairs[groupId] + const crossLinkRestraints = CrossLinkRestraintProvider.get(structure).value!; + const pair = crossLinkRestraints.pairs[groupId]; if (pair) { - return CrossLinkRestraint.Loci(structure, crossLinkRestraints, [groupId]) + return CrossLinkRestraint.Loci(structure, crossLinkRestraints, [groupId]); } } - return EmptyLoci + return EmptyLoci; } function eachCrossLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; if (CrossLinkRestraint.isLoci(loci)) { - if (!Structure.areEquivalent(loci.data.structure, structure)) return false - const crossLinkRestraints = CrossLinkRestraintProvider.get(structure).value! - if (loci.data.crossLinkRestraints !== crossLinkRestraints) return false + if (!Structure.areEquivalent(loci.data.structure, structure)) return false; + const crossLinkRestraints = CrossLinkRestraintProvider.get(structure).value!; + if (loci.data.crossLinkRestraints !== crossLinkRestraints) return false; for (const e of loci.elements) { - if (apply(Interval.ofSingleton(e))) changed = true + if (apply(Interval.ofSingleton(e))) changed = true; } } - return changed + return changed; } // const CrossLinkRestraintVisuals = { 'cross-link-restraint': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CrossLinkRestraintCylinderParams>) => ComplexRepresentation('Cross-link restraint', ctx, getParams, CrossLinkRestraintVisual), -} +}; export const CrossLinkRestraintParams = { ...CrossLinkRestraintCylinderParams, -} +}; export type CrossLinkRestraintParams = typeof CrossLinkRestraintParams export function getCrossLinkRestraintParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(CrossLinkRestraintParams) + return PD.clone(CrossLinkRestraintParams); } export type CrossLinkRestraintRepresentation = StructureRepresentation<CrossLinkRestraintParams> export function CrossLinkRestraintRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CrossLinkRestraintParams>): CrossLinkRestraintRepresentation { - return Representation.createMulti('CrossLinkRestraint', ctx, getParams, StructureRepresentationStateBuilder, CrossLinkRestraintVisuals as unknown as Representation.Def<Structure, CrossLinkRestraintParams>) + return Representation.createMulti('CrossLinkRestraint', ctx, getParams, StructureRepresentationStateBuilder, CrossLinkRestraintVisuals as unknown as Representation.Def<Structure, CrossLinkRestraintParams>); } export const CrossLinkRestraintRepresentationProvider = StructureRepresentationProvider({ @@ -146,4 +146,4 @@ export const CrossLinkRestraintRepresentationProvider = StructureRepresentationP attach: (ctx: CustomProperty.Context, structure: Structure) => CrossLinkRestraintProvider.attach(ctx, structure, void 0, true), detach: (data) => CrossLinkRestraintProvider.ref(data, false) } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/integrative/pair-restraints.ts b/src/mol-model-props/integrative/pair-restraints.ts index 7a74a4412957f165d44893263ec4a01082894c01..82724c787909bae1ff54c0d4b890f1529161ccc9 100644 --- a/src/mol-model-props/integrative/pair-restraints.ts +++ b/src/mol-model-props/integrative/pair-restraints.ts @@ -6,7 +6,7 @@ import { StructureElement, Unit } from '../../mol-model/structure'; -const emptyArray: number[] = [] +const emptyArray: number[] = []; export interface PairRestraint { readonly unitA: Unit, @@ -16,7 +16,7 @@ export interface PairRestraint { } function getPairKey(indexA: StructureElement.UnitIndex, unitA: Unit, indexB: StructureElement.UnitIndex, unitB: Unit) { - return `${indexA}|${unitA.id}|${indexB}|${unitB.id}` + return `${indexA}|${unitA.id}|${indexB}|${unitB.id}`; } export class PairRestraints<T extends PairRestraint> { @@ -25,25 +25,25 @@ export class PairRestraints<T extends PairRestraint> { /** Indices into this.pairs */ getPairIndices(indexA: StructureElement.UnitIndex, unitA: Unit, indexB: StructureElement.UnitIndex, unitB: Unit): ReadonlyArray<number> { - const key = getPairKey(indexA, unitA, indexB, unitB) - return this.pairKeyIndices.get(key) || emptyArray + const key = getPairKey(indexA, unitA, indexB, unitB); + return this.pairKeyIndices.get(key) || emptyArray; } getPairs(indexA: StructureElement.UnitIndex, unitA: Unit, indexB: StructureElement.UnitIndex, unitB: Unit): T[] { - const indices = this.getPairIndices(indexA, unitA, indexB, unitB) - return indices.map(idx => this.pairs[idx]) + const indices = this.getPairIndices(indexA, unitA, indexB, unitB); + return indices.map(idx => this.pairs[idx]); } constructor(public pairs: ReadonlyArray<T>) { - const pairKeyIndices = new Map<string, number[]>() + const pairKeyIndices = new Map<string, number[]>(); this.pairs.forEach((p, i) => { - const key = getPairKey(p.indexA, p.unitA, p.indexB, p.unitB) - const indices = pairKeyIndices.get(key) - if (indices) indices.push(i) - else pairKeyIndices.set(key, [i]) - }) - - this.count = pairs.length - this.pairKeyIndices = pairKeyIndices + const key = getPairKey(p.indexA, p.unitA, p.indexB, p.unitB); + const indices = pairKeyIndices.get(key); + if (indices) indices.push(i); + else pairKeyIndices.set(key, [i]); + }); + + this.count = pairs.length; + this.pairKeyIndices = pairKeyIndices; } } \ No newline at end of file diff --git a/src/mol-model-props/pdbe/preferred-assembly.ts b/src/mol-model-props/pdbe/preferred-assembly.ts index ebc7fb081c24c9e50396450f84618f0a06a09b99..52a2d3c3218cb7e82f803bce135ed94f1ceb5da7 100644 --- a/src/mol-model-props/pdbe/preferred-assembly.ts +++ b/src/mol-model-props/pdbe/preferred-assembly.ts @@ -15,7 +15,7 @@ export namespace PDBePreferredAssembly { export type Property = string export function getFirstFromModel(model: Model): Property { - const symmetry = ModelSymmetry.Provider.get(model) + const symmetry = ModelSymmetry.Provider.get(model); return symmetry?.assemblies.length ? symmetry.assemblies[0].id : ''; } diff --git a/src/mol-model-props/pdbe/struct-ref-domain.ts b/src/mol-model-props/pdbe/struct-ref-domain.ts index db37fee7e8412b3d06e7f5e587aea9822483ebe9..d82e24d84561296ef5fa5b0abda56e891ea864b2 100644 --- a/src/mol-model-props/pdbe/struct-ref-domain.ts +++ b/src/mol-model-props/pdbe/struct-ref-domain.ts @@ -111,7 +111,7 @@ function fromPDBeJson(modelData: Model, data: any): PDBeStructRefDomain.Property beg_pdbx_PDB_ins_code: map.start.author_insertion_code, end_label_seq_id: map.end.residue_number, end_pdbx_PDB_ins_code: map.end.author_insertion_code, - }) + }); } } } diff --git a/src/mol-model-props/pdbe/structure-quality-report.ts b/src/mol-model-props/pdbe/structure-quality-report.ts index 1950f925299c9d2e8f684e5831dbefe1f36e870c..f779bf157e67c3e3a3bf097159b200e184738d21 100644 --- a/src/mol-model-props/pdbe/structure-quality-report.ts +++ b/src/mol-model-props/pdbe/structure-quality-report.ts @@ -17,12 +17,12 @@ import Type from '../../mol-script/language/type'; import { QuerySymbolRuntime } from '../../mol-script/runtime/query/compiler'; import { PropertyWrapper } from '../common/wrapper'; import { CustomModelProperty } from '../common/custom-model-property'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { CustomProperty } from '../common/custom-property'; import { arraySetAdd } from '../../mol-util/array'; import { MmcifFormat } from '../../mol-model-formats/structure/mmcif'; -export { StructureQualityReport } +export { StructureQualityReport }; type StructureQualityReport = PropertyWrapper<{ issues: IndexedCustomProperty.Residue<string[]>, @@ -30,9 +30,9 @@ type StructureQualityReport = PropertyWrapper<{ }| undefined> namespace StructureQualityReport { - export const DefaultServerUrl = 'https://www.ebi.ac.uk/pdbe/api/validation/residuewise_outlier_summary/entry/' + export const DefaultServerUrl = 'https://www.ebi.ac.uk/pdbe/api/validation/residuewise_outlier_summary/entry/'; export function getEntryUrl(pdbId: string, serverUrl: string) { - return `${serverUrl}/${pdbId.toLowerCase()}` + return `${serverUrl}/${pdbId.toLowerCase()}`; } export function isApplicable(model?: Model): boolean { @@ -41,7 +41,7 @@ namespace StructureQualityReport { MmcifFormat.is(model.sourceData) && (model.sourceData.data.db.database_2.database_id.isDefined || model.entryId.length === 4) - ) + ); } export const Schema = { @@ -64,27 +64,27 @@ namespace StructureQualityReport { export function fromJson(model: Model, data: any) { const info = PropertyWrapper.createInfo(); const issueMap = createIssueMapFromJson(model, data); - return { info, data: issueMap } + return { info, data: issueMap }; } export async function fromServer(ctx: CustomProperty.Context, model: Model, props: StructureQualityReportProps): Promise<StructureQualityReport> { - const url = getEntryUrl(model.entryId, props.serverUrl) - const json = await ctx.fetch({ url, type: 'json' }).runInContext(ctx.runtime) + const url = getEntryUrl(model.entryId, props.serverUrl); + const json = await ctx.fetch({ url, type: 'json' }).runInContext(ctx.runtime); const data = json[model.entryId.toLowerCase()]; if (!data) throw new Error('missing data'); - return fromJson(model, data) + return fromJson(model, data); } export function fromCif(ctx: CustomProperty.Context, model: Model, props: StructureQualityReportProps): StructureQualityReport | undefined { let info = PropertyWrapper.tryGetInfoFromCif('pdbe_structure_quality_report', model); - if (!info) return + if (!info) return; const data = getCifData(model); const issueMap = createIssueMapFromCif(model, data.residues, data.groups); - return { info, data: issueMap } + return { info, data: issueMap }; } export async function fromCifOrServer(ctx: CustomProperty.Context, model: Model, props: StructureQualityReportProps): Promise<StructureQualityReport> { - return fromCif(ctx, model, props) || fromServer(ctx, model, props) + return fromCif(ctx, model, props) || fromServer(ctx, model, props); } const _emptyArray: string[] = []; @@ -108,13 +108,13 @@ namespace StructureQualityReport { return { residues: toTable(Schema.pdbe_structure_quality_report_issues, model.sourceData.data.frame.categories.pdbe_structure_quality_report_issues), groups: toTable(Schema.pdbe_structure_quality_report_issue_types, model.sourceData.data.frame.categories.pdbe_structure_quality_report_issue_types), - } + }; } } export const StructureQualityReportParams = { serverUrl: PD.Text(StructureQualityReport.DefaultServerUrl, { description: 'JSON API Server URL' }) -} +}; export type StructureQualityReportParams = typeof StructureQualityReportParams export type StructureQualityReportProps = PD.Values<StructureQualityReportParams> @@ -135,7 +135,7 @@ export const StructureQualityReportProvider: CustomModelProperty.Provider<Struct return { fields: _structure_quality_report_issues_fields, source: ctx.models.map(data => ({ data, rowCount: data.elements.length })) - } + }; } }, { name: 'pdbe_structure_quality_report_issue_types', @@ -155,10 +155,10 @@ export const StructureQualityReportProvider: CustomModelProperty.Provider<Struct getParams: (data: Model) => StructureQualityReportParams, isApplicable: (data: Model) => StructureQualityReport.isApplicable(data), obtain: async (ctx: CustomProperty.Context, data: Model, props: Partial<StructureQualityReportProps>) => { - const p = { ...PD.getDefaultValues(StructureQualityReportParams), ...props } - return await StructureQualityReport.fromCifOrServer(ctx, data, p) + const p = { ...PD.getDefaultValues(StructureQualityReportParams), ...props }; + return await StructureQualityReport.fromCifOrServer(ctx, data, p); } -}) +}); const _structure_quality_report_issues_fields = CifWriter.fields<number, ReportExportContext['models'][0]>() .index('id') @@ -210,7 +210,7 @@ function createExportContext(ctx: CifExportContext): ReportExportContext { info, models, issueTypes: Table.ofArrays(StructureQualityReport.Schema.pdbe_structure_quality_report_issue_types, { group_id, issue_type }) - } + }; } function createIssueMapFromJson(modelData: Model, data: any): StructureQualityReport['data'] | undefined { @@ -266,7 +266,7 @@ function createIssueMapFromCif(modelData: Model, for (const t of issues) { arraySetAdd(issueTypes, t); } - }) + }); return { issues: IndexedCustomProperty.fromResidueMap(ret), diff --git a/src/mol-model-props/pdbe/themes/structure-quality-report.ts b/src/mol-model-props/pdbe/themes/structure-quality-report.ts index 930739b5de1b459b87210d9f5fa28d3dd8d10ad0..c021d6810ae6145858c99673e3f56bb375a02b09 100644 --- a/src/mol-model-props/pdbe/themes/structure-quality-report.ts +++ b/src/mol-model-props/pdbe/themes/structure-quality-report.ts @@ -20,7 +20,7 @@ const ValidationColors = [ Color.fromRgb(255, 255, 0), // 1 Color.fromRgb(255, 128, 0), // 2 Color.fromRgb(255, 0, 0), // 3 or more -] +]; const ValidationColorTable: [string, Color][] = [ ['No Issues', ValidationColors[1]], @@ -28,7 +28,7 @@ const ValidationColorTable: [string, Color][] = [ ['Two Issues', ValidationColors[3]], ['Three Or More Issues', ValidationColors[4]], ['Not Applicable', ValidationColors[9]] -] +]; export const StructureQualityReportColorThemeParams = { type: PD.MappedStatic('issue-count', { @@ -42,7 +42,7 @@ export const StructureQualityReportColorThemeParams = { type Params = typeof StructureQualityReportColorThemeParams export function StructureQualityReportColorTheme(ctx: ThemeDataContext, props: PD.Values<Params>): ColorTheme<Params> { - let color: LocationColor + let color: LocationColor; if (ctx.structure && !ctx.structure.isEmpty && ctx.structure.models[0].customProperties.has(StructureQualityReportProvider.descriptor)) { const getIssues = StructureQualityReport.getIssues; @@ -53,7 +53,7 @@ export function StructureQualityReportColorTheme(ctx: ThemeDataContext, props: P return ValidationColors[Math.min(3, getIssues(location).length) + 1]; } return ValidationColors[0]; - } + }; } else { const issue = props.type.params.kind; color = (location: Location) => { @@ -61,7 +61,7 @@ export function StructureQualityReportColorTheme(ctx: ThemeDataContext, props: P return ValidationColors[4]; } return ValidationColors[0]; - } + }; } } else { color = () => ValidationColors[0]; @@ -74,7 +74,7 @@ export function StructureQualityReportColorTheme(ctx: ThemeDataContext, props: P props: props, description: 'Assigns residue colors according to the number of quality issues or a specific quality issue. Data from wwPDB Validation Report, obtained via PDBe.', legend: TableLegend(ValidationColorTable) - } + }; } export const StructureQualityReportColorThemeProvider: ColorTheme.Provider<Params, 'pdbe-structure-quality-report'> = { @@ -107,4 +107,4 @@ export const StructureQualityReportColorThemeProvider: ColorTheme.Provider<Param attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? StructureQualityReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.models[0].customProperties.reference(StructureQualityReportProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/rcsb/assembly-symmetry.ts b/src/mol-model-props/rcsb/assembly-symmetry.ts index cfcabec150049365c2576535cf1f9d15699b1a67..d6f985984e45a364e16ed7fde5997b5cbb78532d 100644 --- a/src/mol-model-props/rcsb/assembly-symmetry.ts +++ b/src/mol-model-props/rcsb/assembly-symmetry.ts @@ -7,9 +7,9 @@ import { AssemblySymmetryQuery, AssemblySymmetryQueryVariables } from './graphql/types'; import query from './graphql/symmetry.gql'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { CustomPropertyDescriptor, Structure, Model, StructureSelection, QueryContext } from '../../mol-model/structure'; -import { Database as _Database, Column } from '../../mol-data/db' +import { Database as _Database, Column } from '../../mol-data/db'; import { GraphQLClient } from '../../mol-util/graphql-client'; import { CustomProperty } from '../common/custom-property'; import { NonNullableArray } from '../../mol-util/type-helpers'; @@ -27,18 +27,18 @@ const BiologicalAssemblyNames = new Set([ 'complete point assembly', 'representative helical assembly', 'software_defined_assembly' -]) +]); export function isBiologicalAssembly(structure: Structure): boolean { - if (!MmcifFormat.is(structure.models[0].sourceData)) return false - const mmcif = structure.models[0].sourceData.data.db - if (!mmcif.pdbx_struct_assembly.details.isDefined) return false - const id = structure.units[0].conformation.operator.assembly?.id || '' - if (id === '' || id === 'deposited') return true - const indices = Column.indicesOf(mmcif.pdbx_struct_assembly.id, e => e === id) - if (indices.length !== 1) return false - const details = mmcif.pdbx_struct_assembly.details.value(indices[0]) - return BiologicalAssemblyNames.has(details) + if (!MmcifFormat.is(structure.models[0].sourceData)) return false; + const mmcif = structure.models[0].sourceData.data.db; + if (!mmcif.pdbx_struct_assembly.details.isDefined) return false; + const id = structure.units[0].conformation.operator.assembly?.id || ''; + if (id === '' || id === 'deposited') return true; + const indices = Column.indicesOf(mmcif.pdbx_struct_assembly.id, e => e === id); + if (indices.length !== 1) return false; + const details = mmcif.pdbx_struct_assembly.details.value(indices[0]); + return BiologicalAssemblyNames.has(details); } export namespace AssemblySymmetry { @@ -47,55 +47,55 @@ export namespace AssemblySymmetry { Representation = 'rcsb-assembly-symmetry-3d' } - export const DefaultServerUrl = 'https://data.rcsb.org/graphql' + export const DefaultServerUrl = 'https://data.rcsb.org/graphql'; export function isApplicable(structure?: Structure): boolean { return ( !!structure && structure.models.length === 1 && Model.isFromPdbArchive(structure.models[0]) && isBiologicalAssembly(structure) - ) + ); } export async function fetch(ctx: CustomProperty.Context, structure: Structure, props: AssemblySymmetryDataProps): Promise<AssemblySymmetryDataValue> { - if (!isApplicable(structure)) return [] + if (!isApplicable(structure)) return []; - const client = new GraphQLClient(props.serverUrl, ctx.fetch) + const client = new GraphQLClient(props.serverUrl, ctx.fetch); const variables: AssemblySymmetryQueryVariables = { assembly_id: structure.units[0].conformation.operator.assembly?.id || 'deposited', entry_id: structure.units[0].model.entryId - } - const result = await client.request<AssemblySymmetryQuery>(ctx.runtime, query, variables) + }; + const result = await client.request<AssemblySymmetryQuery>(ctx.runtime, query, variables); if (!result.assembly?.rcsb_struct_symmetry) { - console.error('expected `rcsb_struct_symmetry` field') - return [] + console.error('expected `rcsb_struct_symmetry` field'); + return []; } - return result.assembly.rcsb_struct_symmetry as AssemblySymmetryDataValue + return result.assembly.rcsb_struct_symmetry as AssemblySymmetryDataValue; } /** Returns the index of the first non C1 symmetry or -1 */ export function firstNonC1(assemblySymmetryData: AssemblySymmetryDataValue) { for (let i = 0, il = assemblySymmetryData.length; i < il; ++i) { - if (assemblySymmetryData[i].symbol !== 'C1') return i + if (assemblySymmetryData[i].symbol !== 'C1') return i; } - return -1 + return -1; } export type RotationAxes = ReadonlyArray<{ order: number, start: ReadonlyVec3, end: ReadonlyVec3 }> export function isRotationAxes(x: AssemblySymmetryValue['rotation_axes']): x is RotationAxes { - return !!x && x.length > 0 + return !!x && x.length > 0; } export function getAsymIds(assemblySymmetry: AssemblySymmetryValue) { - const asymIds = new Set<string>() + const asymIds = new Set<string>(); for (const c of assemblySymmetry.clusters) { - if (!c?.members) continue + if (!c?.members) continue; for (const m of c.members) { - if (m?.asym_id) asymIds.add(m.asym_id) + if (m?.asym_id) asymIds.add(m.asym_id); } } - return SetUtils.toArray(asymIds) + return SetUtils.toArray(asymIds); } function getAsymIdsStructure(structure: Structure, asymIds: string[]) { @@ -103,45 +103,45 @@ export namespace AssemblySymmetry { MS.struct.generator.atomGroups({ 'chain-test': MS.core.set.has([MS.set(...asymIds), MS.ammp('label_asym_id')]) }) - ]) - const compiled = compile<StructureSelection>(query) - const result = compiled(new QueryContext(structure)) - return StructureSelection.unionStructure(result) + ]); + const compiled = compile<StructureSelection>(query); + const result = compiled(new QueryContext(structure)); + return StructureSelection.unionStructure(result); } /** Returns structure limited to all cluster member chains */ export function getStructure(structure: Structure, assemblySymmetry: AssemblySymmetryValue) { - const asymIds = AssemblySymmetry.getAsymIds(assemblySymmetry) - return asymIds.length > 0 ? getAsymIdsStructure(structure, asymIds) : structure + const asymIds = AssemblySymmetry.getAsymIds(assemblySymmetry); + return asymIds.length > 0 ? getAsymIdsStructure(structure, asymIds) : structure; } } export function getSymmetrySelectParam(structure?: Structure) { - const param = PD.Select<number>(0, [[0, 'First Symmetry']]) + const param = PD.Select<number>(0, [[0, 'First Symmetry']]); if (structure) { - const assemblySymmetryData = AssemblySymmetryDataProvider.get(structure).value + const assemblySymmetryData = AssemblySymmetryDataProvider.get(structure).value; if (assemblySymmetryData) { - const options: [number, string][] = [] + const options: [number, string][] = []; for (let i = 0, il = assemblySymmetryData.length; i < il; ++i) { - const { symbol, kind } = assemblySymmetryData[i] + const { symbol, kind } = assemblySymmetryData[i]; if (symbol !== 'C1') { - options.push([ i, `${i + 1}: ${symbol} ${kind}` ]) + options.push([ i, `${i + 1}: ${symbol} ${kind}` ]); } } if (options.length) { - param.options = options - param.defaultValue = options[0][0] + param.options = options; + param.defaultValue = options[0][0]; } } } - return param + return param; } // export const AssemblySymmetryDataParams = { serverUrl: PD.Text(AssemblySymmetry.DefaultServerUrl, { description: 'GraphQL endpoint URL' }) -} +}; export type AssemblySymmetryDataParams = typeof AssemblySymmetryDataParams export type AssemblySymmetryDataProps = PD.Values<AssemblySymmetryDataParams> @@ -158,10 +158,10 @@ export const AssemblySymmetryDataProvider: CustomStructureProperty.Provider<Asse getParams: (data: Structure) => AssemblySymmetryDataParams, isApplicable: (data: Structure) => AssemblySymmetry.isApplicable(data), obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<AssemblySymmetryDataProps>) => { - const p = { ...PD.getDefaultValues(AssemblySymmetryDataParams), ...props } - return await AssemblySymmetry.fetch(ctx, data, p) + const p = { ...PD.getDefaultValues(AssemblySymmetryDataParams), ...props }; + return await AssemblySymmetry.fetch(ctx, data, p); } -}) +}); // @@ -169,10 +169,10 @@ function getAssemblySymmetryParams(data?: Structure) { return { ... AssemblySymmetryDataParams, symmetryIndex: getSymmetrySelectParam(data) - } + }; } -export const AssemblySymmetryParams = getAssemblySymmetryParams() +export const AssemblySymmetryParams = getAssemblySymmetryParams(); export type AssemblySymmetryParams = typeof AssemblySymmetryParams export type AssemblySymmetryProps = PD.Values<AssemblySymmetryParams> @@ -189,11 +189,11 @@ export const AssemblySymmetryProvider: CustomStructureProperty.Provider<Assembly getParams: getAssemblySymmetryParams, isApplicable: (data: Structure) => AssemblySymmetry.isApplicable(data), obtain: async (ctx: CustomProperty.Context, data: Structure, props: Partial<AssemblySymmetryProps>) => { - const p = { ...PD.getDefaultValues(getAssemblySymmetryParams(data)), ...props } - await AssemblySymmetryDataProvider.attach(ctx, data, p) - const assemblySymmetryData = AssemblySymmetryDataProvider.get(data).value - const assemblySymmetry = assemblySymmetryData?.[p.symmetryIndex] - if (!assemblySymmetry) new Error(`No assembly symmetry found for index ${p.symmetryIndex}`) - return assemblySymmetry + const p = { ...PD.getDefaultValues(getAssemblySymmetryParams(data)), ...props }; + await AssemblySymmetryDataProvider.attach(ctx, data, p); + const assemblySymmetryData = AssemblySymmetryDataProvider.get(data).value; + const assemblySymmetry = assemblySymmetryData?.[p.symmetryIndex]; + if (!assemblySymmetry) new Error(`No assembly symmetry found for index ${p.symmetryIndex}`); + return assemblySymmetry; } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/rcsb/graphql/symmetry.gql.ts b/src/mol-model-props/rcsb/graphql/symmetry.gql.ts index 7980557163cf18d2b970be0ab0ceec172273e6ac..f127ba20a6456c32304b68e3f6a89b50d1b44afc 100644 --- a/src/mol-model-props/rcsb/graphql/symmetry.gql.ts +++ b/src/mol-model-props/rcsb/graphql/symmetry.gql.ts @@ -22,4 +22,4 @@ query AssemblySymmetry($assembly_id: String!, $entry_id: String!) { } } } -` \ No newline at end of file +`; \ No newline at end of file diff --git a/src/mol-model-props/rcsb/representations/assembly-symmetry.ts b/src/mol-model-props/rcsb/representations/assembly-symmetry.ts index 34149fda0708a8147402cf76d73942d355ecd721..7c8f2632dbe301f644a43dfad350fc79398e150d 100644 --- a/src/mol-model-props/rcsb/representations/assembly-symmetry.ts +++ b/src/mol-model-props/rcsb/representations/assembly-symmetry.ts @@ -38,21 +38,21 @@ const OrderColors = ColorMap({ '2': ColorNames.deepskyblue, '3': ColorNames.lime, 'N': ColorNames.red, -}) +}); const OrderColorsLegend = TableLegend(Object.keys(OrderColors).map(name => { - return [name, (OrderColors as any)[name] as Color] as [string, Color] -})) + return [name, (OrderColors as any)[name] as Color] as [string, Color]; +})); function axesColorHelp(value: { name: string, params: {} }) { return value.name === 'byOrder' ? { description: 'Color axes by their order', legend: OrderColorsLegend } - : {} + : {}; } const SharedParams = { ...Mesh.Params, scale: PD.Numeric(2, { min: 0.1, max: 5, step: 0.1 }), -} +}; const AxesParams = { ...SharedParams, @@ -62,122 +62,122 @@ const AxesParams = { colorValue: PD.Color(ColorNames.orange), }, { isFlat: true }) }, { help: axesColorHelp }), -} +}; type AxesParams = typeof AxesParams const CageParams = { ...SharedParams, cageColor: PD.Color(ColorNames.orange), -} +}; type CageParams = typeof CageParams const AssemblySymmetryVisuals = { // cage should come before 'axes' so that the representative loci uses the cage shape 'cage': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CageParams>) => ShapeRepresentation(getCageShape, Mesh.Utils, { modifyState: s => ({ ...s, markerActions: MarkerActions.Highlighting }) }), 'axes': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, AxesParams>) => ShapeRepresentation(getAxesShape, Mesh.Utils, { modifyState: s => ({ ...s, markerActions: MarkerActions.Highlighting }) }), -} +}; export const AssemblySymmetryParams = { ...AxesParams, ...CageParams, visuals: PD.MultiSelect(['axes', 'cage'], PD.objectToOptions(AssemblySymmetryVisuals)), -} +}; export type AssemblySymmetryParams = typeof AssemblySymmetryParams export type AssemblySymmetryProps = PD.Values<AssemblySymmetryParams> // function getAssemblyName(s: Structure) { - const id = s.units[0].conformation.operator.assembly?.id || '' - return isInteger(id) ? `Assembly ${id}` : id + const id = s.units[0].conformation.operator.assembly?.id || ''; + return isInteger(id) ? `Assembly ${id}` : id; } -const t = Mat4.identity() -const tmpV = Vec3() -const tmpCenter = Vec3() -const tmpScale = Vec3() +const t = Mat4.identity(); +const tmpV = Vec3(); +const tmpCenter = Vec3(); +const tmpScale = Vec3(); const getOrderPrimitive = memoize1((order: number): Primitive | undefined => { if (order < 2) { - return Prism(polygon(48, false)) + return Prism(polygon(48, false)); } else if (order === 2) { - const lens = Prism(polygon(48, false)) - const m = Mat4.identity() - Mat4.scale(m, m, Vec3.create(1, 0.35, 1)) - transformPrimitive(lens, m) - return lens + const lens = Prism(polygon(48, false)); + const m = Mat4.identity(); + Mat4.scale(m, m, Vec3.create(1, 0.35, 1)); + transformPrimitive(lens, m); + return lens; } else if (order === 3) { - return Wedge() + return Wedge(); } else { - return Prism(polygon(order, false)) + return Prism(polygon(order, false)); } -}) +}); function getAxesMesh(data: AssemblySymmetryValue, props: PD.Values<AxesParams>, mesh?: Mesh) { - const { scale } = props + const { scale } = props; - const { rotation_axes } = data - if (!AssemblySymmetry.isRotationAxes(rotation_axes)) return Mesh.createEmpty(mesh) + const { rotation_axes } = data; + if (!AssemblySymmetry.isRotationAxes(rotation_axes)) return Mesh.createEmpty(mesh); - const { start, end } = rotation_axes[0] - const radius = (Vec3.distance(start, end) / 500) * scale + const { start, end } = rotation_axes[0]; + const radius = (Vec3.distance(start, end) / 500) * scale; - Vec3.set(tmpScale, radius * 7, radius * 7, radius * 0.4) + Vec3.set(tmpScale, radius * 7, radius * 7, radius * 0.4); - const cylinderProps = { radiusTop: radius, radiusBottom: radius } - const builderState = MeshBuilder.createState(256, 128, mesh) + const cylinderProps = { radiusTop: radius, radiusBottom: radius }; + const builderState = MeshBuilder.createState(256, 128, mesh); - builderState.currentGroup = 0 - Vec3.scale(tmpCenter, Vec3.add(tmpCenter, start, end), 0.5) + builderState.currentGroup = 0; + Vec3.scale(tmpCenter, Vec3.add(tmpCenter, start, end), 0.5); for (let i = 0, il = rotation_axes.length; i < il; ++i) { - const { order, start, end } = rotation_axes[i] - builderState.currentGroup = i - addCylinder(builderState, start, end, 1, cylinderProps) + const { order, start, end } = rotation_axes[i]; + builderState.currentGroup = i; + addCylinder(builderState, start, end, 1, cylinderProps); - const primitive = getOrderPrimitive(order) + const primitive = getOrderPrimitive(order); if (primitive) { - Vec3.scale(tmpCenter, Vec3.add(tmpCenter, start, end), 0.5) + Vec3.scale(tmpCenter, Vec3.add(tmpCenter, start, end), 0.5); if (Vec3.dot(Vec3.unitY, Vec3.sub(tmpV, start, tmpCenter)) === 0) { - Mat4.targetTo(t, start, tmpCenter, Vec3.unitY) + Mat4.targetTo(t, start, tmpCenter, Vec3.unitY); } else { - Mat4.targetTo(t, start, tmpCenter, Vec3.unitX) + Mat4.targetTo(t, start, tmpCenter, Vec3.unitX); } - Mat4.scale(t, t, tmpScale) + Mat4.scale(t, t, tmpScale); - Mat4.setTranslation(t, start) - MeshBuilder.addPrimitive(builderState, t, primitive) - Mat4.setTranslation(t, end) - MeshBuilder.addPrimitive(builderState, t, primitive) + Mat4.setTranslation(t, start); + MeshBuilder.addPrimitive(builderState, t, primitive); + Mat4.setTranslation(t, end); + MeshBuilder.addPrimitive(builderState, t, primitive); } } - return MeshBuilder.getMesh(builderState) + return MeshBuilder.getMesh(builderState); } function getAxesShape(ctx: RuntimeContext, data: Structure, props: AssemblySymmetryProps, shape?: Shape<Mesh>) { - const assemblySymmetry = AssemblySymmetryProvider.get(data).value! + const assemblySymmetry = AssemblySymmetryProvider.get(data).value!; const geo = getAxesMesh(assemblySymmetry, props, shape && shape.geometry); const getColor = (groupId: number) => { if (props.axesColor.name === 'byOrder') { - const { rotation_axes } = assemblySymmetry - const order = rotation_axes![groupId]?.order - if (order === 2) return OrderColors[2] - else if (order === 3) return OrderColors[3] - else return OrderColors.N + const { rotation_axes } = assemblySymmetry; + const order = rotation_axes![groupId]?.order; + if (order === 2) return OrderColors[2]; + else if (order === 3) return OrderColors[3]; + else return OrderColors.N; } else { - return props.axesColor.params.colorValue + return props.axesColor.params.colorValue; } - } + }; const getLabel = (groupId: number) => { - const { type, symbol, kind, rotation_axes } = assemblySymmetry - const order = rotation_axes![groupId]?.order + const { type, symbol, kind, rotation_axes } = assemblySymmetry; + const order = rotation_axes![groupId]?.order; return [ `<small>${data.model.entryId}</small>`, `<small>${getAssemblyName(data)}</small>`, `Axis ${groupId + 1} with Order ${order} of ${type} ${kind} (${symbol})` - ].join(' | ') - } - return Shape.create('Axes', data, geo, getColor, () => 1, getLabel) + ].join(' | '); + }; + return Shape.create('Axes', data, geo, getColor, () => 1, getLabel); } // @@ -185,178 +185,178 @@ function getAxesShape(ctx: RuntimeContext, data: Structure, props: AssemblySymme const getSymbolCage = memoize1((symbol: string): Cage | undefined => { if (symbol.startsWith('D') || symbol.startsWith('C')) { // z axis is prism axis, x/y axes cut through edge midpoints - const fold = parseInt(symbol.substr(1)) + const fold = parseInt(symbol.substr(1)); if (fold === 2) { - return PrismCage(polygon(4, false)) + return PrismCage(polygon(4, false)); } else if (fold === 3) { - return WedgeCage() + return WedgeCage(); } else if (fold > 3) { - return PrismCage(polygon(fold, false)) + return PrismCage(polygon(fold, false)); } } else if (symbol === 'O') { // x/y/z axes cut through order 4 vertices - return OctahedronCage() + return OctahedronCage(); } else if (symbol === 'I') { // z axis cut through order 5 vertex // x axis cut through edge midpoint - const cage = IcosahedronCage() - const m = Mat4.identity() - Mat4.rotate(m, m, degToRad(31.7), Vec3.unitX) - return transformCage(cloneCage(cage), m) + const cage = IcosahedronCage(); + const m = Mat4.identity(); + Mat4.rotate(m, m, degToRad(31.7), Vec3.unitX); + return transformCage(cloneCage(cage), m); } else if (symbol === 'T') { // x/y/z axes cut through edge midpoints - return TetrahedronCage() + return TetrahedronCage(); } -}) +}); function getSymbolScale(symbol: string) { if (symbol.startsWith('D') || symbol.startsWith('C')) { - return 0.75 + return 0.75; } else if (symbol === 'O') { - return 1.2 + return 1.2; } else if (symbol === 'I') { - return 0.25 + return 0.25; } else if (symbol === 'T') { - return 0.8 + return 0.8; } - return 1 + return 1; } function setSymbolTransform(t: Mat4, symbol: string, axes: AssemblySymmetry.RotationAxes, size: number, structure: Structure) { - const eye = Vec3() - const target = Vec3() - const up = Vec3() - let pair: Mutable<AssemblySymmetry.RotationAxes> | undefined = undefined + const eye = Vec3(); + const target = Vec3(); + const up = Vec3(); + let pair: Mutable<AssemblySymmetry.RotationAxes> | undefined = undefined; if (symbol.startsWith('C')) { - pair = [axes[0]] + pair = [axes[0]]; } else if (symbol.startsWith('D')) { - const fold = parseInt(symbol.substr(1)) + const fold = parseInt(symbol.substr(1)); if (fold === 2) { - pair = axes.filter(a => a.order === 2) + pair = axes.filter(a => a.order === 2); } else if (fold >= 3) { - const aN = axes.filter(a => a.order === fold)[0] - const a2 = axes.filter(a => a.order === 2)[0] - pair = [aN, a2] + const aN = axes.filter(a => a.order === fold)[0]; + const a2 = axes.filter(a => a.order === 2)[0]; + pair = [aN, a2]; } } else if (symbol === 'O') { - pair = axes.filter(a => a.order === 4) + pair = axes.filter(a => a.order === 4); } else if (symbol === 'I') { - const a5 = axes.filter(a => a.order === 5)[0] - const a5dir = Vec3.sub(Vec3(), a5.end, a5.start) - pair = [a5] + const a5 = axes.filter(a => a.order === 5)[0]; + const a5dir = Vec3.sub(Vec3(), a5.end, a5.start); + pair = [a5]; for (const a of axes.filter(a => a.order === 3)) { - let d = radToDeg(Vec3.angle(Vec3.sub(up, a.end, a.start), a5dir)) + let d = radToDeg(Vec3.angle(Vec3.sub(up, a.end, a.start), a5dir)); if (equalEps(d, 100.81, 0.1) || equalEps(d, 79.19, 0.1)) { - pair[1] = a - break + pair[1] = a; + break; } } } else if (symbol === 'T') { - pair = axes.filter(a => a.order === 2) + pair = axes.filter(a => a.order === 2); } - Mat4.setIdentity(t) + Mat4.setIdentity(t); if (pair) { - const [aA, aB] = pair - Vec3.scale(eye, Vec3.add(eye, aA.end, aA.start), 0.5) - Vec3.copy(target, aA.end) + const [aA, aB] = pair; + Vec3.scale(eye, Vec3.add(eye, aA.end, aA.start), 0.5); + Vec3.copy(target, aA.end); if (aB) { - Vec3.sub(up, aB.end, aB.start) - const d = Vec3.dot(eye, up) - if (d < 0) Vec3.negate(up, up) - Mat4.targetTo(t, eye, target, up) - Mat4.scaleUniformly(t, t, size * getSymbolScale(symbol)) + Vec3.sub(up, aB.end, aB.start); + const d = Vec3.dot(eye, up); + if (d < 0) Vec3.negate(up, up); + Mat4.targetTo(t, eye, target, up); + Mat4.scaleUniformly(t, t, size * getSymbolScale(symbol)); } else { if (Vec3.dot(Vec3.unitY, Vec3.sub(tmpV, aA.end, aA.start)) === 0) { - Vec3.copy(up, Vec3.unitY) + Vec3.copy(up, Vec3.unitY); } else { - Vec3.copy(up, Vec3.unitX) + Vec3.copy(up, Vec3.unitX); } - Mat4.targetTo(t, eye, target, up) + Mat4.targetTo(t, eye, target, up); - const { sphere } = structure.lookup3d.boundary - let sizeXY = (sphere.radius * 2) * 0.8 // fallback for missing extrema + const { sphere } = structure.lookup3d.boundary; + let sizeXY = (sphere.radius * 2) * 0.8; // fallback for missing extrema if (Sphere3D.hasExtrema(sphere)) { - const n = Mat3.directionTransform(Mat3(), t) - const dirs = unitCircleDirections.map(d => Vec3.transformMat3(Vec3(), d, n)) - sizeXY = getMaxProjectedDistance(sphere.extrema, dirs, sphere.center) + const n = Mat3.directionTransform(Mat3(), t); + const dirs = unitCircleDirections.map(d => Vec3.transformMat3(Vec3(), d, n)); + sizeXY = getMaxProjectedDistance(sphere.extrema, dirs, sphere.center); } - Mat4.scale(t, t, Vec3.create(sizeXY, sizeXY, size * 0.9)) + Mat4.scale(t, t, Vec3.create(sizeXY, sizeXY, size * 0.9)); } } } const unitCircleDirections = (function() { - const dirs: Vec3[] = [] - const circle = polygon(12, false, 1) + const dirs: Vec3[] = []; + const circle = polygon(12, false, 1); for (let i = 0, il = circle.length; i < il; i += 3) { - dirs.push(Vec3.fromArray(Vec3(), circle, i)) + dirs.push(Vec3.fromArray(Vec3(), circle, i)); } - return dirs -})() -const tmpProj = Vec3() + return dirs; +})(); +const tmpProj = Vec3(); function getMaxProjectedDistance(points: Vec3[], directions: Vec3[], center: Vec3) { - let maxDist = 0 + let maxDist = 0; for (const p of points) { for (const d of directions) { - Vec3.projectPointOnVector(tmpProj, p, d, center) - const dist = Vec3.distance(tmpProj, center) - if (dist > maxDist) maxDist = dist + Vec3.projectPointOnVector(tmpProj, p, d, center); + const dist = Vec3.distance(tmpProj, center); + if (dist > maxDist) maxDist = dist; } } - return maxDist + return maxDist; } function getCageMesh(data: Structure, props: PD.Values<CageParams>, mesh?: Mesh) { - const assemblySymmetry = AssemblySymmetryProvider.get(data).value! - const { scale } = props + const assemblySymmetry = AssemblySymmetryProvider.get(data).value!; + const { scale } = props; - const { rotation_axes, symbol } = assemblySymmetry - if (!AssemblySymmetry.isRotationAxes(rotation_axes)) return Mesh.createEmpty(mesh) + const { rotation_axes, symbol } = assemblySymmetry; + if (!AssemblySymmetry.isRotationAxes(rotation_axes)) return Mesh.createEmpty(mesh); - const structure = AssemblySymmetry.getStructure(data, assemblySymmetry) + const structure = AssemblySymmetry.getStructure(data, assemblySymmetry); - const cage = getSymbolCage(symbol) - if (!cage) return Mesh.createEmpty(mesh) + const cage = getSymbolCage(symbol); + if (!cage) return Mesh.createEmpty(mesh); - const { start, end } = rotation_axes[0] - const size = Vec3.distance(start, end) - const radius = (size / 500) * scale + const { start, end } = rotation_axes[0]; + const size = Vec3.distance(start, end); + const radius = (size / 500) * scale; - const builderState = MeshBuilder.createState(256, 128, mesh) - builderState.currentGroup = 0 - setSymbolTransform(t, symbol, rotation_axes, size, structure) - Vec3.scale(tmpCenter, Vec3.add(tmpCenter, start, end), 0.5) - Mat4.setTranslation(t, tmpCenter) - MeshBuilder.addCage(builderState, t, cage, radius, 1, 8) + const builderState = MeshBuilder.createState(256, 128, mesh); + builderState.currentGroup = 0; + setSymbolTransform(t, symbol, rotation_axes, size, structure); + Vec3.scale(tmpCenter, Vec3.add(tmpCenter, start, end), 0.5); + Mat4.setTranslation(t, tmpCenter); + MeshBuilder.addCage(builderState, t, cage, radius, 1, 8); - return MeshBuilder.getMesh(builderState) + return MeshBuilder.getMesh(builderState); } function getCageShape(ctx: RuntimeContext, data: Structure, props: AssemblySymmetryProps, shape?: Shape<Mesh>) { - const assemblySymmetry = AssemblySymmetryProvider.get(data).value! + const assemblySymmetry = AssemblySymmetryProvider.get(data).value!; const geo = getCageMesh(data, props, shape && shape.geometry); const getColor = (groupId: number) => { - return props.cageColor - } + return props.cageColor; + }; const getLabel = (groupId: number) => { - const { type, symbol, kind } = assemblySymmetry - data.model.entryId + const { type, symbol, kind } = assemblySymmetry; + data.model.entryId; return [ `<small>${data.model.entryId}</small>`, `<small>${getAssemblyName(data)}</small>`, `Cage of ${type} ${kind} (${symbol})` - ].join(' | ') - } - return Shape.create('Cage', data, geo, getColor, () => 1, getLabel) + ].join(' | '); + }; + return Shape.create('Cage', data, geo, getColor, () => 1, getLabel); } // export type AssemblySymmetryRepresentation = Representation<Structure, AssemblySymmetryParams> export function AssemblySymmetryRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, AssemblySymmetryParams>): AssemblySymmetryRepresentation { - return Representation.createMulti('Assembly Symmetry', ctx, getParams, Representation.StateBuilder, AssemblySymmetryVisuals as unknown as Representation.Def<Structure, AssemblySymmetryParams>) + return Representation.createMulti('Assembly Symmetry', ctx, getParams, Representation.StateBuilder, AssemblySymmetryVisuals as unknown as Representation.Def<Structure, AssemblySymmetryParams>); } \ No newline at end of file diff --git a/src/mol-model-props/rcsb/representations/validation-report-clashes.ts b/src/mol-model-props/rcsb/representations/validation-report-clashes.ts index 7cc7553b9c07b28cbf014b6346a2f5093dbdd3bc..9f93c3ab73c7cadd5314319448ef7d0ebcc3b803 100644 --- a/src/mol-model-props/rcsb/representations/validation-report-clashes.ts +++ b/src/mol-model-props/rcsb/representations/validation-report-clashes.ts @@ -32,29 +32,29 @@ import { getUnitKindsParam } from '../../../mol-repr/structure/params'; // function createIntraUnitClashCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitClashParams>, mesh?: Mesh) { - if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) + if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh); - const clashes = ClashesProvider.get(structure).value!.intraUnit.get(unit.id) - const { edgeCount, a, b, edgeProps } = clashes - const { magnitude } = edgeProps - const { sizeFactor } = props + const clashes = ClashesProvider.get(structure).value!.intraUnit.get(unit.id); + const { edgeCount, a, b, edgeProps } = clashes; + const { magnitude } = edgeProps; + const { sizeFactor } = props; - if (!edgeCount) return Mesh.createEmpty(mesh) + if (!edgeCount) return Mesh.createEmpty(mesh); - const { elements } = unit - const pos = unit.conformation.invariantPosition + const { elements } = unit; + const pos = unit.conformation.invariantPosition; const builderProps = { linkCount: edgeCount * 2, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - pos(elements[a[edgeIndex]], posA) - pos(elements[b[edgeIndex]], posB) + pos(elements[a[edgeIndex]], posA); + pos(elements[b[edgeIndex]], posB); }, style: (edgeIndex: number) => LinkCylinderStyle.Disk, radius: (edgeIndex: number) => magnitude[edgeIndex] * sizeFactor, - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const IntraUnitClashParams = { @@ -62,7 +62,7 @@ export const IntraUnitClashParams = { ...LinkCylinderParams, linkCap: PD.Boolean(true), sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.01 }), -} +}; export type IntraUnitClashParams = typeof IntraUnitClashParams export function IntraUnitClashVisual(materialId: number): UnitsVisual<IntraUnitClashParams> { @@ -79,95 +79,95 @@ export function IntraUnitClashVisual(materialId: number): UnitsVisual<IntraUnitC newProps.linkScale !== currentProps.linkScale || newProps.linkSpacing !== currentProps.linkSpacing || newProps.linkCap !== currentProps.linkCap - ) + ); } - }, materialId) + }, materialId); } function getIntraClashBoundingSphere(unit: Unit.Atomic, clashes: IntraUnitClashes, elements: number[], boundingSphere: Sphere3D) { return CentroidHelper.fromPairProvider(elements.length, (i, pA, pB) => { - unit.conformation.position(unit.elements[clashes.a[elements[i]]], pA) - unit.conformation.position(unit.elements[clashes.b[elements[i]]], pB) - }, boundingSphere) + unit.conformation.position(unit.elements[clashes.a[elements[i]]], pA); + unit.conformation.position(unit.elements[clashes.b[elements[i]]], pB); + }, boundingSphere); } function getIntraClashLabel(structure: Structure, unit: Unit.Atomic, clashes: IntraUnitClashes, elements: number[]) { - const idx = elements[0] - if (idx === undefined) return '' - const { edgeProps: { id, magnitude, distance } } = clashes - const mag = magnitude[idx].toFixed(2) - const dist = distance[idx].toFixed(2) + const idx = elements[0]; + if (idx === undefined) return ''; + const { edgeProps: { id, magnitude, distance } } = clashes; + const mag = magnitude[idx].toFixed(2); + const dist = distance[idx].toFixed(2); return [ `Clash id: ${id[idx]} | Magnitude: ${mag} \u212B | Distance: ${dist} \u212B`, bondLabel(Bond.Location(structure, unit, clashes.a[idx], structure, unit, clashes.b[idx])) - ].join('</br>') + ].join('</br>'); } function IntraClashLoci(structure: Structure, unit: Unit.Atomic, clashes: IntraUnitClashes, elements: number[]) { return DataLoci('intra-clashes', { unit, clashes }, elements, (boundingSphere: Sphere3D) => getIntraClashBoundingSphere(unit, clashes, elements, boundingSphere), - () => getIntraClashLabel(structure, unit, clashes, elements)) + () => getIntraClashLabel(structure, unit, clashes, elements)); } function getIntraClashLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; if (Unit.isAtomic(unit)) { - const clashes = ClashesProvider.get(structure).value!.intraUnit.get(unit.id) - return IntraClashLoci(structure, unit, clashes, [groupId]) + const clashes = ClashesProvider.get(structure).value!.intraUnit.get(unit.id); + return IntraClashLoci(structure, unit, clashes, [groupId]); } } - return EmptyLoci + return EmptyLoci; } function eachIntraClash(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; // TODO - return changed + return changed; } function createIntraClashIterator(structureGroup: StructureGroup): LocationIterator { - const { structure, group } = structureGroup - const unit = group.units[0] - const clashes = ClashesProvider.get(structure).value!.intraUnit.get(unit.id) - const { a } = clashes - const groupCount = clashes.edgeCount * 2 - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { structure, group } = structureGroup; + const unit = group.units[0]; + const clashes = ClashesProvider.get(structure).value!.intraUnit.get(unit.id); + const { a } = clashes; + const groupCount = clashes.edgeCount * 2; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = unit.elements[a[groupIndex]] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = unit.elements[a[groupIndex]]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } // function createInterUnitClashCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<InterUnitClashParams>, mesh?: Mesh) { - const clashes = ClashesProvider.get(structure).value!.interUnit - const { edges, edgeCount } = clashes - const { sizeFactor } = props + const clashes = ClashesProvider.get(structure).value!.interUnit; + const { edges, edgeCount } = clashes; + const { sizeFactor } = props; - if (!edgeCount) return Mesh.createEmpty(mesh) + if (!edgeCount) return Mesh.createEmpty(mesh); const builderProps = { linkCount: edgeCount, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - const b = edges[edgeIndex] - const uA = b.unitA, uB = b.unitB - uA.conformation.position(uA.elements[b.indexA], posA) - uB.conformation.position(uB.elements[b.indexB], posB) + const b = edges[edgeIndex]; + const uA = b.unitA, uB = b.unitB; + uA.conformation.position(uA.elements[b.indexA], posA); + uB.conformation.position(uB.elements[b.indexB], posB); }, style: (edgeIndex: number) => LinkCylinderStyle.Disk, radius: (edgeIndex: number) => edges[edgeIndex].props.magnitude * sizeFactor - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const InterUnitClashParams = { @@ -175,7 +175,7 @@ export const InterUnitClashParams = { ...LinkCylinderParams, linkCap: PD.Boolean(true), sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.01 }), -} +}; export type InterUnitClashParams = typeof InterUnitClashParams export function InterUnitClashVisual(materialId: number): ComplexVisual<InterUnitClashParams> { @@ -192,65 +192,65 @@ export function InterUnitClashVisual(materialId: number): ComplexVisual<InterUni newProps.linkScale !== currentProps.linkScale || newProps.linkSpacing !== currentProps.linkSpacing || newProps.linkCap !== currentProps.linkCap - ) + ); } - }, materialId) + }, materialId); } function getInterClashBoundingSphere(clashes: InterUnitClashes, elements: number[], boundingSphere: Sphere3D) { return CentroidHelper.fromPairProvider(elements.length, (i, pA, pB) => { - const c = clashes.edges[elements[i]] - c.unitA.conformation.position(c.unitA.elements[c.indexA], pA) - c.unitB.conformation.position(c.unitB.elements[c.indexB], pB) - }, boundingSphere) + const c = clashes.edges[elements[i]]; + c.unitA.conformation.position(c.unitA.elements[c.indexA], pA); + c.unitB.conformation.position(c.unitB.elements[c.indexB], pB); + }, boundingSphere); } function getInterClashLabel(structure: Structure, clashes: InterUnitClashes, elements: number[]) { - const idx = elements[0] - if (idx === undefined) return '' - const c = clashes.edges[idx] - const mag = c.props.magnitude.toFixed(2) - const dist = c.props.distance.toFixed(2) + const idx = elements[0]; + if (idx === undefined) return ''; + const c = clashes.edges[idx]; + const mag = c.props.magnitude.toFixed(2); + const dist = c.props.distance.toFixed(2); return [ `Clash id: ${c.props.id} | Magnitude: ${mag} \u212B | Distance: ${dist} \u212B`, bondLabel(Bond.Location(structure, c.unitA, c.indexA, structure, c.unitB, c.indexB)) - ].join('</br>') + ].join('</br>'); } function InterClashLoci(structure: Structure, clashes: InterUnitClashes, elements: number[]) { return DataLoci('inter-clashes', clashes, elements, (boundingSphere: Sphere3D) => getInterClashBoundingSphere(clashes, elements, boundingSphere), - () => getInterClashLabel(structure, clashes, elements)) + () => getInterClashLabel(structure, clashes, elements)); } function getInterClashLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const clashes = ClashesProvider.get(structure).value!.interUnit - return InterClashLoci(structure, clashes, [groupId]) + const clashes = ClashesProvider.get(structure).value!.interUnit; + return InterClashLoci(structure, clashes, [groupId]); } - return EmptyLoci + return EmptyLoci; } function eachInterClash(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; // TODO - return changed + return changed; } function createInterClashIterator(structure: Structure): LocationIterator { - const clashes = ClashesProvider.get(structure).value!.interUnit - const groupCount = clashes.edgeCount - const instanceCount = 1 - const location = StructureElement.Location.create(structure) + const clashes = ClashesProvider.get(structure).value!.interUnit; + const groupCount = clashes.edgeCount; + const instanceCount = 1; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number) => { - const clash = clashes.edges[groupIndex] - location.unit = clash.unitA - location.element = clash.unitA.elements[clash.indexA] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + const clash = clashes.edges[groupIndex]; + location.unit = clash.unitA; + location.element = clash.unitA.elements[clash.indexA]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } // @@ -258,24 +258,24 @@ function createInterClashIterator(structure: Structure): LocationIterator { const ClashesVisuals = { 'intra-clash': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, IntraUnitClashParams>) => UnitsRepresentation('Intra-unit clash cylinder', ctx, getParams, IntraUnitClashVisual), 'inter-clash': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InterUnitClashParams>) => ComplexRepresentation('Inter-unit clash cylinder', ctx, getParams, InterUnitClashVisual), -} +}; export const ClashesParams = { ...IntraUnitClashParams, ...InterUnitClashParams, unitKinds: getUnitKindsParam(['atomic']), visuals: PD.MultiSelect(['intra-clash', 'inter-clash'], PD.objectToOptions(ClashesVisuals)) -} +}; export type ClashesParams = typeof ClashesParams export function getClashesParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(ClashesParams) + return PD.clone(ClashesParams); } export type ClashesRepresentation = StructureRepresentation<ClashesParams> export function ClashesRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ClashesParams>): ClashesRepresentation { - const repr = Representation.createMulti('Clashes', ctx, getParams, StructureRepresentationStateBuilder, ClashesVisuals as unknown as Representation.Def<Structure, ClashesParams>) - repr.setState({ markerActions: MarkerActions.Highlighting }) - return repr + const repr = Representation.createMulti('Clashes', ctx, getParams, StructureRepresentationStateBuilder, ClashesVisuals as unknown as Representation.Def<Structure, ClashesParams>); + repr.setState({ markerActions: MarkerActions.Highlighting }); + return repr; } export const ClashesRepresentationProvider = StructureRepresentationProvider({ @@ -292,4 +292,4 @@ export const ClashesRepresentationProvider = StructureRepresentationProvider({ attach: (ctx: CustomProperty.Context, structure: Structure) => ClashesProvider.attach(ctx, structure, void 0, true), detach: (data) => ClashesProvider.ref(data, false) } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts index 3f2b8d9536317a945056bcc5205b7977e528628c..99fb472c5888d28c0908bf43c8e64fae7d0363b4 100644 --- a/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts +++ b/src/mol-model-props/rcsb/themes/assembly-symmetry-cluster.ts @@ -6,7 +6,7 @@ import { ThemeDataContext } from '../../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { AssemblySymmetryProvider, AssemblySymmetry } from '../assembly-symmetry'; import { Color } from '../../../mol-util/color'; import { Unit, StructureElement, StructureProperties } from '../../../mol-model/structure'; @@ -15,67 +15,67 @@ import { ScaleLegend, TableLegend } from '../../../mol-util/legend'; import { getPalette, getPaletteParams } from '../../../mol-util/color/palette'; import { CustomProperty } from '../../common/custom-property'; -const DefaultColor = Color(0xCCCCCC) +const DefaultColor = Color(0xCCCCCC); function getAsymId(unit: Unit): StructureElement.Property<string> { switch (unit.kind) { case Unit.Kind.Atomic: - return StructureProperties.chain.label_asym_id + return StructureProperties.chain.label_asym_id; case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return StructureProperties.coarse.asym_id + return StructureProperties.coarse.asym_id; } } function clusterMemberKey(asymId: string, operList: string[]) { - return `${asymId}-${operList.join('|')}` + return `${asymId}-${operList.join('|')}`; } export const AssemblySymmetryClusterColorThemeParams = { ...getPaletteParams({ colorList: 'red-yellow-blue' }), -} +}; export type AssemblySymmetryClusterColorThemeParams = typeof AssemblySymmetryClusterColorThemeParams export function getAssemblySymmetryClusterColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(AssemblySymmetryClusterColorThemeParams) - return params + const params = PD.clone(AssemblySymmetryClusterColorThemeParams); + return params; } export function AssemblySymmetryClusterColorTheme(ctx: ThemeDataContext, props: PD.Values<AssemblySymmetryClusterColorThemeParams>): ColorTheme<AssemblySymmetryClusterColorThemeParams> { - let color: LocationColor = () => DefaultColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor = () => DefaultColor; + let legend: ScaleLegend | TableLegend | undefined; - const assemblySymmetry = ctx.structure && AssemblySymmetryProvider.get(ctx.structure) - const contextHash = assemblySymmetry?.version + const assemblySymmetry = ctx.structure && AssemblySymmetryProvider.get(ctx.structure); + const contextHash = assemblySymmetry?.version; - const clusters = assemblySymmetry?.value?.clusters + const clusters = assemblySymmetry?.value?.clusters; if (clusters?.length && ctx.structure) { - const clusterByMember = new Map<string, number>() + const clusterByMember = new Map<string, number>(); for (let i = 0, il = clusters.length; i < il; ++i) { - const { members } = clusters[i]! + const { members } = clusters[i]!; for (let j = 0, jl = members.length; j < jl; ++j) { - const asymId = members[j]!.asym_id - const operList = [...members[j]!.pdbx_struct_oper_list_ids || []] as string[] - clusterByMember.set(clusterMemberKey(asymId, operList), i) + const asymId = members[j]!.asym_id; + const operList = [...members[j]!.pdbx_struct_oper_list_ids || []] as string[]; + clusterByMember.set(clusterMemberKey(asymId, operList), i); if (operList.length === 0) { - operList.push('1') // TODO hack assuming '1' is the id of the identity operator - clusterByMember.set(clusterMemberKey(asymId, operList), i) + operList.push('1'); // TODO hack assuming '1' is the id of the identity operator + clusterByMember.set(clusterMemberKey(asymId, operList), i); } } } - const palette = getPalette(clusters.length, props) - legend = palette.legend + const palette = getPalette(clusters.length, props); + legend = palette.legend; const _emptyList: any[] = []; color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - const { assembly } = location.unit.conformation.operator - const asymId = getAsymId(location.unit)(location) - const cluster = clusterByMember.get(clusterMemberKey(asymId, assembly?.operList || _emptyList)) - return cluster !== undefined ? palette.color(cluster) : DefaultColor + const { assembly } = location.unit.conformation.operator; + const asymId = getAsymId(location.unit)(location); + const cluster = clusterByMember.get(clusterMemberKey(asymId, assembly?.operList || _emptyList)); + return cluster !== undefined ? palette.color(cluster) : DefaultColor; } - return DefaultColor - } + return DefaultColor; + }; } return { @@ -86,7 +86,7 @@ export function AssemblySymmetryClusterColorTheme(ctx: ThemeDataContext, props: contextHash, description: 'Assigns chain colors according to assembly symmetry cluster membership calculated with BioJava and obtained via RCSB PDB.', legend - } + }; } export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<AssemblySymmetryClusterColorThemeParams, AssemblySymmetry.Tag.Cluster> = { @@ -101,4 +101,4 @@ export const AssemblySymmetryClusterColorThemeProvider: ColorTheme.Provider<Asse attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? AssemblySymmetryProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(AssemblySymmetryProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/rcsb/themes/density-fit.ts b/src/mol-model-props/rcsb/themes/density-fit.ts index ba4fd46e8f08b91c8a8dfcc7af84f7893541907b..eca9c533ea5cfb7248d8cc89660e2d1a6dd5d563 100644 --- a/src/mol-model-props/rcsb/themes/density-fit.ts +++ b/src/mol-model-props/rcsb/themes/density-fit.ts @@ -6,47 +6,47 @@ import { ThemeDataContext } from '../../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { Color, ColorScale } from '../../../mol-util/color'; import { StructureElement, Model } from '../../../mol-model/structure'; import { Location } from '../../../mol-model/location'; import { CustomProperty } from '../../common/custom-property'; import { ValidationReportProvider, ValidationReport } from '../validation-report'; -const DefaultColor = Color(0xCCCCCC) +const DefaultColor = Color(0xCCCCCC); export function DensityFitColorTheme(ctx: ThemeDataContext, props: {}): ColorTheme<{}> { - let color: LocationColor = () => DefaultColor + let color: LocationColor = () => DefaultColor; const scaleRsrz = ColorScale.create({ minLabel: 'Poor', maxLabel: 'Better', domain: [2, 0], listOrName: 'red-yellow-blue', - }) + }); const scaleRscc = ColorScale.create({ minLabel: 'Poor', maxLabel: 'Better', domain: [0.678, 1.0], listOrName: 'red-yellow-blue', - }) + }); - const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]) - const contextHash = validationReport?.version - const model = ctx.structure?.models[0] + const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]); + const contextHash = validationReport?.version; + const model = ctx.structure?.models[0]; if (validationReport?.value && model) { - const { rsrz, rscc } = validationReport.value - const residueIndex = model.atomicHierarchy.residueAtomSegments.index + const { rsrz, rscc } = validationReport.value; + const residueIndex = model.atomicHierarchy.residueAtomSegments.index; color = (location: Location): Color => { if (StructureElement.Location.is(location) && location.unit.model === model) { - const rsrzValue = rsrz.get(residueIndex[location.element]) - if (rsrzValue !== undefined) return scaleRsrz.color(rsrzValue) - const rsccValue = rscc.get(residueIndex[location.element]) - if (rsccValue !== undefined) return scaleRscc.color(rsccValue) - return DefaultColor + const rsrzValue = rsrz.get(residueIndex[location.element]); + if (rsrzValue !== undefined) return scaleRsrz.color(rsrzValue); + const rsccValue = rscc.get(residueIndex[location.element]); + if (rsccValue !== undefined) return scaleRscc.color(rsccValue); + return DefaultColor; } - return DefaultColor - } + return DefaultColor; + }; } return { @@ -57,7 +57,7 @@ export function DensityFitColorTheme(ctx: ThemeDataContext, props: {}): ColorThe contextHash, description: 'Assigns residue colors according to the density fit using normalized Real Space R (RSRZ) for polymer residues and real space correlation coefficient (RSCC) for ligands. Colors range from poor (RSRZ = 2 or RSCC = 0.678) - to better (RSRZ = 0 or RSCC = 1.0). Data from wwPDB Validation Report, obtained via RCSB PDB.', legend: scaleRsrz.legend - } + }; } export const DensityFitColorThemeProvider: ColorTheme.Provider<{}, ValidationReport.Tag.DensityFit> = { @@ -72,4 +72,4 @@ export const DensityFitColorThemeProvider: ColorTheme.Provider<{}, ValidationRep attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? ValidationReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/rcsb/themes/geometry-quality.ts b/src/mol-model-props/rcsb/themes/geometry-quality.ts index 4b008eb6fb6c16697e6ae3d7a666794de5275127..685291259a0679c0875203c3492dd089ce10e247 100644 --- a/src/mol-model-props/rcsb/themes/geometry-quality.ts +++ b/src/mol-model-props/rcsb/themes/geometry-quality.ts @@ -6,7 +6,7 @@ import { ThemeDataContext } from '../../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { Color } from '../../../mol-util/color'; import { StructureElement } from '../../../mol-model/structure'; import { Location } from '../../../mol-model/location'; @@ -16,12 +16,12 @@ import { TableLegend } from '../../../mol-util/legend'; import { PolymerType } from '../../../mol-model/structure/model/types'; import { SetUtils } from '../../../mol-util/set'; -const DefaultColor = Color(0x909090) +const DefaultColor = Color(0x909090); -const NoIssuesColor = Color(0x2166ac) -const OneIssueColor = Color(0xfee08b) -const TwoIssuesColor = Color(0xf46d43) -const ThreeOrMoreIssuesColor = Color(0xa50026) +const NoIssuesColor = Color(0x2166ac); +const OneIssueColor = Color(0xfee08b); +const TwoIssuesColor = Color(0xf46d43); +const ThreeOrMoreIssuesColor = Color(0xa50026); const ColorLegend = TableLegend([ ['Data unavailable', DefaultColor], @@ -29,64 +29,64 @@ const ColorLegend = TableLegend([ ['One issue', OneIssueColor], ['Two issues', TwoIssuesColor], ['Three or more issues', ThreeOrMoreIssuesColor], -]) +]); export function getGeometricQualityColorThemeParams(ctx: ThemeDataContext) { - const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]).value - const options: [string, string][] = [] + const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]).value; + const options: [string, string][] = []; if (validationReport) { - const kinds = new Set<string>() - validationReport.geometryIssues.forEach(v => v.forEach(k => kinds.add(k))) - kinds.forEach(k => options.push([k, k])) + const kinds = new Set<string>(); + validationReport.geometryIssues.forEach(v => v.forEach(k => kinds.add(k))); + kinds.forEach(k => options.push([k, k])); } return { ignore: PD.MultiSelect([] as string[], options) - } + }; } export type GeometricQualityColorThemeParams = ReturnType<typeof getGeometricQualityColorThemeParams> export function GeometryQualityColorTheme(ctx: ThemeDataContext, props: PD.Values<GeometricQualityColorThemeParams>): ColorTheme<GeometricQualityColorThemeParams> { - let color: LocationColor = () => DefaultColor + let color: LocationColor = () => DefaultColor; - const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]) - const contextHash = validationReport?.version + const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]); + const contextHash = validationReport?.version; - const value = validationReport?.value - const model = ctx.structure?.models[0] + const value = validationReport?.value; + const model = ctx.structure?.models[0]; if (value && model) { - const { geometryIssues, clashes, bondOutliers, angleOutliers } = value - const residueIndex = model.atomicHierarchy.residueAtomSegments.index - const { polymerType } = model.atomicHierarchy.derived.residue - const ignore = new Set(props.ignore) + const { geometryIssues, clashes, bondOutliers, angleOutliers } = value; + const residueIndex = model.atomicHierarchy.residueAtomSegments.index; + const { polymerType } = model.atomicHierarchy.derived.residue; + const ignore = new Set(props.ignore); color = (location: Location): Color => { if (StructureElement.Location.is(location) && location.unit.model === model) { - const { element } = location - const rI = residueIndex[element] + const { element } = location; + const rI = residueIndex[element]; - const value = geometryIssues.get(rI) - if (value === undefined) return DefaultColor + const value = geometryIssues.get(rI); + if (value === undefined) return DefaultColor; - let count = SetUtils.differenceSize(value, ignore) + let count = SetUtils.differenceSize(value, ignore); if (count > 0 && polymerType[rI] === PolymerType.NA) { - count = 0 - if (!ignore.has('clash') && clashes.getVertexEdgeCount(element) > 0) count += 1 - if (!ignore.has('mog-bond-outlier') && bondOutliers.index.has(element)) count += 1 - if (!ignore.has('mog-angle-outlier') && angleOutliers.index.has(element)) count += 1 + count = 0; + if (!ignore.has('clash') && clashes.getVertexEdgeCount(element) > 0) count += 1; + if (!ignore.has('mog-bond-outlier') && bondOutliers.index.has(element)) count += 1; + if (!ignore.has('mog-angle-outlier') && angleOutliers.index.has(element)) count += 1; } switch (count) { - case undefined: return DefaultColor - case 0: return NoIssuesColor - case 1: return OneIssueColor - case 2: return TwoIssuesColor - default: return ThreeOrMoreIssuesColor + case undefined: return DefaultColor; + case 0: return NoIssuesColor; + case 1: return OneIssueColor; + case 2: return TwoIssuesColor; + default: return ThreeOrMoreIssuesColor; } } - return DefaultColor - } + return DefaultColor; + }; } return { @@ -97,7 +97,7 @@ export function GeometryQualityColorTheme(ctx: ThemeDataContext, props: PD.Value contextHash, description: 'Assigns residue colors according to the number of (filtered) geometry issues. Data from wwPDB Validation Report, obtained via RCSB PDB.', legend: ColorLegend - } + }; } export const GeometryQualityColorThemeProvider: ColorTheme.Provider<GeometricQualityColorThemeParams, ValidationReport.Tag.GeometryQuality> = { @@ -112,4 +112,4 @@ export const GeometryQualityColorThemeProvider: ColorTheme.Provider<GeometricQua attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? ValidationReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/rcsb/themes/random-coil-index.ts b/src/mol-model-props/rcsb/themes/random-coil-index.ts index 95b8fa31aa454f5c50f5fa72692c8fd73098ff6a..1a1e42fae50ab3daae264c3ffe07afb46f2853e2 100644 --- a/src/mol-model-props/rcsb/themes/random-coil-index.ts +++ b/src/mol-model-props/rcsb/themes/random-coil-index.ts @@ -6,38 +6,38 @@ import { ThemeDataContext } from '../../../mol-theme/theme'; import { ColorTheme, LocationColor } from '../../../mol-theme/color'; -import { ParamDefinition as PD } from '../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { Color, ColorScale } from '../../../mol-util/color'; import { StructureElement, Model } from '../../../mol-model/structure'; import { Location } from '../../../mol-model/location'; import { CustomProperty } from '../../common/custom-property'; import { ValidationReportProvider, ValidationReport } from '../validation-report'; -const DefaultColor = Color(0xCCCCCC) +const DefaultColor = Color(0xCCCCCC); export function RandomCoilIndexColorTheme(ctx: ThemeDataContext, props: {}): ColorTheme<{}> { - let color: LocationColor = () => DefaultColor + let color: LocationColor = () => DefaultColor; const scale = ColorScale.create({ reverse: true, domain: [0, 0.6], listOrName: 'red-yellow-blue', - }) + }); - const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]) - const contextHash = validationReport?.version + const validationReport = ctx.structure && ValidationReportProvider.get(ctx.structure.models[0]); + const contextHash = validationReport?.version; - const rci = validationReport?.value?.rci - const model = ctx.structure?.models[0] + const rci = validationReport?.value?.rci; + const model = ctx.structure?.models[0]; if (rci && model) { - const residueIndex = model.atomicHierarchy.residueAtomSegments.index + const residueIndex = model.atomicHierarchy.residueAtomSegments.index; color = (location: Location): Color => { if (StructureElement.Location.is(location) && location.unit.model === model) { - const value = rci.get(residueIndex[location.element]) - return value === undefined ? DefaultColor : scale.color(value) + const value = rci.get(residueIndex[location.element]); + return value === undefined ? DefaultColor : scale.color(value); } - return DefaultColor - } + return DefaultColor; + }; } return { @@ -48,7 +48,7 @@ export function RandomCoilIndexColorTheme(ctx: ThemeDataContext, props: {}): Col contextHash, description: 'Assigns residue colors according to the Random Coil Index value. Data from wwPDB Validation Report, obtained via RCSB PDB.', legend: scale.legend - } + }; } export const RandomCoilIndexColorThemeProvider: ColorTheme.Provider<{}, ValidationReport.Tag.RandomCoilIndex> = { @@ -63,4 +63,4 @@ export const RandomCoilIndexColorThemeProvider: ColorTheme.Provider<{}, Validati attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? ValidationReportProvider.attach(ctx, data.structure.models[0], void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.models[0].customProperties.reference(ValidationReportProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model-props/rcsb/validation-report.ts b/src/mol-model-props/rcsb/validation-report.ts index 1ed8f1c2b68ded2a22e26a9dc36618723b0bd648..f5a28d38286de67cab3ca8be5ca8ad7f31926a19 100644 --- a/src/mol-model-props/rcsb/validation-report.ts +++ b/src/mol-model-props/rcsb/validation-report.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { CustomPropertyDescriptor, Structure, Unit } from '../../mol-model/structure'; import { CustomProperty } from '../common/custom-property'; import { CustomModelProperty } from '../common/custom-model-property'; @@ -23,7 +23,7 @@ import { QuerySymbolRuntime } from '../../mol-script/runtime/query/compiler'; import { CustomPropSymbol } from '../../mol-script/language/symbol'; import Type from '../../mol-script/language/type'; -export { ValidationReport } +export { ValidationReport }; interface ValidationReport { /** @@ -85,10 +85,10 @@ namespace ValidationReport { Clashes = 'rcsb-clashes', } - export const DefaultBaseUrl = '//ftp.rcsb.org/pub/pdb/validation_reports' + export const DefaultBaseUrl = '//ftp.rcsb.org/pub/pdb/validation_reports'; export function getEntryUrl(pdbId: string, baseUrl: string) { - const id = pdbId.toLowerCase() - return `${baseUrl}/${id.substr(1, 2)}/${id}/${id}_validation.xml.gz` + const id = pdbId.toLowerCase(); + return `${baseUrl}/${id.substr(1, 2)}/${id}/${id}_validation.xml.gz`; } export function isApplicable(model?: Model): boolean { @@ -97,60 +97,60 @@ namespace ValidationReport { MmcifFormat.is(model.sourceData) && (model.sourceData.data.db.database_2.database_id.isDefined || model.entryId.length === 4) - ) + ); } export function fromXml(xml: XMLDocument, model: Model): ValidationReport { - return parseValidationReportXml(xml, model) + return parseValidationReportXml(xml, model); } export async function fetch(ctx: CustomProperty.Context, model: Model, props: ServerSourceProps): Promise<ValidationReport> { - const url = getEntryUrl(model.entryId, props.baseUrl) - const xml = await ctx.fetch({ url, type: 'xml' }).runInContext(ctx.runtime) - return fromXml(xml, model) + const url = getEntryUrl(model.entryId, props.baseUrl); + const xml = await ctx.fetch({ url, type: 'xml' }).runInContext(ctx.runtime); + return fromXml(xml, model); } export async function open(ctx: CustomProperty.Context, model: Model, props: FileSourceProps): Promise<ValidationReport> { - if (props.input === null) throw new Error('No file given') - const xml = await readFromFile(props.input, 'xml').runInContext(ctx.runtime) - return fromXml(xml, model) + if (props.input === null) throw new Error('No file given'); + const xml = await readFromFile(props.input, 'xml').runInContext(ctx.runtime); + return fromXml(xml, model); } export async function obtain(ctx: CustomProperty.Context, model: Model, props: ValidationReportProps): Promise<ValidationReport> { switch(props.source.name) { - case 'file': return open(ctx, model, props.source.params) - case 'server': return fetch(ctx, model, props.source.params) + case 'file': return open(ctx, model, props.source.params); + case 'server': return fetch(ctx, model, props.source.params); } } export const symbols = { hasClash: QuerySymbolRuntime.Dynamic(CustomPropSymbol('rcsb', 'validation-report.has-clash', Type.Bool), ctx => { - const { unit, element } = ctx.element - if (!Unit.isAtomic(unit)) return 0 - const validationReport = ValidationReportProvider.get(unit.model).value - return validationReport && validationReport.clashes.getVertexEdgeCount(element) > 0 + const { unit, element } = ctx.element; + if (!Unit.isAtomic(unit)) return 0; + const validationReport = ValidationReportProvider.get(unit.model).value; + return validationReport && validationReport.clashes.getVertexEdgeCount(element) > 0; } ), issueCount: QuerySymbolRuntime.Dynamic(CustomPropSymbol('rcsb', 'validation-report.issue-count', Type.Num), ctx => { - const { unit, element } = ctx.element - if (!Unit.isAtomic(unit)) return 0 - const validationReport = ValidationReportProvider.get(unit.model).value - return validationReport?.geometryIssues.get(unit.residueIndex[element])?.size || 0 + const { unit, element } = ctx.element; + if (!Unit.isAtomic(unit)) return 0; + const validationReport = ValidationReportProvider.get(unit.model).value; + return validationReport?.geometryIssues.get(unit.residueIndex[element])?.size || 0; } ), - } + }; } const FileSourceParams = { input: PD.File({ accept: '.xml,.gz,.zip' }) -} +}; type FileSourceProps = PD.Values<typeof FileSourceParams> const ServerSourceParams = { baseUrl: PD.Text(ValidationReport.DefaultBaseUrl, { description: 'Base URL to directory tree' }) -} +}; type ServerSourceProps = PD.Values<typeof ServerSourceParams> export const ValidationReportParams = { @@ -158,7 +158,7 @@ export const ValidationReportParams = { 'file': PD.Group(FileSourceParams, { label: 'File', isFlat: true }), 'server': PD.Group(ServerSourceParams, { label: 'Server', isFlat: true }), }, { options: [['file', 'File'], ['server', 'Server']] }) -} +}; export type ValidationReportParams = typeof ValidationReportParams export type ValidationReportProps = PD.Values<ValidationReportParams> @@ -173,10 +173,10 @@ export const ValidationReportProvider: CustomModelProperty.Provider<ValidationRe getParams: (data: Model) => ValidationReportParams, isApplicable: (data: Model) => ValidationReport.isApplicable(data), obtain: async (ctx: CustomProperty.Context, data: Model, props: Partial<ValidationReportProps>) => { - const p = { ...PD.getDefaultValues(ValidationReportParams), ...props } - return await ValidationReport.obtain(ctx, data, p) + const p = { ...PD.getDefaultValues(ValidationReportParams), ...props }; + return await ValidationReport.obtain(ctx, data, p); } -}) +}); // @@ -200,25 +200,25 @@ export interface Clashes { } function createInterUnitClashes(structure: Structure, clashes: ValidationReport['clashes']) { - const builder = new InterUnitGraph.Builder<Unit.Atomic, UnitIndex, InterUnitClashesProps>() - const { a, b, edgeProps: { id, magnitude, distance } } = clashes + const builder = new InterUnitGraph.Builder<Unit.Atomic, UnitIndex, InterUnitClashesProps>(); + const { a, b, edgeProps: { id, magnitude, distance } } = clashes; - const pA = Vec3(), pB = Vec3() + const pA = Vec3(), pB = Vec3(); Structure.eachUnitPair(structure, (unitA: Unit, unitB: Unit) => { - const elementsA = unitA.elements - const elementsB = unitB.elements + const elementsA = unitA.elements; + const elementsB = unitB.elements; - builder.startUnitPair(unitA as Unit.Atomic, unitB as Unit.Atomic) + builder.startUnitPair(unitA as Unit.Atomic, unitB as Unit.Atomic); for (let i = 0, il = clashes.edgeCount * 2; i < il; ++i) { // TODO create lookup - let indexA = SortedArray.indexOf(elementsA, a[i]) - let indexB = SortedArray.indexOf(elementsB, b[i]) + let indexA = SortedArray.indexOf(elementsA, a[i]); + let indexB = SortedArray.indexOf(elementsB, b[i]); if (indexA !== -1 && indexB !== -1) { - unitA.conformation.position(a[i], pA) - unitB.conformation.position(b[i], pB) + unitA.conformation.position(a[i], pA); + unitB.conformation.position(b[i], pB); // check actual distance to avoid clashes between unrelated chain instances if (equalEps(distance[i], Vec3.distance(pA, pB), 0.1)) { @@ -226,83 +226,83 @@ function createInterUnitClashes(structure: Structure, clashes: ValidationReport[ id: id[i], magnitude: magnitude[i], distance: distance[i], - }) + }); } } } - builder.finishUnitPair() + builder.finishUnitPair(); }, { maxRadius: arrayMax(clashes.edgeProps.distance), validUnit: (unit: Unit) => Unit.isAtomic(unit), validUnitPair: (unitA: Unit, unitB: Unit) => unitA.model === unitB.model - }) + }); - return new InterUnitGraph(builder.getMap()) + return new InterUnitGraph(builder.getMap()); } function createIntraUnitClashes(unit: Unit.Atomic, clashes: ValidationReport['clashes']): IntraUnitClashes { - const aIndices: UnitIndex[] = [] - const bIndices: UnitIndex[] = [] - const ids: number[] = [] - const magnitudes: number[] = [] - const distances: number[] = [] + const aIndices: UnitIndex[] = []; + const bIndices: UnitIndex[] = []; + const ids: number[] = []; + const magnitudes: number[] = []; + const distances: number[] = []; - const pA = Vec3(), pB = Vec3() + const pA = Vec3(), pB = Vec3(); - const { elements } = unit - const { a, b, edgeCount, edgeProps } = clashes + const { elements } = unit; + const { a, b, edgeCount, edgeProps } = clashes; for (let i = 0, il = edgeCount * 2; i < il; ++i) { // TODO create lookup - let indexA = SortedArray.indexOf(elements, a[i]) - let indexB = SortedArray.indexOf(elements, b[i]) + let indexA = SortedArray.indexOf(elements, a[i]); + let indexB = SortedArray.indexOf(elements, b[i]); if (indexA !== -1 && indexB !== -1) { - unit.conformation.position(a[i], pA) - unit.conformation.position(b[i], pB) + unit.conformation.position(a[i], pA); + unit.conformation.position(b[i], pB); // check actual distance to avoid clashes between unrelated chain instances if (equalEps(edgeProps.distance[i], Vec3.distance(pA, pB), 0.1)) { - aIndices.push(indexA as UnitIndex) - bIndices.push(indexB as UnitIndex) - ids.push(edgeProps.id[i]) - magnitudes.push(edgeProps.magnitude[i]) - distances.push(edgeProps.distance[i]) + aIndices.push(indexA as UnitIndex); + bIndices.push(indexB as UnitIndex); + ids.push(edgeProps.id[i]); + magnitudes.push(edgeProps.magnitude[i]); + distances.push(edgeProps.distance[i]); } } } - const builder = new IntAdjacencyGraph.EdgeBuilder(elements.length, aIndices, bIndices) - const id = new Int32Array(builder.slotCount) - const magnitude = new Float32Array(builder.slotCount) - const distance = new Float32Array(builder.slotCount) + const builder = new IntAdjacencyGraph.EdgeBuilder(elements.length, aIndices, bIndices); + const id = new Int32Array(builder.slotCount); + const magnitude = new Float32Array(builder.slotCount); + const distance = new Float32Array(builder.slotCount); for (let i = 0, _i = builder.edgeCount; i < _i; i++) { - builder.addNextEdge() - builder.assignProperty(id, ids[i]) - builder.assignProperty(magnitude, magnitudes[i]) - builder.assignProperty(distance, distances[i]) + builder.addNextEdge(); + builder.assignProperty(id, ids[i]); + builder.assignProperty(magnitude, magnitudes[i]); + builder.assignProperty(distance, distances[i]); } - return builder.createGraph({ id, magnitude, distance }) + return builder.createGraph({ id, magnitude, distance }); } function createClashes(structure: Structure, clashes: ValidationReport['clashes']): Clashes { - const intraUnit = IntMap.Mutable<IntraUnitClashes>() + const intraUnit = IntMap.Mutable<IntraUnitClashes>(); for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const group = structure.unitSymmetryGroups[i] - if (!Unit.isAtomic(group.units[0])) continue + const group = structure.unitSymmetryGroups[i]; + if (!Unit.isAtomic(group.units[0])) continue; - const intraClashes = createIntraUnitClashes(group.units[0], clashes) + const intraClashes = createIntraUnitClashes(group.units[0], clashes); for (let j = 0, jl = group.units.length; j < jl; ++j) { - intraUnit.set(group.units[j].id, intraClashes) + intraUnit.set(group.units[j].id, intraClashes); } } return { interUnit: createInterUnitClashes(structure, clashes), intraUnit - } + }; } export const ClashesProvider: CustomStructureProperty.Provider<{}, Clashes> = CustomStructureProperty.createProvider({ @@ -316,22 +316,22 @@ export const ClashesProvider: CustomStructureProperty.Provider<{}, Clashes> = Cu getParams: (data: Structure) => ({}), isApplicable: (data: Structure) => true, obtain: async (ctx: CustomProperty.Context, data: Structure) => { - await ValidationReportProvider.attach(ctx, data.models[0]) - const validationReport = ValidationReportProvider.get(data.models[0]).value! - return createClashes(data, validationReport.clashes) + await ValidationReportProvider.attach(ctx, data.models[0]); + const validationReport = ValidationReportProvider.get(data.models[0]).value!; + return createClashes(data, validationReport.clashes); } -}) +}); // function getItem(a: NamedNodeMap, name: string) { - const item = a.getNamedItem(name) - return item !== null ? item.value : '' + const item = a.getNamedItem(name); + return item !== null ? item.value : ''; } function hasAttr(a: NamedNodeMap, name: string, value: string) { - const item = a.getNamedItem(name) - return item !== null && item.value === value + const item = a.getNamedItem(name); + return item !== null && item.value === value; } function getMogInfo(a: NamedNodeMap) { @@ -340,7 +340,7 @@ function getMogInfo(a: NamedNodeMap) { obs: parseFloat(getItem(a, 'obsval')), stdev: parseFloat(getItem(a, 'stdev')), z: parseFloat(getItem(a, 'Zscore')), - } + }; } function getMolInfo(a: NamedNodeMap) { @@ -349,229 +349,229 @@ function getMolInfo(a: NamedNodeMap) { obs: parseFloat(getItem(a, 'obs')), stdev: parseFloat(getItem(a, 'stdev')), z: parseInt(getItem(a, 'z')), - } + }; } function addIndex(index: number, element: ElementIndex, map: Map<ElementIndex, number[]>) { - if (map.has(element)) map.get(element)!.push(index) - else map.set(element, [index]) + if (map.has(element)) map.get(element)!.push(index); + else map.set(element, [index]); } function ClashesBuilder(elementsCount: number) { - const aIndices: ElementIndex[] = [] - const bIndices: ElementIndex[] = [] - const ids: number[] = [] - const magnitudes: number[] = [] - const distances: number[] = [] + const aIndices: ElementIndex[] = []; + const bIndices: ElementIndex[] = []; + const ids: number[] = []; + const magnitudes: number[] = []; + const distances: number[] = []; - const seen = new Map<string, ElementIndex>() + const seen = new Map<string, ElementIndex>(); return { add(element: ElementIndex, id: number, magnitude: number, distance: number, isSymop: boolean) { - const hash = `${id}|${isSymop ? 's' : ''}` - const other = seen.get(hash) + const hash = `${id}|${isSymop ? 's' : ''}`; + const other = seen.get(hash); if (other !== undefined) { - aIndices[aIndices.length] = element - bIndices[bIndices.length] = other - ids[ids.length] = id - magnitudes[magnitudes.length] = magnitude - distances[distances.length] = distance + aIndices[aIndices.length] = element; + bIndices[bIndices.length] = other; + ids[ids.length] = id; + magnitudes[magnitudes.length] = magnitude; + distances[distances.length] = distance; } else { - seen.set(hash, element) + seen.set(hash, element); } }, get() { - const builder = new IntAdjacencyGraph.EdgeBuilder(elementsCount, aIndices, bIndices) - const id = new Int32Array(builder.slotCount) - const magnitude = new Float32Array(builder.slotCount) - const distance = new Float32Array(builder.slotCount) + const builder = new IntAdjacencyGraph.EdgeBuilder(elementsCount, aIndices, bIndices); + const id = new Int32Array(builder.slotCount); + const magnitude = new Float32Array(builder.slotCount); + const distance = new Float32Array(builder.slotCount); for (let i = 0, _i = builder.edgeCount; i < _i; i++) { - builder.addNextEdge() - builder.assignProperty(id, ids[i]) - builder.assignProperty(magnitude, magnitudes[i]) - builder.assignProperty(distance, distances[i]) + builder.addNextEdge(); + builder.assignProperty(id, ids[i]); + builder.assignProperty(magnitude, magnitudes[i]); + builder.assignProperty(distance, distances[i]); } - return builder.createGraph({ id, magnitude, distance }) + return builder.createGraph({ id, magnitude, distance }); } - } + }; } function parseValidationReportXml(xml: XMLDocument, model: Model): ValidationReport { - const rsrz = new Map<ResidueIndex, number>() - const rscc = new Map<ResidueIndex, number>() - const rci = new Map<ResidueIndex, number>() - const geometryIssues = new Map<ResidueIndex, Set<string>>() + const rsrz = new Map<ResidueIndex, number>(); + const rscc = new Map<ResidueIndex, number>(); + const rci = new Map<ResidueIndex, number>(); + const geometryIssues = new Map<ResidueIndex, Set<string>>(); const bondOutliers = { index: new Map<ElementIndex, number[]>(), data: [] as ValidationReport['bondOutliers']['data'] - } + }; const angleOutliers = { index: new Map<ElementIndex, number[]>(), data: [] as ValidationReport['angleOutliers']['data'] - } + }; - const clashesBuilder = ClashesBuilder(model.atomicHierarchy.atoms._rowCount) + const clashesBuilder = ClashesBuilder(model.atomicHierarchy.atoms._rowCount); - const { index } = model.atomicHierarchy + const { index } = model.atomicHierarchy; - const entries = xml.getElementsByTagName('Entry') + const entries = xml.getElementsByTagName('Entry'); if (entries.length === 1) { - const chemicalShiftLists = entries[0].getElementsByTagName('chemical_shift_list') + const chemicalShiftLists = entries[0].getElementsByTagName('chemical_shift_list'); if (chemicalShiftLists.length === 1) { - const randomCoilIndices = chemicalShiftLists[0].getElementsByTagName('random_coil_index') + const randomCoilIndices = chemicalShiftLists[0].getElementsByTagName('random_coil_index'); for (let j = 0, jl = randomCoilIndices.length; j < jl; ++j) { - const { attributes } = randomCoilIndices[j] - const value = parseFloat(getItem(attributes, 'value')) - const auth_asym_id = getItem(attributes, 'chain') - const auth_comp_id = getItem(attributes, 'rescode') - const auth_seq_id = parseInt(getItem(attributes, 'resnum')) - const rI = index.findResidueAuth({ auth_asym_id, auth_comp_id, auth_seq_id }) - if (rI !== -1) rci.set(rI, value) + const { attributes } = randomCoilIndices[j]; + const value = parseFloat(getItem(attributes, 'value')); + const auth_asym_id = getItem(attributes, 'chain'); + const auth_comp_id = getItem(attributes, 'rescode'); + const auth_seq_id = parseInt(getItem(attributes, 'resnum')); + const rI = index.findResidueAuth({ auth_asym_id, auth_comp_id, auth_seq_id }); + if (rI !== -1) rci.set(rI, value); } } } - const groups = xml.getElementsByTagName('ModelledSubgroup') + const groups = xml.getElementsByTagName('ModelledSubgroup'); for (let i = 0, il = groups.length; i < il; ++i) { - const g = groups[ i ] - const ga = g.attributes + const g = groups[ i ]; + const ga = g.attributes; - const pdbx_PDB_model_num = parseInt(getItem(ga, 'model')) - if (model.modelNum !== pdbx_PDB_model_num) continue + const pdbx_PDB_model_num = parseInt(getItem(ga, 'model')); + if (model.modelNum !== pdbx_PDB_model_num) continue; - const auth_asym_id = getItem(ga, 'chain') - const auth_comp_id = getItem(ga, 'resname') - const auth_seq_id = parseInt(getItem(ga, 'resnum')) - const pdbx_PDB_ins_code = getItem(ga, 'icode').trim() || undefined - const label_alt_id = getItem(ga, 'altcode').trim() || undefined + const auth_asym_id = getItem(ga, 'chain'); + const auth_comp_id = getItem(ga, 'resname'); + const auth_seq_id = parseInt(getItem(ga, 'resnum')); + const pdbx_PDB_ins_code = getItem(ga, 'icode').trim() || undefined; + const label_alt_id = getItem(ga, 'altcode').trim() || undefined; - const rI = index.findResidueAuth({ auth_asym_id, auth_comp_id, auth_seq_id, pdbx_PDB_ins_code }) + const rI = index.findResidueAuth({ auth_asym_id, auth_comp_id, auth_seq_id, pdbx_PDB_ins_code }); // continue if no residue index is found - if (rI === -1) continue + if (rI === -1) continue; - if (ga.getNamedItem('rsrz') !== null) rsrz.set(rI, parseFloat(getItem(ga, 'rsrz'))) - if (ga.getNamedItem('rscc') !== null) rscc.set(rI, parseFloat(getItem(ga, 'rscc'))) + if (ga.getNamedItem('rsrz') !== null) rsrz.set(rI, parseFloat(getItem(ga, 'rsrz'))); + if (ga.getNamedItem('rscc') !== null) rscc.set(rI, parseFloat(getItem(ga, 'rscc'))); - const isPolymer = getItem(ga, 'seq') !== '.' - const issues = new Set<string>() + const isPolymer = getItem(ga, 'seq') !== '.'; + const issues = new Set<string>(); if (isPolymer) { - const molBondOutliers = g.getElementsByTagName('bond-outlier') - if (molBondOutliers.length) issues.add('bond-outlier') + const molBondOutliers = g.getElementsByTagName('bond-outlier'); + if (molBondOutliers.length) issues.add('bond-outlier'); for (let j = 0, jl = molBondOutliers.length; j < jl; ++j) { - const bo = molBondOutliers[j].attributes - const idx = bondOutliers.data.length - const atomA = index.findAtomOnResidue(rI, getItem(bo, 'atom0')) - const atomB = index.findAtomOnResidue(rI, getItem(bo, 'atom1')) - addIndex(idx, atomA, bondOutliers.index) - addIndex(idx, atomB, bondOutliers.index) + const bo = molBondOutliers[j].attributes; + const idx = bondOutliers.data.length; + const atomA = index.findAtomOnResidue(rI, getItem(bo, 'atom0')); + const atomB = index.findAtomOnResidue(rI, getItem(bo, 'atom1')); + addIndex(idx, atomA, bondOutliers.index); + addIndex(idx, atomB, bondOutliers.index); bondOutliers.data.push({ tag: 'bond-outlier', atomA, atomB, ...getMolInfo(bo) - }) + }); } - const molAngleOutliers = g.getElementsByTagName('angle-outlier') - if (molAngleOutliers.length) issues.add('angle-outlier') + const molAngleOutliers = g.getElementsByTagName('angle-outlier'); + if (molAngleOutliers.length) issues.add('angle-outlier'); for (let j = 0, jl = molAngleOutliers.length; j < jl; ++j) { - const ao = molAngleOutliers[j].attributes - const idx = bondOutliers.data.length - const atomA = index.findAtomOnResidue(rI, getItem(ao, 'atom0')) - const atomB = index.findAtomOnResidue(rI, getItem(ao, 'atom1')) - const atomC = index.findAtomOnResidue(rI, getItem(ao, 'atom2')) - addIndex(idx, atomA, angleOutliers.index) - addIndex(idx, atomB, angleOutliers.index) - addIndex(idx, atomC, angleOutliers.index) + const ao = molAngleOutliers[j].attributes; + const idx = bondOutliers.data.length; + const atomA = index.findAtomOnResidue(rI, getItem(ao, 'atom0')); + const atomB = index.findAtomOnResidue(rI, getItem(ao, 'atom1')); + const atomC = index.findAtomOnResidue(rI, getItem(ao, 'atom2')); + addIndex(idx, atomA, angleOutliers.index); + addIndex(idx, atomB, angleOutliers.index); + addIndex(idx, atomC, angleOutliers.index); angleOutliers.data.push({ tag: 'angle-outlier', atomA, atomB, atomC, ...getMolInfo(ao) - }) + }); } - const planeOutliers = g.getElementsByTagName('plane-outlier') - if (planeOutliers.length) issues.add('plane-outlier') + const planeOutliers = g.getElementsByTagName('plane-outlier'); + if (planeOutliers.length) issues.add('plane-outlier'); - if (hasAttr(ga, 'rota', 'OUTLIER')) issues.add('rotamer-outlier') - if (hasAttr(ga, 'rama', 'OUTLIER')) issues.add('ramachandran-outlier') - if (hasAttr(ga, 'RNApucker', 'outlier')) issues.add('RNApucker-outlier') + if (hasAttr(ga, 'rota', 'OUTLIER')) issues.add('rotamer-outlier'); + if (hasAttr(ga, 'rama', 'OUTLIER')) issues.add('ramachandran-outlier'); + if (hasAttr(ga, 'RNApucker', 'outlier')) issues.add('RNApucker-outlier'); } else { - const mogBondOutliers = g.getElementsByTagName('mog-bond-outlier') - if (mogBondOutliers.length) issues.add('mog-bond-outlier') + const mogBondOutliers = g.getElementsByTagName('mog-bond-outlier'); + if (mogBondOutliers.length) issues.add('mog-bond-outlier'); for (let j = 0, jl = mogBondOutliers.length; j < jl; ++j) { - const mbo = mogBondOutliers[j].attributes - const atoms = getItem(mbo, 'atoms').split(',') - const idx = bondOutliers.data.length - const atomA = index.findAtomOnResidue(rI, atoms[0]) - const atomB = index.findAtomOnResidue(rI, atoms[1]) - addIndex(idx, atomA, bondOutliers.index) - addIndex(idx, atomB, bondOutliers.index) + const mbo = mogBondOutliers[j].attributes; + const atoms = getItem(mbo, 'atoms').split(','); + const idx = bondOutliers.data.length; + const atomA = index.findAtomOnResidue(rI, atoms[0]); + const atomB = index.findAtomOnResidue(rI, atoms[1]); + addIndex(idx, atomA, bondOutliers.index); + addIndex(idx, atomB, bondOutliers.index); bondOutliers.data.push({ tag: 'mog-bond-outlier', atomA, atomB, ...getMogInfo(mbo) - }) + }); } - const mogAngleOutliers = g.getElementsByTagName('mog-angle-outlier') - if (mogAngleOutliers.length) issues.add('mog-angle-outlier') + const mogAngleOutliers = g.getElementsByTagName('mog-angle-outlier'); + if (mogAngleOutliers.length) issues.add('mog-angle-outlier'); for (let j = 0, jl = mogAngleOutliers.length; j < jl; ++j) { - const mao = mogAngleOutliers[j].attributes - const atoms = getItem(mao, 'atoms').split(',') - const idx = angleOutliers.data.length - const atomA = index.findAtomOnResidue(rI, atoms[0]) - const atomB = index.findAtomOnResidue(rI, atoms[1]) - const atomC = index.findAtomOnResidue(rI, atoms[2]) - addIndex(idx, atomA, angleOutliers.index) - addIndex(idx, atomB, angleOutliers.index) - addIndex(idx, atomC, angleOutliers.index) + const mao = mogAngleOutliers[j].attributes; + const atoms = getItem(mao, 'atoms').split(','); + const idx = angleOutliers.data.length; + const atomA = index.findAtomOnResidue(rI, atoms[0]); + const atomB = index.findAtomOnResidue(rI, atoms[1]); + const atomC = index.findAtomOnResidue(rI, atoms[2]); + addIndex(idx, atomA, angleOutliers.index); + addIndex(idx, atomB, angleOutliers.index); + addIndex(idx, atomC, angleOutliers.index); angleOutliers.data.push({ tag: 'mog-angle-outlier', atomA, atomB, atomC, ...getMogInfo(mao) - }) + }); } } - const clashes = g.getElementsByTagName('clash') - if (clashes.length) issues.add('clash') + const clashes = g.getElementsByTagName('clash'); + if (clashes.length) issues.add('clash'); for (let j = 0, jl = clashes.length; j < jl; ++j) { - const ca = clashes[j].attributes - const id = parseInt(getItem(ca, 'cid')) - const magnitude = parseFloat(getItem(ca, 'clashmag')) - const distance = parseFloat(getItem(ca, 'dist')) - const label_atom_id = getItem(ca, 'atom') - const element = index.findAtomOnResidue(rI, label_atom_id, label_alt_id) + const ca = clashes[j].attributes; + const id = parseInt(getItem(ca, 'cid')); + const magnitude = parseFloat(getItem(ca, 'clashmag')); + const distance = parseFloat(getItem(ca, 'dist')); + const label_atom_id = getItem(ca, 'atom'); + const element = index.findAtomOnResidue(rI, label_atom_id, label_alt_id); if (element !== -1) { - clashesBuilder.add(element, id, magnitude, distance, false) + clashesBuilder.add(element, id, magnitude, distance, false); } } - const symmClashes = g.getElementsByTagName('symm-clash') - if (symmClashes.length) issues.add('symm-clash') + const symmClashes = g.getElementsByTagName('symm-clash'); + if (symmClashes.length) issues.add('symm-clash'); for (let j = 0, jl = symmClashes.length; j < jl; ++j) { - const sca = symmClashes[j].attributes - const id = parseInt(getItem(sca, 'scid')) - const magnitude = parseFloat(getItem(sca, 'clashmag')) - const distance = parseFloat(getItem(sca, 'dist')) - const label_atom_id = getItem(sca, 'atom') - const element = index.findAtomOnResidue(rI, label_atom_id, label_alt_id) + const sca = symmClashes[j].attributes; + const id = parseInt(getItem(sca, 'scid')); + const magnitude = parseFloat(getItem(sca, 'clashmag')); + const distance = parseFloat(getItem(sca, 'dist')); + const label_atom_id = getItem(sca, 'atom'); + const element = index.findAtomOnResidue(rI, label_atom_id, label_alt_id); if (element !== -1) { - clashesBuilder.add(element, id, magnitude, distance, true) + clashesBuilder.add(element, id, magnitude, distance, true); } } - geometryIssues.set(rI, issues) + geometryIssues.set(rI, issues); } - const clashes = clashesBuilder.get() + const clashes = clashesBuilder.get(); const validationReport = { rsrz, rscc, rci, geometryIssues, bondOutliers, angleOutliers, clashes - } + }; - return validationReport + return validationReport; } \ No newline at end of file diff --git a/src/mol-model/location.ts b/src/mol-model/location.ts index bb25edeb146109bc17466c229e8291f4a53f45d9..cc2946517835b6cbddda16aa1a64435abcbb8202 100644 --- a/src/mol-model/location.ts +++ b/src/mol-model/location.ts @@ -4,12 +4,12 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { StructureElement } from './structure' -import { Bond } from './structure/structure/unit/bonds' +import { StructureElement } from './structure'; +import { Bond } from './structure/structure/unit/bonds'; import { ShapeGroup } from './shape/shape'; /** A null value Location */ -export const NullLocation = { kind: 'null-location' as 'null-location' } +export const NullLocation = { kind: 'null-location' as 'null-location' }; export type NullLocation = typeof NullLocation export function isNullLocation(x: any): x is NullLocation { return !!x && x.kind === 'null-location'; @@ -23,7 +23,7 @@ export interface DataLocation<T = unknown, E = unknown> { element: E } export function DataLocation<T = unknown, E = unknown>(tag: string, data: T, element: E): DataLocation<T, E> { - return { kind: 'data-location', tag, data, element } + return { kind: 'data-location', tag, data, element }; } export function isDataLocation(x: any): x is DataLocation { return !!x && x.kind === 'data-location'; diff --git a/src/mol-model/loci.ts b/src/mol-model/loci.ts index 09e9f621033a855a1485c28dad6d6783aa26f7c7..a93a691737dd8f8723cc14021bf0c1262e4b4a38 100644 --- a/src/mol-model/loci.ts +++ b/src/mol-model/loci.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { StructureElement } from './structure' -import { Bond } from './structure/structure/unit/bonds' +import { StructureElement } from './structure'; +import { Bond } from './structure/structure/unit/bonds'; import { Shape, ShapeGroup } from './shape'; import { Sphere3D } from '../mol-math/geometry'; import { Vec3 } from '../mol-math/linear-algebra'; @@ -18,14 +18,14 @@ import { BoundaryHelper } from '../mol-math/geometry/boundary-helper'; import { stringToWords } from '../mol-util/string'; /** A Loci that includes every loci */ -export const EveryLoci = { kind: 'every-loci' as 'every-loci' } +export const EveryLoci = { kind: 'every-loci' as 'every-loci' }; export type EveryLoci = typeof EveryLoci export function isEveryLoci(x?: Loci): x is EveryLoci { return !!x && x.kind === 'every-loci'; } /** A Loci that is empty */ -export const EmptyLoci = { kind: 'empty-loci' as 'empty-loci' } +export const EmptyLoci = { kind: 'empty-loci' as 'empty-loci' }; export type EmptyLoci = typeof EmptyLoci export function isEmptyLoci(x?: Loci): x is EmptyLoci { return !!x && x.kind === 'empty-loci'; @@ -46,21 +46,21 @@ export function isDataLoci(x?: Loci): x is DataLoci { } export function areDataLociEqual(a: DataLoci, b: DataLoci) { // use shallowEqual to allow simple data objects that are contructed on-the-fly - if (!shallowEqual(a.data, b.data) || a.tag !== b.tag) return false - if (a.elements.length !== b.elements.length) return false + if (!shallowEqual(a.data, b.data) || a.tag !== b.tag) return false; + if (a.elements.length !== b.elements.length) return false; for (let i = 0, il = a.elements.length; i < il; ++i) { - if (!shallowEqual(a.elements[i], b.elements[i])) return false + if (!shallowEqual(a.elements[i], b.elements[i])) return false; } - return true + return true; } export function isDataLociEmpty(loci: DataLoci) { - return loci.elements.length === 0 ? true : false + return loci.elements.length === 0 ? true : false; } export function DataLoci<T = unknown, E = unknown>(tag: string, data: T, elements: ReadonlyArray<E>, getBoundingSphere: DataLoci<T, E>['getBoundingSphere'], getLabel: DataLoci<T, E>['getLabel']): DataLoci<T, E> { - return { kind: 'data-loci', tag, data, elements, getBoundingSphere, getLabel } + return { kind: 'data-loci', tag, data, elements, getBoundingSphere, getLabel }; } -export { Loci } +export { Loci }; type Loci = StructureElement.Loci | Structure.Loci | Bond.Loci | EveryLoci | EmptyLoci | DataLoci | Shape.Loci | ShapeGroup.Loci @@ -69,7 +69,7 @@ namespace Loci { const boundaryHelper = new BoundaryHelper('98'); export function getBundleBoundingSphere(bundle: Bundle<any>): Sphere3D { - const spheres = bundle.loci.map(l => getBoundingSphere(l)).filter(s => !!s) as Sphere3D[] + const spheres = bundle.loci.map(l => getBoundingSphere(l)).filter(s => !!s) as Sphere3D[]; boundaryHelper.reset(); for (const s of spheres) boundaryHelper.includePositionRadius(s.center, s.radius); boundaryHelper.finishedIncludeStep(); @@ -78,27 +78,27 @@ namespace Loci { } export function areEqual(lociA: Loci, lociB: Loci) { - if (isEveryLoci(lociA) && isEveryLoci(lociB)) return true - if (isEmptyLoci(lociA) && isEmptyLoci(lociB)) return true + if (isEveryLoci(lociA) && isEveryLoci(lociB)) return true; + if (isEmptyLoci(lociA) && isEmptyLoci(lociB)) return true; if (isDataLoci(lociA) && isDataLoci(lociB)) { - return areDataLociEqual(lociA, lociB) + return areDataLociEqual(lociA, lociB); } if (Structure.isLoci(lociA) && Structure.isLoci(lociB)) { - return Structure.areLociEqual(lociA, lociB) + return Structure.areLociEqual(lociA, lociB); } if (StructureElement.Loci.is(lociA) && StructureElement.Loci.is(lociB)) { - return StructureElement.Loci.areEqual(lociA, lociB) + return StructureElement.Loci.areEqual(lociA, lociB); } if (Bond.isLoci(lociA) && Bond.isLoci(lociB)) { - return Bond.areLociEqual(lociA, lociB) + return Bond.areLociEqual(lociA, lociB); } if (Shape.isLoci(lociA) && Shape.isLoci(lociB)) { - return Shape.areLociEqual(lociA, lociB) + return Shape.areLociEqual(lociA, lociB); } if (ShapeGroup.isLoci(lociA) && ShapeGroup.isLoci(lociB)) { - return ShapeGroup.areLociEqual(lociA, lociB) + return ShapeGroup.areLociEqual(lociA, lociB); } - return false + return false; } export function isEvery(loci?: Loci): loci is EveryLoci { @@ -106,63 +106,63 @@ namespace Loci { } export function isEmpty(loci: Loci): loci is EmptyLoci { - if (isEveryLoci(loci)) return false - if (isEmptyLoci(loci)) return true - if (isDataLoci(loci)) return isDataLociEmpty(loci) - if (Structure.isLoci(loci)) return Structure.isLociEmpty(loci) - if (StructureElement.Loci.is(loci)) return StructureElement.Loci.isEmpty(loci) - if (Bond.isLoci(loci)) return Bond.isLociEmpty(loci) - if (Shape.isLoci(loci)) return Shape.isLociEmpty(loci) - if (ShapeGroup.isLoci(loci)) return ShapeGroup.isLociEmpty(loci) - return false + if (isEveryLoci(loci)) return false; + if (isEmptyLoci(loci)) return true; + if (isDataLoci(loci)) return isDataLociEmpty(loci); + if (Structure.isLoci(loci)) return Structure.isLociEmpty(loci); + if (StructureElement.Loci.is(loci)) return StructureElement.Loci.isEmpty(loci); + if (Bond.isLoci(loci)) return Bond.isLociEmpty(loci); + if (Shape.isLoci(loci)) return Shape.isLociEmpty(loci); + if (ShapeGroup.isLoci(loci)) return ShapeGroup.isLociEmpty(loci); + return false; } export function remap<T>(loci: Loci, data: T) { if (data instanceof Structure) { if (StructureElement.Loci.is(loci)) { - loci = StructureElement.Loci.remap(loci, data) + loci = StructureElement.Loci.remap(loci, data); } else if (Structure.isLoci(loci)) { - loci = Structure.remapLoci(loci, data) + loci = Structure.remapLoci(loci, data); } else if (Bond.isLoci(loci)) { - loci = Bond.remapLoci(loci, data) + loci = Bond.remapLoci(loci, data); } } - return loci + return loci; } export function getBoundingSphere(loci: Loci, boundingSphere?: Sphere3D): Sphere3D | undefined { if (loci.kind === 'every-loci' || loci.kind === 'empty-loci') return void 0; - if (!boundingSphere) boundingSphere = Sphere3D() + if (!boundingSphere) boundingSphere = Sphere3D(); if (loci.kind === 'structure-loci') { - return Sphere3D.copy(boundingSphere, loci.structure.boundary.sphere) + return Sphere3D.copy(boundingSphere, loci.structure.boundary.sphere); } else if (loci.kind === 'element-loci') { return Sphere3D.copy(boundingSphere, StructureElement.Loci.getBoundary(loci).sphere); } else if (loci.kind === 'bond-loci') { - return Bond.getBoundingSphere(loci, boundingSphere) + return Bond.getBoundingSphere(loci, boundingSphere); } else if (loci.kind === 'shape-loci') { - return Sphere3D.copy(boundingSphere, loci.shape.geometry.boundingSphere) + return Sphere3D.copy(boundingSphere, loci.shape.geometry.boundingSphere); } else if (loci.kind === 'group-loci') { - return ShapeGroup.getBoundingSphere(loci, boundingSphere) + return ShapeGroup.getBoundingSphere(loci, boundingSphere); } else if (loci.kind === 'data-loci') { - return loci.getBoundingSphere(boundingSphere) + return loci.getBoundingSphere(boundingSphere); } } - const tmpSphere3D = Sphere3D.zero() + const tmpSphere3D = Sphere3D.zero(); export function getCenter(loci: Loci, center?: Vec3): Vec3 | undefined { - const boundingSphere = getBoundingSphere(loci, tmpSphere3D) - return boundingSphere ? Vec3.copy(center || Vec3(), boundingSphere.center) : undefined + const boundingSphere = getBoundingSphere(loci, tmpSphere3D); + return boundingSphere ? Vec3.copy(center || Vec3(), boundingSphere.center) : undefined; } export function getPrincipalAxes(loci: Loci): PrincipalAxes | undefined { if (loci.kind === 'every-loci' || loci.kind === 'empty-loci') return void 0; if (loci.kind === 'structure-loci') { - return StructureElement.Loci.getPrincipalAxes(Structure.toStructureElementLoci(loci.structure)) + return StructureElement.Loci.getPrincipalAxes(Structure.toStructureElementLoci(loci.structure)); } else if (loci.kind === 'element-loci') { - return StructureElement.Loci.getPrincipalAxes(loci) + return StructureElement.Loci.getPrincipalAxes(loci); } else if (loci.kind === 'bond-loci') { // TODO return void 0; @@ -185,58 +185,58 @@ namespace Loci { 'residue': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeResidues(loci, true) - : loci + : loci; }, 'chain': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeChains(loci) - : loci + : loci; }, 'entity': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeEntities(loci) - : loci + : loci; }, 'model': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToWholeModels(loci) - : loci + : loci; }, 'structure': (loci: Loci) => { return StructureElement.Loci.is(loci) ? Structure.toStructureElementLoci(loci.structure) : ShapeGroup.isLoci(loci) ? Shape.Loci(loci.shape) - : loci + : loci; }, 'elementInstances': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToAllInstances(loci) - : loci + : loci; }, 'residueInstances': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToAllInstances(StructureElement.Loci.extendToWholeResidues(loci, true)) - : loci + : loci; }, 'chainInstances': (loci: Loci) => { return StructureElement.Loci.is(loci) ? StructureElement.Loci.extendToAllInstances(StructureElement.Loci.extendToWholeChains(loci)) - : loci + : loci; }, - } + }; export type Granularity = keyof typeof Granularity export const GranularityOptions = ParamDefinition.objectToOptions(Granularity, k => { if (k.indexOf('Instances') > 0) return [stringToWords(k), 'With Symmetry']; switch (k) { - case 'element': return'Atom/Coarse Element' - case 'structure': return'Structure/Shape' - default: return stringToWords(k) + case 'element': return'Atom/Coarse Element'; + case 'structure': return'Structure/Shape'; + default: return stringToWords(k); } }); export function applyGranularity(loci: Loci, granularity: Granularity) { - return Granularity[granularity](loci) + return Granularity[granularity](loci); } /** @@ -246,20 +246,20 @@ namespace Loci { export function normalize(loci: Loci, granularity?: Granularity) { if (granularity !== 'element' && Bond.isLoci(loci)) { // convert Bond.Loci to a StructureElement.Loci so granularity can be applied - loci = Bond.toStructureElementLoci(loci) + loci = Bond.toStructureElementLoci(loci); } if (Structure.isLoci(loci)) { // convert to StructureElement.Loci - loci = Structure.toStructureElementLoci(loci.structure) + loci = Structure.toStructureElementLoci(loci.structure); } if (StructureElement.Loci.is(loci)) { // ensure the root structure is used - loci = StructureElement.Loci.remap(loci, loci.structure.root) + loci = StructureElement.Loci.remap(loci, loci.structure.root); } if (granularity) { // needs to be applied AFTER remapping to root - loci = applyGranularity(loci, granularity) + loci = applyGranularity(loci, granularity); } - return loci + return loci; } } \ No newline at end of file diff --git a/src/mol-model/sequence.ts b/src/mol-model/sequence.ts index bd9af242dc8e9daecd99517add461357b0eec763..78a092b256f68e33eea363cd70226d812e914f53 100644 --- a/src/mol-model/sequence.ts +++ b/src/mol-model/sequence.ts @@ -4,4 +4,4 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './sequence/sequence' \ No newline at end of file +export * from './sequence/sequence'; \ No newline at end of file diff --git a/src/mol-model/sequence/constants.ts b/src/mol-model/sequence/constants.ts index 17796f5996821e804b370738c42af8c7facd73d4..5025bf7eec1661979f976c1f41bd18b89c5a790c 100644 --- a/src/mol-model/sequence/constants.ts +++ b/src/mol-model/sequence/constants.ts @@ -39,7 +39,7 @@ const ProteinOneLetterCodes: { [name: string]: AminoAlphabet } = { 'SEC': 'U', // as per IUPAC definition 'PYL': 'O', // as per IUPAC definition -} +}; const DnaOneLetterCodes: { [name: string]: NuclecicAlphabet } = { 'DA': 'A', @@ -47,7 +47,7 @@ const DnaOneLetterCodes: { [name: string]: NuclecicAlphabet } = { 'DG': 'G', 'DT': 'T', 'DU': 'U' -} +}; const RnaOneLetterCodes: { [name: string]: NuclecicAlphabet } = { 'A': 'A', @@ -55,7 +55,7 @@ const RnaOneLetterCodes: { [name: string]: NuclecicAlphabet } = { 'G': 'G', 'T': 'T', 'U': 'U' -} +}; export function getProteinOneLetterCode(residueName: string): AminoAlphabet { const code = ProteinOneLetterCodes[residueName]; diff --git a/src/mol-model/sequence/sequence.ts b/src/mol-model/sequence/sequence.ts index 5e381e198a1da2eefc611c1754a53514b799bcbb..481530ad9b3c5e31672e159bf81dc5f58bd68893 100644 --- a/src/mol-model/sequence/sequence.ts +++ b/src/mol-model/sequence/sequence.ts @@ -6,7 +6,7 @@ */ import { AminoAlphabet, NuclecicAlphabet, getProteinOneLetterCode, getRnaOneLetterCode, getDnaOneLetterCode } from './constants'; -import { Column } from '../../mol-data/db' +import { Column } from '../../mol-data/db'; // TODO add mapping support to other sequence spaces, e.g. uniprot // TODO sequence alignment (take NGL code as starting point) @@ -42,13 +42,13 @@ namespace Sequence { export interface Generic extends Base<Kind.Generic, 'X' | '-'> { } export function create<K extends Kind, Alphabet extends string>(kind: K, code: Column<Alphabet>, label: Column<string>, seqId: Column<number>, compId: Column<string>, microHet: Map<number, string[]>, offset: number = 0): Base<K, Alphabet> { - const length = code.rowCount + const length = code.rowCount; return { kind, code, label, seqId, compId, microHet, offset, length }; } export function getSequenceString(seq: Sequence) { - const array = seq.code.toArray() - return (array instanceof Array ? array : Array.from(array)).join('') + const array = seq.code.toArray(); + return (array instanceof Array ? array : Array.from(array)).join(''); } function determineKind(names: Column<string>) { @@ -62,22 +62,22 @@ namespace Sequence { } function codeProvider(kind: Kind, map?: ReadonlyMap<string, string>) { - let code: (name: string) => string + let code: (name: string) => string; switch (kind) { case Kind.Protein: code = getProteinOneLetterCode; break; case Kind.DNA: code = getDnaOneLetterCode; break; case Kind.RNA: code = getRnaOneLetterCode; break; case Kind.Generic: code = () => 'X'; break; - default: throw new Error(`unknown kind '${kind}'`) + default: throw new Error(`unknown kind '${kind}'`); } if (map && map.size > 0) { return (name: string) => { const ret = code(name); if (ret !== 'X' || !map.has(name)) return ret; return code(map.get(name)!); - } + }; } - return code + return code; } export function ofResidueNames(compId: Column<string>, seqId: Column<number>): Sequence { @@ -148,7 +148,7 @@ namespace Sequence { } for (let i = 0, _i = this.seqId.rowCount; i < _i; i++) { - const seqId = this.seqId.value(i) + const seqId = this.seqId.value(i); const idx = seqId - minSeqId; const name = this.compId.value(i); const code = this.codeFromName(name); @@ -160,33 +160,33 @@ namespace Sequence { compIds[seqId].push(name); } - const microHet = new Map() + const microHet = new Map(); for (let i = minSeqId; i <= maxSeqId; ++i) { - if (compIds[i].length > 1) microHet.set(i, compIds[i]) + if (compIds[i].length > 1) microHet.set(i, compIds[i]); } - this._code = Column.ofStringArray(sequenceArray) as Column<Alphabet> + this._code = Column.ofStringArray(sequenceArray) as Column<Alphabet>; this._label = Column.ofLambda({ value: i => { - const l = labels[i] - return l.length > 1 ? `(${l.join('|')})` : l.join('') + const l = labels[i]; + return l.length > 1 ? `(${l.join('|')})` : l.join(''); }, rowCount: labels.length, schema: Column.Schema.str - }) - this._microHet = microHet + }); + this._microHet = microHet; this._offset = minSeqId - 1; - this._length = count + this._length = count; } constructor(public kind: K, public compId: Column<string>, public seqId: Column<number>) { - this.codeFromName = codeProvider(kind) + this.codeFromName = codeProvider(kind); } } export function ofSequenceRanges(seqIdBegin: Column<number>, seqIdEnd: Column<number>): Sequence { - const kind = Kind.Generic + const kind = Kind.Generic; return new SequenceRangesImpl(kind, seqIdBegin, seqIdEnd) as Sequence; } @@ -211,19 +211,19 @@ namespace Sequence { const count = maxSeqId - minSeqId + 1; - this.code = Column.ofConst('X', count, Column.Schema.str) as Column<Alphabet> - this.label = Column.ofConst('', count, Column.Schema.str) + this.code = Column.ofConst('X', count, Column.Schema.str) as Column<Alphabet>; + this.label = Column.ofConst('', count, Column.Schema.str); this.seqId = Column.ofLambda({ value: row => row + minSeqId + 1, rowCount: count, schema: Column.Schema.int - }) - this.compId = Column.ofConst('', count, Column.Schema.str) + }); + this.compId = Column.ofConst('', count, Column.Schema.str); this.offset = minSeqId - 1; - this.length = count + this.length = count; } } } -export { Sequence } +export { Sequence }; diff --git a/src/mol-model/shape.ts b/src/mol-model/shape.ts index fc1125ad411cce5f45eef76efc8f423fbeb09512..030551a1ad87e3149cf2eec2bae3e8e8e2e3eabb 100644 --- a/src/mol-model/shape.ts +++ b/src/mol-model/shape.ts @@ -4,4 +4,4 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export * from './shape/shape' \ No newline at end of file +export * from './shape/shape'; \ No newline at end of file diff --git a/src/mol-model/shape/shape.ts b/src/mol-model/shape/shape.ts index 06c2330a4d999a5d67c1d7ff4806447824d11e82..d32b799f3e22190027105483b7766b669bebb4e9 100644 --- a/src/mol-model/shape/shape.ts +++ b/src/mol-model/shape/shape.ts @@ -17,7 +17,7 @@ import { ShapeGroupColorTheme } from '../../mol-theme/color/shape-group'; import { Theme } from '../../mol-theme/theme'; import { TransformData, createTransform as _createTransform } from '../../mol-geo/geometry/transform-data'; import { createRenderObject as _createRenderObject, getNextMaterialId } from '../../mol-gl/render-object'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { LocationIterator } from '../../mol-geo/util/location-iterator'; export interface Shape<G extends Geometry = Geometry> { @@ -49,58 +49,58 @@ export namespace Shape { sourceData, geometry, transforms: transforms || [Mat4.identity()], - get groupCount() { return Geometry.getGroupCount(geometry) }, + get groupCount() { return Geometry.getGroupCount(geometry); }, getColor, getSize, getLabel - } + }; } export function getTheme(shape: Shape): Theme { return { color: ShapeGroupColorTheme({ shape }, {}), size: ShapeGroupSizeTheme({ shape }, {}) - } + }; } export function groupIterator(shape: Shape): LocationIterator { - const instanceCount = shape.transforms.length - const location = ShapeGroup.Location(shape) + const instanceCount = shape.transforms.length; + const location = ShapeGroup.Location(shape); const getLocation = (groupIndex: number, instanceIndex: number) => { - location.group = groupIndex - location.instance = instanceIndex - return location - } - return LocationIterator(shape.groupCount, instanceCount, getLocation) + location.group = groupIndex; + location.instance = instanceIndex; + return location; + }; + return LocationIterator(shape.groupCount, instanceCount, getLocation); } export function createTransform(transforms: Mat4[], transformData?: TransformData) { - const transformArray = transformData && transformData.aTransform.ref.value.length >= transforms.length * 16 ? transformData.aTransform.ref.value : new Float32Array(transforms.length * 16) + const transformArray = transformData && transformData.aTransform.ref.value.length >= transforms.length * 16 ? transformData.aTransform.ref.value : new Float32Array(transforms.length * 16); for (let i = 0, il = transforms.length; i < il; ++i) { - Mat4.toArray(transforms[i], transformArray, i * 16) + Mat4.toArray(transforms[i], transformArray, i * 16); } - return _createTransform(transformArray, transforms.length, transformData) + return _createTransform(transformArray, transforms.length, transformData); } export function createRenderObject<G extends Geometry>(shape: Shape<G>, props: PD.Values<Geometry.Params<G>>) { - props - const theme = Shape.getTheme(shape) - const utils = Geometry.getUtils(shape.geometry) + props; + const theme = Shape.getTheme(shape); + const utils = Geometry.getUtils(shape.geometry); - const materialId = getNextMaterialId() - const locationIt = groupIterator(shape) - const transform = Shape.createTransform(shape.transforms) - const values = utils.createValues(shape.geometry, transform, locationIt, theme, props) - const state = utils.createRenderableState(props) + const materialId = getNextMaterialId(); + const locationIt = groupIterator(shape); + const transform = Shape.createTransform(shape.transforms); + const values = utils.createValues(shape.geometry, transform, locationIt, theme, props); + const state = utils.createRenderableState(props); - return _createRenderObject(shape.geometry.kind, values, state, materialId) + return _createRenderObject(shape.geometry.kind, values, state, materialId); } export interface Loci { readonly kind: 'shape-loci', readonly shape: Shape } - export function Loci(shape: Shape): Loci { return { kind: 'shape-loci', shape } } - export function isLoci(x: any): x is Loci { return !!x && x.kind === 'shape-loci' } - export function areLociEqual(a: Loci, b: Loci) { return a.shape === b.shape } - export function isLociEmpty(loci: Loci) { return loci.shape.groupCount === 0 ? true : false } + export function Loci(shape: Shape): Loci { return { kind: 'shape-loci', shape }; } + export function isLoci(x: any): x is Loci { return !!x && x.kind === 'shape-loci'; } + export function areLociEqual(a: Loci, b: Loci) { return a.shape === b.shape; } + export function isLociEmpty(loci: Loci) { return loci.shape.groupCount === 0 ? true : false; } } export namespace ShapeGroup { @@ -137,99 +137,99 @@ export namespace ShapeGroup { } export function areLociEqual(a: Loci, b: Loci) { - if (a.shape !== b.shape) return false - if (a.groups.length !== b.groups.length) return false + if (a.shape !== b.shape) return false; + if (a.groups.length !== b.groups.length) return false; for (let i = 0, il = a.groups.length; i < il; ++i) { - const { ids: idsA, instance: instanceA } = a.groups[i] - const { ids: idsB, instance: instanceB } = b.groups[i] - if (instanceA !== instanceB) return false - if (!OrderedSet.areEqual(idsA, idsB)) return false + const { ids: idsA, instance: instanceA } = a.groups[i]; + const { ids: idsB, instance: instanceB } = b.groups[i]; + if (instanceA !== instanceB) return false; + if (!OrderedSet.areEqual(idsA, idsB)) return false; } - return true + return true; } export function isLociEmpty(loci: Loci) { - return size(loci) === 0 ? true : false + return size(loci) === 0 ? true : false; } export function size(loci: Loci) { - let size = 0 + let size = 0; for (const group of loci.groups) { - size += OrderedSet.size(group.ids) + size += OrderedSet.size(group.ids); } - return size + return size; } const sphereHelper = new CentroidHelper(), tmpPos = Vec3.zero(); function sphereHelperInclude(groups: Loci['groups'], mapping: GroupMapping, positions: Float32Array, transforms: Mat4[]) { - const { indices, offsets } = mapping + const { indices, offsets } = mapping; for (const { ids, instance } of groups) { OrderedSet.forEach(ids, v => { for (let i = offsets[v], il = offsets[v + 1]; i < il; ++i) { - Vec3.fromArray(tmpPos, positions, indices[i] * 3) - Vec3.transformMat4(tmpPos, tmpPos, transforms[instance]) - sphereHelper.includeStep(tmpPos) + Vec3.fromArray(tmpPos, positions, indices[i] * 3); + Vec3.transformMat4(tmpPos, tmpPos, transforms[instance]); + sphereHelper.includeStep(tmpPos); } - }) + }); } } function sphereHelperRadius(groups: Loci['groups'], mapping: GroupMapping, positions: Float32Array, transforms: Mat4[]) { - const { indices, offsets } = mapping + const { indices, offsets } = mapping; for (const { ids, instance } of groups) { OrderedSet.forEach(ids, v => { for (let i = offsets[v], il = offsets[v + 1]; i < il; ++i) { - Vec3.fromArray(tmpPos, positions, indices[i] * 3) - Vec3.transformMat4(tmpPos, tmpPos, transforms[instance]) - sphereHelper.radiusStep(tmpPos) + Vec3.fromArray(tmpPos, positions, indices[i] * 3); + Vec3.transformMat4(tmpPos, tmpPos, transforms[instance]); + sphereHelper.radiusStep(tmpPos); } - }) + }); } } export function getBoundingSphere(loci: Loci, boundingSphere?: Sphere3D) { - if (!boundingSphere) boundingSphere = Sphere3D() + if (!boundingSphere) boundingSphere = Sphere3D(); sphereHelper.reset(); - let padding = 0 + let padding = 0; - const { geometry, transforms } = loci.shape + const { geometry, transforms } = loci.shape; if (geometry.kind === 'mesh' || geometry.kind === 'points') { const positions = geometry.kind === 'mesh' ? geometry.vertexBuffer.ref.value - : geometry.centerBuffer.ref.value - sphereHelperInclude(loci.groups, geometry.groupMapping, positions, transforms) - sphereHelper.finishedIncludeStep() - sphereHelperRadius(loci.groups, geometry.groupMapping, positions, transforms) + : geometry.centerBuffer.ref.value; + sphereHelperInclude(loci.groups, geometry.groupMapping, positions, transforms); + sphereHelper.finishedIncludeStep(); + sphereHelperRadius(loci.groups, geometry.groupMapping, positions, transforms); } else if (geometry.kind === 'lines') { - const start = geometry.startBuffer.ref.value - const end = geometry.endBuffer.ref.value - sphereHelperInclude(loci.groups, geometry.groupMapping, start, transforms) - sphereHelperInclude(loci.groups, geometry.groupMapping, end, transforms) - sphereHelper.finishedIncludeStep() - sphereHelperRadius(loci.groups, geometry.groupMapping, start, transforms) - sphereHelperRadius(loci.groups, geometry.groupMapping, end, transforms) + const start = geometry.startBuffer.ref.value; + const end = geometry.endBuffer.ref.value; + sphereHelperInclude(loci.groups, geometry.groupMapping, start, transforms); + sphereHelperInclude(loci.groups, geometry.groupMapping, end, transforms); + sphereHelper.finishedIncludeStep(); + sphereHelperRadius(loci.groups, geometry.groupMapping, start, transforms); + sphereHelperRadius(loci.groups, geometry.groupMapping, end, transforms); } else if (geometry.kind === 'spheres' || geometry.kind === 'text') { - const positions = geometry.centerBuffer.ref.value - sphereHelperInclude(loci.groups, geometry.groupMapping, positions, transforms) - sphereHelper.finishedIncludeStep() - sphereHelperRadius(loci.groups, geometry.groupMapping, positions, transforms) + const positions = geometry.centerBuffer.ref.value; + sphereHelperInclude(loci.groups, geometry.groupMapping, positions, transforms); + sphereHelper.finishedIncludeStep(); + sphereHelperRadius(loci.groups, geometry.groupMapping, positions, transforms); for (const { ids, instance } of loci.groups) { OrderedSet.forEach(ids, v => { - const value = loci.shape.getSize(v, instance) - if (padding < value) padding = value - }) + const value = loci.shape.getSize(v, instance); + if (padding < value) padding = value; + }); } } else { // use whole shape bounding-sphere for other geometry kinds - return Sphere3D.copy(boundingSphere, geometry.boundingSphere) + return Sphere3D.copy(boundingSphere, geometry.boundingSphere); } - Vec3.copy(boundingSphere.center, sphereHelper.center) - boundingSphere.radius = Math.sqrt(sphereHelper.radiusSq) - Sphere3D.expand(boundingSphere, boundingSphere, padding) - return boundingSphere + Vec3.copy(boundingSphere.center, sphereHelper.center); + boundingSphere.radius = Math.sqrt(sphereHelper.radiusSq); + Sphere3D.expand(boundingSphere, boundingSphere, padding); + return boundingSphere; } } \ No newline at end of file diff --git a/src/mol-model/structure.ts b/src/mol-model/structure.ts index aa63b127e6b1a03c13fe1b72e7f12d9ec5c38f51..1069f684fafcdee5f86a16dc8877d2f8d3350083 100644 --- a/src/mol-model/structure.ts +++ b/src/mol-model/structure.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export * from './structure/coordinates' -export * from './structure/topology' -export * from './structure/model' -export * from './structure/structure' -export * from './structure/query' -export * from './structure/common/custom-property' \ No newline at end of file +export * from './structure/coordinates'; +export * from './structure/topology'; +export * from './structure/model'; +export * from './structure/structure'; +export * from './structure/query'; +export * from './structure/common/custom-property'; \ No newline at end of file diff --git a/src/mol-model/structure/common/custom-property.ts b/src/mol-model/structure/common/custom-property.ts index cc5735efe0094c6b28c616cd8f8f3e1fe670f83f..8f69a41d887313d9237b9d93761c4b1859de3500 100644 --- a/src/mol-model/structure/common/custom-property.ts +++ b/src/mol-model/structure/common/custom-property.ts @@ -4,12 +4,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { CifWriter } from '../../../mol-io/writer/cif' +import { CifWriter } from '../../../mol-io/writer/cif'; import { CifExportContext } from '../export/mmcif'; import { QuerySymbolRuntime } from '../../../mol-script/runtime/query/compiler'; import { UUID } from '../../../mol-util'; -export { CustomPropertyDescriptor, CustomProperties } +export { CustomPropertyDescriptor, CustomProperties }; interface CustomPropertyDescriptor<ExportCtx = CifExportContext, Symbols extends { [name: string]: QuerySymbolRuntime } = { }> { readonly name: string, diff --git a/src/mol-model/structure/coordinates.ts b/src/mol-model/structure/coordinates.ts index 50d52667c502ad55b6071dbd662962f1c45314d8..f18cf55bede8ee0ec76f398ebbe84f99964c7021 100644 --- a/src/mol-model/structure/coordinates.ts +++ b/src/mol-model/structure/coordinates.ts @@ -4,4 +4,4 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export * from './coordinates/coordinates' \ No newline at end of file +export * from './coordinates/coordinates'; \ No newline at end of file diff --git a/src/mol-model/structure/coordinates/coordinates.ts b/src/mol-model/structure/coordinates/coordinates.ts index 6ffd44df8f60dd92bd4de77676712f79837b9f4d..ca9e4174549198d99f85347fcad8cec1c92d0b53 100644 --- a/src/mol-model/structure/coordinates/coordinates.ts +++ b/src/mol-model/structure/coordinates/coordinates.ts @@ -36,7 +36,7 @@ export interface Frame { // -export { Time } +export { Time }; interface Time { value: number @@ -44,7 +44,7 @@ interface Time { } function Time(value: number, unit: Time.Unit) { - return { value, unit } + return { value, unit }; } namespace Time { @@ -55,7 +55,7 @@ namespace Time { // -export { Coordinates } +export { Coordinates }; interface Coordinates { readonly id: UUID @@ -74,9 +74,9 @@ interface Coordinates { namespace Coordinates { export function create(frames: Frame[], deltaTime: Time, timeOffset: Time): Coordinates { - const elementCount = frames[0].elementCount - const hasVelocities = !!frames[0].velocities - const hasForces = !!frames[0].forces + const elementCount = frames[0].elementCount; + const hasVelocities = !!frames[0].velocities; + const hasForces = !!frames[0].forces; return { id: UUID.create22(), @@ -86,7 +86,7 @@ namespace Coordinates { hasForces, deltaTime, timeOffset - } + }; } export function getAtomicConformation(frame: Frame, atomId: Column<number>): AtomicConformation { @@ -99,6 +99,6 @@ namespace Coordinates { x: frame.x, y: frame.y, z: frame.z, - } + }; } } \ No newline at end of file diff --git a/src/mol-model/structure/export/categories/atom_site.ts b/src/mol-model/structure/export/categories/atom_site.ts index 1e86bfc5a0fa922721b2535b3ae1cc0d6a307eaa..fb8b014bc15edb201c405f72772560035b45d244 100644 --- a/src/mol-model/structure/export/categories/atom_site.ts +++ b/src/mol-model/structure/export/categories/atom_site.ts @@ -80,7 +80,7 @@ export const _atom_site: CifCategory<CifExportContext> = { })) }; } -} +}; function prepostfixed(prefix: string | undefined, postfix: string | undefined, name: string) { if (prefix && postfix) return `${prefix}_${name}_${postfix}`; @@ -135,7 +135,7 @@ export function chainIdFields<K, D>(getLocation: (key: K, data: D) => StructureE const ret = CifField.build<K, D>() .str(prepostfixed(prefix, postfix, `label_asym_id`), mappedProp(getLocation, P.chain.label_asym_id)) .str(prepostfixed(prefix, postfix, `label_entity_id`), mappedProp(getLocation, P.chain.label_entity_id)) - .str(prepostfixed(prefix, postfix, `auth_asym_id`), mappedProp(getLocation, P.chain.auth_asym_id)) + .str(prepostfixed(prefix, postfix, `auth_asym_id`), mappedProp(getLocation, P.chain.auth_asym_id)); addModelNum(ret, getLocation, options); return ret.getFields(); @@ -144,7 +144,7 @@ export function chainIdFields<K, D>(getLocation: (key: K, data: D) => StructureE export function entityIdFields<K, D>(getLocation: (key: K, data: D) => StructureElement.Location, options?: IdFieldsOptions): CifField<K, D>[] { const prefix = options && options.prefix, postfix = options && options.postfix; const ret = CifField.build<K, D>() - .str(prepostfixed(prefix, postfix, `label_entity_id`), mappedProp(getLocation, P.chain.label_entity_id)) + .str(prepostfixed(prefix, postfix, `label_entity_id`), mappedProp(getLocation, P.chain.label_entity_id)); addModelNum(ret, getLocation, options); return ret.getFields(); diff --git a/src/mol-model/structure/export/categories/atom_site_operator_mapping.ts b/src/mol-model/structure/export/categories/atom_site_operator_mapping.ts index ed4ac2076ae8d4caa7981a28560e6ef29c875a8e..c76615de78285c00c2db84ff0ee1ea847f5452b3 100644 --- a/src/mol-model/structure/export/categories/atom_site_operator_mapping.ts +++ b/src/mol-model/structure/export/categories/atom_site_operator_mapping.ts @@ -36,7 +36,7 @@ export const AtomSiteOperatorMappingSchema = { // NCS ncs_id: Column.Schema.Str(), } -} +}; const asmValueKind = (i: number, xs: Entry[]) => typeof xs[i].operator.assembly === 'undefined' ? Column.ValueKind.NotPresent : Column.ValueKind.Present; const symmetryValueKind = (i: number, xs: Entry[]) => xs[i].operator.spgrOp === -1 ? Column.ValueKind.NotPresent : Column.ValueKind.Present; @@ -55,14 +55,14 @@ const Fields = CifWriter.fields<number, Entry[], keyof (typeof AtomSiteOperatorM .vec('symmetry_hkl', [(i, xs) => xs[i].operator.hkl[0], (i, xs) => xs[i].operator.hkl[1], (i, xs) => xs[i].operator.hkl[2]], { valueKind: symmetryValueKind }) // NCS .str('ncs_id', (i, xs) => xs[i].operator.ncsId || '', { valueKind: (i, xs) => !xs[i].operator.ncsId ? Column.ValueKind.NotPresent : Column.ValueKind.Present }) - .getFields() + .getFields(); const Category: CifWriter.Category<Entry[]> = { name: 'molstar_atom_site_operator_mapping', instance(entries: Entry[]) { return { fields: Fields, source: [{ data: entries, rowCount: entries.length }] }; } -} +}; interface Entry { label_asym_id: string, diff --git a/src/mol-model/structure/export/categories/misc.ts b/src/mol-model/structure/export/categories/misc.ts index a180891eca685b38a0be07b74caa5f022321a4a9..31887e0d6864f09315fa4fcce6aa6edcfd50a077 100644 --- a/src/mol-model/structure/export/categories/misc.ts +++ b/src/mol-model/structure/export/categories/misc.ts @@ -20,7 +20,7 @@ export const _chem_comp: CifCategory<CifExportContext> = { const indices = Column.indicesOf(id, id => names.has(id)); return CifCategory.ofTable(chem_comp, indices); } -} +}; export const _pdbx_chem_comp_identifier: CifCategory<CifExportContext> = { name: 'pdbx_chem_comp_identifier', @@ -32,7 +32,7 @@ export const _pdbx_chem_comp_identifier: CifCategory<CifExportContext> = { const indices = Column.indicesOf(comp_id, id => names.has(id)); return CifCategory.ofTable(pdbx_chem_comp_identifier, indices); } -} +}; export const _pdbx_nonpoly_scheme: CifCategory<CifExportContext> = { name: 'pdbx_nonpoly_scheme', @@ -42,4 +42,4 @@ export const _pdbx_nonpoly_scheme: CifCategory<CifExportContext> = { // TODO: filter? return CifCategory.ofTable(pdbx_nonpoly_scheme); } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model/structure/export/categories/secondary-structure.ts b/src/mol-model/structure/export/categories/secondary-structure.ts index 53f596ead1d7d8aca52c57d2182f8e27317b8b4c..1f1458a4f44b299434547fbab489f3e889079d9a 100644 --- a/src/mol-model/structure/export/categories/secondary-structure.ts +++ b/src/mol-model/structure/export/categories/secondary-structure.ts @@ -39,7 +39,7 @@ export const _struct_sheet_range: CifCategory<CifExportContext> = { function compare_ssr(x: SSElement<SecondaryStructure.Sheet>, y: SSElement<SecondaryStructure.Sheet>) { const a = x.element, b = y.element; - return a.sheet_id < b.sheet_id ? -1 : a.sheet_id === b.sheet_id ? x.start.element - y.start.element : 1 + return a.sheet_id < b.sheet_id ? -1 : a.sheet_id === b.sheet_id ? x.start.element - y.start.element : 1; }; const struct_conf_fields: CifField[] = [ @@ -71,8 +71,8 @@ interface SSElement<T extends SecondaryStructure.Element> { function findElements<T extends SecondaryStructure.Element>(ctx: CifExportContext, kind: SecondaryStructure.Element['kind']) { // TODO: encode secondary structure for different models? - const secondaryStructure = ModelSecondaryStructure.Provider.get(ctx.firstModel) - if (!secondaryStructure) return [] as SSElement<T>[] + const secondaryStructure = ModelSecondaryStructure.Provider.get(ctx.firstModel); + if (!secondaryStructure) return [] as SSElement<T>[]; const { key, elements } = secondaryStructure; const ssElements: SSElement<any>[] = []; @@ -108,7 +108,7 @@ function findElements<T extends SecondaryStructure.Element>(ctx: CifExportContex end: StructureElement.Location.create(structure, unit, segs.offsets[prev]), length: prev - start + 1, element - } + }; break; } } diff --git a/src/mol-model/structure/export/mmcif.ts b/src/mol-model/structure/export/mmcif.ts index 3c4417914da2cefca3fa3c25ae56c778e8341a77..c6368925dfc083010e5e77665404c76db48e3668 100644 --- a/src/mol-model/structure/export/mmcif.ts +++ b/src/mol-model/structure/export/mmcif.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { CifWriter } from '../../../mol-io/writer/cif' -import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif' -import { Structure } from '../structure' +import { CifWriter } from '../../../mol-io/writer/cif'; +import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif'; +import { Structure } from '../structure'; import { _atom_site } from './categories/atom_site'; import CifCategory = CifWriter.Category import { _struct_conf, _struct_sheet_range } from './categories/secondary-structure'; @@ -41,10 +41,10 @@ const _entity: CifCategory<CifExportContext> = { const indices = getUniqueEntityIndicesFromStructures(structures); return CifCategory.ofTable(structures[0].model.entities.data, indices); } -} +}; function isWithoutSymmetry(structure: Structure) { - return structure.units.every(u => u.conformation.operator.isIdentity) + return structure.units.every(u => u.conformation.operator.isIdentity); } const Categories = [ @@ -97,7 +97,7 @@ export const mmCIF_Export_Filters = { includeCategory(name) { return name === 'atom_site'; }, includeField(cat, field) { return _Filters.AtomSitePositionsFieldNames.has(field); } } -} +}; function encodeCustomProp(customProp: CustomPropertyDescriptor, ctx: CifExportContext, encoder: CifWriter.Encoder, params: encode_mmCIF_categories_Params) { if (!customProp.cifExport || customProp.cifExport.categories.length === 0) return; @@ -160,4 +160,4 @@ function to_mmCIF(name: string, structure: Structure, asBinary = false) { return enc.getData(); } -export default to_mmCIF \ No newline at end of file +export default to_mmCIF; \ No newline at end of file diff --git a/src/mol-model/structure/model.ts b/src/mol-model/structure/model.ts index a1cb4a8bd81a7af47e32eafbc8236632cc61c6d9..539da30c415d2c7374ac5faba5c6fdf8492429c5 100644 --- a/src/mol-model/structure/model.ts +++ b/src/mol-model/structure/model.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Model } from './model/model' -import * as Types from './model/types' -import { Symmetry } from './model/properties/symmetry' -import StructureSequence from './model/properties/sequence' +import { Model } from './model/model'; +import * as Types from './model/types'; +import { Symmetry } from './model/properties/symmetry'; +import StructureSequence from './model/properties/sequence'; -export * from './model/properties/custom/indexed' -export * from './model/indexing' -export { Model, Types, Symmetry, StructureSequence } \ No newline at end of file +export * from './model/properties/custom/indexed'; +export * from './model/indexing'; +export { Model, Types, Symmetry, StructureSequence }; \ No newline at end of file diff --git a/src/mol-model/structure/model/model.ts b/src/mol-model/structure/model/model.ts index f9c39208313a08e56afe38d33fefd07e9ba746e9..85fad5533cc3c25b63c8a9272592b390f760d01f 100644 --- a/src/mol-model/structure/model/model.ts +++ b/src/mol-model/structure/model/model.ts @@ -95,10 +95,10 @@ export namespace Model { export type Trajectory = ReadonlyArray<Model> export function trajectoryFromModelAndCoordinates(model: Model, coordinates: Coordinates): Trajectory { - const trajectory: Mutable<Model.Trajectory> = [] - const { frames } = coordinates + const trajectory: Mutable<Model.Trajectory> = []; + const { frames } = coordinates; for (let i = 0, il = frames.length; i < il; ++i) { - const f = frames[i] + const f = frames[i]; const m = { ...model, id: UUID.create22(), @@ -109,106 +109,106 @@ export namespace Model { customProperties: new CustomProperties(), _staticPropertyData: Object.create(null), _dynamicPropertyData: Object.create(null) - } - trajectory.push(m) + }; + trajectory.push(m); } - return trajectory + return trajectory; } export function trajectoryFromTopologyAndCoordinates(topology: Topology, coordinates: Coordinates): Task<Trajectory> { return Task.create('Create Trajectory', async ctx => { const model = (await createModels(topology.basic, topology.sourceData, ctx))[0]; - if (!model) throw new Error('found no model') - const trajectory = trajectoryFromModelAndCoordinates(model, coordinates) - const bondData = { pairs: topology.bonds, count: model.atomicHierarchy.atoms._rowCount } - const indexPairBonds = IndexPairBonds.fromData(bondData) + if (!model) throw new Error('found no model'); + const trajectory = trajectoryFromModelAndCoordinates(model, coordinates); + const bondData = { pairs: topology.bonds, count: model.atomicHierarchy.atoms._rowCount }; + const indexPairBonds = IndexPairBonds.fromData(bondData); let index = 0; for (const m of trajectory) { - IndexPairBonds.Provider.set(m, indexPairBonds) + IndexPairBonds.Provider.set(m, indexPairBonds); m.trajectoryInfo.index = index++; m.trajectoryInfo.size = trajectory.length; } - return trajectory - }) + return trajectory; + }); } - const CenterProp = '__Center__' + const CenterProp = '__Center__'; export function getCenter(model: Model): Vec3 { - if (model._dynamicPropertyData[CenterProp]) return model._dynamicPropertyData[CenterProp] - const center = calcModelCenter(model.atomicConformation, model.coarseConformation) - model._dynamicPropertyData[CenterProp] = center - return center + if (model._dynamicPropertyData[CenterProp]) return model._dynamicPropertyData[CenterProp]; + const center = calcModelCenter(model.atomicConformation, model.coarseConformation); + model._dynamicPropertyData[CenterProp] = center; + return center; } // export function isFromPdbArchive(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false - const { db } = model.sourceData.data + if (!MmcifFormat.is(model.sourceData)) return false; + const { db } = model.sourceData.data; return ( db.database_2.database_id.isDefined - ) + ); } export function hasSecondaryStructure(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false - const { db } = model.sourceData.data + if (!MmcifFormat.is(model.sourceData)) return false; + const { db } = model.sourceData.data; return ( db.struct_conf.id.isDefined || db.struct_sheet_range.id.isDefined - ) + ); } - const tmpAngles90 = Vec3.create(1.5708, 1.5708, 1.5708) // in radians - const tmpLengths1 = Vec3.create(1, 1, 1) + const tmpAngles90 = Vec3.create(1.5708, 1.5708, 1.5708); // in radians + const tmpLengths1 = Vec3.create(1, 1, 1); export function hasCrystalSymmetry(model: Model) { - const spacegroup = ModelSymmetry.Provider.get(model)?.spacegroup + const spacegroup = ModelSymmetry.Provider.get(model)?.spacegroup; return !!spacegroup && !( spacegroup.num === 1 && Vec3.equals(spacegroup.cell.anglesInRadians, tmpAngles90) && Vec3.equals(spacegroup.cell.size, tmpLengths1) - ) + ); } export function isFromXray(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false - const { db } = model.sourceData.data + if (!MmcifFormat.is(model.sourceData)) return false; + const { db } = model.sourceData.data; for (let i = 0; i < db.exptl.method.rowCount; i++) { - const v = db.exptl.method.value(i).toUpperCase() - if (v.indexOf('DIFFRACTION') >= 0) return true + const v = db.exptl.method.value(i).toUpperCase(); + if (v.indexOf('DIFFRACTION') >= 0) return true; } - return false + return false; } export function isFromEm(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false - const { db } = model.sourceData.data + if (!MmcifFormat.is(model.sourceData)) return false; + const { db } = model.sourceData.data; for (let i = 0; i < db.exptl.method.rowCount; i++) { - const v = db.exptl.method.value(i).toUpperCase() - if (v.indexOf('MICROSCOPY') >= 0) return true + const v = db.exptl.method.value(i).toUpperCase(); + if (v.indexOf('MICROSCOPY') >= 0) return true; } - return false + return false; } export function isFromNmr(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false - const { db } = model.sourceData.data + if (!MmcifFormat.is(model.sourceData)) return false; + const { db } = model.sourceData.data; for (let i = 0; i < db.exptl.method.rowCount; i++) { - const v = db.exptl.method.value(i).toUpperCase() - if (v.indexOf('NMR') >= 0) return true + const v = db.exptl.method.value(i).toUpperCase(); + if (v.indexOf('NMR') >= 0) return true; } - return false + return false; } export function hasXrayMap(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false + if (!MmcifFormat.is(model.sourceData)) return false; // Check exprimental method to exclude models solved with // 'ELECTRON CRYSTALLOGRAPHY' which also have structure factors - if (!isFromXray(model)) return false - const { db } = model.sourceData.data - const { status_code_sf } = db.pdbx_database_status - return status_code_sf.isDefined && status_code_sf.value(0) === 'REL' + if (!isFromXray(model)) return false; + const { db } = model.sourceData.data; + const { status_code_sf } = db.pdbx_database_status; + return status_code_sf.isDefined && status_code_sf.value(0) === 'REL'; } /** @@ -217,18 +217,18 @@ export namespace Model { * EMDB entry of type 'other EM volume'. */ export function hasEmMap(model: Model) { - if (!MmcifFormat.is(model.sourceData)) return false - const { db } = model.sourceData.data - const { db_name, content_type } = db.pdbx_database_related + if (!MmcifFormat.is(model.sourceData)) return false; + const { db } = model.sourceData.data; + const { db_name, content_type } = db.pdbx_database_related; for (let i = 0, il = db.pdbx_database_related._rowCount; i < il; ++i) { if (db_name.value(i).toUpperCase() === 'EMDB' && content_type.value(i) === 'associated EM volume') { - return true + return true; } } - return false + return false; } export function hasDensityMap(model: Model) { - return hasXrayMap(model) || hasEmMap(model) + return hasXrayMap(model) || hasEmMap(model); } } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/atomic.ts b/src/mol-model/structure/model/properties/atomic.ts index 65b7bb2cbbf97f583911af6c54409be3f3e89718..9eea6443a54f7f34019d471ffc3c3e48444ae104 100644 --- a/src/mol-model/structure/model/properties/atomic.ts +++ b/src/mol-model/structure/model/properties/atomic.ts @@ -4,6 +4,6 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './atomic/conformation' -export * from './atomic/hierarchy' -export * from './atomic/measures' \ No newline at end of file +export * from './atomic/conformation'; +export * from './atomic/hierarchy'; +export * from './atomic/measures'; \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/atomic/bonds.ts b/src/mol-model/structure/model/properties/atomic/bonds.ts index a2e0b56dfb72a06b51ab322bfeb14be645736baf..cfe6011506fc2304a0a7f8f4cfb28b20098fde74 100644 --- a/src/mol-model/structure/model/properties/atomic/bonds.ts +++ b/src/mol-model/structure/model/properties/atomic/bonds.ts @@ -58,16 +58,16 @@ const IntraBondOrderTable = new Map([ ['DT|C5|C6', 2], ['DT|C2|O2', 2], ['DT|C4|O4', 2] -]) +]); /** * Get order for bonds in aminoacids and nucleotides assuming standard IUPAC naming */ export function getIntraBondOrderFromTable (compId: string, atomId1: string, atomId2: string) { - [ atomId1, atomId2 ] = atomId1 < atomId2 ? [ atomId1, atomId2 ] : [ atomId2, atomId1 ] - if (AminoAcidNames.has(compId) && atomId1 === 'C' && atomId2 === 'O') return 2 - if (BaseNames.has(compId) && atomId1 === 'OP1' && atomId2 === 'P') return 2 - return IntraBondOrderTable.get(`${compId}|${atomId1}|${atomId2}`) || 1 + [ atomId1, atomId2 ] = atomId1 < atomId2 ? [ atomId1, atomId2 ] : [ atomId2, atomId1 ]; + if (AminoAcidNames.has(compId) && atomId1 === 'C' && atomId2 === 'O') return 2; + if (BaseNames.has(compId) && atomId1 === 'OP1' && atomId2 === 'P') return 2; + return IntraBondOrderTable.get(`${compId}|${atomId1}|${atomId2}`) || 1; } /** @@ -76,7 +76,7 @@ export function getIntraBondOrderFromTable (compId: string, atomId1: string, ato */ const InterBondOrderTable = new Map([ ['LYS|NZ|RET|C15', 2] // Schiff base in Rhodopsin and Bacteriorhodopsin -]) +]); /** * Get order for bonds between component assuming PDBx/mmCIF naming. @@ -86,5 +86,5 @@ export function getInterBondOrderFromTable (compId1: string, atomId1: string, co [ compId1, compId2 ] = [ compId2, compId1 ]; [ atomId1, atomId2 ] = [ atomId2, atomId1 ]; } - return InterBondOrderTable.get(`${compId1}|${atomId1}|${compId2}|${atomId2}`) || 1 + return InterBondOrderTable.get(`${compId1}|${atomId1}|${compId2}|${atomId2}`) || 1; } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/atomic/conformation.ts b/src/mol-model/structure/model/properties/atomic/conformation.ts index 27dbfcae377828f13e7b608b49e22f32de1bc3a8..a520d892e033f71be6e6a507f762fdf3ef8d3e0d 100644 --- a/src/mol-model/structure/model/properties/atomic/conformation.ts +++ b/src/mol-model/structure/model/properties/atomic/conformation.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column } from '../../../../../mol-data/db' -import UUID from '../../../../../mol-util/uuid' +import { Column } from '../../../../../mol-data/db'; +import UUID from '../../../../../mol-util/uuid'; export interface AtomicConformation { id: UUID, diff --git a/src/mol-model/structure/model/properties/atomic/hierarchy.ts b/src/mol-model/structure/model/properties/atomic/hierarchy.ts index 0f1bee9cd65d589251a2a74fa83f5f4266841d1a..ee0cafea2d5e43d696b47d30b8a7ad52961d65ea 100644 --- a/src/mol-model/structure/model/properties/atomic/hierarchy.ts +++ b/src/mol-model/structure/model/properties/atomic/hierarchy.ts @@ -5,10 +5,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column, Table } from '../../../../../mol-data/db' -import { Segmentation } from '../../../../../mol-data/int' -import { mmCIF_Schema as mmCIF } from '../../../../../mol-io/reader/cif/schema/mmcif' -import { ElementSymbol, MoleculeType, PolymerType } from '../../types' +import { Column, Table } from '../../../../../mol-data/db'; +import { Segmentation } from '../../../../../mol-data/int'; +import { mmCIF_Schema as mmCIF } from '../../../../../mol-io/reader/cif/schema/mmcif'; +import { ElementSymbol, MoleculeType, PolymerType } from '../../types'; import { ChainIndex, EntityIndex, ResidueIndex, ElementIndex } from '../../indexing'; import SortedRanges from '../../../../../mol-data/int/sorted-ranges'; @@ -100,7 +100,7 @@ export const ChainsSchema = { * For mmCIF files, this points to _entity.id in the ENTITY category. */ label_entity_id: mmCIF.atom_site.label_entity_id -} +}; export type ChainsSchema = typeof ChainsSchema export type Chains = Table<ChainsSchema> @@ -243,6 +243,6 @@ export namespace AtomicHierarchy { } export function chainResidueCount(segs: AtomicSegments, cI: ChainIndex) { - return chainEndResidueIndexExcl(segs, cI) - chainStartResidueIndex(segs, cI) + return chainEndResidueIndexExcl(segs, cI) - chainStartResidueIndex(segs, cI); } } diff --git a/src/mol-model/structure/model/properties/atomic/measures.ts b/src/mol-model/structure/model/properties/atomic/measures.ts index 7f320ee712bb6f119deb311f326e816291eee907..39120c2a6c2e4401b340bf48f06c9b8f2bd42f00 100644 --- a/src/mol-model/structure/model/properties/atomic/measures.ts +++ b/src/mol-model/structure/model/properties/atomic/measures.ts @@ -12,12 +12,12 @@ export const AtomicNumbers: { [e: string]: number | undefined } = { // http://dx.doi.org/10.1021/jp8111556 (or 2.0) export const ElementVdwRadii: { [e: number]: number | undefined } = { 1: 1.1, 2: 1.4, 3: 1.81, 4: 1.53, 5: 1.92, 6: 1.7, 7: 1.55, 8: 1.52, 9: 1.47, 10: 1.54, 11: 2.27, 12: 1.73, 13: 1.84, 14: 2.1, 15: 1.8, 16: 1.8, 17: 1.75, 18: 1.88, 19: 2.75, 20: 2.31, 21: 2.3, 22: 2.15, 23: 2.05, 24: 2.05, 25: 2.05, 26: 2.05, 27: 2.0, 28: 2.0, 29: 2.0, 30: 2.1, 31: 1.87, 32: 2.11, 33: 1.85, 34: 1.9, 35: 1.83, 36: 2.02, 37: 3.03, 38: 2.49, 39: 2.4, 40: 2.3, 41: 2.15, 42: 2.1, 43: 2.05, 44: 2.05, 45: 2.0, 46: 2.05, 47: 2.1, 48: 2.2, 49: 2.2, 50: 1.93, 51: 2.17, 52: 2.06, 53: 1.98, 54: 2.16, 55: 3.43, 56: 2.68, 57: 2.5, 58: 2.48, 59: 2.47, 60: 2.45, 61: 2.43, 62: 2.42, 63: 2.4, 64: 2.38, 65: 2.37, 66: 2.35, 67: 2.33, 68: 2.32, 69: 2.3, 70: 2.28, 71: 2.27, 72: 2.25, 73: 2.2, 74: 2.1, 75: 2.05, 76: 2.0, 77: 2.0, 78: 2.05, 79: 2.1, 80: 2.05, 81: 1.96, 82: 2.02, 83: 2.07, 84: 1.97, 85: 2.02, 86: 2.2, 87: 3.48, 88: 2.83, 89: 2.0, 90: 2.4, 91: 2.0, 92: 2.3, 93: 2.0, 94: 2.0, 95: 2.0, 96: 2.0, 97: 2.0, 98: 2.0, 99: 2.0, 100: 2.0, 101: 2.0, 102: 2.0, 103: 2.0, 104: 2.0, 105: 2.0, 106: 2.0, 107: 2.0, 108: 2.0, 109: 2.0 -} +}; // https://doi.org/10.1515/pac-2015-0305 (table 2, 3, and 4) export const ElementAtomWeights: { [e: number]: number | undefined } = { 1: 1.008, 2: 4.0026, 3: 6.94, 4: 9.0122, 5: 10.81, 6: 10.81, 7: 14.007, 8: 15.999, 9: 18.998, 10: 20.180, 11: 22.990, 12: 24.305, 13: 26.982, 14: 28.085, 15: 30.974, 16: 32.06, 17: 35.45, 18: 39.948, 19: 39.098, 20: 40.078, 21: 44.956, 22: 47.867, 23: 50.942, 24: 51.996, 25: 54.938, 26: 55.845, 27: 58.933, 28: 58.693, 29: 63.546, 30: 65.38, 31: 69.723, 32: 72.630, 33: 74.922, 34: 78.971, 35: 79.904, 36: 83.798, 37: 85.468, 38: 87.62, 39: 88.906, 40: 91.224, 41: 92.906, 42: 95.95, 43: 96.906, 44: 101.07, 45: 102.91, 46: 106.42, 47: 107.87, 48: 112.41, 49: 114.82, 50: 118.71, 51: 121.76, 52: 127.60, 53: 127.60, 54: 131.29, 55: 132.91, 56: 137.33, 57: 138.91, 58: 140.12, 59: 140.91, 60: 144.24, 61: 144.912, 62: 150.36, 63: 151.96, 64: 157.25, 65: 158.93, 66: 162.50, 67: 164.93, 68: 167.26, 69: 168.93, 70: 173.05, 71: 174.97, 72: 178.49, 73: 180.95, 74: 183.84, 75: 186.21, 76: 190.23, 77: 192.22, 78: 195.08, 79: 196.97, 80: 200.59, 81: 204.38, 82: 207.2, 83: 208.98, 84: 1.97, 85: 2.02, 86: 2.2, 87: 3.48, 88: 2.83, 89: 2.0, 90: 232.04, 91: 231.04, 92: 238.03, 93: 237.048, 94: 244.064, 95: 243.061, 96: 247.070, 97: 247.070, 98: 251.079, 99: 252.083, 100: 257.095, 101: 258.098, 102: 259.101, 103: 262.110, 104: 267.122, 105: 270.131, 106: 271.134, 107: 270.133, 108: 270.134, 109: 278.156 -} +}; export const DefaultVdwRadius = 1.7; // C export const DefaultAtomWeight = 10.81; // C @@ -25,15 +25,15 @@ export const DefaultAtomNumber = 0; export function VdwRadius(element: ElementSymbol): number { const i = AtomicNumbers[element as any as string]; - return i === void 0 ? DefaultVdwRadius : ElementVdwRadii[i]! + return i === void 0 ? DefaultVdwRadius : ElementVdwRadii[i]!; } export function AtomWeight(element: ElementSymbol): number { const i = AtomicNumbers[element as any as string]; - return i === void 0 ? DefaultAtomWeight : ElementAtomWeights[i]! + return i === void 0 ? DefaultAtomWeight : ElementAtomWeights[i]!; } export function AtomNumber(element: ElementSymbol): number { const i = AtomicNumbers[element as any as string]; - return i === void 0 ? DefaultAtomNumber : i + return i === void 0 ? DefaultAtomNumber : i; } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/atomic/types.ts b/src/mol-model/structure/model/properties/atomic/types.ts index d032a400bda0c6632c4bc6ece609ecac3c557115..108d39eb9ab50d1fd401cc2230ac3966ba1f98d2 100644 --- a/src/mol-model/structure/model/properties/atomic/types.ts +++ b/src/mol-model/structure/model/properties/atomic/types.ts @@ -14,48 +14,48 @@ export const enum Elements { H = 'H', D = 'D', T = 'T', HE = 'HE', LI = 'LI', BE = 'BE', B = 'B', C = 'C', N = 'N', O = 'O', F = 'F', NE = 'NE', NA = 'NA', MG = 'MG', AL = 'AL', SI = 'SI', P = 'P', S = 'S', CL = 'CL', AR = 'AR', K = 'K', CA = 'CA', SC = 'SC', TI = 'TI', V = 'V', CR = 'CR', MN = 'MN', FE = 'FE', CO = 'CO', NI = 'NI', CU = 'CU', ZN = 'ZN', GA = 'GA', GE = 'GE', AS = 'AS', SE = 'SE', BR = 'BR', KR = 'KR', RB = 'RB', SR = 'SR', Y = 'Y', ZR = 'ZR', NB = 'NB', MO = 'MO', TC = 'TC', RU = 'RU', RH = 'RH', PD = 'PD', AG = 'AG', CD = 'CD', IN = 'IN', SN = 'SN', SB = 'SB', TE = 'TE', I = 'I', XE = 'XE', CS = 'CS', BA = 'BA', LA = 'LA', CE = 'CE', PR = 'PR', ND = 'ND', PM = 'PM', SM = 'SM', EU = 'EU', GD = 'GD', TB = 'TB', DY = 'DY', HO = 'HO', ER = 'ER', TM = 'TM', YB = 'YB', LU = 'LU', HF = 'HF', TA = 'TA', W = 'W', RE = 'RE', OS = 'OS', IR = 'IR', PT = 'PT', AU = 'AU', HG = 'HG', TL = 'TL', PB = 'PB', BI = 'BI', PO = 'PO', AT = 'AT', RN = 'RN', FR = 'FR', RA = 'RA', AC = 'AC', TH = 'TH', PA = 'PA', U = 'U', NP = 'NP', PU = 'PU', AM = 'AM', CM = 'CM', BK = 'BK', CF = 'CF', ES = 'ES', FM = 'FM', MD = 'MD', NO = 'NO', LR = 'LR', RF = 'RF', DB = 'DB', SG = 'SG', BH = 'BH', HS = 'HS', MT = 'MT', DS = 'DS', RG = 'RG', CN = 'CN', NH = 'NH', FL = 'FL', MC = 'MC', LV = 'LV', TS = 'TS', OG = 'OG' } -export const AlkaliMetals = new Set<ElementSymbol>(['LI', 'NA', 'K', 'RB', 'CS', 'FR'] as ElementSymbol[]) -export function isAlkaliMetal(element: ElementSymbol) { return AlkaliMetals.has(element) } +export const AlkaliMetals = new Set<ElementSymbol>(['LI', 'NA', 'K', 'RB', 'CS', 'FR'] as ElementSymbol[]); +export function isAlkaliMetal(element: ElementSymbol) { return AlkaliMetals.has(element); } -export const AlkalineEarthMetals = new Set<ElementSymbol>(['BE', 'MG', 'CA', 'SR', 'BA', 'RA'] as ElementSymbol[]) -export function isAlkalineEarthMetal(element: ElementSymbol) { return AlkalineEarthMetals.has(element) } +export const AlkalineEarthMetals = new Set<ElementSymbol>(['BE', 'MG', 'CA', 'SR', 'BA', 'RA'] as ElementSymbol[]); +export function isAlkalineEarthMetal(element: ElementSymbol) { return AlkalineEarthMetals.has(element); } -export const PolyatomicNonmetals = new Set<ElementSymbol>(['C', 'P', 'S', 'SE'] as ElementSymbol[]) -export function isPolyatomicNonmetal(element: ElementSymbol) { return PolyatomicNonmetals.has(element) } +export const PolyatomicNonmetals = new Set<ElementSymbol>(['C', 'P', 'S', 'SE'] as ElementSymbol[]); +export function isPolyatomicNonmetal(element: ElementSymbol) { return PolyatomicNonmetals.has(element); } -export const DiatomicNonmetals = new Set<ElementSymbol>(['H', 'N', 'O', 'F', 'CL', 'BR', 'I'] as ElementSymbol[]) -export function isDiatomicNonmetal(element: ElementSymbol) { return DiatomicNonmetals.has(element) } +export const DiatomicNonmetals = new Set<ElementSymbol>(['H', 'N', 'O', 'F', 'CL', 'BR', 'I'] as ElementSymbol[]); +export function isDiatomicNonmetal(element: ElementSymbol) { return DiatomicNonmetals.has(element); } -export const NobleGases = new Set<ElementSymbol>(['HE', 'NE', 'AR', 'KR', 'XE', 'RN'] as ElementSymbol[]) -export function isNobleGas(element: ElementSymbol) { return NobleGases.has(element) } +export const NobleGases = new Set<ElementSymbol>(['HE', 'NE', 'AR', 'KR', 'XE', 'RN'] as ElementSymbol[]); +export function isNobleGas(element: ElementSymbol) { return NobleGases.has(element); } -export const PostTransitionMetals = new Set<ElementSymbol>(['ZN', 'GA', 'CD', 'IN', 'SN', 'HG', 'TI', 'PB', 'BI', 'PO', 'CN'] as ElementSymbol[]) -export function isPostTransitionMetal(element: ElementSymbol) { return PostTransitionMetals.has(element) } +export const PostTransitionMetals = new Set<ElementSymbol>(['ZN', 'GA', 'CD', 'IN', 'SN', 'HG', 'TI', 'PB', 'BI', 'PO', 'CN'] as ElementSymbol[]); +export function isPostTransitionMetal(element: ElementSymbol) { return PostTransitionMetals.has(element); } -export const Metalloids = new Set<ElementSymbol>(['B', 'SI', 'GE', 'AS', 'SB', 'TE', 'AT'] as ElementSymbol[]) -export function isMetalloid(element: ElementSymbol) { return Metalloids.has(element) } +export const Metalloids = new Set<ElementSymbol>(['B', 'SI', 'GE', 'AS', 'SB', 'TE', 'AT'] as ElementSymbol[]); +export function isMetalloid(element: ElementSymbol) { return Metalloids.has(element); } -export const Halogens = new Set<ElementSymbol>(['F', 'CL', 'BR', 'I', 'AT'] as ElementSymbol[]) -export function isHalogen(element: ElementSymbol) { return Halogens.has(element) } +export const Halogens = new Set<ElementSymbol>(['F', 'CL', 'BR', 'I', 'AT'] as ElementSymbol[]); +export function isHalogen(element: ElementSymbol) { return Halogens.has(element); } export function isTransitionMetal(element: ElementSymbol) { - const no = AtomNumber(element) + const no = AtomNumber(element); return ( (no >= 21 && no <= 29) || (no >= 39 && no <= 47) || (no >= 72 && no <= 79) || (no >= 104 && no <= 108) - ) + ); } export function isLanthanide (element: ElementSymbol) { - const no = AtomNumber(element) - return no >= 57 && no <= 71 + const no = AtomNumber(element); + return no >= 57 && no <= 71; } export function isActinide (element: ElementSymbol) { - const no = AtomNumber(element) - return no >= 89 && no <= 103 + const no = AtomNumber(element); + return no >= 89 && no <= 103; } export function isMetal(element: ElementSymbol) { @@ -66,7 +66,7 @@ export function isMetal(element: ElementSymbol) { isActinide(element) || isTransitionMetal(element) || isPostTransitionMetal(element) - ) + ); } export function isNonmetal(element: ElementSymbol) { @@ -74,5 +74,5 @@ export function isNonmetal(element: ElementSymbol) { isDiatomicNonmetal(element) || isPolyatomicNonmetal(element) || isNobleGas(element) - ) + ); } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/coarse.ts b/src/mol-model/structure/model/properties/coarse.ts index d1fc3decf25a10a9a54c5924d5c4cdfaa7ab556a..9519cc71933a085d785d29d6737845d4a444e704 100644 --- a/src/mol-model/structure/model/properties/coarse.ts +++ b/src/mol-model/structure/model/properties/coarse.ts @@ -4,5 +4,5 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './coarse/conformation' -export * from './coarse/hierarchy' \ No newline at end of file +export * from './coarse/conformation'; +export * from './coarse/hierarchy'; \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/coarse/conformation.ts b/src/mol-model/structure/model/properties/coarse/conformation.ts index 14511087657f84a8580a3d444c11677c483c3af3..c3ac4b3200b26a9486d3fd85ae1a2b151ebb06e5 100644 --- a/src/mol-model/structure/model/properties/coarse/conformation.ts +++ b/src/mol-model/structure/model/properties/coarse/conformation.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import UUID from '../../../../../mol-util/uuid' +import UUID from '../../../../../mol-util/uuid'; import { Mat3 } from '../../../../../mol-math/linear-algebra'; export interface CoarseConformation { diff --git a/src/mol-model/structure/model/properties/coarse/hierarchy.ts b/src/mol-model/structure/model/properties/coarse/hierarchy.ts index 9b492981242a325cdf661d128e0e9a322f1c157e..6b0b6143a664d53075b4bbf9efb819fe0d46c4d7 100644 --- a/src/mol-model/structure/model/properties/coarse/hierarchy.ts +++ b/src/mol-model/structure/model/properties/coarse/hierarchy.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column } from '../../../../../mol-data/db' +import { Column } from '../../../../../mol-data/db'; import { Segmentation } from '../../../../../mol-data/int'; import { ElementIndex, ChainIndex, EntityIndex } from '../../indexing'; import SortedRanges from '../../../../../mol-data/int/sorted-ranges'; diff --git a/src/mol-model/structure/model/properties/common.ts b/src/mol-model/structure/model/properties/common.ts index f8ae77e6b3869499d0eae32c3db939d6c92a8111..8abf7d13b15b21d26efd2e7301618ce7fb7066d6 100644 --- a/src/mol-model/structure/model/properties/common.ts +++ b/src/mol-model/structure/model/properties/common.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { mmCIF_Database, mmCIF_Schema } from '../../../../mol-io/reader/cif/schema/mmcif' +import { mmCIF_Database, mmCIF_Schema } from '../../../../mol-io/reader/cif/schema/mmcif'; import { Table, Column } from '../../../../mol-data/db'; import { EntityIndex } from '../indexing'; @@ -13,7 +13,7 @@ export type EntitySubtype = ( mmCIF_Schema['entity_poly']['type']['T'] | mmCIF_Schema['pdbx_entity_branch']['type']['T'] ) -export const EntitySubtype = Column.Schema.Aliased<EntitySubtype>(Column.Schema.Str('')) +export const EntitySubtype = Column.Schema.Aliased<EntitySubtype>(Column.Schema.Str('')); export interface Entities { data: mmCIF_Database['entity'], diff --git a/src/mol-model/structure/model/properties/seconday-structure.ts b/src/mol-model/structure/model/properties/seconday-structure.ts index 82a44214d6ded72fed3d4f11d776994d9c1523ea..c4faacb0c74832588c71534758f685461a6a4acc 100644 --- a/src/mol-model/structure/model/properties/seconday-structure.ts +++ b/src/mol-model/structure/model/properties/seconday-structure.ts @@ -19,7 +19,7 @@ interface SecondaryStructure { } function SecondaryStructure(type: SecondaryStructure['type'], key: SecondaryStructure['key'], elements: SecondaryStructure['elements'], getIndex: SecondaryStructure['getIndex']) { - return { type, key, elements, getIndex } + return { type, key, elements, getIndex }; } namespace SecondaryStructure { @@ -50,4 +50,4 @@ namespace SecondaryStructure { } } -export { SecondaryStructure } \ No newline at end of file +export { SecondaryStructure }; \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/sequence.ts b/src/mol-model/structure/model/properties/sequence.ts index f05dd175091aad6396e32c882c774333924597e6..9205a7c3457953bea0c6844af52b293ac0eeaf61 100644 --- a/src/mol-model/structure/model/properties/sequence.ts +++ b/src/mol-model/structure/model/properties/sequence.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Column } from '../../../../mol-data/db' +import { Column } from '../../../../mol-data/db'; import { AtomicHierarchy } from './atomic/hierarchy'; import { Entities } from './common'; import { Sequence } from '../../../sequence'; @@ -24,29 +24,29 @@ namespace StructureSequence { readonly sequence: Sequence } - const Empty: StructureSequence = { byEntityKey: {}, sequences: [] } + const Empty: StructureSequence = { byEntityKey: {}, sequences: [] }; function merge(...entitySeqs: StructureSequence[]): StructureSequence { - const sequences: StructureSequence.Entity[] = [] - const byEntityKey: { [key: number]: StructureSequence.Entity } = {} + const sequences: StructureSequence.Entity[] = []; + const byEntityKey: { [key: number]: StructureSequence.Entity } = {}; for (let i = 0, il = entitySeqs.length; i < il; ++i) { - sequences.push(...entitySeqs[i].sequences) - Object.assign(byEntityKey, entitySeqs[i].byEntityKey) + sequences.push(...entitySeqs[i].sequences); + Object.assign(byEntityKey, entitySeqs[i].byEntityKey); } - return { sequences, byEntityKey } + return { sequences, byEntityKey }; } export function fromHierarchy(entities: Entities, atomicHierarchy: AtomicHierarchy, coarseHierarchy: CoarseHierarchy): StructureSequence { - const atomic = fromAtomicHierarchy(entities, atomicHierarchy) - const coarse = coarseHierarchy.isDefined ? fromCoarseHierarchy(entities, coarseHierarchy) : Empty - return merge(atomic, coarse) + const atomic = fromAtomicHierarchy(entities, atomicHierarchy); + const coarse = coarseHierarchy.isDefined ? fromCoarseHierarchy(entities, coarseHierarchy) : Empty; + return merge(atomic, coarse); } export function fromAtomicHierarchy(entities: Entities, hierarchy: AtomicHierarchy): StructureSequence { - const { label_comp_id, label_seq_id } = hierarchy.residues - const { chainAtomSegments, residueAtomSegments } = hierarchy - const { count, offsets } = chainAtomSegments + const { label_comp_id, label_seq_id } = hierarchy.residues; + const { chainAtomSegments, residueAtomSegments } = hierarchy; + const { count, offsets } = chainAtomSegments; const byEntityKey: StructureSequence['byEntityKey'] = { }; const sequences: StructureSequence.Entity[] = []; @@ -85,14 +85,14 @@ namespace StructureSequence { } export function fromCoarseHierarchy(entities: Entities, hierarchy: CoarseHierarchy): StructureSequence { - const spheres = fromCoarseElements(entities, hierarchy.spheres) - const gaussians = fromCoarseElements(entities, hierarchy.gaussians) - return merge(spheres, gaussians) + const spheres = fromCoarseElements(entities, hierarchy.spheres); + const gaussians = fromCoarseElements(entities, hierarchy.gaussians); + return merge(spheres, gaussians); } export function fromCoarseElements(entities: Entities, elements: CoarseElements): StructureSequence { - const { chainElementSegments, seq_id_begin, seq_id_end } = elements - const { count, offsets } = chainElementSegments + const { chainElementSegments, seq_id_begin, seq_id_end } = elements; + const { count, offsets } = chainElementSegments; const byEntityKey: StructureSequence['byEntityKey'] = { }; const sequences: StructureSequence.Entity[] = []; @@ -131,4 +131,4 @@ namespace StructureSequence { } } -export default StructureSequence \ No newline at end of file +export default StructureSequence; \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/symmetry.ts b/src/mol-model/structure/model/properties/symmetry.ts index e4768e1f56e2fe8b59f2f21407db96ab04c5ed5b..315f708dd2e0e531ad9f10d63a66d4710b74d8ac 100644 --- a/src/mol-model/structure/model/properties/symmetry.ts +++ b/src/mol-model/structure/model/properties/symmetry.ts @@ -4,10 +4,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { SymmetryOperator } from '../../../../mol-math/geometry/symmetry-operator' -import { arrayFind } from '../../../../mol-data/util' -import { StructureQuery } from '../../query' -import { Model } from '../../model' +import { SymmetryOperator } from '../../../../mol-math/geometry/symmetry-operator'; +import { arrayFind } from '../../../../mol-data/util'; +import { StructureQuery } from '../../query'; +import { Model } from '../../model'; import { Spacegroup } from '../../../../mol-math/geometry'; import { Vec3 } from '../../../../mol-math/linear-algebra'; import { ModelSymmetry } from '../../../../mol-model-formats/structure/property/symmetry'; @@ -65,28 +65,28 @@ namespace Symmetry { export function findAssembly(model: Model, id: string): Assembly | undefined { const _id = id.toLocaleLowerCase(); - const symmetry = ModelSymmetry.Provider.get(model) + const symmetry = ModelSymmetry.Provider.get(model); return symmetry ? arrayFind(symmetry.assemblies, a => a.id.toLowerCase() === _id) : undefined; } export function getUnitcellLabel(symmetry: Symmetry) { - const { cell, name, num } = symmetry.spacegroup - const { size, anglesInRadians } = cell - const a = size[0].toFixed(2) - const b = size[1].toFixed(2) - const c = size[2].toFixed(2) - const alpha = radToDeg(anglesInRadians[0]).toFixed(2) - const beta = radToDeg(anglesInRadians[1]).toFixed(2) - const gamma = radToDeg(anglesInRadians[2]).toFixed(2) - const label: string[] = [] + const { cell, name, num } = symmetry.spacegroup; + const { size, anglesInRadians } = cell; + const a = size[0].toFixed(2); + const b = size[1].toFixed(2); + const c = size[2].toFixed(2); + const alpha = radToDeg(anglesInRadians[0]).toFixed(2); + const beta = radToDeg(anglesInRadians[1]).toFixed(2); + const gamma = radToDeg(anglesInRadians[2]).toFixed(2); + const label: string[] = []; // name - label.push(`Unitcell <b>${name}</b> #${num}`) + label.push(`Unitcell <b>${name}</b> #${num}`); // sizes - label.push(`${a}\u00D7${b}\u00D7${c} \u212B`) + label.push(`${a}\u00D7${b}\u00D7${c} \u212B`); // angles - label.push(`\u03b1=${alpha}\u00B0 \u03b2=${beta}\u00B0 \u03b3=${gamma}\u00B0`) - return label.join(' | ') + label.push(`\u03b1=${alpha}\u00B0 \u03b2=${beta}\u00B0 \u03b3=${gamma}\u00B0`); + return label.join(' | '); } } -export { Symmetry } \ No newline at end of file +export { Symmetry }; \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/utils/atomic-derived.ts b/src/mol-model/structure/model/properties/utils/atomic-derived.ts index c0cf4cc84f61da049cea848aad3cca0a793d11d3..e0209893929bd2787bb7377f3236660b7fddc0e9 100644 --- a/src/mol-model/structure/model/properties/utils/atomic-derived.ts +++ b/src/mol-model/structure/model/properties/utils/atomic-derived.ts @@ -13,56 +13,56 @@ import { ChemicalComponentMap } from '../common'; import { isProductionMode } from '../../../../../mol-util/debug'; export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemicalComponentMap: ChemicalComponentMap): AtomicDerivedData { - const { label_comp_id, _rowCount: n } = data.residues + const { label_comp_id, _rowCount: n } = data.residues; - const traceElementIndex = new Int32Array(n) - const directionFromElementIndex = new Int32Array(n) - const directionToElementIndex = new Int32Array(n) - const moleculeType = new Uint8Array(n) - const polymerType = new Uint8Array(n) + const traceElementIndex = new Int32Array(n); + const directionFromElementIndex = new Int32Array(n); + const directionToElementIndex = new Int32Array(n); + const moleculeType = new Uint8Array(n); + const polymerType = new Uint8Array(n); - const moleculeTypeMap = new Map<string, MoleculeType>() - const polymerTypeMap = new Map<string, PolymerType>() + const moleculeTypeMap = new Map<string, MoleculeType>(); + const polymerTypeMap = new Map<string, PolymerType>(); for (let i = 0 as ResidueIndex; i < n; ++i) { - const compId = label_comp_id.value(i) - const chemCompMap = chemicalComponentMap + const compId = label_comp_id.value(i); + const chemCompMap = chemicalComponentMap; - let molType: MoleculeType - let polyType: PolymerType + let molType: MoleculeType; + let polyType: PolymerType; if (moleculeTypeMap.has(compId)) { - molType = moleculeTypeMap.get(compId)! - polyType = polymerTypeMap.get(compId)! + molType = moleculeTypeMap.get(compId)!; + polyType = polymerTypeMap.get(compId)!; } else { - let type: string + let type: string; if (chemCompMap.has(compId)) { - type = chemCompMap.get(compId)!.type + type = chemCompMap.get(compId)!.type; } else { - if (!isProductionMode) console.info('chemComp not found', compId) - type = getComponentType(compId) + if (!isProductionMode) console.info('chemComp not found', compId); + type = getComponentType(compId); } - molType = getMoleculeType(type, compId) + molType = getMoleculeType(type, compId); // TODO if unknown molecule type, use atom names to guess molecule type - polyType = getPolymerType(type, molType) - moleculeTypeMap.set(compId, molType) - polymerTypeMap.set(compId, polyType) + polyType = getPolymerType(type, molType); + moleculeTypeMap.set(compId, molType); + polymerTypeMap.set(compId, polyType); } - moleculeType[i] = molType - polymerType[i] = polyType + moleculeType[i] = molType; + polymerType[i] = polyType; - const traceAtomId = getAtomIdForAtomRole(polyType, 'trace') - let traceIndex = index.findAtomsOnResidue(i, traceAtomId) + const traceAtomId = getAtomIdForAtomRole(polyType, 'trace'); + let traceIndex = index.findAtomsOnResidue(i, traceAtomId); if (traceIndex === -1) { - const coarseAtomId = getAtomIdForAtomRole(polyType, 'coarseBackbone') - traceIndex = index.findAtomsOnResidue(i, coarseAtomId) + const coarseAtomId = getAtomIdForAtomRole(polyType, 'coarseBackbone'); + traceIndex = index.findAtomsOnResidue(i, coarseAtomId); } - traceElementIndex[i] = traceIndex + traceElementIndex[i] = traceIndex; - const directionFromAtomId = getAtomIdForAtomRole(polyType, 'directionFrom') - directionFromElementIndex[i] = index.findAtomsOnResidue(i, directionFromAtomId) + const directionFromAtomId = getAtomIdForAtomRole(polyType, 'directionFrom'); + directionFromElementIndex[i] = index.findAtomsOnResidue(i, directionFromAtomId); - const directionToAtomId = getAtomIdForAtomRole(polyType, 'directionTo') - directionToElementIndex[i] = index.findAtomsOnResidue(i, directionToAtomId) + const directionToAtomId = getAtomIdForAtomRole(polyType, 'directionTo'); + directionToElementIndex[i] = index.findAtomsOnResidue(i, directionToAtomId); } return { @@ -73,5 +73,5 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi moleculeType: moleculeType as unknown as ArrayLike<MoleculeType>, polymerType: polymerType as unknown as ArrayLike<PolymerType>, } - } + }; } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/utils/atomic-index.ts b/src/mol-model/structure/model/properties/utils/atomic-index.ts index b16cbb5289ee2b1dfead9b7a32b2fdb2453a0f6b..3e82b9d5dfbe6c9f08766eb366271cf60cbf9694 100644 --- a/src/mol-model/structure/model/properties/utils/atomic-index.ts +++ b/src/mol-model/structure/model/properties/utils/atomic-index.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { AtomicData, AtomicSegments } from '../atomic' -import { Interval, Segmentation, SortedArray } from '../../../../../mol-data/int' -import { Entities } from '../common' +import { AtomicData, AtomicSegments } from '../atomic'; +import { Interval, Segmentation, SortedArray } from '../../../../../mol-data/int'; +import { Entities } from '../common'; import { ChainIndex, ResidueIndex, EntityIndex, ElementIndex } from '../../indexing'; import { AtomicIndex, AtomicHierarchy } from '../atomic/hierarchy'; import { cantorPairing } from '../../../../../mol-data/util'; @@ -83,8 +83,8 @@ class Index implements AtomicIndex { } findEntity(label_asym_id: string): EntityIndex { - const entityIndex = this.map.label_asym_id.get(label_asym_id) - return entityIndex !== undefined ? entityIndex : -1 as EntityIndex + const entityIndex = this.map.label_asym_id.get(label_asym_id); + return entityIndex !== undefined ? entityIndex : -1 as EntityIndex; } findChainLabel(key: AtomicIndex.ChainLabelKey): ChainIndex { @@ -96,9 +96,9 @@ class Index implements AtomicIndex { } findChainAuth(key: AtomicIndex.ChainAuthKey): ChainIndex { - if (!this.map.auth_asym_id_auth_seq_id.has(key.auth_asym_id)) return -1 as ChainIndex - const rm = this.map.auth_asym_id_auth_seq_id.get(key.auth_asym_id)! - return rm.has(key.auth_seq_id) ? rm.get(key.auth_seq_id)! : -1 as ChainIndex + if (!this.map.auth_asym_id_auth_seq_id.has(key.auth_asym_id)) return -1 as ChainIndex; + const rm = this.map.auth_asym_id_auth_seq_id.get(key.auth_asym_id)!; + return rm.has(key.auth_seq_id) ? rm.get(key.auth_seq_id)! : -1 as ChainIndex; } findResidue(label_entity_id: string, label_asym_id: string, auth_seq_id: number, pdbx_PDB_ins_code?: string): ResidueIndex @@ -106,7 +106,7 @@ class Index implements AtomicIndex { findResidue(label_entity_id_or_key: string | AtomicIndex.ResidueKey, label_asym_id?: string, auth_seq_id?: number, pdbx_PDB_ins_code?: string): ResidueIndex { let key: AtomicIndex.ResidueKey; if (arguments.length === 1) { - key = label_entity_id_or_key as AtomicIndex.ResidueKey + key = label_entity_id_or_key as AtomicIndex.ResidueKey; } else { _tempResidueKey.label_entity_id = label_entity_id_or_key as string; _tempResidueKey.label_asym_id = label_asym_id!; @@ -170,7 +170,7 @@ class Index implements AtomicIndex { } findAtomsOnResidue(rI: ResidueIndex, label_atom_ids: Set<string>) { - return findAtomByNames(this.residueOffsets[rI], this.residueOffsets[rI + 1], this.map.label_atom_id, label_atom_ids) + return findAtomByNames(this.residueOffsets[rI], this.residueOffsets[rI + 1], this.map.label_atom_id, label_atom_ids); } constructor(private map: Mapping) { @@ -218,13 +218,13 @@ export function getAtomicIndex(data: AtomicData, entities: Entities, segments: A map.chain_index_entity_index[chainIndex] = entityIndex; const authAsymId = auth_asym_id.value(chainIndex); - let auth_asym_id_auth_seq_id = map.auth_asym_id_auth_seq_id.get(authAsymId) + let auth_asym_id_auth_seq_id = map.auth_asym_id_auth_seq_id.get(authAsymId); if (!auth_asym_id_auth_seq_id) { auth_asym_id_auth_seq_id = new Map<number, ChainIndex>(); - map.auth_asym_id_auth_seq_id.set(authAsymId, auth_asym_id_auth_seq_id) + map.auth_asym_id_auth_seq_id.set(authAsymId, auth_asym_id_auth_seq_id); } - const labelAsymId = label_asym_id.value(chainIndex) + const labelAsymId = label_asym_id.value(chainIndex); if (!map.label_asym_id.has(labelAsymId)) map.label_asym_id.set(labelAsymId, entityIndex); updateMapMapIndex(map.entity_index_label_asym_id, entityIndex, labelAsymId, chainIndex); @@ -237,11 +237,11 @@ export function getAtomicIndex(data: AtomicData, entities: Entities, segments: A while (residuesIt.hasNext) { const residueSegment = residuesIt.move(); const rI = residueSegment.index; - const authSeqId = auth_seq_id.value(rI) + const authSeqId = auth_seq_id.value(rI); const insCode = pdbx_PDB_ins_code.value(rI); chain_index_label_seq_id.set(getResidueId(label_seq_id.value(rI), insCode), rI); chain_index_auth_seq_id.set(getResidueId(authSeqId, insCode), rI); - auth_asym_id_auth_seq_id.set(authSeqId, chainIndex) + auth_asym_id_auth_seq_id.set(authSeqId, chainIndex); } } diff --git a/src/mol-model/structure/model/properties/utils/atomic-ranges.ts b/src/mol-model/structure/model/properties/utils/atomic-ranges.ts index 19fc6abe65e27f96c3bc8940dd2e1c1045201860..b8862f209617c5db4cb3e46de45eb900d142ad12 100644 --- a/src/mol-model/structure/model/properties/utils/atomic-ranges.ts +++ b/src/mol-model/structure/model/properties/utils/atomic-ranges.ts @@ -16,92 +16,92 @@ import { Entities } from '../common'; import StructureSequence from '../sequence'; function areBackboneConnected(riStart: ResidueIndex, riEnd: ResidueIndex, conformation: AtomicConformation, index: AtomicIndex, derived: AtomicDerivedData) { - const { polymerType, traceElementIndex, directionFromElementIndex, directionToElementIndex } = derived.residue - const ptStart = polymerType[riStart] - const ptEnd = polymerType[riEnd] - if (ptStart === PolymerType.NA || ptEnd === PolymerType.NA) return false - if (traceElementIndex[riStart] === -1 || traceElementIndex[riEnd] === -1) return false + const { polymerType, traceElementIndex, directionFromElementIndex, directionToElementIndex } = derived.residue; + const ptStart = polymerType[riStart]; + const ptEnd = polymerType[riEnd]; + if (ptStart === PolymerType.NA || ptEnd === PolymerType.NA) return false; + if (traceElementIndex[riStart] === -1 || traceElementIndex[riEnd] === -1) return false; - let eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(ptStart, 'backboneStart')) - let eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(ptEnd, 'backboneEnd')) + let eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(ptStart, 'backboneStart')); + let eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(ptEnd, 'backboneEnd')); if (eiStart === -1 || eiEnd === -1) { - eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(ptStart, 'coarseBackbone')) - eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(ptEnd, 'coarseBackbone')) + eiStart = index.findAtomsOnResidue(riStart, getAtomIdForAtomRole(ptStart, 'coarseBackbone')); + eiEnd = index.findAtomsOnResidue(riEnd, getAtomIdForAtomRole(ptEnd, 'coarseBackbone')); } - const { x, y, z } = conformation - const pStart = Vec3.create(x[eiStart], y[eiStart], z[eiStart]) - const pEnd = Vec3.create(x[eiEnd], y[eiEnd], z[eiEnd]) - const isCoarse = directionFromElementIndex[riStart] === -1 || directionToElementIndex[riStart] === -1 || directionFromElementIndex[riEnd] === -1 || directionToElementIndex[riEnd] === -1 - return Vec3.distance(pStart, pEnd) < (isCoarse ? 10 : 3) + const { x, y, z } = conformation; + const pStart = Vec3.create(x[eiStart], y[eiStart], z[eiStart]); + const pEnd = Vec3.create(x[eiEnd], y[eiEnd], z[eiEnd]); + const isCoarse = directionFromElementIndex[riStart] === -1 || directionToElementIndex[riStart] === -1 || directionFromElementIndex[riEnd] === -1 || directionToElementIndex[riEnd] === -1; + return Vec3.distance(pStart, pEnd) < (isCoarse ? 10 : 3); } export function getAtomicRanges(hierarchy: AtomicHierarchy, entities: Entities, conformation: AtomicConformation, sequence: StructureSequence): AtomicRanges { - const polymerRanges: number[] = [] - const gapRanges: number[] = [] - const cyclicPolymerMap = new Map<ResidueIndex, ResidueIndex>() - const chainIt = Segmentation.transientSegments(hierarchy.chainAtomSegments, Interval.ofBounds(0, hierarchy.atoms._rowCount)) - const residueIt = Segmentation.transientSegments(hierarchy.residueAtomSegments, Interval.ofBounds(0, hierarchy.atoms._rowCount)) - const { index, derived } = hierarchy - const { label_seq_id } = hierarchy.residues - const { label_entity_id } = hierarchy.chains - const { moleculeType, traceElementIndex } = derived.residue + const polymerRanges: number[] = []; + const gapRanges: number[] = []; + const cyclicPolymerMap = new Map<ResidueIndex, ResidueIndex>(); + const chainIt = Segmentation.transientSegments(hierarchy.chainAtomSegments, Interval.ofBounds(0, hierarchy.atoms._rowCount)); + const residueIt = Segmentation.transientSegments(hierarchy.residueAtomSegments, Interval.ofBounds(0, hierarchy.atoms._rowCount)); + const { index, derived } = hierarchy; + const { label_seq_id } = hierarchy.residues; + const { label_entity_id } = hierarchy.chains; + const { moleculeType, traceElementIndex } = derived.residue; - let prevSeqId: number - let prevStart: number - let prevEnd: number - let startIndex: number + let prevSeqId: number; + let prevStart: number; + let prevEnd: number; + let startIndex: number; while (chainIt.hasNext) { const chainSegment = chainIt.move(); residueIt.setSegment(chainSegment); - prevSeqId = -1 - prevStart = -1 - prevEnd = -1 - startIndex = -1 + prevSeqId = -1; + prevStart = -1; + prevEnd = -1; + startIndex = -1; - const eI = entities.getEntityIndex(label_entity_id.value(chainSegment.index)) - const seq = sequence.byEntityKey[eI] - const maxSeqId = seq ? seq.sequence.seqId.value(seq.sequence.seqId.rowCount - 1) : -1 + const eI = entities.getEntityIndex(label_entity_id.value(chainSegment.index)); + const seq = sequence.byEntityKey[eI]; + const maxSeqId = seq ? seq.sequence.seqId.value(seq.sequence.seqId.rowCount - 1) : -1; // check cyclic peptides, seqIds and distance must be compatible - const riStart = hierarchy.residueAtomSegments.index[chainSegment.start] - const riEnd = hierarchy.residueAtomSegments.index[chainSegment.end - 1] - const seqIdStart = label_seq_id.value(riStart) - const seqIdEnd = label_seq_id.value(riEnd) + const riStart = hierarchy.residueAtomSegments.index[chainSegment.start]; + const riEnd = hierarchy.residueAtomSegments.index[chainSegment.end - 1]; + const seqIdStart = label_seq_id.value(riStart); + const seqIdEnd = label_seq_id.value(riEnd); if (seqIdStart === 1 && seqIdEnd === maxSeqId && conformation.xyzDefined && areBackboneConnected(riStart, riEnd, conformation, index, derived)) { - cyclicPolymerMap.set(riStart, riEnd) - cyclicPolymerMap.set(riEnd, riStart) + cyclicPolymerMap.set(riStart, riEnd); + cyclicPolymerMap.set(riEnd, riStart); } while (residueIt.hasNext) { const residueSegment = residueIt.move(); - const residueIndex = residueSegment.index - const seqId = label_seq_id.value(residueIndex) + const residueIndex = residueSegment.index; + const seqId = label_seq_id.value(residueIndex); // treat polymers residues that don't have a trace element resolved as gaps if (isPolymer(moleculeType[residueIndex]) && traceElementIndex[residueIndex] !== -1) { if (startIndex !== -1) { if (seqId !== prevSeqId + 1) { - polymerRanges.push(startIndex, prevEnd - 1) - gapRanges.push(prevStart, residueSegment.end - 1) - startIndex = residueSegment.start + polymerRanges.push(startIndex, prevEnd - 1); + gapRanges.push(prevStart, residueSegment.end - 1); + startIndex = residueSegment.start; } else if (!residueIt.hasNext) { - polymerRanges.push(startIndex, residueSegment.end - 1) + polymerRanges.push(startIndex, residueSegment.end - 1); // TODO // if (seqId !== maxSeqId) { // gapRanges.push(residueSegment.end - 1, residueSegment.end - 1) // } } else { - const riStart = hierarchy.residueAtomSegments.index[residueSegment.start] - const riEnd = hierarchy.residueAtomSegments.index[prevEnd - 1] + const riStart = hierarchy.residueAtomSegments.index[residueSegment.start]; + const riEnd = hierarchy.residueAtomSegments.index[prevEnd - 1]; if (conformation.xyzDefined && !areBackboneConnected(riStart, riEnd, conformation, hierarchy.index, derived)) { - polymerRanges.push(startIndex, prevEnd - 1) - startIndex = residueSegment.start + polymerRanges.push(startIndex, prevEnd - 1); + startIndex = residueSegment.start; } } } else { - startIndex = residueSegment.start // start polymer + startIndex = residueSegment.start; // start polymer // TODO // if (seqId !== 1) { // gapRanges.push(residueSegment.start, residueSegment.start) @@ -109,14 +109,14 @@ export function getAtomicRanges(hierarchy: AtomicHierarchy, entities: Entities, } } else { if (startIndex !== -1) { - polymerRanges.push(startIndex, prevEnd - 1) - startIndex = -1 + polymerRanges.push(startIndex, prevEnd - 1); + startIndex = -1; } } - prevStart = residueSegment.start - prevEnd = residueSegment.end - prevSeqId = seqId + prevStart = residueSegment.start; + prevEnd = residueSegment.end; + prevSeqId = seqId; } } @@ -124,5 +124,5 @@ export function getAtomicRanges(hierarchy: AtomicHierarchy, entities: Entities, polymerRanges: SortedRanges.ofSortedRanges(polymerRanges as ElementIndex[]), gapRanges: SortedRanges.ofSortedRanges(gapRanges as ElementIndex[]), cyclicPolymerMap - } + }; } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/utils/coarse-keys.ts b/src/mol-model/structure/model/properties/utils/coarse-keys.ts index 888932dff1987a24ce737c2a9090489e03b29ef0..fb1c74d4476d7ad12fa9e2db1ea0643cfbd41d0f 100644 --- a/src/mol-model/structure/model/properties/utils/coarse-keys.ts +++ b/src/mol-model/structure/model/properties/utils/coarse-keys.ts @@ -33,19 +33,19 @@ function createLookUp(entities: Entities, chain: Map<number, Map<string, number> const cm = chain.get(eKey)!; if (!cm.has(c)) return -1 as ChainIndex; return cm.get(c)! as ChainIndex; - } + }; const findSequenceKey: CoarsedElementKeys['findSequenceKey'] = (e, c, s) => { const eKey = getEntKey(e); if (eKey < 0) return -1 as ElementIndex; const cm = chain.get(eKey); - if (cm === undefined) return -1 as ElementIndex - const cKey = cm.get(c) - if (cKey === undefined) return -1 as ElementIndex - const sm = seq.get(cKey)! - const { elementIndices, seqRanges } = sm - const idx = SortedRanges.firstIntersectionIndex(seqRanges, OrderedSet.ofSingleton(s)) - return (idx !== -1 ? elementIndices[idx] : -1) as ElementIndex - } + if (cm === undefined) return -1 as ElementIndex; + const cKey = cm.get(c); + if (cKey === undefined) return -1 as ElementIndex; + const sm = seq.get(cKey)!; + const { elementIndices, seqRanges } = sm; + const idx = SortedRanges.firstIntersectionIndex(seqRanges, OrderedSet.ofSingleton(s)); + return (idx !== -1 ? elementIndices[idx] : -1) as ElementIndex; + }; return { findChainKey, findSequenceKey }; } @@ -72,34 +72,34 @@ export function getCoarseKeys(data: CoarseElementData, entities: Entities): Coar } for (let cI = 0; cI < chainElementSegments.count; cI++) { - const start = chainElementSegments.offsets[cI] + const start = chainElementSegments.offsets[cI]; const end = chainElementSegments.offsets[cI + 1]; - const eK = entityKey[start] + const eK = entityKey[start]; - chainToEntity[cI] = eK + chainToEntity[cI] = eK; const map = getElementSubstructureKeyMap(chainMaps, eK); const key = getElementKey(map, asym_id.value(start), chainCounter) as ChainIndex; for (let i = start; i < end; i++) chainKey[i] = key; // create seq_id map for the ranges defined by seq_id_begin and seq_id_end - const elementIndices: number[] = [] - const seqRanges: number[] = [] + const elementIndices: number[] = []; + const seqRanges: number[] = []; for (let i = start; i < end; i++) { - const seqStart = seq_id_begin.value(i) - const seqEnd = seq_id_end.value(i) - elementIndices.push(i) - seqRanges.push(seqStart, seqEnd) + const seqStart = seq_id_begin.value(i); + const seqEnd = seq_id_end.value(i); + elementIndices.push(i); + seqRanges.push(seqStart, seqEnd); } - const seqMap = { elementIndices, seqRanges: SortedRanges.ofSortedRanges(seqRanges) } - seqMaps.set(key, seqMap) + const seqMap = { elementIndices, seqRanges: SortedRanges.ofSortedRanges(seqRanges) }; + seqMaps.set(key, seqMap); } const { findChainKey, findSequenceKey } = createLookUp(entities, chainMaps, seqMaps); const getEntityFromChain: CoarsedElementKeys['getEntityFromChain'] = c => { - return chainToEntity[c] - } + return chainToEntity[c]; + }; return { chainKey, entityKey, findSequenceKey, findChainKey, getEntityFromChain }; } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/utils/coarse-ranges.ts b/src/mol-model/structure/model/properties/utils/coarse-ranges.ts index 74c5f432ea7e9ad99aa7f6c39aa7e11f712e6eba..2a3912e36a5cd997745cd4ddc31ada59590e19ad 100644 --- a/src/mol-model/structure/model/properties/utils/coarse-ranges.ts +++ b/src/mol-model/structure/model/properties/utils/coarse-ranges.ts @@ -14,38 +14,38 @@ import { ChemicalComponent } from '../common'; // TODO add gaps at the ends of the chains by comparing to the polymer sequence data export function getCoarseRanges(data: CoarseElementData, chemicalComponentMap: ReadonlyMap<string, ChemicalComponent>): CoarseRanges { - const polymerRanges: number[] = [] - const gapRanges: number[] = [] - const chainIt = Segmentation.transientSegments(data.chainElementSegments, Interval.ofBounds(0, data.count)) + const polymerRanges: number[] = []; + const gapRanges: number[] = []; + const chainIt = Segmentation.transientSegments(data.chainElementSegments, Interval.ofBounds(0, data.count)); - const { seq_id_begin, seq_id_end } = data + const { seq_id_begin, seq_id_end } = data; while (chainIt.hasNext) { const { start, end } = chainIt.move(); - let startIndex = -1 - let prevSeqEnd = -1 + let startIndex = -1; + let prevSeqEnd = -1; for (let i = start; i < end; ++i) { - const seqEnd = seq_id_end.value(i) + const seqEnd = seq_id_end.value(i); if (i === start) { - startIndex = i - prevSeqEnd = seq_id_end.value(i) + startIndex = i; + prevSeqEnd = seq_id_end.value(i); } else { if (prevSeqEnd !== seq_id_begin.value(i) - 1) { - polymerRanges.push(startIndex, i - 1) - gapRanges.push(i - 1, i) - startIndex = i + polymerRanges.push(startIndex, i - 1); + gapRanges.push(i - 1, i); + startIndex = i; } } if (i === end - 1) { - polymerRanges.push(startIndex, i) + polymerRanges.push(startIndex, i); } - prevSeqEnd = seqEnd + prevSeqEnd = seqEnd; } } return { polymerRanges: SortedRanges.ofSortedRanges(polymerRanges as ElementIndex[]), gapRanges: SortedRanges.ofSortedRanges(gapRanges as ElementIndex[]) - } + }; } \ No newline at end of file diff --git a/src/mol-model/structure/model/properties/utils/guess-element.ts b/src/mol-model/structure/model/properties/utils/guess-element.ts index 54a66a8f99537da61f09ebcdab5c4a30e33237fc..1edda9dbbb4e47d78d9516213d437eb981a205d0 100644 --- a/src/mol-model/structure/model/properties/utils/guess-element.ts +++ b/src/mol-model/structure/model/properties/utils/guess-element.ts @@ -4,30 +4,30 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -const elm1 = [ 'H', 'C', 'O', 'N', 'S', 'P' ] -const elm2 = [ 'NA', 'CL', 'FE' ] +const elm1 = [ 'H', 'C', 'O', 'N', 'S', 'P' ]; +const elm2 = [ 'NA', 'CL', 'FE' ]; function charAtIsNumber(str: string, index: number) { - const code = str.charCodeAt(index) - return code >= 48 && code <= 57 + const code = str.charCodeAt(index); + return code >= 48 && code <= 57; } export function guessElement(str: string) { - let at = str.trim().toUpperCase() + let at = str.trim().toUpperCase(); - if (charAtIsNumber(at, 0)) at = at.substr(1) + if (charAtIsNumber(at, 0)) at = at.substr(1); // parse again to check for a second integer - if (charAtIsNumber(at, 0)) at = at.substr(1) - const n = at.length + if (charAtIsNumber(at, 0)) at = at.substr(1); + const n = at.length; - if (n === 0) return '' - if (n === 1) return at + if (n === 0) return ''; + if (n === 1) return at; if (n === 2) { - if (elm2.indexOf(at) !== -1) return at - if (elm1.indexOf(at[0]) !== -1) return at[0] + if (elm2.indexOf(at) !== -1) return at; + if (elm1.indexOf(at[0]) !== -1) return at[0]; } if (n >= 3) { - if (elm1.indexOf(at[0]) !== -1) return at[0] + if (elm1.indexOf(at[0]) !== -1) return at[0]; } - return '' + return ''; } diff --git a/src/mol-model/structure/model/types.ts b/src/mol-model/structure/model/types.ts index fd37efe1d499a5c0193eac441e13ad09cdbc80e3..59a6e7a8be33d9a20fe9129e48833a2939a51f49 100644 --- a/src/mol-model/structure/model/types.ts +++ b/src/mol-model/structure/model/types.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import BitFlags from '../../../mol-util/bit-flags' +import BitFlags from '../../../mol-util/bit-flags'; import { SaccharideCompIdMap } from '../structure/carbohydrates/constants'; import { mmCIF_Schema } from '../../../mol-io/reader/cif/schema/mmcif'; import { SetUtils } from '../../../mol-util/set'; @@ -132,71 +132,71 @@ export const PolymerTypeAtomRoleId: { [k in PolymerType]: { [k in AtomRole]: Set backboneEnd: new Set(['C\'', 'C*']), coarseBackbone: new Set(['P']) } -} +}; export const ProteinBackboneAtoms = new Set([ 'CA', 'C', 'N', 'O', 'O1', 'O2', 'OC1', 'OC2', 'OX1', 'OXT', 'H', 'H1', 'H2', 'H3', 'HA', 'HN', 'HXT', 'BB' -]) +]); export const NucleicBackboneAtoms = new Set([ 'P', 'OP1', 'OP2', 'HOP2', 'HOP3', 'O2\'', 'O3\'', 'O4\'', 'O5\'', 'C1\'', 'C2\'', 'C3\'', 'C4\'', 'C5\'', 'H1\'', 'H2\'', 'H2\'\'', 'HO2\'', 'H3\'', 'H4\'', 'H5\'', 'H5\'\'', 'HO3\'', 'HO5\'', 'O2*', 'O3*', 'O4*', 'O5*', 'C1*', 'C2*', 'C3*', 'C4*', 'C5*' -]) +]); /** Chemical component type names for D-linked protein */ export const DProteinComponentTypeNames = new Set([ 'D-PEPTIDE LINKING', 'D-PEPTIDE NH3 AMINO TERMINUS', 'D-PEPTIDE COOH CARBOXY TERMINUS', 'D-GAMMA-PEPTIDE, C-DELTA LINKING', 'D-BETA-PEPTIDE, C-GAMMA LINKING' -]) +]); /** Chemical component type names for L-linked protein */ export const LProteinComponentTypeNames = new Set([ 'L-PEPTIDE LINKING', 'L-PEPTIDE NH3 AMINO TERMINUS', 'L-PEPTIDE COOH CARBOXY TERMINUS', 'L-GAMMA-PEPTIDE, C-DELTA LINKING', 'L-BETA-PEPTIDE, C-GAMMA LINKING' -]) +]); /** Chemical component type names for gamma protein, overlaps with D/L-linked */ export const GammaProteinComponentTypeNames = new Set([ 'D-GAMMA-PEPTIDE, C-DELTA LINKING', 'L-GAMMA-PEPTIDE, C-DELTA LINKING' -]) +]); /** Chemical component type names for beta protein, overlaps with D/L-linked */ export const BetaProteinComponentTypeNames = new Set([ 'D-BETA-PEPTIDE, C-GAMMA LINKING', 'L-BETA-PEPTIDE, C-GAMMA LINKING' -]) +]); /** Chemical component type names for protein termini, overlaps with D/L-linked */ export const ProteinTerminusComponentTypeNames = new Set([ 'D-PEPTIDE NH3 AMINO TERMINUS', 'D-PEPTIDE COOH CARBOXY TERMINUS', 'L-PEPTIDE NH3 AMINO TERMINUS', 'L-PEPTIDE COOH CARBOXY TERMINUS' -]) +]); /** Chemical component type names for pepdite-like protein */ export const OtherProteinComponentTypeNames = new Set([ 'PEPTIDE LINKING', 'PEPTIDE-LIKE', -]) +]); /** Chemical component type names for protein */ export const ProteinComponentTypeNames = SetUtils.unionMany( DProteinComponentTypeNames, LProteinComponentTypeNames, OtherProteinComponentTypeNames -) +); /** Chemical component type names for DNA */ export const DNAComponentTypeNames = new Set([ 'DNA LINKING', 'L-DNA LINKING', 'DNA OH 5 PRIME TERMINUS', 'DNA OH 3 PRIME TERMINUS', -]) +]); /** Chemical component type names for RNA */ export const RNAComponentTypeNames = new Set([ 'RNA LINKING', 'L-RNA LINKING', 'RNA OH 5 PRIME TERMINUS', 'RNA OH 3 PRIME TERMINUS', -]) +]); /** Chemical component type names for saccharide */ export const SaccharideComponentTypeNames = new Set([ @@ -206,23 +206,23 @@ export const SaccharideComponentTypeNames = new Set([ // the following four are marked to be deprecated in the mmCIF dictionary 'D-SACCHARIDE 1,4 AND 1,4 LINKING', 'L-SACCHARIDE 1,4 AND 1,4 LINKING', 'D-SACCHARIDE 1,4 AND 1,6 LINKING', 'L-SACCHARIDE 1,4 AND 1,6 LINKING', -]) +]); /** Chemical component type names for other */ export const OtherComponentTypeNames = new Set([ 'NON-POLYMER', 'OTHER' -]) +]); /** Common names for water molecules */ export const WaterNames = new Set([ 'SOL', 'WAT', 'HOH', 'H2O', 'W', 'DOD', 'D3O', 'TIP3', 'TIP4', 'SPC' -]) +]); export const AminoAcidNamesL = new Set([ 'HIS', 'ARG', 'LYS', 'ILE', 'PHE', 'LEU', 'TRP', 'ALA', 'MET', 'PRO', 'CYS', 'ASN', 'VAL', 'GLY', 'SER', 'GLN', 'TYR', 'ASP', 'GLU', 'THR', 'SEC', 'PYL', 'UNK' // unknown amino acid from CCD -]) +]); export const AminoAcidNamesD = new Set([ 'DAL', // D-ALANINE 'DAR', // D-ARGININE @@ -245,92 +245,92 @@ export const AminoAcidNamesD = new Set([ 'DVA', // D-VALINE 'DNE' // D-NORLEUCINE // ??? // D-SELENOCYSTEINE -]) -export const AminoAcidNames = SetUtils.unionMany(AminoAcidNamesL, AminoAcidNamesD) +]); +export const AminoAcidNames = SetUtils.unionMany(AminoAcidNamesL, AminoAcidNamesD); export const RnaBaseNames = new Set([ 'A', 'C', 'T', 'G', 'I', 'U', 'N' // unknown RNA base from CCD -]) +]); export const DnaBaseNames = new Set([ 'DA', 'DC', 'DT', 'DG', 'DI', 'DU', 'DN' // unknown DNA base from CCD -]) -export const PeptideBaseNames = new Set([ 'APN', 'CPN', 'TPN', 'GPN' ]) -export const PurineBaseNames = new Set([ 'A', 'G', 'I', 'DA', 'DG', 'DI', 'APN', 'GPN' ]) -export const PyrimidineBaseNames = new Set([ 'C', 'T', 'U', 'DC', 'DT', 'DU', 'CPN', 'TPN' ]) -export const BaseNames = SetUtils.unionMany(RnaBaseNames, DnaBaseNames, PeptideBaseNames) +]); +export const PeptideBaseNames = new Set([ 'APN', 'CPN', 'TPN', 'GPN' ]); +export const PurineBaseNames = new Set([ 'A', 'G', 'I', 'DA', 'DG', 'DI', 'APN', 'GPN' ]); +export const PyrimidineBaseNames = new Set([ 'C', 'T', 'U', 'DC', 'DT', 'DU', 'CPN', 'TPN' ]); +export const BaseNames = SetUtils.unionMany(RnaBaseNames, DnaBaseNames, PeptideBaseNames); -export const isPurineBase = (compId: string) => PurineBaseNames.has(compId.toUpperCase()) -export const isPyrimidineBase = (compId: string) => PyrimidineBaseNames.has(compId.toUpperCase()) +export const isPurineBase = (compId: string) => PurineBaseNames.has(compId.toUpperCase()); +export const isPyrimidineBase = (compId: string) => PyrimidineBaseNames.has(compId.toUpperCase()); -export const PolymerNames = SetUtils.unionMany(AminoAcidNames, BaseNames) +export const PolymerNames = SetUtils.unionMany(AminoAcidNames, BaseNames); /** get the molecule type from component type and id */ export function getMoleculeType(compType: string, compId: string): MoleculeType { - compType = compType.toUpperCase() - compId = compId.toUpperCase() + compType = compType.toUpperCase(); + compId = compId.toUpperCase(); if (PeptideBaseNames.has(compId)) { - return MoleculeType.PNA + return MoleculeType.PNA; } else if (ProteinComponentTypeNames.has(compType)) { - return MoleculeType.Protein + return MoleculeType.Protein; } else if (RNAComponentTypeNames.has(compType)) { - return MoleculeType.RNA + return MoleculeType.RNA; } else if (DNAComponentTypeNames.has(compType)) { - return MoleculeType.DNA + return MoleculeType.DNA; } else if (SaccharideComponentTypeNames.has(compType)) { - return MoleculeType.Saccharide + return MoleculeType.Saccharide; } else if (WaterNames.has(compId)) { - return MoleculeType.Water + return MoleculeType.Water; } else if (IonNames.has(compId)) { - return MoleculeType.Ion + return MoleculeType.Ion; } else if (OtherComponentTypeNames.has(compType)) { if (SaccharideCompIdMap.has(compId)) { // trust our saccharide table more than given 'non-polymer' or 'other' component type - return MoleculeType.Saccharide + return MoleculeType.Saccharide; } else { - return MoleculeType.Other + return MoleculeType.Other; } } else { - return MoleculeType.Unknown + return MoleculeType.Unknown; } } export function getPolymerType(compType: string, molType: MoleculeType): PolymerType { - compType = compType.toUpperCase() + compType = compType.toUpperCase(); if (molType === MoleculeType.Protein) { if (GammaProteinComponentTypeNames.has(compType)) { - return PolymerType.GammaProtein + return PolymerType.GammaProtein; } else if (BetaProteinComponentTypeNames.has(compType)) { - return PolymerType.BetaProtein + return PolymerType.BetaProtein; } else if (ProteinTerminusComponentTypeNames.has(compType)) { - return PolymerType.NA + return PolymerType.NA; } else { - return PolymerType.Protein + return PolymerType.Protein; } } else if (molType === MoleculeType.RNA) { - return PolymerType.RNA + return PolymerType.RNA; } else if (molType === MoleculeType.DNA) { - return PolymerType.DNA + return PolymerType.DNA; } else if (molType === MoleculeType.PNA) { - return PolymerType.PNA + return PolymerType.PNA; } else { - return PolymerType.NA + return PolymerType.NA; } } export function getComponentType(compId: string): mmCIF_Schema['chem_comp']['type']['T'] { - compId = compId.toUpperCase() + compId = compId.toUpperCase(); if (AminoAcidNames.has(compId)) { - return 'peptide linking' + return 'peptide linking'; } else if (RnaBaseNames.has(compId)) { - return 'RNA linking' + return 'RNA linking'; } else if (DnaBaseNames.has(compId)) { - return 'DNA linking' + return 'DNA linking'; } else if (SaccharideCompIdMap.has(compId)) { - return 'saccharide' + return 'saccharide'; } else { - return 'other' + return 'other'; } } @@ -349,58 +349,58 @@ export function getDefaultChemicalComponent(compId: string): ChemicalComponent { } export function getEntityType(compId: string): mmCIF_Schema['entity']['type']['T'] { - compId = compId.toUpperCase() + compId = compId.toUpperCase(); if (WaterNames.has(compId)) { - return 'water' + return 'water'; } else if (PolymerNames.has(compId)) { - return 'polymer' + return 'polymer'; } else if (SaccharideCompIdMap.has(compId)) { - return 'branched' + return 'branched'; } else { - return 'non-polymer' + return 'non-polymer'; } } export function getEntitySubtype(compId: string, compType: string): EntitySubtype { - compId = compId.toUpperCase() - compType = compType.toUpperCase() + compId = compId.toUpperCase(); + compType = compType.toUpperCase(); if (LProteinComponentTypeNames.has(compType)) { - return 'polypeptide(L)' + return 'polypeptide(L)'; } else if (DProteinComponentTypeNames.has(compType)) { - return 'polypeptide(D)' + return 'polypeptide(D)'; } else if (RNAComponentTypeNames.has(compType)) { - return 'polyribonucleotide' + return 'polyribonucleotide'; } else if (DNAComponentTypeNames.has(compType)) { - return 'polydeoxyribonucleotide' + return 'polydeoxyribonucleotide'; } else if (SaccharideComponentTypeNames.has(compType)) { - return 'oligosaccharide' + return 'oligosaccharide'; } else if (SaccharideCompIdMap.has(compId)) { - return 'oligosaccharide' + return 'oligosaccharide'; } else if (PeptideBaseNames.has(compId)) { - return 'peptide nucleic acid' + return 'peptide nucleic acid'; } else if (AminoAcidNamesL.has(compId)) { - return 'polypeptide(L)' + return 'polypeptide(L)'; } else if (AminoAcidNamesD.has(compId)) { - return 'polypeptide(D)' + return 'polypeptide(D)'; } else if (RnaBaseNames.has(compId)) { - return 'polyribonucleotide' + return 'polyribonucleotide'; } else if (DnaBaseNames.has(compId)) { - return 'polydeoxyribonucleotide' + return 'polydeoxyribonucleotide'; } else { - return 'other' + return 'other'; } } export function isPolymer(moleculeType: MoleculeType) { - return isNucleic(moleculeType) || isProtein(moleculeType) + return isNucleic(moleculeType) || isProtein(moleculeType); } export function isNucleic(moleculeType: MoleculeType) { - return moleculeType === MoleculeType.DNA || moleculeType === MoleculeType.RNA || moleculeType === MoleculeType.PNA + return moleculeType === MoleculeType.DNA || moleculeType === MoleculeType.RNA || moleculeType === MoleculeType.PNA; } export function isProtein(moleculeType: MoleculeType) { - return moleculeType === MoleculeType.Protein + return moleculeType === MoleculeType.Protein; } /** @@ -437,12 +437,12 @@ export const IonNames = new Set([ 'YB2', 'YH', 'YT3', 'ZCM', 'ZN', 'ZN2', 'ZN3', 'ZNO', 'ZO3', // additional ion names 'OHX' -]) +]); export type SecondaryStructureType = BitFlags<SecondaryStructureType.Flag> export namespace SecondaryStructureType { - export const is: (ss: SecondaryStructureType, f: Flag) => boolean = BitFlags.has - export const create: (fs: Flag) => SecondaryStructureType = BitFlags.create + export const is: (ss: SecondaryStructureType, f: Flag) => boolean = BitFlags.has; + export const create: (fs: Flag) => SecondaryStructureType = BitFlags.create; export const enum Flag { None = 0x0, @@ -531,7 +531,7 @@ export namespace SecondaryStructureType { TURN_TY2_P: Flag.Turn | Flag.ClassicTurn | Flag.Turn2, // type II turn (protein) TURN_TY3P_P: Flag.Turn | Flag.InverseTurn | Flag.Turn3, // type III prime turn (protein) TURN_TY3_P: Flag.Turn | Flag.ClassicTurn | Flag.Turn3, // type III turn (protein) - } + }; export const SecondaryStructurePdb: { [value: string]: number } = { 1: Flag.Helix | Flag.RightHanded | Flag.HelixAlpha, // Right-handed alpha (default) @@ -544,7 +544,7 @@ export namespace SecondaryStructureType { 8: Flag.Helix | Flag.LeftHanded | Flag.HelixGamma, // Left-handed gamma 9: Flag.Helix | Flag.Helix27, // 27 ribbon/helix 10: Flag.Helix | Flag.HelixPolyproline, // Polyproline - } + }; export const SecondaryStructureStride: { [value: string]: number } = { H: Flag.Helix | Flag.HelixAlpha, // Alpha helix @@ -554,7 +554,7 @@ export namespace SecondaryStructureType { B: Flag.Beta | Flag.BetaStrand, // Isolated bridge T: Flag.Turn, // Turn C: Flag.NA, // Coil (none of the above) - } + }; export const SecondaryStructureDssp: { [value: string]: number } = { H: Flag.Helix | Flag.HelixAlpha, // alpha-helix @@ -564,7 +564,7 @@ export namespace SecondaryStructureType { I: Flag.Helix | Flag.HelixPi, // 5 helix (pi-helix) T: Flag.Turn, // hydrogen bonded turn S: Flag.Bend, // bend - } + }; } /** Maximum accessible surface area observed for amino acids. Taken from: http://dx.doi.org/10.1371/journal.pone.0080635 */ @@ -589,12 +589,12 @@ export const MaxAsa = { 'TRP': 264.0, 'TYR': 255.0, 'VAL': 165.0 -} -export const DefaultMaxAsa = 121.0 +}; +export const DefaultMaxAsa = 121.0; export type BondType = BitFlags<BondType.Flag> export namespace BondType { - export const is: (b: BondType, f: Flag) => boolean = BitFlags.has + export const is: (b: BondType, f: Flag) => boolean = BitFlags.has; export const enum Flag { None = 0x0, Covalent = 0x1, @@ -621,11 +621,11 @@ export namespace BondType { 'disulfide': Flag.HydrogenBond, 'aromatic': Flag.HydrogenBond, 'computed': Flag.HydrogenBond, - } + }; export type Names = keyof typeof Names export function isName(name: string): name is Names { - return name in Names + return name in Names; } export function fromName(name: Names): Flag { @@ -640,11 +640,11 @@ export namespace BondType { } export function fromNames(names: Names[]): Flag { - let f = Flag.None + let f = Flag.None; for (let i = 0, il = names.length; i < il; ++i) { - f |= fromName(names[i]) + f |= fromName(names[i]); } - return f + return f; } } @@ -679,5 +679,5 @@ export const ResidueHydrophobicity = { 'TRP': [ -1.85, -2.09, -0.24 ], 'TYR': [ -0.94, -0.71, 0.23 ], 'VAL': [ 0.07, -0.46, -0.53 ] -} -export const DefaultResidueHydrophobicity = [ 0.00, 0.00, 0.00 ] \ No newline at end of file +}; +export const DefaultResidueHydrophobicity = [ 0.00, 0.00, 0.00 ]; \ No newline at end of file diff --git a/src/mol-model/structure/model/util.ts b/src/mol-model/structure/model/util.ts index 2793632f772a453cd2e41801d7b7f59697def1e4..0067accbec64009cf407e9219724530f162b460a 100644 --- a/src/mol-model/structure/model/util.ts +++ b/src/mol-model/structure/model/util.ts @@ -10,36 +10,36 @@ import { CoarseConformation } from './properties/coarse'; import { arrayMinMax } from '../../../mol-util/array'; export function calcModelCenter(atomicConformation: AtomicConformation, coarseConformation?: CoarseConformation) { - let rangesX: number[] = [] - let rangesY: number[] = [] - let rangesZ: number[] = [] + let rangesX: number[] = []; + let rangesY: number[] = []; + let rangesZ: number[] = []; if (atomicConformation.x.length) { - rangesX.push(...arrayMinMax(atomicConformation.x)) - rangesY.push(...arrayMinMax(atomicConformation.y)) - rangesZ.push(...arrayMinMax(atomicConformation.z)) + rangesX.push(...arrayMinMax(atomicConformation.x)); + rangesY.push(...arrayMinMax(atomicConformation.y)); + rangesZ.push(...arrayMinMax(atomicConformation.z)); } if (coarseConformation) { if (coarseConformation.spheres.x.length) { - rangesX.push(...arrayMinMax(coarseConformation.spheres.x)) - rangesY.push(...arrayMinMax(coarseConformation.spheres.y)) - rangesZ.push(...arrayMinMax(coarseConformation.spheres.z)) + rangesX.push(...arrayMinMax(coarseConformation.spheres.x)); + rangesY.push(...arrayMinMax(coarseConformation.spheres.y)); + rangesZ.push(...arrayMinMax(coarseConformation.spheres.z)); } if (coarseConformation.gaussians.x.length) { - rangesX.push(...arrayMinMax(coarseConformation.gaussians.x)) - rangesY.push(...arrayMinMax(coarseConformation.gaussians.y)) - rangesZ.push(...arrayMinMax(coarseConformation.gaussians.z)) + rangesX.push(...arrayMinMax(coarseConformation.gaussians.x)); + rangesY.push(...arrayMinMax(coarseConformation.gaussians.y)); + rangesZ.push(...arrayMinMax(coarseConformation.gaussians.z)); } } - const [minX, maxX] = arrayMinMax(rangesX) - const [minY, maxY] = arrayMinMax(rangesY) - const [minZ, maxZ] = arrayMinMax(rangesZ) + const [minX, maxX] = arrayMinMax(rangesX); + const [minY, maxY] = arrayMinMax(rangesY); + const [minZ, maxZ] = arrayMinMax(rangesZ); - const x = minX + (maxX - minX) / 2 - const y = minY + (maxY - minY) / 2 - const z = minZ + (maxZ - minZ) / 2 + const x = minX + (maxX - minX) / 2; + const y = minY + (maxY - minY) / 2; + const z = minZ + (maxZ - minZ) / 2; - return Vec3.create(x, y, z) + return Vec3.create(x, y, z); } \ No newline at end of file diff --git a/src/mol-model/structure/query.ts b/src/mol-model/structure/query.ts index 8538f0bc795a9043518a5109bf5df6f86609586e..e727c2b4a91a211e4eb243ac79ae48c8277548d4 100644 --- a/src/mol-model/structure/query.ts +++ b/src/mol-model/structure/query.ts @@ -4,15 +4,15 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { StructureSelection } from './query/selection' -import { StructureQuery } from './query/query' -export * from './query/context' -import * as generators from './query/queries/generators' -import * as modifiers from './query/queries/modifiers' -import * as filters from './query/queries/filters' -import * as combinators from './query/queries/combinators' -import * as internal from './query/queries/internal' -import pred from './query/predicates' +import { StructureSelection } from './query/selection'; +import { StructureQuery } from './query/query'; +export * from './query/context'; +import * as generators from './query/queries/generators'; +import * as modifiers from './query/queries/modifiers'; +import * as filters from './query/queries/filters'; +import * as combinators from './query/queries/combinators'; +import * as internal from './query/queries/internal'; +import pred from './query/predicates'; export const Queries = { generators, @@ -21,6 +21,6 @@ export const Queries = { combinators, pred, internal -} +}; -export { StructureSelection, StructureQuery } \ No newline at end of file +export { StructureSelection, StructureQuery }; \ No newline at end of file diff --git a/src/mol-model/structure/query/predicates.ts b/src/mol-model/structure/query/predicates.ts index f2384afcbc9f89dc6bf35526e60daa1e30766083..9fe386367034ccbd886aeda23ba54abab45df8fb 100644 --- a/src/mol-model/structure/query/predicates.ts +++ b/src/mol-model/structure/query/predicates.ts @@ -8,7 +8,7 @@ import { QueryFn, QueryPredicate, QueryContextView } from './context'; namespace Predicates { export interface SetLike<A> { has(v: A): boolean } - function isSetLike<A>(x: any): x is SetLike<A> { return !!x && !!x.has } + function isSetLike<A>(x: any): x is SetLike<A> { return !!x && !!x.has; } export function eq<A>(p: QueryFn<A>, value: A): QueryPredicate { return l => p(l) === value; } export function lt<A>(p: QueryFn<A>, value: A): QueryPredicate { return l => p(l) < value; } @@ -59,7 +59,7 @@ namespace Predicates { return l => { for (let i = 0; i < count; i++) if (!ps[i]) return false; return true; - } + }; } } } @@ -93,10 +93,10 @@ namespace Predicates { return l => { for (let i = 0; i < count; i++) if (ps[i]) return true; return false; - } + }; } } } } -export default Predicates \ No newline at end of file +export default Predicates; \ No newline at end of file diff --git a/src/mol-model/structure/query/queries/combinators.ts b/src/mol-model/structure/query/queries/combinators.ts index 852fea6d3e1b81b74d3660dfdb14f4b6fd890cfa..75b1ae900b11c988e2bc34cdedc6ec3f7bc637d0 100644 --- a/src/mol-model/structure/query/queries/combinators.ts +++ b/src/mol-model/structure/query/queries/combinators.ts @@ -25,7 +25,7 @@ export function merge(queries: ArrayLike<StructureQuery>): StructureQuery { }); } return ret.getSelection(); - } + }; } export function intersect(queries: ArrayLike<StructureQuery>): StructureQuery { diff --git a/src/mol-model/structure/query/queries/filters.ts b/src/mol-model/structure/query/queries/filters.ts index 3b689246c33f2db5e22062ab22e426d75c4a7737..d2af04dd58eea5997a2d9578b3e6d125e66e66b1 100644 --- a/src/mol-model/structure/query/queries/filters.ts +++ b/src/mol-model/structure/query/queries/filters.ts @@ -145,7 +145,7 @@ export function within(params: WithinParams): StructureQuery { minRadius: params.minRadius ? Math.max(0, params.minRadius) : 0, elementRadius: params.elementRadius!, invert: !!params.invert, - } + }; if (ctx.minRadius === 0 && typeof params.minRadius === 'undefined') { return withinMaxRadiusLookup(ctx); @@ -154,7 +154,7 @@ export function within(params: WithinParams): StructureQuery { } else { return withinMinMaxRadius(ctx); } - } + }; } interface WithinContext { @@ -323,7 +323,7 @@ export function isConnectedTo({ query, target, disjunct, invert, bondTest }: IsC input: ctx.inputStructure, disjunct, target: StructureSelection.unionStructure(targetSel) - } + }; const ret = StructureSelection.LinearBuilder(ctx.inputStructure); ctx.pushCurrentBond(); @@ -336,9 +336,9 @@ export function isConnectedTo({ query, target, disjunct, invert, bondTest }: IsC ret.add(s); } if (sI % 5 === 0) ctx.throwIfTimedOut(); - }) + }); ctx.popCurrentBond(); return ret.getSelection(); - } + }; } \ No newline at end of file diff --git a/src/mol-model/structure/query/queries/generators.ts b/src/mol-model/structure/query/queries/generators.ts index afac8b988674b8fe329eab0bf1fca5f2a5ea83e9..c4b8d415ece0d8e54690b2d7cb043cc3dc5e34f9 100644 --- a/src/mol-model/structure/query/queries/generators.ts +++ b/src/mol-model/structure/query/queries/generators.ts @@ -5,10 +5,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { StructureQuery } from '../query' -import { StructureSelection } from '../selection' -import { Unit, StructureProperties as P, StructureElement } from '../../structure' -import { Segmentation, SortedArray } from '../../../../mol-data/int' +import { StructureQuery } from '../query'; +import { StructureSelection } from '../selection'; +import { Unit, StructureProperties as P, StructureElement } from '../../structure'; +import { Segmentation, SortedArray } from '../../../../mol-data/int'; import { LinearGroupingBuilder } from '../utils/builders'; import { QueryPredicate, QueryFn, QueryContextView } from '../context'; import { UnitRing } from '../../structure/unit/rings'; @@ -53,7 +53,7 @@ export function atoms(params?: Partial<AtomsQueryParams>): StructureQuery { groupBy: params.groupBy || _zero, }; - if (!params.groupBy) return atomGroupsSegmented(normalized) + if (!params.groupBy) return atomGroupsSegmented(normalized); return atomGroupsGrouped(normalized); } @@ -126,7 +126,7 @@ function atomGroupsSegmented({ unitTest, entityTest, chainTest, residueTest, ato } } } else { - const { chainElementSegments } = Unit.Kind.Spheres ? model.coarseHierarchy.spheres : model.coarseHierarchy.gaussians + const { chainElementSegments } = Unit.Kind.Spheres ? model.coarseHierarchy.spheres : model.coarseHierarchy.gaussians; const chainsIt = Segmentation.transientSegments(chainElementSegments, elements); while (chainsIt.hasNext) { @@ -195,7 +195,7 @@ function atomGroupsGrouped({ unitTest, entityTest, chainTest, residueTest, atomT } } } else { - const { chainElementSegments } = Unit.Kind.Spheres ? model.coarseHierarchy.spheres : model.coarseHierarchy.gaussians + const { chainElementSegments } = Unit.Kind.Spheres ? model.coarseHierarchy.spheres : model.coarseHierarchy.gaussians; const chainsIt = Segmentation.transientSegments(chainElementSegments, elements); while (chainsIt.hasNext) { const chainSegment = chainsIt.move(); @@ -264,7 +264,7 @@ export function rings(fingerprints?: ArrayLike<UnitRing.Fingerprint>, onlyAromat } return ret.getSelection(); - } + }; } export function querySelection(selection: StructureQuery, query: StructureQuery, inComplement: boolean = false): StructureQuery { @@ -283,7 +283,7 @@ export function querySelection(selection: StructureQuery, query: StructureQuery, const result = query(ctx); ctx.popInputStructure(); return StructureSelection.withInputStructure(result, ctx.inputStructure); - } + }; } export function bondedAtomicPairs(bondTest?: QueryPredicate): StructureQuery { diff --git a/src/mol-model/structure/query/queries/modifiers.ts b/src/mol-model/structure/query/queries/modifiers.ts index 6c7fd7319cbf17b7bbc3d34cb9cc0e7e532b4a24..c10826c0b29dac17a3b315fb78a1832724e6c461 100644 --- a/src/mol-model/structure/query/queries/modifiers.ts +++ b/src/mol-model/structure/query/queries/modifiers.ts @@ -120,7 +120,7 @@ function createElementRadiusFn(ctx: QueryContext, eRadius: QueryFn<number>): Str ctx.element.unit = e.unit; ctx.element.element = e.element; return eRadius(ctx); - } + }; } function findStructureRadius(ctx: QueryContext, eRadius: QueryFn<number>) { @@ -196,7 +196,7 @@ export function querySelection(selection: StructureQuery, query: StructureQuery) if (sI % 10 === 0) ctx.throwIfTimedOut(); }); return ret.getSelection(); - } + }; } export function intersectBy(query: StructureQuery, by: StructureQuery): StructureQuery { @@ -326,7 +326,7 @@ export function includeConnected({ query, layerCount, wholeResidues, bondTest }: ctx.popCurrentBond(); return builder.getSelection(); - } + }; } function includeConnectedStep(ctx: QueryContext, wholeResidues: boolean, structure: Structure) { diff --git a/src/mol-model/structure/query/query.ts b/src/mol-model/structure/query/query.ts index a126749a8702af003a5611071f2c4b1c2a1b18d3..cad6c30a06d4368893a62e898a7320b57a859be1 100644 --- a/src/mol-model/structure/query/query.ts +++ b/src/mol-model/structure/query/query.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Structure } from '../structure' -import { StructureSelection } from './selection' +import { Structure } from '../structure'; +import { StructureSelection } from './selection'; import { QueryContext, QueryFn, QueryContextOptions } from './context'; interface StructureQuery extends QueryFn<StructureSelection> { } @@ -15,4 +15,4 @@ namespace StructureQuery { } } -export { StructureQuery } \ No newline at end of file +export { StructureQuery }; \ No newline at end of file diff --git a/src/mol-model/structure/query/selection.ts b/src/mol-model/structure/query/selection.ts index 8ddc41813c192588674b3096a05d06b3d7908a1d..db1a6da535587b2b3aec77f7ae73688dbe93a07f 100644 --- a/src/mol-model/structure/query/selection.ts +++ b/src/mol-model/structure/query/selection.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { HashSet } from '../../../mol-data/generic' -import { Structure, StructureElement, Unit } from '../structure' +import { HashSet } from '../../../mol-data/generic'; +import { Structure, StructureElement, Unit } from '../structure'; import { structureUnion } from './utils/structure-set'; import { OrderedSet, SortedArray } from '../../../mol-data/int'; @@ -17,8 +17,8 @@ namespace StructureSelection { export interface Singletons { readonly kind: 'singletons', readonly source: Structure, readonly structure: Structure } export interface Sequence { readonly kind: 'sequence', readonly source: Structure, readonly structures: Structure[] } - export function Singletons(source: Structure, structure: Structure): Singletons { return { kind: 'singletons', source, structure } } - export function Sequence(source: Structure, structures: Structure[]): Sequence { return { kind: 'sequence', source, structures } } + export function Singletons(source: Structure, structure: Structure): Singletons { return { kind: 'singletons', source, structure }; } + export function Sequence(source: Structure, structures: Structure[]): Sequence { return { kind: 'sequence', source, structures }; } export function Empty(source: Structure): StructureSelection { return Singletons(source, Structure.Empty); }; export function isSingleton(s: StructureSelection): s is Singletons { return s.kind === 'singletons'; } @@ -63,7 +63,7 @@ namespace StructureSelection { const { unitMap } = sel.source; for (const _unit of unionStructure(sel).units) { - const unit = unitMap.get(_unit.id) + const unit = unitMap.get(_unit.id); if (unit === _unit) { elements[elements.length] = { unit, @@ -155,4 +155,4 @@ namespace StructureSelection { // TODO: spatial lookup? } -export { StructureSelection } \ No newline at end of file +export { StructureSelection }; \ No newline at end of file diff --git a/src/mol-model/structure/query/utils/structure-distance.ts b/src/mol-model/structure/query/utils/structure-distance.ts index bdea7bfe1089c874d003b9786ae161b5673fafab..f2e58d15817e4e7f947fb1c82af7eb4cdcafdac7 100644 --- a/src/mol-model/structure/query/utils/structure-distance.ts +++ b/src/mol-model/structure/query/utils/structure-distance.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Structure, Unit } from '../../structure' +import { Structure, Unit } from '../../structure'; import { Vec3 } from '../../../../mol-math/linear-algebra'; import { QueryFn, QueryContext } from '../context'; diff --git a/src/mol-model/structure/query/utils/structure-set.ts b/src/mol-model/structure/query/utils/structure-set.ts index 9741f3f3533c7c3a30792985ec03d1353f7dfbc3..f17c4c7b3832227a58cef7ba3f4ae8faa218bdbe 100644 --- a/src/mol-model/structure/query/utils/structure-set.ts +++ b/src/mol-model/structure/query/utils/structure-set.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Structure, Unit, StructureElement } from '../../structure' +import { Structure, Unit, StructureElement } from '../../structure'; import { SortedArray } from '../../../../mol-data/int'; import { StructureSubsetBuilder } from '../../structure/util/subset-builder'; diff --git a/src/mol-model/structure/structure.ts b/src/mol-model/structure/structure.ts index 87fff95a3737f764815cc6ccadae92fd849e053b..7292744e5f10c3a96a94314e02dbf35079c6b783 100644 --- a/src/mol-model/structure/structure.ts +++ b/src/mol-model/structure/structure.ts @@ -4,13 +4,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import StructureElement from './structure/element' -import Structure from './structure/structure' -import Unit from './structure/unit' -import StructureSymmetry from './structure/symmetry' -import { Bond } from './structure/unit/bonds' -import StructureProperties from './structure/properties' +import StructureElement from './structure/element'; +import Structure from './structure/structure'; +import Unit from './structure/unit'; +import StructureSymmetry from './structure/symmetry'; +import { Bond } from './structure/unit/bonds'; +import StructureProperties from './structure/properties'; -export { StructureElement, Bond, Structure, Unit, StructureSymmetry, StructureProperties } -export * from './structure/unit/rings' -export * from './export/mmcif' \ No newline at end of file +export { StructureElement, Bond, Structure, Unit, StructureSymmetry, StructureProperties }; +export * from './structure/unit/rings'; +export * from './export/mmcif'; \ No newline at end of file diff --git a/src/mol-model/structure/structure/carbohydrates/compute.ts b/src/mol-model/structure/structure/carbohydrates/compute.ts index 6e31b6015b9090b379cb12274a6ccd523637e48e..4eafc8d7f0c27c7a1452c5b69c1835b61662a879 100644 --- a/src/mol-model/structure/structure/carbohydrates/compute.ts +++ b/src/mol-model/structure/structure/carbohydrates/compute.ts @@ -28,137 +28,137 @@ const SugarRingFps = [ UnitRing.elementFingerprint([C, C, C, C, O]), UnitRing.elementFingerprint([C, C, C, C, C, O]), UnitRing.elementFingerprint([C, C, C, C, C, C, O]), -] +]; function getAnomericCarbon(unit: Unit.Atomic, ringAtoms: ArrayLike<StructureElement.UnitIndex>): ElementIndex { - let indexHasTwoOxygen = -1, indexHasOxygenAndCarbon = -1, indexHasC1Name = -1, indexIsCarbon = -1 - const { elements } = unit - const { type_symbol, label_atom_id } = unit.model.atomicHierarchy.atoms + let indexHasTwoOxygen = -1, indexHasOxygenAndCarbon = -1, indexHasC1Name = -1, indexIsCarbon = -1; + const { elements } = unit; + const { type_symbol, label_atom_id } = unit.model.atomicHierarchy.atoms; const { b: neighbor, offset } = unit.bonds; for (let i = 0, il = ringAtoms.length; i < il; ++i) { - const ei = elements[ringAtoms[i]] - if (type_symbol.value(ei) !== C) continue - let linkedOxygenCount = 0 - let linkedCarbonCount = 0 + const ei = elements[ringAtoms[i]]; + if (type_symbol.value(ei) !== C) continue; + let linkedOxygenCount = 0; + let linkedCarbonCount = 0; for (let j = offset[ringAtoms[i]], jl = offset[ringAtoms[i] + 1]; j < jl; ++j) { - const ej = elements[neighbor[j]] - const typeSymbol = type_symbol.value(ej) - if (typeSymbol === O) ++linkedOxygenCount - else if (typeSymbol === C) ++linkedCarbonCount + const ej = elements[neighbor[j]]; + const typeSymbol = type_symbol.value(ej); + if (typeSymbol === O) ++linkedOxygenCount; + else if (typeSymbol === C) ++linkedCarbonCount; } if (linkedOxygenCount === 2) { // found anomeric carbon - indexHasTwoOxygen = ei - break + indexHasTwoOxygen = ei; + break; } else if (linkedOxygenCount === 1 && linkedCarbonCount === 1) { // possibly an anomeric carbon if this is a mono-saccharide without a glycosidic bond - indexHasOxygenAndCarbon = ei + indexHasOxygenAndCarbon = ei; } else if (label_atom_id.value(ei).startsWith('C1')) { // likely the anomeric carbon as it is named C1 by convention - indexHasC1Name = ei + indexHasC1Name = ei; } else { // use any carbon as a fallback - indexIsCarbon = ei + indexIsCarbon = ei; } } return (indexHasTwoOxygen !== -1 ? indexHasTwoOxygen : indexHasOxygenAndCarbon !== -1 ? indexHasOxygenAndCarbon : indexHasC1Name !== -1 ? indexHasC1Name : indexIsCarbon !== -1 ? indexIsCarbon - : elements[ringAtoms[0]]) as ElementIndex + : elements[ringAtoms[0]]) as ElementIndex; } function getAltId(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - const { elements } = unit - const { label_alt_id } = unit.model.atomicHierarchy.atoms - return label_alt_id.value(elements[index]) + const { elements } = unit; + const { label_alt_id } = unit.model.atomicHierarchy.atoms; + return label_alt_id.value(elements[index]); } function getDirection(direction: Vec3, unit: Unit.Atomic, index: ElementIndex, center: Vec3) { - const { position } = unit.conformation - Vec3.normalize(direction, Vec3.sub(direction, center, position(index, direction))) - return direction + const { position } = unit.conformation; + Vec3.normalize(direction, Vec3.sub(direction, center, position(index, direction))); + return direction; } function getAtomId(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - const { elements } = unit - const { label_atom_id } = unit.model.atomicHierarchy.atoms - return label_atom_id.value(elements[index]) + const { elements } = unit; + const { label_atom_id } = unit.model.atomicHierarchy.atoms; + return label_atom_id.value(elements[index]); } function filterFusedRings(unitRings: UnitRings, rings: UnitRings.Index[] | undefined) { - if (!rings || !rings.length) return + if (!rings || !rings.length) return; - const { unit, all } = unitRings - const fusedRings = new Set<UnitRings.Index>() - const ringCombinations = combinations(fillSerial(new Array(rings.length) as number[]), 2) + const { unit, all } = unitRings; + const fusedRings = new Set<UnitRings.Index>(); + const ringCombinations = combinations(fillSerial(new Array(rings.length) as number[]), 2); for (let i = 0, il = ringCombinations.length; i < il; ++i) { const rc = ringCombinations[i]; const r0 = all[rings[rc[0]]], r1 = all[rings[rc[1]]]; if (SortedArray.areIntersecting(r0, r1) && UnitRing.getAltId(unit, r0) === UnitRing.getAltId(unit, r1)) { - fusedRings.add(rings[rc[0]]) - fusedRings.add(rings[rc[1]]) + fusedRings.add(rings[rc[0]]); + fusedRings.add(rings[rc[1]]); } } if (fusedRings.size) { - const filteredRings: UnitRings.Index[] = [] + const filteredRings: UnitRings.Index[] = []; for (let i = 0, il = rings.length; i < il; ++i) { - if (!fusedRings.has(rings[i])) filteredRings.push(rings[i]) + if (!fusedRings.has(rings[i])) filteredRings.push(rings[i]); } - return filteredRings + return filteredRings; } else { - return rings + return rings; } } function getSaccharideComp(compId: string, model: Model) { - return model.properties.saccharideComponentMap.get(compId) + return model.properties.saccharideComponentMap.get(compId); } export function computeCarbohydrates(structure: Structure): Carbohydrates { // skip computation if there are no saccharide components in any model if (structure.models.reduce((a, v) => a + v.properties.saccharideComponentMap.size, 0) === 0) - return EmptyCarbohydrates + return EmptyCarbohydrates; - const links: CarbohydrateLink[] = [] - const terminalLinks: CarbohydrateTerminalLink[] = [] - const elements: CarbohydrateElement[] = [] - const partialElements: PartialCarbohydrateElement[] = [] + const links: CarbohydrateLink[] = []; + const terminalLinks: CarbohydrateTerminalLink[] = []; + const elements: CarbohydrateElement[] = []; + const partialElements: PartialCarbohydrateElement[] = []; - const elementsWithRingMap = new Map<string, number[]>() + const elementsWithRingMap = new Map<string, number[]>(); function ringElementKey(residueIndex: number, unitId: number, altId: string) { - return `${residueIndex}|${unitId}|${altId}` + return `${residueIndex}|${unitId}|${altId}`; } function addRingElement(key: string, elementIndex: number) { - if (elementsWithRingMap.has(key)) elementsWithRingMap.get(key)!.push(elementIndex) - else elementsWithRingMap.set(key, [elementIndex]) + if (elementsWithRingMap.has(key)) elementsWithRingMap.get(key)!.push(elementIndex); + else elementsWithRingMap.set(key, [elementIndex]); } function fixLinkDirection(iA: number, iB: number) { - Vec3.sub(elements[iA].geometry.direction, elements[iB].geometry.center, elements[iA].geometry.center) - Vec3.normalize(elements[iA].geometry.direction, elements[iA].geometry.direction) + Vec3.sub(elements[iA].geometry.direction, elements[iB].geometry.center, elements[iA].geometry.center); + Vec3.normalize(elements[iA].geometry.direction, elements[iA].geometry.direction); } - const tmpV = Vec3.zero() + const tmpV = Vec3.zero(); function fixTerminalLinkDirection(iA: number, indexB: number, unitB: Unit.Atomic) { const pos = unitB.conformation.position, geo = elements[iA].geometry; - Vec3.sub(geo.direction, pos(unitB.elements[indexB], tmpV), geo.center) - Vec3.normalize(geo.direction, geo.direction) + Vec3.sub(geo.direction, pos(unitB.elements[indexB], tmpV), geo.center); + Vec3.normalize(geo.direction, geo.direction); } // get carbohydrate elements and carbohydrate links induced by intra-residue bonds for (let i = 0, il = structure.units.length; i < il; ++i) { - const unit = structure.units[i] - if (!Unit.isAtomic(unit)) continue + const unit = structure.units[i]; + if (!Unit.isAtomic(unit)) continue; - const { model, rings } = unit - const { chainAtomSegments, residueAtomSegments, residues } = model.atomicHierarchy - const { label_comp_id } = residues + const { model, rings } = unit; + const { chainAtomSegments, residueAtomSegments, residues } = model.atomicHierarchy; + const { label_comp_id } = residues; - const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements) - const residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements) + const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements); + const residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements); let sugarResidueMap: Map<ResidueIndex, UnitRings.Index[]> | undefined = void 0; @@ -168,8 +168,8 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { while (residueIt.hasNext) { const { index: residueIndex } = residueIt.move(); - const saccharideComp = getSaccharideComp(label_comp_id.value(residueIndex), model) - if (!saccharideComp) continue + const saccharideComp = getSaccharideComp(label_comp_id.value(residueIndex), model); + if (!saccharideComp) continue; if (!sugarResidueMap) { sugarResidueMap = UnitRings.byFingerprintAndResidue(rings, SugarRingFps); @@ -178,28 +178,28 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { const sugarRings = filterFusedRings(rings, sugarResidueMap.get(residueIndex)); if (!sugarRings || !sugarRings.length) { - partialElements.push({ unit, residueIndex, component: saccharideComp }) + partialElements.push({ unit, residueIndex, component: saccharideComp }); continue; } - const ringElements: number[] = [] + const ringElements: number[] = []; for (let j = 0, jl = sugarRings.length; j < jl; ++j) { const ringAtoms = rings.all[sugarRings[j]]; - const anomericCarbon = getAnomericCarbon(unit, ringAtoms) + const anomericCarbon = getAnomericCarbon(unit, ringAtoms); - const ma = PrincipalAxes.calculateMomentsAxes(getPositions(unit, ringAtoms)) - const center = Vec3.copy(Vec3.zero(), ma.origin) - const normal = Vec3.copy(Vec3.zero(), ma.dirC) - const direction = getDirection(Vec3.zero(), unit, anomericCarbon, center) - Vec3.orthogonalize(direction, normal, direction) + const ma = PrincipalAxes.calculateMomentsAxes(getPositions(unit, ringAtoms)); + const center = Vec3.copy(Vec3.zero(), ma.origin); + const normal = Vec3.copy(Vec3.zero(), ma.dirC); + const direction = getDirection(Vec3.zero(), unit, anomericCarbon, center); + Vec3.orthogonalize(direction, normal, direction); - const ringAltId = UnitRing.getAltId(unit, ringAtoms) - const elementIndex = elements.length - ringElements.push(elementIndex) + const ringAltId = UnitRing.getAltId(unit, ringAtoms); + const elementIndex = elements.length; + ringElements.push(elementIndex); - addRingElement(ringElementKey(residueIndex, unit.id, ringAltId), elementIndex) - if (ringAltId) addRingElement(ringElementKey(residueIndex, unit.id, ''), elementIndex) + addRingElement(ringElementKey(residueIndex, unit.id, ringAltId), elementIndex); + if (ringAltId) addRingElement(ringElementKey(residueIndex, unit.id, ''), elementIndex); elements.push({ geometry: { center, normal, direction }, @@ -207,26 +207,26 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { ringIndex: sugarRings[j], altId: ringAltId, unit, residueIndex - }) + }); } // add carbohydrate links induced by intra-residue bonds // (e.g. for structures from the PDB archive __before__ carbohydrate remediation) - const ringCombinations = combinations(fillSerial(new Array(sugarRings.length) as number[]), 2) + const ringCombinations = combinations(fillSerial(new Array(sugarRings.length) as number[]), 2); for (let j = 0, jl = ringCombinations.length; j < jl; ++j) { const rc = ringCombinations[j]; const r0 = rings.all[sugarRings[rc[0]]], r1 = rings.all[sugarRings[rc[1]]]; // 1,6 glycosidic links are distance 3 and 1,4 glycosidic links are distance 2 if (IntAdjacencyGraph.areVertexSetsConnected(unit.bonds, r0, r1, 3)) { - const re0 = ringElements[rc[0]] - const re1 = ringElements[rc[1]] + const re0 = ringElements[rc[0]]; + const re1 = ringElements[rc[1]]; if (elements[re0].altId === elements[re1].altId) { // TODO handle better, for now fix both directions as it is unclear where the C1 atom is // would need to know the path connecting the two rings - fixLinkDirection(re0, re1) - fixLinkDirection(re1, re0) - links.push({ carbohydrateIndexA: re0, carbohydrateIndexB: re1 }) - links.push({ carbohydrateIndexA: re1, carbohydrateIndexB: re0 }) + fixLinkDirection(re0, re1); + fixLinkDirection(re1, re0); + links.push({ carbohydrateIndexA: re0, carbohydrateIndexB: re1 }); + links.push({ carbohydrateIndexA: re1, carbohydrateIndexB: re0 }); } } } @@ -235,28 +235,28 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { } function getRingElementIndices(unit: Unit.Atomic, index: StructureElement.UnitIndex) { - return elementsWithRingMap.get(ringElementKey(unit.getResidueIndex(index), unit.id, getAltId(unit, index))) || [] + return elementsWithRingMap.get(ringElementKey(unit.getResidueIndex(index), unit.id, getAltId(unit, index))) || []; } // add carbohydrate links induced by intra-unit bonds // (e.g. for structures from the PDB archive __after__ carbohydrate remediation) for (let i = 0, il = elements.length; i < il; ++i) { - const cA = elements[i] - const { unit } = cA + const cA = elements[i]; + const { unit } = cA; for (let j = i + 1; j < il; ++j) { - const cB = elements[j] - if (unit !== cB.unit || cA.residueIndex === cB.residueIndex) continue - const rA = unit.rings.all[cA.ringIndex] - const rB = unit.rings.all[cB.ringIndex] + const cB = elements[j]; + if (unit !== cB.unit || cA.residueIndex === cB.residueIndex) continue; + const rA = unit.rings.all[cA.ringIndex]; + const rB = unit.rings.all[cB.ringIndex]; if (IntAdjacencyGraph.areVertexSetsConnected(unit.bonds, rA, rB, 3)) { // TODO handle better, for now fix both directions as it is unclear where the C1 atom is // would need to know the path connecting the two rings - fixLinkDirection(i, j) - fixLinkDirection(j, i) - links.push({ carbohydrateIndexA: i, carbohydrateIndexB: j }) - links.push({ carbohydrateIndexA: j, carbohydrateIndexB: i }) + fixLinkDirection(i, j); + fixLinkDirection(j, i); + links.push({ carbohydrateIndexA: i, carbohydrateIndexB: j }); + links.push({ carbohydrateIndexA: j, carbohydrateIndexB: i }); } } } @@ -266,44 +266,44 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { // PDB archive __before__ carbohydrate remediation // plus terminal links for __before__ and __after__ for (let i = 0, il = structure.units.length; i < il; ++i) { - const unit = structure.units[i] - if (!Unit.isAtomic(unit)) continue + const unit = structure.units[i]; + if (!Unit.isAtomic(unit)) continue; structure.interUnitBonds.getConnectedUnits(unit).forEach(pairBonds => { pairBonds.connectedIndices.forEach(indexA => { pairBonds.getEdges(indexA).forEach(({ props, indexB }) => { - if (!BondType.isCovalent(props.flag)) return + if (!BondType.isCovalent(props.flag)) return; - const { unitA, unitB } = pairBonds - const ringElementIndicesA = getRingElementIndices(unitA, indexA) - const ringElementIndicesB = getRingElementIndices(unitB, indexB) + const { unitA, unitB } = pairBonds; + const ringElementIndicesA = getRingElementIndices(unitA, indexA); + const ringElementIndicesB = getRingElementIndices(unitB, indexB); if (ringElementIndicesA.length > 0 && ringElementIndicesB.length > 0) { - const lA = ringElementIndicesA.length - const lB = ringElementIndicesB.length + const lA = ringElementIndicesA.length; + const lB = ringElementIndicesB.length; for (let j = 0, jl = Math.max(lA, lB); j < jl; ++j) { - const ringElementIndexA = ringElementIndicesA[Math.min(j, lA - 1)] - const ringElementIndexB = ringElementIndicesB[Math.min(j, lB - 1)] - const atomIdA = getAtomId(unitA, indexA) + const ringElementIndexA = ringElementIndicesA[Math.min(j, lA - 1)]; + const ringElementIndexB = ringElementIndicesB[Math.min(j, lB - 1)]; + const atomIdA = getAtomId(unitA, indexA); if (atomIdA.startsWith('O1') || atomIdA.startsWith('C1')) { - fixLinkDirection(ringElementIndexA, ringElementIndexB) + fixLinkDirection(ringElementIndexA, ringElementIndexB); } links.push({ carbohydrateIndexA: ringElementIndexA, carbohydrateIndexB: ringElementIndexB - }) + }); } } else if (ringElementIndicesB.length === 0) { for (const ringElementIndexA of ringElementIndicesA) { - const atomIdA = getAtomId(unitA, indexA) + const atomIdA = getAtomId(unitA, indexA); if (atomIdA.startsWith('O1') || atomIdA.startsWith('C1')) { - fixTerminalLinkDirection(ringElementIndexA, indexB, unitB) + fixTerminalLinkDirection(ringElementIndexA, indexB, unitB); } terminalLinks.push({ carbohydrateIndex: ringElementIndexA, elementIndex: indexB, elementUnit: unitB, fromCarbohydrate: true - }) + }); } } else if (ringElementIndicesA.length === 0) { for (const ringElementIndexB of ringElementIndicesB) { @@ -312,94 +312,94 @@ export function computeCarbohydrates(structure: Structure): Carbohydrates { elementIndex: indexA, elementUnit: unitA, fromCarbohydrate: false - }) + }); } } - }) - }) - }) + }); + }); + }); } - return { links, terminalLinks, elements, partialElements, ...buildLookups(elements, links, terminalLinks) } + return { links, terminalLinks, elements, partialElements, ...buildLookups(elements, links, terminalLinks) }; } function buildLookups (elements: CarbohydrateElement[], links: CarbohydrateLink[], terminalLinks: CarbohydrateTerminalLink[]) { function key(unit: Unit, element: ElementIndex) { - return cantorPairing(unit.id, element) + return cantorPairing(unit.id, element); } function getIndices(map: Map<number, number[]>, unit: Unit.Atomic, index: ElementIndex): ReadonlyArray<number> { - const indices: number[] = [] - const il = map.get(key(unit, index)) + const indices: number[] = []; + const il = map.get(key(unit, index)); if (il !== undefined) { - for (const i of il) arraySetAdd(indices, i) + for (const i of il) arraySetAdd(indices, i); } - return indices + return indices; } // elements - const elementsMap = new Map<number, number[]>() + const elementsMap = new Map<number, number[]>(); for (let i = 0, il = elements.length; i < il; ++i) { - const { unit, ringIndex } = elements[i] - const ring = unit.rings.all[ringIndex] + const { unit, ringIndex } = elements[i]; + const ring = unit.rings.all[ringIndex]; for (let j = 0, jl = ring.length; j < jl; ++j) { - const k = key(unit, unit.elements[ring[j]]) - const e = elementsMap.get(k) - if (e === undefined) elementsMap.set(k, [i]) - else e.push(i) + const k = key(unit, unit.elements[ring[j]]); + const e = elementsMap.get(k); + if (e === undefined) elementsMap.set(k, [i]); + else e.push(i); } } function getElementIndices(unit: Unit.Atomic, index: ElementIndex) { - return getIndices(elementsMap, unit, index) + return getIndices(elementsMap, unit, index); } // links - const linksMap = new Map<number, number[]>() + const linksMap = new Map<number, number[]>(); for (let i = 0, il = links.length; i < il; ++i) { - const l = links[i] - const { unit, ringIndex } = elements[l.carbohydrateIndexA] - const ring = unit.rings.all[ringIndex] + const l = links[i]; + const { unit, ringIndex } = elements[l.carbohydrateIndexA]; + const ring = unit.rings.all[ringIndex]; for (let j = 0, jl = ring.length; j < jl; ++j) { - const k = key(unit, unit.elements[ring[j]]) - const e = linksMap.get(k) - if (e === undefined) linksMap.set(k, [i]) - else e.push(i) + const k = key(unit, unit.elements[ring[j]]); + const e = linksMap.get(k); + if (e === undefined) linksMap.set(k, [i]); + else e.push(i); } } function getLinkIndices(unit: Unit.Atomic, index: ElementIndex) { - return getIndices(linksMap, unit, index) + return getIndices(linksMap, unit, index); } // terminal links - const terminalLinksMap = new Map<number, number[]>() + const terminalLinksMap = new Map<number, number[]>(); for (let i = 0, il = terminalLinks.length; i < il; ++i) { - const { fromCarbohydrate, carbohydrateIndex, elementUnit, elementIndex } = terminalLinks[i] + const { fromCarbohydrate, carbohydrateIndex, elementUnit, elementIndex } = terminalLinks[i]; if (fromCarbohydrate) { - const { unit, ringIndex } = elements[carbohydrateIndex] - const ring = unit.rings.all[ringIndex] + const { unit, ringIndex } = elements[carbohydrateIndex]; + const ring = unit.rings.all[ringIndex]; for (let j = 0, jl = ring.length; j < jl; ++j) { - const k = key(unit, unit.elements[ring[j]]) - const e = terminalLinksMap.get(k) - if (e === undefined) terminalLinksMap.set(k, [i]) - else e.push(i) + const k = key(unit, unit.elements[ring[j]]); + const e = terminalLinksMap.get(k); + if (e === undefined) terminalLinksMap.set(k, [i]); + else e.push(i); } } else { - const k = key(elementUnit, elementUnit.elements[elementIndex]) - const e = terminalLinksMap.get(k) - if (e === undefined) terminalLinksMap.set(k, [i]) - else e.push(i) + const k = key(elementUnit, elementUnit.elements[elementIndex]); + const e = terminalLinksMap.get(k); + if (e === undefined) terminalLinksMap.set(k, [i]); + else e.push(i); } } function getTerminalLinkIndices(unit: Unit.Atomic, index: ElementIndex) { - return getIndices(terminalLinksMap, unit, index) + return getIndices(terminalLinksMap, unit, index); } - return { getElementIndices, getLinkIndices, getTerminalLinkIndices } + return { getElementIndices, getLinkIndices, getTerminalLinkIndices }; } \ No newline at end of file diff --git a/src/mol-model/structure/structure/carbohydrates/constants.ts b/src/mol-model/structure/structure/carbohydrates/constants.ts index 63e9fb04ad17389aa0683bd14491e4b8225a6cae..75bf58eb934aab2ae0e53901c616b3f521f0c637 100644 --- a/src/mol-model/structure/structure/carbohydrates/constants.ts +++ b/src/mol-model/structure/structure/carbohydrates/constants.ts @@ -30,7 +30,7 @@ export const SaccharideColors = ColorMap({ Red: 0xed1c24, Secondary: 0xf1ece1 -}) +}); export const enum SaccharideType { Hexose, HexNAc, Hexosamine, Hexuronate, Deoxyhexose, DeoxyhexNAc, DiDeoxyhexose, @@ -50,10 +50,10 @@ const SaccharideTypeNameMap = { [SaccharideType.DiDeoxynonulosonate]: 'Di-deoxynonulosonate', [SaccharideType.Unknown]: 'Unknown', [SaccharideType.Assigned]: 'Assigned', -} +}; export function getSaccharideName(type: SaccharideType) { - return SaccharideTypeNameMap[type] + return SaccharideTypeNameMap[type]; } const SaccharideTypeShapeMap = { @@ -69,17 +69,17 @@ const SaccharideTypeShapeMap = { [SaccharideType.DiDeoxynonulosonate]: SaccharideShape.FlatDiamond, [SaccharideType.Unknown]: SaccharideShape.FlatHexagon, [SaccharideType.Assigned]: SaccharideShape.Pentagon, -} +}; export function getSaccharideShape(type: SaccharideType, ringMemberCount: number): SaccharideShape { if (type === SaccharideType.Unknown) { - if (ringMemberCount === 4) return SaccharideShape.DiamondPrism - else if (ringMemberCount === 5) return SaccharideShape.PentagonalPrism - else if (ringMemberCount === 6) return SaccharideShape.HexagonalPrism - else if (ringMemberCount === 7) return SaccharideShape.HeptagonalPrism - else return SaccharideShape.FlatHexagon + if (ringMemberCount === 4) return SaccharideShape.DiamondPrism; + else if (ringMemberCount === 5) return SaccharideShape.PentagonalPrism; + else if (ringMemberCount === 6) return SaccharideShape.HexagonalPrism; + else if (ringMemberCount === 7) return SaccharideShape.HeptagonalPrism; + else return SaccharideShape.FlatHexagon; } else { - return SaccharideTypeShapeMap[type] + return SaccharideTypeShapeMap[type]; } } @@ -95,7 +95,7 @@ export const UnknownSaccharideComponent: SaccharideComponent = { name: 'Unknown', color: SaccharideColors.Secondary, type: SaccharideType.Unknown -} +}; const Monosaccharides: SaccharideComponent[] = [ { abbr: 'Glc', name: 'Glucose', color: SaccharideColors.Blue, type: SaccharideType.Hexose }, @@ -184,16 +184,16 @@ const Monosaccharides: SaccharideComponent[] = [ { abbr: 'Tag', name: 'Tagatose', color: SaccharideColors.Yellow, type: SaccharideType.Assigned }, { abbr: 'Sor', name: 'Sorbose', color: SaccharideColors.Orange, type: SaccharideType.Assigned }, { abbr: 'Psi', name: 'Psicose', color: SaccharideColors.Pink, type: SaccharideType.Assigned }, -] +]; export const SaccharidesSnfgMap = (function () { - const map = new Map<string, SaccharideComponent>() + const map = new Map<string, SaccharideComponent>(); for (let i = 0, il = Monosaccharides.length; i < il; ++i) { - const saccharide = Monosaccharides[i] - map.set(saccharide.abbr, saccharide) + const saccharide = Monosaccharides[i]; + map.set(saccharide.abbr, saccharide); } - return map -})() + return map; +})(); export const MonosaccharidesColorTable: [string, Color][] = [ ['Glc-family', SaccharideColors.Blue], @@ -206,7 +206,7 @@ export const MonosaccharidesColorTable: [string, Color][] = [ ['Ido-family', SaccharideColors.Brown], ['Fuc-family', SaccharideColors.Red], ['Generic/Unknown/Secondary', SaccharideColors.Secondary], -] +]; const CommonSaccharideNames: { [k: string]: string[] } = { // Hexose @@ -300,30 +300,30 @@ const CommonSaccharideNames: { [k: string]: string[] } = { Tag: ['T6T'], Sor: ['SOE'], Psi: ['PSV', 'SF6', 'SF9'], -} +}; const UnknownSaccharideNames = [ 'NGZ', // via CCD 'LAT', // BETA-LACTOSE, Gal-Glc di-saccharide via GlyFinder 'PUF', 'GDA', '9WJ', // via updated CCD -] +]; export const SaccharideCompIdMap = (function () { - const map = new Map<string, SaccharideComponent>() + const map = new Map<string, SaccharideComponent>(); for (let i = 0, il = Monosaccharides.length; i < il; ++i) { - const saccharide = Monosaccharides[i] - const names = CommonSaccharideNames[saccharide.abbr] + const saccharide = Monosaccharides[i]; + const names = CommonSaccharideNames[saccharide.abbr]; if (names) { for (let j = 0, jl = names.length; j < jl; ++j) { - map.set(names[j], saccharide) + map.set(names[j], saccharide); } } } for (let i = 0, il = UnknownSaccharideNames.length; i < il; ++i) { - map.set(UnknownSaccharideNames[i], UnknownSaccharideComponent) + map.set(UnknownSaccharideNames[i], UnknownSaccharideComponent); } - return map -})() + return map; +})(); export type SaccharideComponentMap = ReadonlyMap<string, SaccharideComponent> diff --git a/src/mol-model/structure/structure/carbohydrates/data.ts b/src/mol-model/structure/structure/carbohydrates/data.ts index a82baa4148487232cc749a0716ae30b46cc80441..5ff9b89e5d7a2de8b3587912b74a9238b80407fc 100644 --- a/src/mol-model/structure/structure/carbohydrates/data.ts +++ b/src/mol-model/structure/structure/carbohydrates/data.ts @@ -51,7 +51,7 @@ export interface Carbohydrates { getTerminalLinkIndices: (unit: Unit.Atomic, element: ElementIndex) => ReadonlyArray<number> } -const EmptyArray: ReadonlyArray<any> = [] +const EmptyArray: ReadonlyArray<any> = []; export const EmptyCarbohydrates: Carbohydrates = { links: EmptyArray, terminalLinks: EmptyArray, @@ -61,4 +61,4 @@ export const EmptyCarbohydrates: Carbohydrates = { getElementIndices: () => EmptyArray, getLinkIndices: () => EmptyArray, getTerminalLinkIndices: () => EmptyArray, -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-model/structure/structure/element.ts b/src/mol-model/structure/structure/element.ts index 6b71476f0181f54176cf34a98f358799a3f50aae..c5a7f0cfbcf30823c0beff6eebd8d2cda7bc18dc 100644 --- a/src/mol-model/structure/structure/element.ts +++ b/src/mol-model/structure/structure/element.ts @@ -7,4 +7,4 @@ import * as StructureElement from './element/index'; -export default StructureElement \ No newline at end of file +export default StructureElement; \ No newline at end of file diff --git a/src/mol-model/structure/structure/element/bundle.ts b/src/mol-model/structure/structure/element/bundle.ts index d8866b794e9a42182169b8bbbd6c183930cb395c..023ae37d00612f0e0ce85f562667226e4a8f5c27 100644 --- a/src/mol-model/structure/structure/element/bundle.ts +++ b/src/mol-model/structure/structure/element/bundle.ts @@ -34,10 +34,10 @@ export interface Bundle { } export namespace Bundle { - export const Empty: Bundle = { hash: -1, elements: [] } + export const Empty: Bundle = { hash: -1, elements: [] }; export function fromSubStructure(parent: Structure, structure: Structure) { - return fromLoci(StructureSelection.toLociWithSourceUnits(StructureSelection.Singletons(parent, structure))) + return fromLoci(StructureSelection.toLociWithSourceUnits(StructureSelection.Singletons(parent, structure))); } export function fromSelection(selection: StructureSelection) { @@ -49,19 +49,19 @@ export namespace Bundle { unit: Unit set: SortedArray<UnitIndex> ranges: SortedRanges<UnitIndex> - }[] = [] + }[] = []; for (const e of loci.elements) { - const { unit, indices } = e - if (OrderedSet.size(indices) === 0) continue + const { unit, indices } = e; + if (OrderedSet.size(indices) === 0) continue; const ranges: UnitIndex[] = []; const set: UnitIndex[] = []; if (OrderedSet.isInterval(indices)) { if (OrderedSet.size(indices) === 1) { - set.push(Interval.min(indices)) + set.push(Interval.min(indices)); } else { - ranges.push(Interval.min(indices), Interval.max(indices)) + ranges.push(Interval.min(indices), Interval.max(indices)); } } else { let i = 0, len = indices.length; @@ -71,10 +71,10 @@ export namespace Bundle { while (i < len && indices[i - 1] + 1 === indices[i]) i++; const end = i; if (end - start > 2) { - ranges.push(indices[start], indices[end - 1]) + ranges.push(indices[start], indices[end - 1]); } else { for (let j = start; j < end; j++) { - set[set.length] = indices[j] + set[set.length] = indices[j]; } } } @@ -84,7 +84,7 @@ export namespace Bundle { unit, set: SortedArray.ofSortedArray(set), ranges: SortedRanges.ofSortedRanges(ranges) - }) + }); } const elementGroups = new Map<number, { @@ -93,130 +93,130 @@ export namespace Bundle { ranges: SortedRanges<UnitIndex> }>(); for (let i = 0, il = _elements.length; i < il; ++i) { - const e = _elements[i] - const key = hash2(hashFnv32a(e.ranges), hashFnv32a(e.set)) + const e = _elements[i]; + const key = hash2(hashFnv32a(e.ranges), hashFnv32a(e.set)); if (elementGroups.has(key)) { - const { groupedUnits } = elementGroups.get(key)! + const { groupedUnits } = elementGroups.get(key)!; if (groupedUnits.has(e.unit.invariantId)) { - groupedUnits.get(e.unit.invariantId)!.push(e.unit.id) + groupedUnits.get(e.unit.invariantId)!.push(e.unit.id); } else { - groupedUnits.set(e.unit.invariantId, [e.unit.id]) + groupedUnits.set(e.unit.invariantId, [e.unit.id]); } } else { - const groupedUnits = new Map<number, number[]>() - groupedUnits.set(e.unit.invariantId, [e.unit.id]) - elementGroups.set(key, { groupedUnits, set: e.set, ranges: e.ranges }) + const groupedUnits = new Map<number, number[]>(); + groupedUnits.set(e.unit.invariantId, [e.unit.id]); + elementGroups.set(key, { groupedUnits, set: e.set, ranges: e.ranges }); } } - const elements: BundleElement[] = [] + const elements: BundleElement[] = []; elementGroups.forEach(e => { - const groupedUnits: SortedArray<number>[] = [] - e.groupedUnits.forEach(g => groupedUnits.push(SortedArray.ofUnsortedArray(g))) - groupedUnits.sort((a, b) => a[0] - b[0]) // sort by first unit id of each group - elements.push({ groupedUnits, set: e.set, ranges: e.ranges }) - }) + const groupedUnits: SortedArray<number>[] = []; + e.groupedUnits.forEach(g => groupedUnits.push(SortedArray.ofUnsortedArray(g))); + groupedUnits.sort((a, b) => a[0] - b[0]); // sort by first unit id of each group + elements.push({ groupedUnits, set: e.set, ranges: e.ranges }); + }); - return { hash: loci.structure.hashCode, elements } + return { hash: loci.structure.hashCode, elements }; } function getUnitsFromIds(unitIds: ArrayLike<number>, structure: Structure) { - const units: Unit[] = [] + const units: Unit[] = []; for (let i = 0, il = unitIds.length; i < il; ++i) { - const unitId = unitIds[i] - if (structure.unitMap.has(unitId)) units.push(structure.unitMap.get(unitId)) + const unitId = unitIds[i]; + if (structure.unitMap.has(unitId)) units.push(structure.unitMap.get(unitId)); } - return units + return units; } export function toLoci(bundle: Bundle, structure: Structure): Loci { if (bundle.hash !== -1 && bundle.hash !== structure.hashCode) { - new Error('Bundle not compatible with given structure') + new Error('Bundle not compatible with given structure'); } - const elements: Loci['elements'][0][] = [] + const elements: Loci['elements'][0][] = []; for (const e of bundle.elements) { for (const g of e.groupedUnits) { - const units = getUnitsFromIds(g, structure) - if (units.length === 0) continue + const units = getUnitsFromIds(g, structure); + if (units.length === 0) continue; - let indices: OrderedSet<UnitIndex> + let indices: OrderedSet<UnitIndex>; if (e.ranges.length === 0) { - indices = e.set + indices = e.set; } else if (e.set.length === 0) { if (e.ranges.length === 2) { - indices = Interval.ofRange(e.ranges[0], e.ranges[1]) + indices = Interval.ofRange(e.ranges[0], e.ranges[1]); } else { - const _indices = new Int32Array(SortedRanges.size(e.ranges)) - SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = v) - indices = SortedArray.ofSortedArray(_indices) + const _indices = new Int32Array(SortedRanges.size(e.ranges)); + SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = v); + indices = SortedArray.ofSortedArray(_indices); } } else { - const rangesSize = SortedRanges.size(e.ranges) - const _indices = new Int32Array(e.set.length + rangesSize) - SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = v) - _indices.set(e.set, rangesSize) - indices = SortedArray.ofUnsortedArray(_indices) // requires sort + const rangesSize = SortedRanges.size(e.ranges); + const _indices = new Int32Array(e.set.length + rangesSize); + SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = v); + _indices.set(e.set, rangesSize); + indices = SortedArray.ofUnsortedArray(_indices); // requires sort } for (const unit of units) { - elements.push({ unit, indices }) + elements.push({ unit, indices }); } } } - return Loci(structure, elements) + return Loci(structure, elements); } export function toStructure(bundle: Bundle, parent: Structure): Structure { if (bundle.hash !== -1 && bundle.hash !== parent.hashCode) { - new Error('Bundle not compatible with given structure') + new Error('Bundle not compatible with given structure'); } - const units: Unit[] = [] + const units: Unit[] = []; for (const e of bundle.elements) { for (const g of e.groupedUnits) { - const _units = getUnitsFromIds(g, parent) - if (_units.length === 0) continue - - const ue = _units[0].elements // the elements are grouped by unit.invariantId - const rangesSize = SortedRanges.size(e.ranges) - const setSize = e.set.length - const _indices = new Int32Array(setSize + rangesSize) - let indices: SortedArray<ElementIndex> + const _units = getUnitsFromIds(g, parent); + if (_units.length === 0) continue; + + const ue = _units[0].elements; // the elements are grouped by unit.invariantId + const rangesSize = SortedRanges.size(e.ranges); + const setSize = e.set.length; + const _indices = new Int32Array(setSize + rangesSize); + let indices: SortedArray<ElementIndex>; if (rangesSize === 0) { for (let i = 0, il = setSize; i < il; ++i) { - _indices[i] = ue[e.set[i]] + _indices[i] = ue[e.set[i]]; } - indices = SortedArray.ofSortedArray(_indices) + indices = SortedArray.ofSortedArray(_indices); } else if (setSize === 0) { - SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = ue[v]) - indices = SortedArray.ofSortedArray(_indices) + SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = ue[v]); + indices = SortedArray.ofSortedArray(_indices); } else { if (SortedArray.min(e.set) > SortedRanges.max(e.ranges)) { - SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = ue[v]) + SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = ue[v]); for (let i = 0, il = setSize; i < il; ++i) { - _indices[i + rangesSize] = ue[e.set[i]] + _indices[i + rangesSize] = ue[e.set[i]]; } - indices = SortedArray.ofSortedArray(_indices) + indices = SortedArray.ofSortedArray(_indices); } else if (SortedRanges.min(e.ranges) > SortedArray.max(e.set)) { for (let i = 0, il = setSize; i < il; ++i) { - _indices[i] = ue[e.set[i]] + _indices[i] = ue[e.set[i]]; } - SortedRanges.forEach(e.ranges, (v, i) => _indices[i + setSize] = ue[v]) - indices = SortedArray.ofSortedArray(_indices) + SortedRanges.forEach(e.ranges, (v, i) => _indices[i + setSize] = ue[v]); + indices = SortedArray.ofSortedArray(_indices); } else { - SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = ue[v]) + SortedRanges.forEach(e.ranges, (v, i) => _indices[i] = ue[v]); for (let i = 0, il = setSize; i < il; ++i) { - _indices[i + rangesSize] = ue[e.set[i]] + _indices[i + rangesSize] = ue[e.set[i]]; } - indices = SortedArray.ofUnsortedArray(_indices) // requires sort + indices = SortedArray.ofUnsortedArray(_indices); // requires sort } } for (const unit of _units) { - units.push(unit.getChild(indices)) + units.push(unit.getChild(indices)); } } } - return Structure.create(units, { parent }) + return Structure.create(units, { parent }); } @@ -225,7 +225,7 @@ export namespace Bundle { groupedUnits: MS.core.type.list(e.groupedUnits.map(u => MS.core.type.list(u))), ranges: MS.core.type.list(e.ranges), set: MS.core.type.list(e.set), - }) + }); } export function toExpression(bundle: Bundle): Expression { @@ -235,16 +235,16 @@ export namespace Bundle { } export function areEqual(a: Bundle, b: Bundle) { - if (a.elements.length !== b.elements.length) return false + if (a.elements.length !== b.elements.length) return false; for (let i = 0, il = a.elements.length; i < il; ++i) { - const elementA = a.elements[i], elementB = b.elements[i] - if (elementA.groupedUnits.length !== elementB.groupedUnits.length) return false + const elementA = a.elements[i], elementB = b.elements[i]; + if (elementA.groupedUnits.length !== elementB.groupedUnits.length) return false; for (let j = 0, jl = elementB.groupedUnits.length; j < jl; ++j) { - if (!SortedArray.areEqual(elementA.groupedUnits[j], elementB.groupedUnits[j])) return false + if (!SortedArray.areEqual(elementA.groupedUnits[j], elementB.groupedUnits[j])) return false; } - if (!SortedArray.areEqual(elementA.set, elementB.set)) return false - if (!SortedRanges.areEqual(elementA.ranges, elementB.ranges)) return false + if (!SortedArray.areEqual(elementA.set, elementB.set)) return false; + if (!SortedRanges.areEqual(elementA.ranges, elementB.ranges)) return false; } - return true + return true; } } \ No newline at end of file diff --git a/src/mol-model/structure/structure/element/element.ts b/src/mol-model/structure/structure/element/element.ts index eef0e1b784359fcf96bc12964d61e2117879dac7..fe980b2e006083dc2bfea2698cda4e6d39a410b0 100644 --- a/src/mol-model/structure/structure/element/element.ts +++ b/src/mol-model/structure/structure/element/element.ts @@ -50,5 +50,5 @@ export function chainIndex(e: Location) { } export function entityIndex(l: Location) { - return StructureProperties.entity.key(l) + return StructureProperties.entity.key(l); } \ No newline at end of file diff --git a/src/mol-model/structure/structure/element/index.ts b/src/mol-model/structure/structure/element/index.ts index 722e195332a2a8d105a1ac57fca5ffb887d5c75e..fe0604e97a45faf45e8769304de8dc72a48e2586 100644 --- a/src/mol-model/structure/structure/element/index.ts +++ b/src/mol-model/structure/structure/element/index.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export * from './location' -export * from './loci' -export * from './bundle' -export * from './stats' -export * from './element' \ No newline at end of file +export * from './location'; +export * from './loci'; +export * from './bundle'; +export * from './stats'; +export * from './element'; \ No newline at end of file diff --git a/src/mol-model/structure/structure/element/location.ts b/src/mol-model/structure/structure/element/location.ts index 7ad162417a242a4d8d59b6423f77a5901ebbd828..7544519ac478b78933251c9e95aef812e1d9c584 100644 --- a/src/mol-model/structure/structure/element/location.ts +++ b/src/mol-model/structure/structure/element/location.ts @@ -10,7 +10,7 @@ import Unit from '../unit'; import { Vec3 } from '../../../../mol-math/linear-algebra'; import Structure from '../structure'; -export { Location } +export { Location }; interface Location<U = Unit> { readonly kind: 'element-location', @@ -36,15 +36,15 @@ namespace Location { export function set(a: Location, structure?: Structure, unit?: Unit, element?: ElementIndex): Location { if (structure) a.structure = structure; - if (unit) a.unit = unit - if (element !== undefined) a.element = element + if (unit) a.unit = unit; + if (element !== undefined) a.element = element; return a; } export function copy(out: Location, a: Location): Location { - out.unit = a.unit - out.element = a.element - return out + out.unit = a.unit; + out.element = a.element; + return out; } export function is(x: any): x is Location { @@ -52,7 +52,7 @@ namespace Location { } export function areEqual(a: Location, b: Location) { - return a.unit === b.unit && a.element === b.element + return a.unit === b.unit && a.element === b.element; } const pA = Vec3.zero(), pB = Vec3.zero(); diff --git a/src/mol-model/structure/structure/element/loci.ts b/src/mol-model/structure/structure/element/loci.ts index cc8f6fa27a745eadae53da5ac5834dc741832bef..cb8c366ba727411cbbb2a0a8bace4864f4420fdf 100644 --- a/src/mol-model/structure/structure/element/loci.ts +++ b/src/mol-model/structure/structure/element/loci.ts @@ -50,23 +50,23 @@ export namespace Loci { } export function areEqual(a: Loci, b: Loci) { - if (a.structure !== b.structure) return false - if (a.elements.length !== b.elements.length) return false + if (a.structure !== b.structure) return false; + if (a.elements.length !== b.elements.length) return false; for (let i = 0, il = a.elements.length; i < il; ++i) { - const elementA = a.elements[i] - const elementB = b.elements[i] - if (elementA.unit.id !== elementB.unit.id) return false - if (!OrderedSet.areEqual(elementA.indices, elementB.indices)) return false + const elementA = a.elements[i]; + const elementB = b.elements[i]; + if (elementA.unit.id !== elementB.unit.id) return false; + if (!OrderedSet.areEqual(elementA.indices, elementB.indices)) return false; } - return true + return true; } export function isEmpty(loci: Loci) { - return size(loci) === 0 + return size(loci) === 0; } export function isWholeStructure(loci: Loci) { - return size(loci) === loci.structure.elementCount + return size(loci) === loci.structure.elementCount; } export function size(loci: Loci) { @@ -104,38 +104,38 @@ export namespace Loci { return Loci(loci.structure, [{ unit: loci.elements[0].unit, indices: OrderedSet.ofSingleton(OrderedSet.start(loci.elements[0].indices)) - }]) + }]); } export function firstResidue(loci: Loci): Loci { if (isEmpty(loci)) return loci; - return extendToWholeResidues(firstElement(loci)) + return extendToWholeResidues(firstElement(loci)); } export function firstChain(loci: Loci): Loci { if (isEmpty(loci)) return loci; - return extendToWholeChains(firstElement(loci)) + return extendToWholeChains(firstElement(loci)); } export function toStructure(loci: Loci): Structure { - const units: Unit[] = [] + const units: Unit[] = []; for (const e of loci.elements) { - const { unit, indices } = e - const elements = new Int32Array(OrderedSet.size(indices)) - OrderedSet.forEach(indices, (v, i) => elements[i] = unit.elements[v]) - units.push(unit.getChild(SortedArray.ofSortedArray(elements))) + const { unit, indices } = e; + const elements = new Int32Array(OrderedSet.size(indices)); + OrderedSet.forEach(indices, (v, i) => elements[i] = unit.elements[v]); + units.push(unit.getChild(SortedArray.ofSortedArray(elements))); } - return Structure.create(units, { parent: loci.structure.parent }) + return Structure.create(units, { parent: loci.structure.parent }); } // TODO: there should be a version that property supports partitioned units export function remap(loci: Loci, structure: Structure): Loci { - if (structure === loci.structure) return loci + if (structure === loci.structure) return loci; const elements: Loci['elements'][0][] = []; loci.elements.forEach(e => { - if (!structure.unitMap.has(e.unit.id)) return - const unit = structure.unitMap.get(e.unit.id) + if (!structure.unitMap.has(e.unit.id)) return; + const unit = structure.unitMap.get(e.unit.id); const indices = OrderedSet.indexedIntersect(e.indices, e.unit.elements, unit.elements); if (OrderedSet.size(indices) > 0) elements.push({ unit, indices }); @@ -157,7 +157,7 @@ export namespace Loci { for (const e of ys.elements) { if (map.has(e.unit.id)) { elements[elements.length] = { unit: e.unit, indices: OrderedSet.union(map.get(e.unit.id)!, e.indices) }; - map.delete(e.unit.id) + map.delete(e.unit.id); } else { elements[elements.length] = e; } @@ -240,7 +240,7 @@ export namespace Loci { export function extendToWholeResidues(loci: Loci, restrictToConformation?: boolean): Loci { const elements: Loci['elements'][0][] = []; - const residueAltIds = new Set<string>() + const residueAltIds = new Set<string>(); for (const lociElement of loci.elements) { if (isWholeUnit(lociElement)) { @@ -259,22 +259,22 @@ export namespace Loci { const indices = lociElement.indices, len = OrderedSet.size(indices); let i = 0; while (i < len) { - residueAltIds.clear() - const eI = unitElements[OrderedSet.getAt(indices, i)] + residueAltIds.clear(); + const eI = unitElements[OrderedSet.getAt(indices, i)]; const rI = residueIndex[eI]; - residueAltIds.add(label_alt_id.value(eI)) + residueAltIds.add(label_alt_id.value(eI)); i++; while (i < len) { - const eI = unitElements[OrderedSet.getAt(indices, i)] + const eI = unitElements[OrderedSet.getAt(indices, i)]; if (residueIndex[eI] !== rI) break; - residueAltIds.add(label_alt_id.value(eI)) + residueAltIds.add(label_alt_id.value(eI)); i++; } - const hasSharedAltId = residueAltIds.has('') + const hasSharedAltId = residueAltIds.has(''); for (let j = residueOffsets[rI], _j = residueOffsets[rI + 1]; j < _j; j++) { const idx = OrderedSet.indexOf(unitElements, j); if (idx >= 0) { - const altId = label_alt_id.value(j) + const altId = label_alt_id.value(j); if (!restrictToConformation || hasSharedAltId || !altId || residueAltIds.has(altId)) { newIndices[newIndices.length] = idx as UnitIndex; } @@ -294,9 +294,9 @@ export namespace Loci { function getChainSegments(unit: Unit) { switch (unit.kind) { - case Unit.Kind.Atomic: return unit.model.atomicHierarchy.chainAtomSegments - case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.chainElementSegments - case Unit.Kind.Gaussians: return unit.model.coarseHierarchy.gaussians.chainElementSegments + case Unit.Kind.Atomic: return unit.model.atomicHierarchy.chainAtomSegments; + case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.chainElementSegments; + case Unit.Kind.Gaussians: return unit.model.coarseHierarchy.gaussians.chainElementSegments; } } @@ -306,9 +306,9 @@ export namespace Loci { function makeIndexSet(newIndices: number[]): OrderedSet<UnitIndex> { if (newIndices.length > 12 && newIndices[newIndices.length - 1] - newIndices[0] === newIndices.length - 1) { - return Interval.ofRange(newIndices[0], newIndices[newIndices.length - 1]) + return Interval.ofRange(newIndices[0], newIndices[newIndices.length - 1]); } else { - return SortedArray.ofSortedArray(newIndices) + return SortedArray.ofSortedArray(newIndices); } } @@ -396,77 +396,77 @@ export namespace Loci { } function entityModelKey(location: Location) { - return `${location.unit.model.id}|${StructureProperties.entity.id(location)}` + return `${location.unit.model.id}|${StructureProperties.entity.id(location)}`; } export function extendToWholeEntities(loci: Loci): Loci { - const elements: Loci['elements'][0][] = [] - const l = Location.create(loci.structure) - const entities = new Set<string>() - const { units } = loci.structure + const elements: Loci['elements'][0][] = []; + const l = Location.create(loci.structure); + const entities = new Set<string>(); + const { units } = loci.structure; for (let i = 0, len = loci.elements.length; i < len; i++) { - const e = loci.elements[i] - l.unit = e.unit - l.element = e.unit.elements[0] - entities.add(entityModelKey(l)) + const e = loci.elements[i]; + l.unit = e.unit; + l.element = e.unit.elements[0]; + entities.add(entityModelKey(l)); } for (let i = 0, il = units.length; i < il; ++i) { - const unit = units[i] - l.unit = unit - l.element = unit.elements[0] + const unit = units[i]; + l.unit = unit; + l.element = unit.elements[0]; if (entities.has(entityModelKey(l))) { - const indices = OrderedSet.ofBounds(0, unit.elements.length) as OrderedSet<UnitIndex> - elements[elements.length] = { unit, indices } + const indices = OrderedSet.ofBounds(0, unit.elements.length) as OrderedSet<UnitIndex>; + elements[elements.length] = { unit, indices }; } } - return Loci(loci.structure, elements) + return Loci(loci.structure, elements); } export function extendToWholeModels(loci: Loci): Loci { - const elements: Loci['elements'][0][] = [] - const models = new Set<string>() - const { units } = loci.structure + const elements: Loci['elements'][0][] = []; + const models = new Set<string>(); + const { units } = loci.structure; for (let i = 0, len = loci.elements.length; i < len; i++) { - const e = loci.elements[i] - models.add(e.unit.model.id) + const e = loci.elements[i]; + models.add(e.unit.model.id); } for (let i = 0, il = units.length; i < il; ++i) { - const unit = units[i] + const unit = units[i]; if (models.has(unit.model.id)) { - const indices = OrderedSet.ofBounds(0, unit.elements.length) as OrderedSet<UnitIndex> - elements[elements.length] = { unit, indices } + const indices = OrderedSet.ofBounds(0, unit.elements.length) as OrderedSet<UnitIndex>; + elements[elements.length] = { unit, indices }; } } - return Loci(loci.structure, elements) + return Loci(loci.structure, elements); } export function extendToAllInstances(loci: Loci): Loci { const elements: Loci['elements'][0][] = []; - const byInvariantId = new Map<number, OrderedSet<UnitIndex>>() - const { unitSymmetryGroups, unitSymmetryGroupsIndexMap } = loci.structure + const byInvariantId = new Map<number, OrderedSet<UnitIndex>>(); + const { unitSymmetryGroups, unitSymmetryGroupsIndexMap } = loci.structure; for (let i = 0, len = loci.elements.length; i < len; i++) { - const e = loci.elements[i] - const { invariantId } = e.unit + const e = loci.elements[i]; + const { invariantId } = e.unit; if (byInvariantId.has(invariantId)) { - byInvariantId.set(invariantId, OrderedSet.union(e.indices, byInvariantId.get(invariantId)!)) + byInvariantId.set(invariantId, OrderedSet.union(e.indices, byInvariantId.get(invariantId)!)); } else { - byInvariantId.set(invariantId, e.indices) + byInvariantId.set(invariantId, e.indices); } } byInvariantId.forEach((indices, invariantId) => { - const { units } = unitSymmetryGroups[unitSymmetryGroupsIndexMap.get(invariantId)] + const { units } = unitSymmetryGroups[unitSymmetryGroupsIndexMap.get(invariantId)]; for (let i = 0, il = units.length; i < il; ++i) { - elements[elements.length] = { unit: units[i], indices } + elements[elements.length] = { unit: units[i], indices }; } - }) + }); return Loci(loci.structure, elements); } @@ -505,33 +505,33 @@ export namespace Loci { const tempPos = Vec3.zero(); export function toPositionsArray(loci: Loci, positions: NumberArray, offset = 0) { - let m = offset + let m = offset; for (const e of loci.elements) { - const { indices } = e - const pos = e.unit.conformation.position - const { elements } = e.unit - const indexCount = OrderedSet.size(indices) + const { indices } = e; + const pos = e.unit.conformation.position; + const { elements } = e.unit; + const indexCount = OrderedSet.size(indices); for (let i = 0; i < indexCount; i++) { - const eI = elements[OrderedSet.getAt(indices, i)] - pos(eI, tempPos) - Vec3.toArray(tempPos, positions, m + i * 3) + const eI = elements[OrderedSet.getAt(indices, i)]; + pos(eI, tempPos); + Vec3.toArray(tempPos, positions, m + i * 3); } - m += indexCount * 3 + m += indexCount * 3; } - return positions + return positions; } export function getPrincipalAxes(loci: Loci): PrincipalAxes { - const elementCount = size(loci) - const positions = toPositionsArray(loci, new Float32Array(3 * elementCount)) - return PrincipalAxes.ofPositions(positions) + const elementCount = size(loci); + const positions = toPositionsArray(loci, new Float32Array(3 * elementCount)); + return PrincipalAxes.ofPositions(positions); } function sourceIndex(unit: Unit, element: ElementIndex) { return Unit.isAtomic(unit) ? unit.model.atomicHierarchy.atoms.sourceIndex.value(element) // TODO: when implemented, this should map to the source index. - : element + : element; } export function toExpression(loci: Loci) { @@ -571,22 +571,22 @@ export namespace Loci { const opGroups = new Map<string, OpData>(); for (let i = 0, il = opData.length; i < il; ++i) { - const d = opData[i] - const hash = hash2(hashFnv32a(d.atom.ranges), hashFnv32a(d.atom.set)) - const key = `${hash}|${d.entity ? (d.entity.modelLabel + d.entity.modelIndex) : ''}` + const d = opData[i]; + const hash = hash2(hashFnv32a(d.atom.ranges), hashFnv32a(d.atom.set)); + const key = `${hash}|${d.entity ? (d.entity.modelLabel + d.entity.modelIndex) : ''}`; if (opGroups.has(key)) { - opGroups.get(key)!.chain.opName.push(...d.chain.opName) + opGroups.get(key)!.chain.opName.push(...d.chain.opName); } else { - opGroups.set(key, d) + opGroups.set(key, d); } } const opQueries: Expression[] = []; opGroups.forEach(d => { - const { ranges, set } = d.atom - const { opName } = d.chain + const { ranges, set } = d.atom; + const { opName } = d.chain; - const opProp = MS.struct.atomProperty.core.operatorName() + const opProp = MS.struct.atomProperty.core.operatorName(); const siProp = MS.struct.atomProperty.core.sourceIndex(); const tests: Expression[] = []; @@ -599,7 +599,7 @@ export namespace Loci { } if (d.entity) { - const { modelLabel, modelIndex } = d.entity + const { modelLabel, modelIndex } = d.entity; opQueries.push(MS.struct.generator.atomGroups({ 'atom-test': tests.length > 1 ? MS.core.logic.or(tests) : tests[0], 'chain-test': opName.length > 1 @@ -609,16 +609,16 @@ export namespace Loci { MS.core.rel.eq([MS.struct.atomProperty.core.modelLabel(), modelLabel]), MS.core.rel.eq([MS.struct.atomProperty.core.modelIndex(), modelIndex]), ]) - })) + })); } else { opQueries.push(MS.struct.generator.atomGroups({ 'atom-test': tests.length > 1 ? MS.core.logic.or(tests) : tests[0], 'chain-test': opName.length > 1 ? MS.core.set.has([MS.core.type.set(opName), opProp]) : MS.core.rel.eq([opProp, opName[0]]) - })) + })); } - }) + }); return MS.struct.modifier.union([ opQueries.length === 1 @@ -666,6 +666,6 @@ export namespace Loci { : { atom: { set, ranges }, chain: { opName: [ opName ] }, - } + }; } } \ No newline at end of file diff --git a/src/mol-model/structure/structure/element/stats.ts b/src/mol-model/structure/structure/element/stats.ts index b4dc38c1322fa3903695841510b9baf6c8ac87b7..355a2584a94c9b5203b69e14e93149ec15c3ce5d 100644 --- a/src/mol-model/structure/structure/element/stats.ts +++ b/src/mol-model/structure/structure/element/stats.ts @@ -44,99 +44,99 @@ export namespace Stats { firstChainLoc: Location.create(void 0), firstUnitLoc: Location.create(void 0), firstStructureLoc: Location.create(void 0), - } + }; } function addCountHelper<K>(map: Map<K, number>, key: K, inc: number) { - const count = map.get(key) || 0 - map.set(key, count + inc) + const count = map.get(key) || 0; + map.set(key, count + inc); } function handleElement(stats: Stats, structure: Structure, element: Loci['elements'][0]) { - const { indices, unit } = element - const { elements } = unit - const size = OrderedSet.size(indices) + const { indices, unit } = element; + const { elements } = unit; + const size = OrderedSet.size(indices); - const lociResidueAltIdCounts = new Map<string, number>() - const residueAltIdCounts = new Map<string, number>() + const lociResidueAltIdCounts = new Map<string, number>(); + const residueAltIdCounts = new Map<string, number>(); if (size > 0) { - Location.set(stats.firstElementLoc, structure, unit, elements[OrderedSet.start(indices)]) + Location.set(stats.firstElementLoc, structure, unit, elements[OrderedSet.start(indices)]); } // count single element unit as unit not element if (size === elements.length) { - stats.unitCount += 1 + stats.unitCount += 1; if (stats.unitCount === 1) { - Location.set(stats.firstUnitLoc, structure, unit, elements[OrderedSet.start(indices)]) + Location.set(stats.firstUnitLoc, structure, unit, elements[OrderedSet.start(indices)]); } } else if (size === 1) { if (Unit.Traits.is(unit.traits, Unit.Trait.MultiChain)) { - return + return; } else { - stats.elementCount += 1 + stats.elementCount += 1; if (stats.elementCount === 1) { - Location.set(stats.firstElementLoc, structure, unit, elements[OrderedSet.start(indices)]) + Location.set(stats.firstElementLoc, structure, unit, elements[OrderedSet.start(indices)]); } } } else { if (Unit.isAtomic(unit)) { - const { index, offsets } = unit.model.atomicHierarchy.residueAtomSegments + const { index, offsets } = unit.model.atomicHierarchy.residueAtomSegments; const { label_alt_id } = unit.model.atomicHierarchy.atoms; - let i = 0 + let i = 0; while (i < size) { - lociResidueAltIdCounts.clear() - let j = 0 - const eI = elements[OrderedSet.getAt(indices, i)] - const rI = index[eI] - addCountHelper(lociResidueAltIdCounts, label_alt_id.value(eI), 1) - ++i - ++j + lociResidueAltIdCounts.clear(); + let j = 0; + const eI = elements[OrderedSet.getAt(indices, i)]; + const rI = index[eI]; + addCountHelper(lociResidueAltIdCounts, label_alt_id.value(eI), 1); + ++i; + ++j; while (i < size) { - const eI = elements[OrderedSet.getAt(indices, i)] - if (index[eI] !== rI) break - addCountHelper(lociResidueAltIdCounts, label_alt_id.value(eI), 1) - ++i - ++j + const eI = elements[OrderedSet.getAt(indices, i)]; + if (index[eI] !== rI) break; + addCountHelper(lociResidueAltIdCounts, label_alt_id.value(eI), 1); + ++i; + ++j; } if (offsets[rI + 1] - offsets[rI] === j) { // full residue - stats.residueCount += 1 + stats.residueCount += 1; if (stats.residueCount === 1) { - Location.set(stats.firstResidueLoc, structure, unit, offsets[rI]) + Location.set(stats.firstResidueLoc, structure, unit, offsets[rI]); } } else { // partial residue - residueAltIdCounts.clear() + residueAltIdCounts.clear(); for (let l = offsets[rI], _l = offsets[rI + 1]; l < _l; ++l) { - addCountHelper(residueAltIdCounts, label_alt_id.value(l), 1) + addCountHelper(residueAltIdCounts, label_alt_id.value(l), 1); } // check if shared atom count match if (residueAltIdCounts.get('') === lociResidueAltIdCounts.get('')) { lociResidueAltIdCounts.forEach((v, k) => { - if (residueAltIdCounts.get(k) !== v) return + if (residueAltIdCounts.get(k) !== v) return; if (k !== '') { - stats.conformationCount += 1 + stats.conformationCount += 1; if (stats.conformationCount === 1) { for (let l = offsets[rI], _l = offsets[rI + 1]; l < _l; ++l) { if (k === label_alt_id.value(l)) { - Location.set(stats.firstConformationLoc, structure, unit, l) - break + Location.set(stats.firstConformationLoc, structure, unit, l); + break; } } } } - j -= v - }) + j -= v; + }); } - stats.elementCount += j + stats.elementCount += j; } } } else { - stats.elementCount += size + stats.elementCount += size; if (stats.elementCount === 1) { - Location.set(stats.firstElementLoc, structure, unit, elements[OrderedSet.start(indices)]) + Location.set(stats.firstElementLoc, structure, unit, elements[OrderedSet.start(indices)]); } } } @@ -175,7 +175,7 @@ export namespace Stats { const { index, offsets } = segments; let i = 0; while (i < size) { - let j = 0 + let j = 0; const eI = elements[OrderedSet.getAt(indices, i)]; const cI = index[eI]; ++i; @@ -221,7 +221,7 @@ export namespace Stats { for (let elIndex = start; elIndex < end; elIndex++) { element = lociElements[elIndex]; - const { indices, unit } = element + const { indices, unit } = element; const size = OrderedSet.size(indices); if (size === 0) continue; @@ -235,7 +235,7 @@ export namespace Stats { let i = 0; while (i < size) { - let j = 0 + let j = 0; const eI = elements[OrderedSet.getAt(indices, i)]; const cI = index[eI]; ++i; @@ -267,7 +267,7 @@ export namespace Stats { for (let elIndex = start; elIndex < end; elIndex++) { element = lociElements[elIndex]; - const { indices, unit } = element + const { indices, unit } = element; const size = OrderedSet.size(indices); if (size === 0) continue; @@ -286,19 +286,19 @@ export namespace Stats { } export function ofLoci(loci: Loci) { - const stats = create() - if (Loci.isEmpty(loci)) return stats + const stats = create(); + if (Loci.isEmpty(loci)) return stats; let hasPartitions = false; if (Loci.isWholeStructure(loci)) { - stats.structureCount += 1 + stats.structureCount += 1; if (stats.structureCount === 1) { - const { unit, indices } = loci.elements[0] - Location.set(stats.firstStructureLoc, loci.structure, unit, unit.elements[OrderedSet.min(indices)]) + const { unit, indices } = loci.elements[0]; + Location.set(stats.firstStructureLoc, loci.structure, unit, unit.elements[OrderedSet.min(indices)]); } } else { for (const e of loci.elements) { - handleElement(stats, loci.structure, e) + handleElement(stats, loci.structure, e); if (!Unit.Traits.is(e.unit.traits, Unit.Trait.Partitioned)) { handleUnitChainsSimple(stats, loci.structure, e); } else { @@ -326,53 +326,53 @@ export namespace Stats { } } - return stats + return stats; } /** Adds counts of two Stats objects together, assumes they describe different structures */ export function add(out: Stats, a: Stats, b: Stats) { if (a.elementCount === 1 && b.elementCount === 0) { - Location.copy(out.firstElementLoc, a.firstElementLoc) + Location.copy(out.firstElementLoc, a.firstElementLoc); } else if (a.elementCount === 0 && b.elementCount === 1) { - Location.copy(out.firstElementLoc, b.firstElementLoc) + Location.copy(out.firstElementLoc, b.firstElementLoc); } if (a.conformationCount === 1 && b.conformationCount === 0) { - Location.copy(out.firstConformationLoc, a.firstConformationLoc) + Location.copy(out.firstConformationLoc, a.firstConformationLoc); } else if (a.conformationCount === 0 && b.conformationCount === 1) { - Location.copy(out.firstConformationLoc, b.firstConformationLoc) + Location.copy(out.firstConformationLoc, b.firstConformationLoc); } if (a.residueCount === 1 && b.residueCount === 0) { - Location.copy(out.firstResidueLoc, a.firstResidueLoc) + Location.copy(out.firstResidueLoc, a.firstResidueLoc); } else if (a.residueCount === 0 && b.residueCount === 1) { - Location.copy(out.firstResidueLoc, b.firstResidueLoc) + Location.copy(out.firstResidueLoc, b.firstResidueLoc); } if (a.chainCount === 1 && b.chainCount === 0) { - Location.copy(out.firstChainLoc, a.firstChainLoc) + Location.copy(out.firstChainLoc, a.firstChainLoc); } else if (a.chainCount === 0 && b.chainCount === 1) { - Location.copy(out.firstChainLoc, b.firstChainLoc) + Location.copy(out.firstChainLoc, b.firstChainLoc); } if (a.unitCount === 1 && b.unitCount === 0) { - Location.copy(out.firstUnitLoc, a.firstUnitLoc) + Location.copy(out.firstUnitLoc, a.firstUnitLoc); } else if (a.unitCount === 0 && b.unitCount === 1) { - Location.copy(out.firstUnitLoc, b.firstUnitLoc) + Location.copy(out.firstUnitLoc, b.firstUnitLoc); } if (a.structureCount === 1 && b.structureCount === 0) { - Location.copy(out.firstStructureLoc, a.firstStructureLoc) + Location.copy(out.firstStructureLoc, a.firstStructureLoc); } else if (a.structureCount === 0 && b.structureCount === 1) { - Location.copy(out.firstStructureLoc, b.firstStructureLoc) + Location.copy(out.firstStructureLoc, b.firstStructureLoc); } - out.elementCount = a.elementCount + b.elementCount - out.conformationCount = a.conformationCount + b.conformationCount - out.residueCount = a.residueCount + b.residueCount - out.chainCount = a.chainCount + b.chainCount - out.unitCount = a.unitCount + b.unitCount - out.structureCount = a.structureCount + b.structureCount - return out + out.elementCount = a.elementCount + b.elementCount; + out.conformationCount = a.conformationCount + b.conformationCount; + out.residueCount = a.residueCount + b.residueCount; + out.chainCount = a.chainCount + b.chainCount; + out.unitCount = a.unitCount + b.unitCount; + out.structureCount = a.structureCount + b.structureCount; + return out; } } \ No newline at end of file diff --git a/src/mol-model/structure/structure/properties.ts b/src/mol-model/structure/structure/properties.ts index 9153ddbe40029be14a44ef203fe5570c90f694e4..47b738a8c75cb18f15baf99a02af996c1e577afe 100644 --- a/src/mol-model/structure/structure/properties.ts +++ b/src/mol-model/structure/structure/properties.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import StructureElement from './element' -import Unit from './unit' +import StructureElement from './element'; +import Unit from './unit'; import { VdwRadius } from '../model/properties/atomic'; import { SecondaryStructureType } from '../model/types'; import { SecondaryStructureProvider } from '../../../mol-model-props/computed/secondary-structure'; @@ -18,7 +18,7 @@ const constant = { true: p(l => true), false: p(l => false), zero: p(l => 0) -} +}; function notAtomic(): never { throw 'Property only available for atomic models.'; @@ -55,35 +55,35 @@ const atom = { // Derived vdw_radius: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : VdwRadius(l.unit.model.atomicHierarchy.atoms.type_symbol.value(l.element))), -} +}; function _compId(l: StructureElement.Location) { - return !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.label_comp_id.value(l.unit.residueIndex[l.element]) + return !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.label_comp_id.value(l.unit.residueIndex[l.element]); } function compId(l: StructureElement.Location) { - if (!Unit.isAtomic(l.unit)) notAtomic() - if (!hasMicroheterogeneity(l)) return _compId(l) - return l.unit.model.atomicHierarchy.residues.label_comp_id.value(l.unit.residueIndex[l.element]) + if (!Unit.isAtomic(l.unit)) notAtomic(); + if (!hasMicroheterogeneity(l)) return _compId(l); + return l.unit.model.atomicHierarchy.residues.label_comp_id.value(l.unit.residueIndex[l.element]); } function seqId(l: StructureElement.Location) { - return !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.label_seq_id.value(l.unit.residueIndex[l.element]) + return !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.residues.label_seq_id.value(l.unit.residueIndex[l.element]); } function hasMicroheterogeneity(l: StructureElement.Location) { - if (!Unit.isAtomic(l.unit)) notAtomic() - const entitySeq = l.unit.model.sequence.byEntityKey[eK(l)] - return entitySeq && entitySeq.sequence.microHet.has(seqId(l)) + if (!Unit.isAtomic(l.unit)) notAtomic(); + const entitySeq = l.unit.model.sequence.byEntityKey[eK(l)]; + return entitySeq && entitySeq.sequence.microHet.has(seqId(l)); } function microheterogeneityCompIds(l: StructureElement.Location) { - if (!Unit.isAtomic(l.unit)) notAtomic() - const entitySeq = l.unit.model.sequence.byEntityKey[eK(l)] + if (!Unit.isAtomic(l.unit)) notAtomic(); + const entitySeq = l.unit.model.sequence.byEntityKey[eK(l)]; if (entitySeq) { - return entitySeq.sequence.microHet.get(seqId(l)) || [compId(l)] + return entitySeq.sequence.microHet.get(seqId(l)) || [compId(l)]; } else { - return [compId(l)] + return [compId(l)]; } } @@ -102,17 +102,17 @@ const residue = { hasMicroheterogeneity: p(hasMicroheterogeneity), microheterogeneityCompIds: p(microheterogeneityCompIds), secondary_structure_type: p(l => { - if (!Unit.isAtomic(l.unit)) notAtomic() - const secStruc = SecondaryStructureProvider.get(l.structure).value?.get(l.unit.id) - return secStruc?.type[l.unit.residueIndex[l.element]] ?? SecondaryStructureType.Flag.NA + if (!Unit.isAtomic(l.unit)) notAtomic(); + const secStruc = SecondaryStructureProvider.get(l.structure).value?.get(l.unit.id); + return secStruc?.type[l.unit.residueIndex[l.element]] ?? SecondaryStructureType.Flag.NA; }), secondary_structure_key: p(l => { - if (!Unit.isAtomic(l.unit)) notAtomic() - const secStruc = SecondaryStructureProvider.get(l.structure).value?.get(l.unit.id) - return secStruc?.key[l.unit.residueIndex[l.element]] ?? -1 + if (!Unit.isAtomic(l.unit)) notAtomic(); + const secStruc = SecondaryStructureProvider.get(l.structure).value?.get(l.unit.id); + return secStruc?.key[l.unit.residueIndex[l.element]] ?? -1; }), chem_comp_type: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.properties.chemicalComponentMap.get(compId(l))!.type), -} +}; const chain = { key: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.chainIndex[l.element]), @@ -120,7 +120,7 @@ const chain = { label_asym_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.chains.label_asym_id.value(l.unit.chainIndex[l.element])), auth_asym_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.chains.auth_asym_id.value(l.unit.chainIndex[l.element])), label_entity_id: p(l => !Unit.isAtomic(l.unit) ? notAtomic() : l.unit.model.atomicHierarchy.chains.label_entity_id.value(l.unit.chainIndex[l.element])) -} +}; const coarse = { key: atom.key, @@ -139,16 +139,16 @@ const coarse = { gaussian_weight: p(l => !Unit.isGaussians(l.unit) ? notCoarse('gaussians') : l.unit.coarseConformation.weight[l.element]), gaussian_covariance_matrix: p(l => !Unit.isGaussians(l.unit) ? notCoarse('gaussians') : l.unit.coarseConformation.covariance_matrix[l.element]) -} +}; function eK(l: StructureElement.Location) { switch (l.unit.kind) { case Unit.Kind.Atomic: - return l.unit.model.atomicHierarchy.index.getEntityFromChain(l.unit.chainIndex[l.element]) + return l.unit.model.atomicHierarchy.index.getEntityFromChain(l.unit.chainIndex[l.element]); case Unit.Kind.Spheres: - return l.unit.model.coarseHierarchy.spheres.entityKey[l.element] + return l.unit.model.coarseHierarchy.spheres.entityKey[l.element]; case Unit.Kind.Gaussians: - return l.unit.model.coarseHierarchy.gaussians.entityKey[l.element] + return l.unit.model.coarseHierarchy.gaussians.entityKey[l.element]; } } @@ -166,7 +166,7 @@ const entity = { pdbx_mutation: p(l => l.unit.model.entities.data.pdbx_mutation.value(eK(l))), pdbx_fragment: p(l => l.unit.model.entities.data.pdbx_fragment.value(eK(l))), pdbx_ec: p(l => l.unit.model.entities.data.pdbx_ec.value(eK(l))) -} +}; const _emptyList: any[] = []; const unit = { @@ -185,7 +185,7 @@ const unit = { pdbx_struct_assembly_id: p(l => l.unit.conformation.operator.assembly?.id || SymmetryOperator.DefaultName), pdbx_struct_oper_list_ids: p(l => l.unit.conformation.operator.assembly?.operList || _emptyList), struct_ncs_oper_id: p(l => l.unit.conformation.operator.ncsId), -} +}; const StructureProperties = { constant, @@ -195,7 +195,7 @@ const StructureProperties = { entity, unit, coarse -} +}; type StructureProperties = typeof StructureProperties -export default StructureProperties \ No newline at end of file +export default StructureProperties; \ No newline at end of file diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index 5abebeeff9ec5f917ea132b033775b2e554b93dd..67c4fb71dfe09794e4286f01e247dfbd9ce7f7c4 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/src/mol-model/structure/structure/structure.ts @@ -5,13 +5,13 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { IntMap, SortedArray, Iterator, Segmentation, Interval, OrderedSet } from '../../../mol-data/int' -import { UniqueArray } from '../../../mol-data/generic' -import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator' -import { Model, ElementIndex } from '../model' +import { IntMap, SortedArray, Iterator, Segmentation, Interval, OrderedSet } from '../../../mol-data/int'; +import { UniqueArray } from '../../../mol-data/generic'; +import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator'; +import { Model, ElementIndex } from '../model'; import { sort, arraySwap, hash1, sortArray, hashString, hashFnv32a } from '../../../mol-data/util'; -import StructureElement from './element' -import Unit from './unit' +import StructureElement from './element'; +import Unit from './unit'; import { StructureLookup3D } from './util/lookup3d'; import { CoarseElements } from '../model/properties/coarse'; import { StructureSubsetBuilder } from './util/subset-builder'; @@ -91,7 +91,7 @@ class Structure { /** Count of all bonds (intra- and inter-unit) in the structure */ get bondCount() { if (!this._props.bondCount) { - this._props.bondCount = this.interUnitBonds.edgeCount + Bond.getIntraUnitBondCount(this) + this._props.bondCount = this.interUnitBonds.edgeCount + Bond.getIntraUnitBondCount(this); } return this._props.bondCount; } @@ -123,28 +123,28 @@ class Structure { /** Count of all polymer residues in the structure */ get polymerResidueCount() { if (this._props.polymerResidueCount === -1) { - this._props.polymerResidueCount = getPolymerResidueCount(this) + this._props.polymerResidueCount = getPolymerResidueCount(this); } return this._props.polymerResidueCount; } get polymerUnitCount() { if (this._props.polymerUnitCount === -1) { - this._props.polymerUnitCount = getPolymerUnitCount(this) + this._props.polymerUnitCount = getPolymerUnitCount(this); } return this._props.polymerUnitCount; } get uniqueElementCount() { if (this._props.uniqueElementCount === -1) { - this._props.uniqueElementCount = getUniqueElementCount(this) + this._props.uniqueElementCount = getUniqueElementCount(this); } return this._props.uniqueElementCount; } get atomicResidueCount() { if (this._props.atomicResidueCount === -1) { - this._props.atomicResidueCount = getAtomicResidueCount(this) + this._props.atomicResidueCount = getAtomicResidueCount(this); } return this._props.atomicResidueCount; } @@ -154,9 +154,9 @@ class Structure { * twice as many elements as polymer residues */ get isCoarseGrained() { - const ec = this.elementCount - const prc = this.polymerResidueCount - return prc && ec ? ec / prc < 2 : false + const ec = this.elementCount; + const prc = this.polymerResidueCount; + return prc && ec ? ec / prc < 2 : false; } get isEmpty() { @@ -171,7 +171,7 @@ class Structure { /** Hash based on all unit.id values in the structure, reflecting the units transformation */ get transformHash() { if (this._props.transformHash !== -1) return this._props.transformHash; - this._props.transformHash = hashFnv32a(this.units.map(u => u.id)) + this._props.transformHash = hashFnv32a(this.units.map(u => u.id)); return this._props.transformHash; } @@ -327,12 +327,12 @@ class Structure { /** The master-model, other models can have bonds to it */ get masterModel(): Model | undefined { - return this._props.masterModel + return this._props.masterModel; } /** A representative model, e.g. the first model of a trajectory */ get representativeModel(): Model | undefined { - return this._props.representativeModel + return this._props.representativeModel; } hasElement(e: StructureElement.Location) { @@ -341,7 +341,7 @@ class Structure { } getModelIndex(m: Model) { - return this.models.indexOf(m) + return this.models.indexOf(m); } private initUnits(units: ArrayLike<Unit>) { @@ -468,56 +468,56 @@ function getUniqueAtomicResidueIndices(structure: Structure): ReadonlyMap<UUID, for (const id of modelIds) { const array = map.get(id)!.array; sortArray(array); - ret.set(id, array) + ret.set(id, array); } return ret; } function getUniqueElementCount(structure: Structure): number { - const { unitSymmetryGroups } = structure - let uniqueElementCount = 0 + const { unitSymmetryGroups } = structure; + let uniqueElementCount = 0; for (let i = 0, _i = unitSymmetryGroups.length; i < _i; i++) { - uniqueElementCount += unitSymmetryGroups[i].elements.length + uniqueElementCount += unitSymmetryGroups[i].elements.length; } - return uniqueElementCount + return uniqueElementCount; } function getPolymerResidueCount(structure: Structure): number { - const { units } = structure - let polymerResidueCount = 0 + const { units } = structure; + let polymerResidueCount = 0; for (let i = 0, _i = units.length; i < _i; i++) { polymerResidueCount += units[i].polymerElements.length; } - return polymerResidueCount + return polymerResidueCount; } function getPolymerUnitCount(structure: Structure): number { - const { units } = structure - let polymerUnitCount = 0 + const { units } = structure; + let polymerUnitCount = 0; for (let i = 0, _i = units.length; i < _i; i++) { - if (units[i].polymerElements.length > 0) polymerUnitCount += 1 + if (units[i].polymerElements.length > 0) polymerUnitCount += 1; } - return polymerUnitCount + return polymerUnitCount; } function getAtomicResidueCount(structure: Structure): number { - const { units } = structure - let atomicResidueCount = 0 + const { units } = structure; + let atomicResidueCount = 0; for (let i = 0, _i = units.length; i < _i; i++) { - const unit = units[i] - if (!Unit.isAtomic(unit)) continue - const { elements, residueIndex } = unit - let idx = -1 - let prevIdx = -1 + const unit = units[i]; + if (!Unit.isAtomic(unit)) continue; + const { elements, residueIndex } = unit; + let idx = -1; + let prevIdx = -1; for (let j = 0, jl = elements.length; j < jl; ++j) { - idx = residueIndex[elements[j]] + idx = residueIndex[elements[j]]; if (idx !== prevIdx) { - atomicResidueCount += 1 - prevIdx = idx + atomicResidueCount += 1; + prevIdx = idx; } } } - return atomicResidueCount + return atomicResidueCount; } interface SerialMapping { @@ -531,19 +531,19 @@ interface SerialMapping { getSerialIndex: (unit: Unit, element: ElementIndex) => Structure.SerialIndex } function getSerialMapping(structure: Structure): SerialMapping { - const { units, elementCount, unitIndexMap } = structure - const cumulativeUnitElementCount = new Uint32Array(units.length) - const unitIndices = new Uint32Array(elementCount) - const elementIndices = new Uint32Array(elementCount) as unknown as ElementIndex[] + const { units, elementCount, unitIndexMap } = structure; + const cumulativeUnitElementCount = new Uint32Array(units.length); + const unitIndices = new Uint32Array(elementCount); + const elementIndices = new Uint32Array(elementCount) as unknown as ElementIndex[]; for (let i = 0, m = 0, il = units.length; i < il; ++i) { - cumulativeUnitElementCount[i] = m - const { elements } = units[i] + cumulativeUnitElementCount[i] = m; + const { elements } = units[i]; for (let j = 0, jl = elements.length; j < jl; ++j) { - const mj = m + j - unitIndices[mj] = i - elementIndices[mj] = elements[j] + const mj = m + j; + unitIndices[mj] = i; + elementIndices[mj] = elements[j]; } - m += elements.length + m += elements.length; } return { cumulativeUnitElementCount, @@ -551,7 +551,7 @@ function getSerialMapping(structure: Structure): SerialMapping { elementIndices, getSerialIndex: (unit, element) => cumulativeUnitElementCount[unitIndexMap.get(unit.id)] + OrderedSet.indexOf(unit.elements, element) as Structure.SerialIndex - } + }; } namespace Structure { @@ -580,9 +580,9 @@ namespace Structure { } export function toStructureElementLoci(structure: Structure): StructureElement.Loci { - const elements: StructureElement.Loci['elements'][0][] = [] + const elements: StructureElement.Loci['elements'][0][] = []; for (const unit of structure.units) { - elements.push({ unit, indices: Interval.ofBounds(0, unit.elements.length) }) + elements.push({ unit, indices: Interval.ofBounds(0, unit.elements.length) }); } return StructureElement.Loci(structure, elements); } @@ -596,16 +596,16 @@ namespace Structure { } export function areLociEqual(a: Loci, b: Loci) { - return a.structure === b.structure + return a.structure === b.structure; } export function isLociEmpty(loci: Loci) { - return loci.structure.isEmpty + return loci.structure.isEmpty; } export function remapLoci(loci: Loci, structure: Structure) { - if (structure === loci.structure) return loci - return Loci(structure) + if (structure === loci.structure) return loci; + return Loci(structure); } export function create(units: ReadonlyArray<Unit>, props?: Props): Structure { @@ -613,21 +613,21 @@ namespace Structure { } export function ofTrajectory(trajectory: ReadonlyArray<Model>): Structure { - if (trajectory.length === 0) return Empty + if (trajectory.length === 0) return Empty; const units: Unit[] = []; - let count = 0 + let count = 0; for (let i = 0, il = trajectory.length; i < il; ++i) { - const structure = ofModel(trajectory[i]) + const structure = ofModel(trajectory[i]); for (let j = 0, jl = structure.units.length; j < jl; ++j) { - const u = structure.units[j] - const invariantId = u.invariantId + count - const chainGroupId = u.chainGroupId + count - const newUnit = Unit.create(units.length, invariantId, chainGroupId, u.traits, u.kind, u.model, u.conformation.operator, u.elements) - units.push(newUnit) + const u = structure.units[j]; + const invariantId = u.invariantId + count; + const chainGroupId = u.chainGroupId + count; + const newUnit = Unit.create(units.length, invariantId, chainGroupId, u.traits, u.kind, u.model, u.conformation.operator, u.elements); + units.push(newUnit); } - count = units.length + count = units.length; } return create(units, { representativeModel: trajectory[0], label: trajectory[0].label }); @@ -652,15 +652,15 @@ namespace Structure { // set to true for chains that consist of "single atom residues", // note that it assumes there are no "zero atom residues" - let singleAtomResidues = AtomicHierarchy.chainResidueCount(model.atomicHierarchy, c) === chains.offsets[c + 1] - chains.offsets[c] + let singleAtomResidues = AtomicHierarchy.chainResidueCount(model.atomicHierarchy, c) === chains.offsets[c + 1] - chains.offsets[c]; // merge all consecutive "single atom chains" with same entity_id and same auth_asym_id - let multiChain = false + let multiChain = false; while (c + 1 < chains.count && chains.offsets[c + 1] - chains.offsets[c] === 1 && chains.offsets[c + 2] - chains.offsets[c + 1] === 1 ) { - singleAtomResidues = true + singleAtomResidues = true; const e1 = index.getEntityFromChain(c); const e2 = index.getEntityFromChain(c + 1 as ChainIndex); if (e1 !== e2) break; @@ -673,7 +673,7 @@ namespace Structure { const op2 = atomicChainOperatorMappinng.get(c + 1 as ChainIndex); if (op1 !== op2) break; - multiChain = true + multiChain = true; c++; } @@ -709,7 +709,7 @@ namespace Structure { function partitionAtomicUnitByAtom(model: Model, indices: SortedArray, builder: StructureBuilder, multiChain: boolean, operator: SymmetryOperator) { const { x, y, z } = model.atomicConformation; - const position = { x, y, z, indices } + const position = { x, y, z, indices }; const lookup = GridLookup3D(position, getBoundary(position), 8192); const { offset, count, array } = lookup.buckets; @@ -729,23 +729,23 @@ namespace Structure { // keeps atoms of residues together function partitionAtomicUnitByResidue(model: Model, indices: SortedArray, builder: StructureBuilder, multiChain: boolean, operator: SymmetryOperator) { - const { residueAtomSegments } = model.atomicHierarchy + const { residueAtomSegments } = model.atomicHierarchy; - const startIndices: number[] = [] - const endIndices: number[] = [] + const startIndices: number[] = []; + const endIndices: number[] = []; - const residueIt = Segmentation.transientSegments(residueAtomSegments, indices) + const residueIt = Segmentation.transientSegments(residueAtomSegments, indices); while (residueIt.hasNext) { const residueSegment = residueIt.move(); - startIndices[startIndices.length] = indices[residueSegment.start] - endIndices[endIndices.length] = indices[residueSegment.end] + startIndices[startIndices.length] = indices[residueSegment.start]; + endIndices[endIndices.length] = indices[residueSegment.end]; } - const firstResidueAtomCount = endIndices[0] - startIndices[0] - const gridCellCount = 512 * firstResidueAtomCount + const firstResidueAtomCount = endIndices[0] - startIndices[0]; + const gridCellCount = 512 * firstResidueAtomCount; const { x, y, z } = model.atomicConformation; - const position = { x, y, z, indices: SortedArray.ofSortedArray(startIndices) } + const position = { x, y, z, indices: SortedArray.ofSortedArray(startIndices) }; const lookup = GridLookup3D(position, getBoundary(position), gridCellCount); const { offset, count, array } = lookup.buckets; @@ -756,7 +756,7 @@ namespace Structure { const start = offset[i]; const set: number[] = []; for (let j = 0, _j = count[i]; j < _j; j++) { - const k = array[start + j] + const k = array[start + j]; for (let l = startIndices[k], _l = endIndices[k]; l < _l; l++) { set[set.length] = l; } @@ -807,7 +807,7 @@ namespace Structure { } addUnit(kind: Unit.Kind, model: Model, operator: SymmetryOperator, elements: StructureElement.Set, traits: Unit.Traits, invariantId?: number): Unit { - if (invariantId === undefined) invariantId = this.invariantId() + if (invariantId === undefined) invariantId = this.invariantId(); const chainGroupId = this.inChainGroup ? this.chainGroupId : ++this.chainGroupId; const unit = Unit.create(this.units.length, invariantId, chainGroupId, traits, kind, model, operator, elements); this.units.push(unit); @@ -843,7 +843,7 @@ namespace Structure { /** Hash based on all unit.model conformation values in the structure */ export function conformationHash(s: Structure) { - return hashString(s.units.map(u => Unit.conformationId(u)).join('|')) + return hashString(s.units.map(u => Unit.conformationId(u)).join('|')); } // TODO: there should be a version that properly supports partitioned units @@ -869,17 +869,17 @@ namespace Structure { return a === b || ( a.hashCode === b.hashCode && StructureSymmetry.areTransformGroupsEquivalent(a.unitSymmetryGroups, b.unitSymmetryGroups) - ) + ); } /** Check if the structures or their parents are equivalent */ export function areRootsEquivalent(a: Structure, b: Structure) { - return areEquivalent(a.root, b.root) + return areEquivalent(a.root, b.root); } /** Check if the structures or their parents are equal */ export function areRootsEqual(a: Structure, b: Structure) { - return a.root === b.root + return a.root === b.root; } export class ElementLocationIterator implements Iterator<StructureElement.Location> { @@ -970,13 +970,13 @@ namespace Structure { } export function elementDescription(s: Structure) { - return s.elementCount === 1 ? '1 element' : `${s.elementCount} elements` + return s.elementCount === 1 ? '1 element' : `${s.elementCount} elements`; } export function validUnitPair(s: Structure, a: Unit, b: Unit) { return s.masterModel ? a.model === b.model || a.model === s.masterModel || b.model === s.masterModel - : a.model === b.model + : a.model === b.model; } export interface EachUnitPairProps { @@ -990,7 +990,7 @@ namespace Structure { * and unit pairs if within a max distance. */ export function eachUnitPair(structure: Structure, callback: (unitA: Unit, unitB: Unit) => void, props: EachUnitPairProps) { - const { maxRadius, validUnit, validUnitPair } = props + const { maxRadius, validUnit, validUnitPair } = props; if (!structure.units.some(u => validUnit(u))) return; const lookup = structure.lookup3d; @@ -1023,53 +1023,53 @@ namespace Structure { fiberResidueCount: 15, residueCountFactor: 1 - } + }; export type SizeThresholds = typeof DefaultSizeThresholds function getPolymerSymmetryGroups(structure: Structure) { - return structure.unitSymmetryGroups.filter(ug => ug.units[0].polymerElements.length > 0) + return structure.unitSymmetryGroups.filter(ug => ug.units[0].polymerElements.length > 0); } /** * Try to match fiber-like structures like 6nk4 */ function isFiberLike(structure: Structure, thresholds: SizeThresholds) { - const polymerSymmetryGroups = getPolymerSymmetryGroups(structure) + const polymerSymmetryGroups = getPolymerSymmetryGroups(structure); return ( polymerSymmetryGroups.length === 1 && polymerSymmetryGroups[0].units.length > 2 && polymerSymmetryGroups[0].units[0].polymerElements.length < thresholds.fiberResidueCount - ) + ); } function hasHighSymmetry(structure: Structure, thresholds: SizeThresholds) { - const polymerSymmetryGroups = getPolymerSymmetryGroups(structure) + const polymerSymmetryGroups = getPolymerSymmetryGroups(structure); return ( polymerSymmetryGroups.length >= 1 && polymerSymmetryGroups[0].units.length > thresholds.highSymmetryUnitCount - ) + ); } export enum Size { Small, Medium, Large, Huge, Gigantic } export function getSize(structure: Structure, thresholds: Partial<SizeThresholds> = {}): Size { - const t = { ...DefaultSizeThresholds, ...thresholds } + const t = { ...DefaultSizeThresholds, ...thresholds }; if (structure.polymerResidueCount >= t.largeResidueCount * t.residueCountFactor) { if (hasHighSymmetry(structure, t)) { - return Size.Huge + return Size.Huge; } else { - return Size.Gigantic + return Size.Gigantic; } } else if (isFiberLike(structure, t)) { - return Size.Small + return Size.Small; } else if (structure.polymerResidueCount < t.smallResidueCount * t.residueCountFactor) { - return Size.Small + return Size.Small; } else if (structure.polymerResidueCount < t.mediumResidueCount * t.residueCountFactor) { - return Size.Medium + return Size.Medium; } else { - return Size.Large + return Size.Large; } } } -export default Structure \ No newline at end of file +export default Structure; \ No newline at end of file diff --git a/src/mol-model/structure/structure/symmetry.ts b/src/mol-model/structure/structure/symmetry.ts index 620ffe31bfa0eab0c6065714b5c4d6441f6bc722..4c4dbb20b1c095132f740f413d5dbb8aa30d25ff 100644 --- a/src/mol-model/structure/structure/symmetry.ts +++ b/src/mol-model/structure/structure/symmetry.ts @@ -26,7 +26,7 @@ namespace StructureSymmetry { const assembly = Symmetry.findAssembly(models[0], asmName); if (!assembly) throw new Error(`Assembly '${asmName}' is not defined.`); - const coordinateSystem = SymmetryOperator.create(assembly.id, Mat4.identity(), { assembly: { id: assembly.id, operId: 0, operList: [] } }) + const coordinateSystem = SymmetryOperator.create(assembly.id, Mat4.identity(), { assembly: { id: assembly.id, operId: 0, operList: [] } }); const assembler = Structure.Builder({ coordinateSystem, label: structure.label }); const queryCtx = new QueryContext(structure); @@ -56,7 +56,7 @@ namespace StructureSymmetry { const models = structure.models; if (models.length !== 1) throw new Error('Can only build symmetry assemblies from structures based on 1 model.'); - const modelCenter = Vec3() + const modelCenter = Vec3(); const assembler = Structure.Builder({ label: structure.label, representativeModel: models[0] }); const queryCtx = new QueryContext(structure); @@ -70,7 +70,7 @@ namespace StructureSymmetry { const { units } = StructureSelection.unionStructure(selection); for (const { index, shift: [i, j, k] } of g.operators) { - const operators = getOperatorsForIndex(symmetry, index, i, j, k, modelCenter) + const operators = getOperatorsForIndex(symmetry, index, i, j, k, modelCenter); for (const unit of units) { for (const op of operators) { assembler.addWithOperator(unit, op); @@ -110,7 +110,7 @@ namespace StructureSymmetry { const ret: Unit.SymmetryGroup[] = []; for (const eqUnits of groups.groups) { - ret.push(Unit.SymmetryGroup(eqUnits.map(id => s.unitMap.get(id)))) + ret.push(Unit.SymmetryGroup(eqUnits.map(id => s.unitMap.get(id)))); } return ret; @@ -118,16 +118,16 @@ namespace StructureSymmetry { /** Checks if transform groups are equal up to their unit's transformations */ export function areTransformGroupsEquivalent(a: ReadonlyArray<Unit.SymmetryGroup>, b: ReadonlyArray<Unit.SymmetryGroup>) { - if (a.length !== b.length) return false + if (a.length !== b.length) return false; for (let i = 0, il = a.length; i < il; ++i) { const au = a[i].units, bu = b[i].units; if (au.length !== bu.length) return false; - if (a[i].hashCode !== b[i].hashCode) return false + if (a[i].hashCode !== b[i].hashCode) return false; for (let j = 0, _j = au.length; j < _j; j++) { if (au[j].conformation !== bu[j].conformation) return false; } } - return true + return true; } } @@ -140,44 +140,44 @@ function getSelector(asymIds: string[]) { function getOperatorsForIndex(symmetry: Symmetry, index: number, i: number, j: number, k: number, modelCenter: Vec3) { const { spacegroup, ncsOperators } = symmetry; - const operators: SymmetryOperator[] = [] + const operators: SymmetryOperator[] = []; - const { toFractional } = spacegroup.cell - const ref = Vec3.transformMat4(Vec3(), modelCenter, toFractional) + const { toFractional } = spacegroup.cell; + const ref = Vec3.transformMat4(Vec3(), modelCenter, toFractional); - const symOp = Spacegroup.getSymmetryOperatorRef(spacegroup, index, i, j, k, ref) + const symOp = Spacegroup.getSymmetryOperatorRef(spacegroup, index, i, j, k, ref); if (ncsOperators && ncsOperators.length) { for (let u = 0, ul = ncsOperators.length; u < ul; ++u) { - const ncsOp = ncsOperators![u] - const matrix = Mat4.mul(Mat4(), symOp.matrix, ncsOp.matrix) + const ncsOp = ncsOperators![u]; + const matrix = Mat4.mul(Mat4(), symOp.matrix, ncsOp.matrix); const operator = SymmetryOperator.create(`${symOp.name} ${ncsOp.name}`, matrix, { assembly: symOp.assembly, ncsId: ncsOp.ncsId, hkl: symOp.hkl, spgrOp: symOp.spgrOp }); - operators.push(operator) + operators.push(operator); } } else { - operators.push(symOp) + operators.push(symOp); } - return operators + return operators; } function getOperatorsForRange(symmetry: Symmetry, ijkMin: Vec3, ijkMax: Vec3, modelCenter: Vec3) { const { spacegroup, ncsOperators } = symmetry; - const ncsCount = (ncsOperators && ncsOperators.length) || 0 + const ncsCount = (ncsOperators && ncsOperators.length) || 0; const operators: SymmetryOperator[] = []; if (!ncsCount && ijkMin[0] <= 0 && ijkMax[0] >= 0 && ijkMin[1] <= 0 && ijkMax[1] >= 0 && ijkMin[2] <= 0 && ijkMax[2] >= 0) { - operators[0] = Spacegroup.getSymmetryOperator(spacegroup, 0, 0, 0, 0) + operators[0] = Spacegroup.getSymmetryOperator(spacegroup, 0, 0, 0, 0); } - const { toFractional } = spacegroup.cell - const ref = Vec3.transformMat4(Vec3(), modelCenter, toFractional) + const { toFractional } = spacegroup.cell; + const ref = Vec3.transformMat4(Vec3(), modelCenter, toFractional); for (let op = 0; op < spacegroup.operators.length; op++) { for (let i = ijkMin[0]; i <= ijkMax[0]; i++) { @@ -185,7 +185,7 @@ function getOperatorsForRange(symmetry: Symmetry, ijkMin: Vec3, ijkMax: Vec3, mo for (let k = ijkMin[2]; k <= ijkMax[2]; k++) { // check if we have added identity as the 1st operator. if (!ncsCount && op === 0 && i === 0 && j === 0 && k === 0) continue; - operators.push(...getOperatorsForIndex(symmetry, op, i, j, k, ref)) + operators.push(...getOperatorsForIndex(symmetry, op, i, j, k, ref)); } } } @@ -219,8 +219,8 @@ async function _buildNCS(ctx: RuntimeContext, structure: Structure) { const models = structure.models; if (models.length !== 1) throw new Error('Can only build NCS from structures based on 1 model.'); - const symmetry = ModelSymmetry.Provider.get(models[0]) - if (!symmetry) return structure + const symmetry = ModelSymmetry.Provider.get(models[0]); + if (!symmetry) return structure; const operators = symmetry.ncsOperators; if (!operators || !operators.length) return structure; @@ -231,13 +231,13 @@ async function findSymmetryRange(ctx: RuntimeContext, structure: Structure, ijkM const models = structure.models; if (models.length !== 1) throw new Error('Can only build symmetries from structures based on 1 model.'); - const symmetry = ModelSymmetry.Provider.get(models[0]) - if (!symmetry) return structure + const symmetry = ModelSymmetry.Provider.get(models[0]); + if (!symmetry) return structure; const { spacegroup } = symmetry; if (SpacegroupCell.isZero(spacegroup.cell)) return structure; - const modelCenter = Model.getCenter(models[0]) + const modelCenter = Model.getCenter(models[0]); const operators = getOperatorsForRange(symmetry, ijkMin, ijkMax, modelCenter); return assembleOperators(structure, operators); } @@ -246,21 +246,21 @@ async function findMatesRadius(ctx: RuntimeContext, structure: Structure, radius const models = structure.models; if (models.length !== 1) throw new Error('Can only build symmetries from structures based on 1 model.'); - const symmetry = ModelSymmetry.Provider.get(models[0]) - if (!symmetry) return structure + const symmetry = ModelSymmetry.Provider.get(models[0]); + if (!symmetry) return structure; const { spacegroup } = symmetry; if (SpacegroupCell.isZero(spacegroup.cell)) return structure; if (ctx.shouldUpdate) await ctx.update('Initialing...'); - const modelCenter = Model.getCenter(models[0]) + const modelCenter = Model.getCenter(models[0]); const operators = getOperatorsCached333(symmetry, modelCenter); const lookup = structure.lookup3d; // keep track of added invariant-unit and operator combinations - const added = new Set<string>() + const added = new Set<string>(); function hash(unit: Unit, oper: SymmetryOperator) { - return `${unit.invariantId}|${oper.name}` + return `${unit.invariantId}|${oper.name}`; } const assembler = Structure.Builder({ label: structure.label }); @@ -277,10 +277,10 @@ async function findMatesRadius(ctx: RuntimeContext, structure: Structure, radius const closeUnit = units[closeUnits.indices[uI]]; if (!closeUnit.lookup3d.check(center[0], center[1], center[2], boundingSphere.radius + radius)) continue; - const h = hash(unit, oper) + const h = hash(unit, oper); if (!added.has(h)) { assembler.addWithOperator(unit, oper); - added.add(h) + added.add(h); } } } diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts index 6872d2710552bd4ed7b433b23d64284b3e258955..3eda6cfa5a89c9383794105906db6a25cc4ea284 100644 --- a/src/mol-model/structure/structure/unit.ts +++ b/src/mol-model/structure/structure/unit.ts @@ -5,14 +5,14 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator' -import { Model } from '../model' -import { GridLookup3D, Lookup3D } from '../../../mol-math/geometry' -import { IntraUnitBonds, computeIntraUnitBonds } from './unit/bonds' +import { SymmetryOperator } from '../../../mol-math/geometry/symmetry-operator'; +import { Model } from '../model'; +import { GridLookup3D, Lookup3D } from '../../../mol-math/geometry'; +import { IntraUnitBonds, computeIntraUnitBonds } from './unit/bonds'; import { CoarseElements, CoarseSphereConformation, CoarseGaussianConformation } from '../model/properties/coarse'; import { ValueRef, BitFlags } from '../../../mol-util'; import { UnitRings } from './unit/rings'; -import StructureElement from './element' +import StructureElement from './element'; import { ChainIndex, ResidueIndex, ElementIndex } from '../model/indexing'; import { IntMap, SortedArray, Segmentation } from '../../../mol-data/int'; import { hash2, hashFnv32a } from '../../../mol-data/util'; @@ -61,25 +61,25 @@ namespace Unit { for (let i = 0, _i = units.length; i < _i; i++) { unitIndexMap.set(units[i].id, i); } - return unitIndexMap + return unitIndexMap; } export function SymmetryGroup(units: Unit[]) { const props: { unitIndexMap?: IntMap<number> - } = {} + } = {}; return { elements: units[0].elements, units, get unitIndexMap () { - if (props.unitIndexMap) return props.unitIndexMap - props.unitIndexMap = getUnitIndexMap(units) - return props.unitIndexMap + if (props.unitIndexMap) return props.unitIndexMap; + props.unitIndexMap = getUnitIndexMap(units); + return props.unitIndexMap; }, hashCode: hashUnit(units[0]), transformHash: hashFnv32a(units.map(u => u.id)) - } + }; } export namespace SymmetryGroup { @@ -93,12 +93,12 @@ namespace Unit { for (let i = 0, _i = symmetryGroups.length; i < _i; i++) { unitSymmetryGroupsIndexMap.set(symmetryGroups[i].units[0].invariantId, i); } - return unitSymmetryGroupsIndexMap + return unitSymmetryGroupsIndexMap; } } export function conformationId (unit: Unit) { - return Unit.isAtomic(unit) ? unit.model.atomicConformation.id : unit.model.coarseConformation.id + return Unit.isAtomic(unit) ? unit.model.atomicConformation.id : unit.model.coarseConformation.id; } export function hashUnit(u: Unit) { @@ -112,8 +112,8 @@ namespace Unit { Partitioned = 0x2 } export namespace Traits { - export const is: (t: Traits, f: Trait) => boolean = BitFlags.has - export const create: (f: Trait) => Traits = BitFlags.create + export const is: (t: Traits, f: Trait) => boolean = BitFlags.has; + export const create: (f: Trait) => Traits = BitFlags.create; } export interface Base { @@ -266,11 +266,11 @@ namespace Unit { get residueCount(): number { if (this.props.residueCount.ref !== undefined) return this.props.residueCount.ref; - let residueCount = 0 - const residueIt = Segmentation.transientSegments(this.model.atomicHierarchy.residueAtomSegments, this.elements) + let residueCount = 0; + const residueIt = Segmentation.transientSegments(this.model.atomicHierarchy.residueAtomSegments, this.elements); while (residueIt.hasNext) { - residueIt.move() - residueCount += 1 + residueIt.move(); + residueCount += 1; } this.props.residueCount.ref = residueCount; @@ -384,7 +384,7 @@ namespace Unit { constructor(id: number, invariantId: number, chainGroupId: number, traits: Traits, model: Model, kind: K, elements: StructureElement.Set, conformation: SymmetryOperator.ArrayMapping<ElementIndex>, props: CoarseProperties) { this.kind = kind; - this.objectPrimitive = kind === Kind.Spheres ? 'sphere' : 'gaussian' + this.objectPrimitive = kind === Kind.Spheres ? 'sphere' : 'gaussian'; this.id = id; this.invariantId = invariantId; this.chainGroupId = chainGroupId; diff --git a/src/mol-model/structure/structure/unit/bonds.ts b/src/mol-model/structure/structure/unit/bonds.ts index ebda56117bb93d604118b5de9ab464ee86b64904..35ab588e44c4a37e179081280e4318f6c7d990c7 100644 --- a/src/mol-model/structure/structure/unit/bonds.ts +++ b/src/mol-model/structure/structure/unit/bonds.ts @@ -5,16 +5,16 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Unit, StructureElement } from '../../structure' +import { Unit, StructureElement } from '../../structure'; import Structure from '../structure'; import { BondType } from '../../model/types'; import { SortedArray, Iterator } from '../../../../mol-data/int'; import { CentroidHelper } from '../../../../mol-math/geometry/centroid-helper'; import { Sphere3D } from '../../../../mol-math/geometry'; -export * from './bonds/data' -export * from './bonds/intra-compute' -export * from './bonds/inter-compute' +export * from './bonds/data'; +export * from './bonds/intra-compute'; +export * from './bonds/inter-compute'; namespace Bond { export interface Location<U extends Unit = Unit> { @@ -52,7 +52,7 @@ namespace Bond { locA.aStructure.label === locB.aStructure.label && locA.bStructure.label === locB.bStructure.label && locA.aIndex === locB.aIndex && locA.bIndex === locB.bIndex && locA.aUnit.id === locB.aUnit.id && locA.bUnit.id === locB.bUnit.id - ) + ); } export interface Loci { @@ -70,55 +70,55 @@ namespace Bond { } export function areLociEqual(a: Loci, b: Loci) { - if (a.structure !== b.structure) return false - if (a.bonds.length !== b.bonds.length) return false + if (a.structure !== b.structure) return false; + if (a.bonds.length !== b.bonds.length) return false; for (let i = 0, il = a.bonds.length; i < il; ++i) { - if (!areLocationsEqual(a.bonds[i], b.bonds[i])) return false + if (!areLocationsEqual(a.bonds[i], b.bonds[i])) return false; } - return true + return true; } export function isLociEmpty(loci: Loci) { - return loci.bonds.length === 0 ? true : false + return loci.bonds.length === 0 ? true : false; } export function remapLoci(loci: Loci, structure: Structure): Loci { - if (structure === loci.structure) return loci + if (structure === loci.structure) return loci; const bonds: Loci['bonds'][0][] = []; loci.bonds.forEach(l => { - const unitA = structure.unitMap.get(l.aUnit.id) - if (!unitA) return - const unitB = structure.unitMap.get(l.bUnit.id) - if (!unitB) return - - const elementA = l.aUnit.elements[l.aIndex] - const indexA = SortedArray.indexOf(unitA.elements, elementA) as StructureElement.UnitIndex | -1 - if (indexA === -1) return - const elementB = l.bUnit.elements[l.bIndex] - const indexB = SortedArray.indexOf(unitB.elements, elementB) as StructureElement.UnitIndex | -1 - if (indexB === -1) return - - bonds.push(Location(loci.structure, unitA, indexA, loci.structure, unitB, indexB)) + const unitA = structure.unitMap.get(l.aUnit.id); + if (!unitA) return; + const unitB = structure.unitMap.get(l.bUnit.id); + if (!unitB) return; + + const elementA = l.aUnit.elements[l.aIndex]; + const indexA = SortedArray.indexOf(unitA.elements, elementA) as StructureElement.UnitIndex | -1; + if (indexA === -1) return; + const elementB = l.bUnit.elements[l.bIndex]; + const indexB = SortedArray.indexOf(unitB.elements, elementB) as StructureElement.UnitIndex | -1; + if (indexB === -1) return; + + bonds.push(Location(loci.structure, unitA, indexA, loci.structure, unitB, indexB)); }); return Loci(structure, bonds); } export function toStructureElementLoci(loci: Loci): StructureElement.Loci { - const elements: StructureElement.Loci['elements'][0][] = [] - const map = new Map<number, number[]>() + const elements: StructureElement.Loci['elements'][0][] = []; + const map = new Map<number, number[]>(); for (const lociBond of loci.bonds) { - const { aIndex, aUnit, bIndex, bUnit } = lociBond + const { aIndex, aUnit, bIndex, bUnit } = lociBond; if (aUnit === bUnit) { - if (map.has(aUnit.id)) map.get(aUnit.id)!.push(aIndex, bIndex) - else map.set(aUnit.id, [aIndex, bIndex]) + if (map.has(aUnit.id)) map.get(aUnit.id)!.push(aIndex, bIndex); + else map.set(aUnit.id, [aIndex, bIndex]); } else { - if (map.has(aUnit.id)) map.get(aUnit.id)!.push(aIndex) - else map.set(aUnit.id, [aIndex]) - if (map.has(bUnit.id)) map.get(bUnit.id)!.push(bIndex) - else map.set(bUnit.id, [bIndex]) + if (map.has(aUnit.id)) map.get(aUnit.id)!.push(aIndex); + else map.set(aUnit.id, [aIndex]); + if (map.has(bUnit.id)) map.get(bUnit.id)!.push(bIndex); + else map.set(bUnit.id, [bIndex]); } } @@ -126,8 +126,8 @@ namespace Bond { elements.push({ unit: loci.structure.unitMap.get(id)!, indices: SortedArray.deduplicate(SortedArray.ofUnsortedArray(indices)) - }) - }) + }); + }); return StructureElement.Loci(loci.structure, elements); } @@ -159,12 +159,12 @@ namespace Bond { } export function getIntraUnitBondCount(structure: Structure) { - let count = 0 + let count = 0; for (let i = 0, il = structure.units.length; i < il; ++i) { - const u = structure.units[i] - if (Unit.isAtomic(u)) count += u.bonds.edgeCount / 2 // only count one direction + const u = structure.units[i]; + if (Unit.isAtomic(u)) count += u.bonds.edgeCount / 2; // only count one direction } - return count + return count; } export interface ElementBondData { @@ -190,58 +190,58 @@ namespace Bond { hasNext: boolean; move(): ElementBondData { - this.advance() - return this.current + this.advance(); + return this.current; } setElement(structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - this.structure = structure - this.unit = unit - this.index = index + this.structure = structure; + this.unit = unit; + this.index = index; - this.interBondIndices = structure.interUnitBonds.getEdgeIndices(index, unit) - this.interBondCount = this.interBondIndices.length - this.interBondIndex = 0 + this.interBondIndices = structure.interUnitBonds.getEdgeIndices(index, unit); + this.interBondCount = this.interBondIndices.length; + this.interBondIndex = 0; - this.intraBondEnd = unit.bonds.offset[index + 1] - this.intraBondIndex = unit.bonds.offset[index] + this.intraBondEnd = unit.bonds.offset[index + 1]; + this.intraBondIndex = unit.bonds.offset[index]; - this.hasNext = this.interBondIndex < this.interBondCount || this.intraBondIndex < this.intraBondEnd + this.hasNext = this.interBondIndex < this.interBondCount || this.intraBondIndex < this.intraBondEnd; } private advance() { if (this.intraBondIndex < this.intraBondEnd) { - this.current.otherUnit = this.unit - this.current.otherIndex = this.unit.bonds.b[this.intraBondIndex] as StructureElement.UnitIndex - this.current.type = this.unit.bonds.edgeProps.flags[this.intraBondIndex] - this.current.order = this.unit.bonds.edgeProps.order[this.intraBondIndex] - this.intraBondIndex += 1 + this.current.otherUnit = this.unit; + this.current.otherIndex = this.unit.bonds.b[this.intraBondIndex] as StructureElement.UnitIndex; + this.current.type = this.unit.bonds.edgeProps.flags[this.intraBondIndex]; + this.current.order = this.unit.bonds.edgeProps.order[this.intraBondIndex]; + this.intraBondIndex += 1; } else if (this.interBondIndex < this.interBondCount) { - const b = this.structure.interUnitBonds.edges[this.interBondIndex] - this.current.otherUnit = b.unitA !== this.unit ? b.unitA : b.unitB - this.current.otherIndex = b.indexA !== this.index ? b.indexA : b.indexB - this.current.type = b.props.flag - this.current.order = b.props.order - this.interBondIndex += 1 + const b = this.structure.interUnitBonds.edges[this.interBondIndex]; + this.current.otherUnit = b.unitA !== this.unit ? b.unitA : b.unitB; + this.current.otherIndex = b.indexA !== this.index ? b.indexA : b.indexB; + this.current.type = b.props.flag; + this.current.order = b.props.order; + this.interBondIndex += 1; } else { - this.hasNext = false - return + this.hasNext = false; + return; } - this.hasNext = this.interBondIndex < this.interBondCount || this.intraBondIndex < this.intraBondEnd + this.hasNext = this.interBondIndex < this.interBondCount || this.intraBondIndex < this.intraBondEnd; } constructor() { - this.hasNext = false + this.hasNext = false; } } export function getBoundingSphere(loci: Loci, boundingSphere: Sphere3D) { return CentroidHelper.fromPairProvider(loci.bonds.length, (i, pA, pB) => { - const { aUnit, aIndex, bUnit, bIndex } = loci.bonds[i] - aUnit.conformation.position(aUnit.elements[aIndex], pA) - bUnit.conformation.position(bUnit.elements[bIndex], pB) - }, boundingSphere) + const { aUnit, aIndex, bUnit, bIndex } = loci.bonds[i]; + aUnit.conformation.position(aUnit.elements[aIndex], pA); + bUnit.conformation.position(bUnit.elements[bIndex], pB); + }, boundingSphere); } } -export { Bond } \ No newline at end of file +export { Bond }; \ No newline at end of file diff --git a/src/mol-model/structure/structure/unit/bonds/common.ts b/src/mol-model/structure/structure/unit/bonds/common.ts index 1c66e2d00bbad8fc657668126bdf5de7ad928a79..1195c499d2a3efde993201a0776987abe95cddec 100644 --- a/src/mol-model/structure/structure/unit/bonds/common.ts +++ b/src/mol-model/structure/structure/unit/bonds/common.ts @@ -14,7 +14,7 @@ export interface BondComputationProps { export const DefaultBondComputationProps: BondComputationProps = { forceCompute: false, noCompute: false -} +}; // H,D,T are all mapped to H const __ElementIndex: { [e: string]: number | undefined } = { 'H': 0, 'h': 0, 'D': 0, 'd': 0, 'T': 0, 't': 0, 'He': 2, 'HE': 2, 'he': 2, 'Li': 3, 'LI': 3, 'li': 3, 'Be': 4, 'BE': 4, 'be': 4, 'B': 5, 'b': 5, 'C': 6, 'c': 6, 'N': 7, 'n': 7, 'O': 8, 'o': 8, 'F': 9, 'f': 9, 'Ne': 10, 'NE': 10, 'ne': 10, 'Na': 11, 'NA': 11, 'na': 11, 'Mg': 12, 'MG': 12, 'mg': 12, 'Al': 13, 'AL': 13, 'al': 13, 'Si': 14, 'SI': 14, 'si': 14, 'P': 15, 'p': 15, 'S': 16, 's': 16, 'Cl': 17, 'CL': 17, 'cl': 17, 'Ar': 18, 'AR': 18, 'ar': 18, 'K': 19, 'k': 19, 'Ca': 20, 'CA': 20, 'ca': 20, 'Sc': 21, 'SC': 21, 'sc': 21, 'Ti': 22, 'TI': 22, 'ti': 22, 'V': 23, 'v': 23, 'Cr': 24, 'CR': 24, 'cr': 24, 'Mn': 25, 'MN': 25, 'mn': 25, 'Fe': 26, 'FE': 26, 'fe': 26, 'Co': 27, 'CO': 27, 'co': 27, 'Ni': 28, 'NI': 28, 'ni': 28, 'Cu': 29, 'CU': 29, 'cu': 29, 'Zn': 30, 'ZN': 30, 'zn': 30, 'Ga': 31, 'GA': 31, 'ga': 31, 'Ge': 32, 'GE': 32, 'ge': 32, 'As': 33, 'AS': 33, 'as': 33, 'Se': 34, 'SE': 34, 'se': 34, 'Br': 35, 'BR': 35, 'br': 35, 'Kr': 36, 'KR': 36, 'kr': 36, 'Rb': 37, 'RB': 37, 'rb': 37, 'Sr': 38, 'SR': 38, 'sr': 38, 'Y': 39, 'y': 39, 'Zr': 40, 'ZR': 40, 'zr': 40, 'Nb': 41, 'NB': 41, 'nb': 41, 'Mo': 42, 'MO': 42, 'mo': 42, 'Tc': 43, 'TC': 43, 'tc': 43, 'Ru': 44, 'RU': 44, 'ru': 44, 'Rh': 45, 'RH': 45, 'rh': 45, 'Pd': 46, 'PD': 46, 'pd': 46, 'Ag': 47, 'AG': 47, 'ag': 47, 'Cd': 48, 'CD': 48, 'cd': 48, 'In': 49, 'IN': 49, 'in': 49, 'Sn': 50, 'SN': 50, 'sn': 50, 'Sb': 51, 'SB': 51, 'sb': 51, 'Te': 52, 'TE': 52, 'te': 52, 'I': 53, 'i': 53, 'Xe': 54, 'XE': 54, 'xe': 54, 'Cs': 55, 'CS': 55, 'cs': 55, 'Ba': 56, 'BA': 56, 'ba': 56, 'La': 57, 'LA': 57, 'la': 57, 'Ce': 58, 'CE': 58, 'ce': 58, 'Pr': 59, 'PR': 59, 'pr': 59, 'Nd': 60, 'ND': 60, 'nd': 60, 'Pm': 61, 'PM': 61, 'pm': 61, 'Sm': 62, 'SM': 62, 'sm': 62, 'Eu': 63, 'EU': 63, 'eu': 63, 'Gd': 64, 'GD': 64, 'gd': 64, 'Tb': 65, 'TB': 65, 'tb': 65, 'Dy': 66, 'DY': 66, 'dy': 66, 'Ho': 67, 'HO': 67, 'ho': 67, 'Er': 68, 'ER': 68, 'er': 68, 'Tm': 69, 'TM': 69, 'tm': 69, 'Yb': 70, 'YB': 70, 'yb': 70, 'Lu': 71, 'LU': 71, 'lu': 71, 'Hf': 72, 'HF': 72, 'hf': 72, 'Ta': 73, 'TA': 73, 'ta': 73, 'W': 74, 'w': 74, 'Re': 75, 'RE': 75, 're': 75, 'Os': 76, 'OS': 76, 'os': 76, 'Ir': 77, 'IR': 77, 'ir': 77, 'Pt': 78, 'PT': 78, 'pt': 78, 'Au': 79, 'AU': 79, 'au': 79, 'Hg': 80, 'HG': 80, 'hg': 80, 'Tl': 81, 'TL': 81, 'tl': 81, 'Pb': 82, 'PB': 82, 'pb': 82, 'Bi': 83, 'BI': 83, 'bi': 83, 'Po': 84, 'PO': 84, 'po': 84, 'At': 85, 'AT': 85, 'at': 85, 'Rn': 86, 'RN': 86, 'rn': 86, 'Fr': 87, 'FR': 87, 'fr': 87, 'Ra': 88, 'RA': 88, 'ra': 88, 'Ac': 89, 'AC': 89, 'ac': 89, 'Th': 90, 'TH': 90, 'th': 90, 'Pa': 91, 'PA': 91, 'pa': 91, 'U': 92, 'u': 92, 'Np': 93, 'NP': 93, 'np': 93, 'Pu': 94, 'PU': 94, 'pu': 94, 'Am': 95, 'AM': 95, 'am': 95, 'Cm': 96, 'CM': 96, 'cm': 96, 'Bk': 97, 'BK': 97, 'bk': 97, 'Cf': 98, 'CF': 98, 'cf': 98, 'Es': 99, 'ES': 99, 'es': 99, 'Fm': 100, 'FM': 100, 'fm': 100, 'Md': 101, 'MD': 101, 'md': 101, 'No': 102, 'NO': 102, 'no': 102, 'Lr': 103, 'LR': 103, 'lr': 103, 'Rf': 104, 'RF': 104, 'rf': 104, 'Db': 105, 'DB': 105, 'db': 105, 'Sg': 106, 'SG': 106, 'sg': 106, 'Bh': 107, 'BH': 107, 'bh': 107, 'Hs': 108, 'HS': 108, 'hs': 108, 'Mt': 109, 'MT': 109, 'mt': 109 }; diff --git a/src/mol-model/structure/structure/unit/bonds/data.ts b/src/mol-model/structure/structure/unit/bonds/data.ts index b57120430ce51bf71f650f4f3255aecb11989d6c..8df4dd05105f96809e93d0f746d443adc06e1457 100644 --- a/src/mol-model/structure/structure/unit/bonds/data.ts +++ b/src/mol-model/structure/structure/unit/bonds/data.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { BondType } from '../../../model/types' +import { BondType } from '../../../model/types'; import { IntAdjacencyGraph } from '../../../../../mol-math/graph'; import Unit from '../../unit'; import StructureElement from '../../element'; @@ -37,4 +37,4 @@ namespace InterUnitBonds { export type BondInfo = InterUnitGraph.EdgeInfo<StructureElement.UnitIndex, InterUnitEdgeProps> } -export { IntraUnitBonds, InterUnitBonds, InterUnitEdgeProps } \ No newline at end of file +export { IntraUnitBonds, InterUnitBonds, InterUnitEdgeProps }; \ No newline at end of file diff --git a/src/mol-model/structure/structure/unit/bonds/inter-compute.ts b/src/mol-model/structure/structure/unit/bonds/inter-compute.ts index e76a48ba563a57a4bbe7f14d687072c3cb0d5bc9..8f105db900ffefa52d7826d9a7db1a5d40b67231 100644 --- a/src/mol-model/structure/structure/unit/bonds/inter-compute.ts +++ b/src/mol-model/structure/structure/unit/bonds/inter-compute.ts @@ -21,12 +21,12 @@ import { StructConn } from '../../../../../mol-model-formats/structure/property/ const MAX_RADIUS = 4; -const tmpDistVecA = Vec3() -const tmpDistVecB = Vec3() +const tmpDistVecA = Vec3(); +const tmpDistVecB = Vec3(); function getDistance(unitA: Unit.Atomic, indexA: ElementIndex, unitB: Unit.Atomic, indexB: ElementIndex) { - unitA.conformation.position(indexA, tmpDistVecA) - unitB.conformation.position(indexB, tmpDistVecB) - return Vec3.distance(tmpDistVecA, tmpDistVecB) + unitA.conformation.position(indexA, tmpDistVecA); + unitB.conformation.position(indexB, tmpDistVecB); + return Vec3.distance(tmpDistVecA, tmpDistVecB); } const _imageTransform = Mat4.zero(); @@ -46,8 +46,8 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput const { occupancy: occupancyB } = unitB.model.atomicConformation; const { lookup3d } = unitB; - const structConn = unitA.model === unitB.model && StructConn.Provider.get(unitA.model) - const indexPairs = unitA.model === unitB.model && IndexPairBonds.Provider.get(unitA.model) + const structConn = unitA.model === unitB.model && StructConn.Provider.get(unitA.model); + const indexPairs = unitA.model === unitB.model && IndexPairBonds.Provider.get(unitA.model); // the lookup queries need to happen in the "unitB space". // that means imageA = inverseOperB(operA(aI)) @@ -58,9 +58,9 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput const { center: bCenter, radius: bRadius } = lookup3d.boundary.sphere; const testDistanceSq = (bRadius + MAX_RADIUS) * (bRadius + MAX_RADIUS); - builder.startUnitPair(unitA, unitB) - const symmUnitA = unitA.conformation.operator.name - const symmUnitB = unitB.conformation.operator.name + builder.startUnitPair(unitA, unitB); + const symmUnitA = unitA.conformation.operator.name; + const symmUnitB = unitB.conformation.operator.name; for (let _aI = 0 as StructureElement.UnitIndex; _aI < atomCount; _aI++) { const aI = atomsA[_aI]; @@ -69,7 +69,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput if (Vec3.squaredDistance(imageA, bCenter) > testDistanceSq) continue; if (!props.forceCompute && indexPairs) { - const { order, symmetryA, symmetryB } = indexPairs.edgeProps + const { order, symmetryA, symmetryB } = indexPairs.edgeProps; for (let i = indexPairs.offset[aI], il = indexPairs.offset[aI + 1]; i < il; ++i) { const _bI = SortedArray.indexOf(unitA.elements, indexPairs.b[i]) as StructureElement.UnitIndex; if (_bI < 0) continue; @@ -78,15 +78,15 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput builder.add(_aI, _bI, { order: order[i], flag: BondType.Flag.Covalent }); } } - continue // assume `indexPairs` supplies all bonds + continue; // assume `indexPairs` supplies all bonds } const structConnEntries = props.forceCompute ? void 0 : structConn && structConn.byAtomIndex.get(aI); if (structConnEntries && structConnEntries.length) { let added = false; for (const se of structConnEntries) { - const { partnerA, partnerB } = se - const p = partnerA.atomIndex === aI ? partnerB : partnerA + const { partnerA, partnerB } = se; + const p = partnerA.atomIndex === aI ? partnerB : partnerA; const _bI = SortedArray.indexOf(unitB.elements, p.atomIndex) as StructureElement.UnitIndex; if (_bI < 0) continue; @@ -158,7 +158,7 @@ function findPairBonds(unitA: Unit.Atomic, unitB: Unit.Atomic, props: BondComput } } - builder.finishUnitPair() + builder.finishUnitPair(); } export interface InterBondComputationProps extends BondComputationProps { @@ -166,7 +166,7 @@ export interface InterBondComputationProps extends BondComputationProps { } function findBonds(structure: Structure, props: InterBondComputationProps) { - const builder = new InterUnitGraph.Builder<Unit.Atomic, StructureElement.UnitIndex, InterUnitEdgeProps>() + const builder = new InterUnitGraph.Builder<Unit.Atomic, StructureElement.UnitIndex, InterUnitEdgeProps>(); if (props.noCompute) { // TODO add function that only adds bonds defined in structConn and avoids using @@ -176,12 +176,12 @@ function findBonds(structure: Structure, props: InterBondComputationProps) { } Structure.eachUnitPair(structure, (unitA: Unit, unitB: Unit) => { - findPairBonds(unitA as Unit.Atomic, unitB as Unit.Atomic, props, builder) + findPairBonds(unitA as Unit.Atomic, unitB as Unit.Atomic, props, builder); }, { maxRadius: MAX_RADIUS, validUnit: (unit: Unit) => Unit.isAtomic(unit), validUnitPair: (unitA: Unit, unitB: Unit) => props.validUnitPair(structure, unitA, unitB) - }) + }); return new InterUnitBonds(builder.getMap()); } diff --git a/src/mol-model/structure/structure/unit/bonds/intra-compute.ts b/src/mol-model/structure/structure/unit/bonds/intra-compute.ts index 6ba3b6246e2626083145b321ed06eb16de86fdc1..b4ce07ab9c39e9eea7dd20fe321c550337cc0c95 100644 --- a/src/mol-model/structure/structure/unit/bonds/intra-compute.ts +++ b/src/mol-model/structure/structure/unit/bonds/intra-compute.ts @@ -5,9 +5,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { BondType } from '../../../model/types' -import { IntraUnitBonds } from './data' -import Unit from '../../unit' +import { BondType } from '../../../model/types'; +import { IntraUnitBonds } from './data'; +import Unit from '../../unit'; import { IntAdjacencyGraph } from '../../../../../mol-math/graph'; import { BondComputationProps, getElementIdx, MetalsSet, getElementThreshold, isHydrogen, getElementPairThreshold, DefaultBondComputationProps } from './common'; import { SortedArray } from '../../../../../mol-data/int'; @@ -42,9 +42,9 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni const { label_comp_id } = unit.model.atomicHierarchy.residues; const query3d = unit.lookup3d; - const structConn = StructConn.Provider.get(unit.model) - const component = ComponentBond.Provider.get(unit.model) - const indexPairs = IndexPairBonds.Provider.get(unit.model) + const structConn = StructConn.Provider.get(unit.model); + const component = ComponentBond.Provider.get(unit.model); + const indexPairs = IndexPairBonds.Provider.get(unit.model); const atomA: StructureElement.UnitIndex[] = []; const atomB: StructureElement.UnitIndex[] = []; @@ -60,7 +60,7 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni const aI = atoms[_aI]; if (!props.forceCompute && indexPairs) { - const { edgeProps } = indexPairs + const { edgeProps } = indexPairs; for (let i = indexPairs.offset[aI], il = indexPairs.offset[aI + 1]; i < il; ++i) { const _bI = SortedArray.indexOf(unit.elements, indexPairs.b[i]) as StructureElement.UnitIndex; if (_bI < 0) continue; @@ -70,18 +70,18 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni order[order.length] = edgeProps.order[i]; flags[flags.length] = BondType.Flag.Covalent; } - continue // assume `indexPairs` supplies all bonds + continue; // assume `indexPairs` supplies all bonds } const structConnEntries = props.forceCompute ? void 0 : structConn && structConn.byAtomIndex.get(aI); let hasStructConn = false; if (structConnEntries) { for (const se of structConnEntries) { - const { partnerA, partnerB } = se + const { partnerA, partnerB } = se; // symmetry must be the same for intra-unit bonds - if (partnerA.symmetry !== partnerB.symmetry) continue + if (partnerA.symmetry !== partnerB.symmetry) continue; - const p = partnerA.atomIndex === aI ? partnerB : partnerA + const p = partnerA.atomIndex === aI ? partnerB : partnerA; const _bI = SortedArray.indexOf(unit.elements, p.atomIndex) as StructureElement.UnitIndex; if (_bI < 0) continue; @@ -109,7 +109,7 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni lastResidue = raI; const aeI = getElementIdx(type_symbol.value(aI)); - const atomIdA = label_atom_id.value(aI) + const atomIdA = label_atom_id.value(aI); const componentPairs = componentMap ? componentMap.get(atomIdA) : void 0; const { indices, count, squaredDistances } = query3d.find(x[aI], y[aI], z[aI], MAX_RADIUS); @@ -176,7 +176,7 @@ function _computeBonds(unit: Unit.Atomic, props: BondComputationProps): IntraUni } function computeIntraUnitBonds(unit: Unit.Atomic, props?: Partial<BondComputationProps>) { - const p = { ...DefaultBondComputationProps, ...props } + const p = { ...DefaultBondComputationProps, ...props }; if (p.noCompute) { // TODO add function that only adds bonds defined in structConn of chemCompBond // and avoid using unit.lookup @@ -185,4 +185,4 @@ function computeIntraUnitBonds(unit: Unit.Atomic, props?: Partial<BondComputatio return _computeBonds(unit, p); } -export { computeIntraUnitBonds } \ No newline at end of file +export { computeIntraUnitBonds }; \ No newline at end of file diff --git a/src/mol-model/structure/structure/unit/rings.ts b/src/mol-model/structure/structure/unit/rings.ts index c7776ba611efcff5088f397ab28296a406fa643c..aec8a7054eaeecd4b1e636ffaab604d0860f6aa4 100644 --- a/src/mol-model/structure/structure/unit/rings.ts +++ b/src/mol-model/structure/structure/unit/rings.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { computeRings, getFingerprint, createIndex } from './rings/compute' +import { computeRings, getFingerprint, createIndex } from './rings/compute'; import Unit from '../unit'; import StructureElement from '../element'; import { SortedArray } from '../../../../mol-data/int'; @@ -94,8 +94,8 @@ namespace UnitRing { Elements.GE, Elements.AS, Elements.SN, Elements.SB, Elements.BI - ] as ElementSymbol[]) - const AromaticRingPlanarityThreshold = 0.05 + ] as ElementSymbol[]); + const AromaticRingPlanarityThreshold = 0.05; export function isAromatic(unit: Unit.Atomic, ring: UnitRing): boolean { const { elements, bonds: { b, offset, edgeProps: { flags } } } = unit; @@ -103,30 +103,30 @@ namespace UnitRing { const { label_comp_id } = unit.model.atomicHierarchy.residues; // ignore Proline (can be flat because of bad geometry) - if (label_comp_id.value(unit.getResidueIndex(ring[0])) === 'PRO') return false + if (label_comp_id.value(unit.getResidueIndex(ring[0])) === 'PRO') return false; - let aromaticBondCount = 0 - let hasAromaticRingElement = false + let aromaticBondCount = 0; + let hasAromaticRingElement = false; for (let i = 0, il = ring.length; i < il; ++i) { - const aI = ring[i] + const aI = ring[i]; if (!hasAromaticRingElement && AromaticRingElements.has(type_symbol.value(elements[aI]))) { - hasAromaticRingElement = true + hasAromaticRingElement = true; } for (let j = offset[aI], jl = offset[aI + 1]; j < jl; ++j) { // comes e.g. from `chem_comp_bond.pdbx_aromatic_flag` if (BondType.is(BondType.Flag.Aromatic, flags[j])) { - if (SortedArray.has(ring, b[j])) aromaticBondCount += 1 + if (SortedArray.has(ring, b[j])) aromaticBondCount += 1; } } } - if (aromaticBondCount === 2 * ring.length) return true - if (!hasAromaticRingElement) return false + if (aromaticBondCount === 2 * ring.length) return true; + if (!hasAromaticRingElement) return false; - const ma = PrincipalAxes.calculateMomentsAxes(getPositions(unit, ring)) - return Vec3.magnitude(ma.dirC) < AromaticRingPlanarityThreshold + const ma = PrincipalAxes.calculateMomentsAxes(getPositions(unit, ring)); + return Vec3.magnitude(ma.dirC) < AromaticRingPlanarityThreshold; } /** Get the alternate location of the 1st non '' alt loc atom. */ @@ -203,11 +203,11 @@ function addSingleResidueRings(rings: UnitRings, fp: UnitRing.Fingerprint, map: } function getAromaticRings(unit: Unit.Atomic, rings: ReadonlyArray<UnitRing>): ReadonlyArray<UnitRings.Index> { - const aromaticRings: UnitRings.Index[] = [] + const aromaticRings: UnitRings.Index[] = []; for (let i = 0 as UnitRings.Index, il = rings.length; i < il; ++i) { - if (UnitRing.isAromatic(unit, rings[i])) aromaticRings.push(i) + if (UnitRing.isAromatic(unit, rings[i])) aromaticRings.push(i); } - return aromaticRings + return aromaticRings; } -export { UnitRing, UnitRings } \ No newline at end of file +export { UnitRing, UnitRings }; \ No newline at end of file diff --git a/src/mol-model/structure/structure/unit/rings/compute.ts b/src/mol-model/structure/structure/unit/rings/compute.ts index 3c84b1d73ced506b404b13225c73a58f1c7e77f2..489191e0a7f749d24915f3e19adaab1b385fa98c 100644 --- a/src/mol-model/structure/structure/unit/rings/compute.ts +++ b/src/mol-model/structure/structure/unit/rings/compute.ts @@ -187,7 +187,7 @@ function addRing(state: State, a: number, b: number) { if (current < 0) break; } - const len = leftOffset + rightOffset + const len = leftOffset + rightOffset; // rings must have at least three elements if (len < 3) { return; @@ -348,7 +348,7 @@ export function createIndex(rings: ArrayLike<SortedArray<StructureElement.UnitIn // for each ring atom, assign all aromatic rings that it is present in for (let aI = 0, _aI = aromaticRings.length; aI < _aI; aI++) { - const rI = aromaticRings[aI] + const rI = aromaticRings[aI]; const r = rings[rI]; for (let i = 0, _i = r.length; i < _i; i++) { const e = r[i]; diff --git a/src/mol-model/structure/structure/util/boundary.ts b/src/mol-model/structure/structure/util/boundary.ts index 58532658fd99179f95d42c0c6fa8eb4ad91a5460..30d0ac14f780cb8d4c9be3cfb27425aa4587c1ad 100644 --- a/src/mol-model/structure/structure/util/boundary.ts +++ b/src/mol-model/structure/structure/util/boundary.ts @@ -18,8 +18,8 @@ const tmpSphere = Sphere3D(); const boundaryHelper = new BoundaryHelper('98'); export function computeStructureBoundary(s: Structure): Boundary { - const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE) - const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE) + const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE); + const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); const { units } = s; diff --git a/src/mol-model/structure/structure/util/lookup3d.ts b/src/mol-model/structure/structure/util/lookup3d.ts index f3874e364d5b19cb41828405d0bae1159e6d6570..2a231567d46805ebeb8e8e457c5e8dd54dc65a61 100644 --- a/src/mol-model/structure/structure/util/lookup3d.ts +++ b/src/mol-model/structure/structure/util/lookup3d.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import Structure from '../structure' +import Structure from '../structure'; import { Lookup3D, GridLookup3D, Box3D, Sphere3D, Result } from '../../../../mol-math/geometry'; import { Vec3 } from '../../../../mol-math/linear-algebra'; import { computeStructureBoundary } from './boundary'; @@ -37,8 +37,8 @@ export namespace StructureResult { out.units[i] = result.units[i]; out.squaredDistances[i] = result.squaredDistances[i]; } - out.count = result.count - return out + out.count = result.count; + return out; } } @@ -175,7 +175,7 @@ export class StructureLookup3D { radius[i] = s.radius; } - const position = { x: xs, y: ys, z: zs, radius, indices: OrderedSet.ofBounds(0, unitCount) } + const position = { x: xs, y: ys, z: zs, radius, indices: OrderedSet.ofBounds(0, unitCount) }; this.unitLookup = GridLookup3D(position, getBoundary(position)); } } \ No newline at end of file diff --git a/src/mol-model/structure/structure/util/polymer.ts b/src/mol-model/structure/structure/util/polymer.ts index 02ca015b771978b4ee16f9d4a7d063bfc6ff00d1..fcb803db8e24863d5b7394a778d50110f77957b5 100644 --- a/src/mol-model/structure/structure/util/polymer.ts +++ b/src/mol-model/structure/structure/util/polymer.ts @@ -10,83 +10,83 @@ import SortedRanges from '../../../../mol-data/int/sorted-ranges'; import { isNucleic, isProtein } from '../../../../mol-model/structure/model/types'; export function getAtomicPolymerElements(unit: Unit.Atomic) { - const indices: ElementIndex[] = [] - const { elements, model } = unit - const { residueAtomSegments } = unit.model.atomicHierarchy - const { traceElementIndex } = model.atomicHierarchy.derived.residue - const polymerIt = SortedRanges.transientSegments(unit.model.atomicRanges.polymerRanges, elements) - const residueIt = Segmentation.transientSegments(residueAtomSegments, elements) + const indices: ElementIndex[] = []; + const { elements, model } = unit; + const { residueAtomSegments } = unit.model.atomicHierarchy; + const { traceElementIndex } = model.atomicHierarchy.derived.residue; + const polymerIt = SortedRanges.transientSegments(unit.model.atomicRanges.polymerRanges, elements); + const residueIt = Segmentation.transientSegments(residueAtomSegments, elements); while (polymerIt.hasNext) { - const polymerSegment = polymerIt.move() - residueIt.setSegment(polymerSegment) + const polymerSegment = polymerIt.move(); + residueIt.setSegment(polymerSegment); while (residueIt.hasNext) { - const residueSegment = residueIt.move() - const { start, end, index } = residueSegment + const residueSegment = residueIt.move(); + const { start, end, index } = residueSegment; if (OrderedSet.areIntersecting(Interval.ofRange(elements[start], elements[end - 1]), elements)) { - const elementIndex = traceElementIndex[index] - indices.push(elementIndex === -1 ? residueAtomSegments.offsets[index] : elementIndex) + const elementIndex = traceElementIndex[index]; + indices.push(elementIndex === -1 ? residueAtomSegments.offsets[index] : elementIndex); } } } - return SortedArray.ofSortedArray<ElementIndex>(indices) + return SortedArray.ofSortedArray<ElementIndex>(indices); } export function getCoarsePolymerElements(unit: Unit.Spheres | Unit.Gaussians) { - const indices: ElementIndex[] = [] - const { elements, model } = unit - const { spheres, gaussians } = model.coarseHierarchy - const polymerRanges = Unit.isSpheres(unit) ? spheres.polymerRanges : gaussians.polymerRanges - const polymerIt = SortedRanges.transientSegments(polymerRanges, elements) + const indices: ElementIndex[] = []; + const { elements, model } = unit; + const { spheres, gaussians } = model.coarseHierarchy; + const polymerRanges = Unit.isSpheres(unit) ? spheres.polymerRanges : gaussians.polymerRanges; + const polymerIt = SortedRanges.transientSegments(polymerRanges, elements); while (polymerIt.hasNext) { - const { start, end } = polymerIt.move() - for (let i = start; i < end; ++i) { indices.push(elements[i]) } + const { start, end } = polymerIt.move(); + for (let i = start; i < end; ++i) { indices.push(elements[i]); } } - return SortedArray.ofSortedArray<ElementIndex>(indices) + return SortedArray.ofSortedArray<ElementIndex>(indices); } // export function getAtomicGapElements(unit: Unit.Atomic) { - const indices: ElementIndex[] = [] - const { elements, model, residueIndex } = unit - const { residueAtomSegments } = unit.model.atomicHierarchy - const { traceElementIndex } = model.atomicHierarchy.derived.residue + const indices: ElementIndex[] = []; + const { elements, model, residueIndex } = unit; + const { residueAtomSegments } = unit.model.atomicHierarchy; + const { traceElementIndex } = model.atomicHierarchy.derived.residue; const gapIt = SortedRanges.transientSegments(unit.model.atomicRanges.gapRanges, unit.elements); while (gapIt.hasNext) { const gapSegment = gapIt.move(); - const indexStart = residueIndex[elements[gapSegment.start]] - const indexEnd = residueIndex[elements[gapSegment.end - 1]] - const elementIndexStart = traceElementIndex[indexStart] - const elementIndexEnd = traceElementIndex[indexEnd] - indices.push(elementIndexStart === -1 ? residueAtomSegments.offsets[indexStart] : elementIndexStart) - indices.push(elementIndexEnd === -1 ? residueAtomSegments.offsets[indexEnd] : elementIndexEnd) + const indexStart = residueIndex[elements[gapSegment.start]]; + const indexEnd = residueIndex[elements[gapSegment.end - 1]]; + const elementIndexStart = traceElementIndex[indexStart]; + const elementIndexEnd = traceElementIndex[indexEnd]; + indices.push(elementIndexStart === -1 ? residueAtomSegments.offsets[indexStart] : elementIndexStart); + indices.push(elementIndexEnd === -1 ? residueAtomSegments.offsets[indexEnd] : elementIndexEnd); } - return SortedArray.ofSortedArray<ElementIndex>(indices) + return SortedArray.ofSortedArray<ElementIndex>(indices); } export function getCoarseGapElements(unit: Unit.Spheres | Unit.Gaussians) { - const indices: ElementIndex[] = [] - const { elements, model } = unit - const { spheres, gaussians } = model.coarseHierarchy - const gapRanges = Unit.isSpheres(unit) ? spheres.gapRanges : gaussians.gapRanges - const gapIt = SortedRanges.transientSegments(gapRanges, elements) + const indices: ElementIndex[] = []; + const { elements, model } = unit; + const { spheres, gaussians } = model.coarseHierarchy; + const gapRanges = Unit.isSpheres(unit) ? spheres.gapRanges : gaussians.gapRanges; + const gapIt = SortedRanges.transientSegments(gapRanges, elements); while (gapIt.hasNext) { - const { start, end } = gapIt.move() - indices.push(elements[start], elements[end - 1]) + const { start, end } = gapIt.move(); + indices.push(elements[start], elements[end - 1]); } - return SortedArray.ofSortedArray<ElementIndex>(indices) + return SortedArray.ofSortedArray<ElementIndex>(indices); } // export function getNucleotideElements(unit: Unit.Atomic) { - const indices: ElementIndex[] = [] - const { elements, model } = unit - const { chainAtomSegments, residueAtomSegments } = model.atomicHierarchy - const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue - const chainIt = Segmentation.transientSegments(chainAtomSegments, elements) - const residueIt = Segmentation.transientSegments(residueAtomSegments, elements) + const indices: ElementIndex[] = []; + const { elements, model } = unit; + const { chainAtomSegments, residueAtomSegments } = model.atomicHierarchy; + const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue; + const chainIt = Segmentation.transientSegments(chainAtomSegments, elements); + const residueIt = Segmentation.transientSegments(residueAtomSegments, elements); while (chainIt.hasNext) { residueIt.setSegment(chainIt.move()); @@ -94,21 +94,21 @@ export function getNucleotideElements(unit: Unit.Atomic) { const { index } = residueIt.move(); if (isNucleic(moleculeType[index])) { - const elementIndex = traceElementIndex[index] - indices.push(elementIndex === -1 ? residueAtomSegments.offsets[index] : elementIndex) + const elementIndex = traceElementIndex[index]; + indices.push(elementIndex === -1 ? residueAtomSegments.offsets[index] : elementIndex); } } } - return SortedArray.ofSortedArray<ElementIndex>(indices) + return SortedArray.ofSortedArray<ElementIndex>(indices); } export function getProteinElements(unit: Unit.Atomic) { - const indices: ElementIndex[] = [] - const { elements, model } = unit - const { chainAtomSegments, residueAtomSegments } = model.atomicHierarchy - const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue - const chainIt = Segmentation.transientSegments(chainAtomSegments, elements) - const residueIt = Segmentation.transientSegments(residueAtomSegments, elements) + const indices: ElementIndex[] = []; + const { elements, model } = unit; + const { chainAtomSegments, residueAtomSegments } = model.atomicHierarchy; + const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue; + const chainIt = Segmentation.transientSegments(chainAtomSegments, elements); + const residueIt = Segmentation.transientSegments(residueAtomSegments, elements); while (chainIt.hasNext) { residueIt.setSegment(chainIt.move()); @@ -116,10 +116,10 @@ export function getProteinElements(unit: Unit.Atomic) { const { index } = residueIt.move(); if (isProtein(moleculeType[index])) { - const elementIndex = traceElementIndex[index] - indices.push(elementIndex === -1 ? residueAtomSegments.offsets[index] : elementIndex) + const elementIndex = traceElementIndex[index]; + indices.push(elementIndex === -1 ? residueAtomSegments.offsets[index] : elementIndex); } } } - return SortedArray.ofSortedArray<ElementIndex>(indices) + return SortedArray.ofSortedArray<ElementIndex>(indices); } \ No newline at end of file diff --git a/src/mol-model/structure/structure/util/principal-axes.ts b/src/mol-model/structure/structure/util/principal-axes.ts index a9823976b60f5f40f44fd32106ef0d4bd0f6ebfd..67972aaf84b0e74095365bd8e2e4f2588d86b303 100644 --- a/src/mol-model/structure/structure/util/principal-axes.ts +++ b/src/mol-model/structure/structure/util/principal-axes.ts @@ -10,17 +10,17 @@ import { Vec3 } from '../../../../mol-math/linear-algebra'; const tempPos = Vec3.zero(); export function toPositionsArray(unit: Unit) { - const pos = unit.conformation.invariantPosition - const { elements } = unit - const positions = new Float32Array(elements.length * 3) + const pos = unit.conformation.invariantPosition; + const { elements } = unit; + const positions = new Float32Array(elements.length * 3); for (let i = 0, il = elements.length; i < il; i++) { - pos(elements[i], tempPos) - Vec3.toArray(tempPos, positions, i * 3) + pos(elements[i], tempPos); + Vec3.toArray(tempPos, positions, i * 3); } - return positions + return positions; } export function getPrincipalAxes(unit: Unit): PrincipalAxes { - const positions = toPositionsArray(unit) - return PrincipalAxes.ofPositions(positions) + const positions = toPositionsArray(unit); + return PrincipalAxes.ofPositions(positions); } \ No newline at end of file diff --git a/src/mol-model/structure/structure/util/unit-transforms.ts b/src/mol-model/structure/structure/util/unit-transforms.ts index 472147133be4821342c792d19b2821157ef400bb..79d73da5cea24afdffae4202d7b8e8fadf204802 100644 --- a/src/mol-model/structure/structure/util/unit-transforms.ts +++ b/src/mol-model/structure/structure/util/unit-transforms.ts @@ -9,7 +9,7 @@ import { Mat4 } from '../../../../mol-math/linear-algebra'; import { IntMap } from '../../../../mol-data/int'; import { fillIdentityTransform } from '../../../../mol-geo/geometry/transform-data'; -const tmpMat = Mat4() +const tmpMat = Mat4(); export class StructureUnitTransforms { private unitTransforms: Float32Array @@ -24,53 +24,53 @@ export class StructureUnitTransforms { version = 0; constructor(readonly structure: Structure) { - this.unitTransforms = new Float32Array(structure.units.length * 16) - this.size = structure.units.length - this.reset() // to set to identity - let groupOffset = 0 + this.unitTransforms = new Float32Array(structure.units.length * 16); + this.size = structure.units.length; + this.reset(); // to set to identity + let groupOffset = 0; for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const g = structure.unitSymmetryGroups[i] - this.groupIndexMap.set(g.hashCode, i) - const groupTransforms = this.unitTransforms.subarray(groupOffset, groupOffset + g.units.length * 16) - this.groupUnitTransforms.push(groupTransforms) + const g = structure.unitSymmetryGroups[i]; + this.groupIndexMap.set(g.hashCode, i); + const groupTransforms = this.unitTransforms.subarray(groupOffset, groupOffset + g.units.length * 16); + this.groupUnitTransforms.push(groupTransforms); for (let j = 0, jl = g.units.length; j < jl; ++j) { - this.unitOffsetMap.set(g.units[j].id, groupOffset + j * 16) + this.unitOffsetMap.set(g.units[j].id, groupOffset + j * 16); } - groupOffset += g.units.length * 16 + groupOffset += g.units.length * 16; } } reset() { this.version = 0; fillIdentityTransform(this.unitTransforms, this.size); - this._isIdentity = true + this._isIdentity = true; } get isIdentity() { if (this._isIdentity === undefined) { - this._isIdentity = true + this._isIdentity = true; for (let i = 0, il = this.size * 16; i < il; i += 16) { - Mat4.fromArray(tmpMat, this.unitTransforms, i) + Mat4.fromArray(tmpMat, this.unitTransforms, i); if (!Mat4.isIdentity(tmpMat)) { - this._isIdentity = false - break + this._isIdentity = false; + break; } } } - return this._isIdentity + return this._isIdentity; } setTransform(matrix: Mat4, unit: Unit) { this.version = (this.version + 1) % 0x7fffffff; - Mat4.toArray(matrix, this.unitTransforms, this.unitOffsetMap.get(unit.id)) - this._isIdentity = undefined + Mat4.toArray(matrix, this.unitTransforms, this.unitOffsetMap.get(unit.id)); + this._isIdentity = undefined; } getTransform(out: Mat4, unit: Unit) { - return Mat4.fromArray(out, this.unitTransforms, this.unitOffsetMap.get(unit.id)) + return Mat4.fromArray(out, this.unitTransforms, this.unitOffsetMap.get(unit.id)); } getSymmetryGroupTransforms(group: Unit.SymmetryGroup): Float32Array { - return this.groupUnitTransforms[this.groupIndexMap.get(group.hashCode)] + return this.groupUnitTransforms[this.groupIndexMap.get(group.hashCode)]; } } \ No newline at end of file diff --git a/src/mol-model/structure/topology.ts b/src/mol-model/structure/topology.ts index 4fc8e81360f43f3a2c56d433b00f11fe61ceea7a..163512f6902fc49678f5e55e62c92bdb10491755 100644 --- a/src/mol-model/structure/topology.ts +++ b/src/mol-model/structure/topology.ts @@ -4,4 +4,4 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export * from './topology/topology' \ No newline at end of file +export * from './topology/topology'; \ No newline at end of file diff --git a/src/mol-model/structure/topology/topology.ts b/src/mol-model/structure/topology/topology.ts index 6ef843f72f937e518baaa489571ca361759bc377..f8863254322187503d5d8bd9cd43cbbfcd566388 100644 --- a/src/mol-model/structure/topology/topology.ts +++ b/src/mol-model/structure/topology/topology.ts @@ -9,7 +9,7 @@ import { Column } from '../../../mol-data/db'; import { BasicData } from '../../../mol-model-formats/structure/basic/schema'; import { ModelFormat } from '../../../mol-model-formats/structure/format'; -export { Topology } +export { Topology }; interface Topology { readonly id: UUID @@ -56,6 +56,6 @@ namespace Topology { basic, sourceData: format, bonds - } + }; } } \ No newline at end of file diff --git a/src/mol-model/structure/util.ts b/src/mol-model/structure/util.ts index ea455e01b833108a7b44be81aa372ea1f2d176b7..8af7a2a8b1b3d65b5e29ed8a380b0a463a286881 100644 --- a/src/mol-model/structure/util.ts +++ b/src/mol-model/structure/util.ts @@ -11,58 +11,58 @@ import { Unit } from './structure'; import { NumberArray } from '../../mol-util/type-helpers'; export function getCoarseBegCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIndex) { - const entityKey = unit.coarseElements.entityKey[element] - const seq = unit.model.sequence.byEntityKey[entityKey].sequence - const seq_id_begin = unit.coarseElements.seq_id_begin.value(element) - return seq.compId.value(seq_id_begin - 1) // 1-indexed + const entityKey = unit.coarseElements.entityKey[element]; + const seq = unit.model.sequence.byEntityKey[entityKey].sequence; + const seq_id_begin = unit.coarseElements.seq_id_begin.value(element); + return seq.compId.value(seq_id_begin - 1); // 1-indexed } export function getElementMoleculeType(unit: Unit, element: ElementIndex): MoleculeType { switch (unit.kind) { case Unit.Kind.Atomic: - return unit.model.atomicHierarchy.derived.residue.moleculeType[unit.residueIndex[element]] + return unit.model.atomicHierarchy.derived.residue.moleculeType[unit.residueIndex[element]]; case Unit.Kind.Spheres: case Unit.Kind.Gaussians: // TODO add unit.model.coarseHierarchy.derived.residue.moleculeType - const compId = getCoarseBegCompId(unit, element) - const cc = unit.model.properties.chemicalComponentMap.get(compId) - if (cc) return getMoleculeType(cc.type, compId) + const compId = getCoarseBegCompId(unit, element); + const cc = unit.model.properties.chemicalComponentMap.get(compId); + if (cc) return getMoleculeType(cc.type, compId); } - return MoleculeType.Unknown + return MoleculeType.Unknown; } export function getAtomicMoleculeType(model: Model, rI: ResidueIndex): MoleculeType { - return model.atomicHierarchy.derived.residue.moleculeType[rI] + return model.atomicHierarchy.derived.residue.moleculeType[rI]; } -const EmptyAtomIds = new Set<string>() +const EmptyAtomIds = new Set<string>(); export function getAtomIdForAtomRole(polymerType: PolymerType, atomRole: AtomRole) { - const p = PolymerTypeAtomRoleId[polymerType] + const p = PolymerTypeAtomRoleId[polymerType]; if (p !== undefined) { - const a = p[atomRole] - if (a !== undefined) return a + const a = p[atomRole]; + if (a !== undefined) return a; } - return EmptyAtomIds + return EmptyAtomIds; } export function residueLabel(model: Model, rI: number) { - const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy - const { label_comp_id, label_seq_id } = residues - const { label_asym_id } = chains - const cI = chainAtomSegments.index[residueAtomSegments.offsets[rI]] - return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}` + const { residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy; + const { label_comp_id, label_seq_id } = residues; + const { label_asym_id } = chains; + const cI = chainAtomSegments.index[residueAtomSegments.offsets[rI]]; + return `${label_asym_id.value(cI)} ${label_comp_id.value(rI)} ${label_seq_id.value(rI)}`; } export function elementLabel(model: Model, index: ElementIndex) { - const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy - const { label_atom_id } = atoms - const { auth_seq_id, label_comp_id } = residues - const { auth_asym_id } = chains + const { atoms, residues, chains, residueAtomSegments, chainAtomSegments } = model.atomicHierarchy; + const { label_atom_id } = atoms; + const { auth_seq_id, label_comp_id } = residues; + const { auth_asym_id } = chains; - const residueIndex = residueAtomSegments.index[index] - const chainIndex = chainAtomSegments.index[residueIndex] + const residueIndex = residueAtomSegments.index[index]; + const chainIndex = chainAtomSegments.index[residueIndex]; - return `[${label_comp_id.value(residueIndex)}]${auth_seq_id.value(residueIndex)}:${auth_asym_id.value(chainIndex)}.${label_atom_id.value(index)}` + return `[${label_comp_id.value(residueIndex)}]${auth_seq_id.value(residueIndex)}:${auth_asym_id.value(chainIndex)}.${label_atom_id.value(index)}`; } // const centerPos = Vec3.zero() @@ -80,14 +80,14 @@ export function elementLabel(model: Model, index: ElementIndex) { // return Vec3.distance(centerMin, centroid) // } -const tmpPositionsVec = Vec3.zero() +const tmpPositionsVec = Vec3.zero(); export function getPositions(unit: Unit, indices: ArrayLike<number>): NumberArray { - const pos = unit.conformation.position - const positions = new Float32Array(indices.length * 3) - const { elements } = unit + const pos = unit.conformation.position; + const positions = new Float32Array(indices.length * 3); + const { elements } = unit; for (let i = 0, il = indices.length; i < il; ++i) { - pos(elements[indices[i]], tmpPositionsVec) - Vec3.toArray(tmpPositionsVec, positions, i * 3) + pos(elements[indices[i]], tmpPositionsVec); + Vec3.toArray(tmpPositionsVec, positions, i * 3); } - return positions + return positions; } \ No newline at end of file diff --git a/src/mol-model/volume.ts b/src/mol-model/volume.ts index c622e171bf076b1d77cca1d2f027464ac44734ee..70aad4db3d39bd24f02fb1cede4b3ec389d69824 100644 --- a/src/mol-model/volume.ts +++ b/src/mol-model/volume.ts @@ -4,4 +4,4 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './volume/data' \ No newline at end of file +export * from './volume/data'; \ No newline at end of file diff --git a/src/mol-model/volume/data.ts b/src/mol-model/volume/data.ts index 9afc2c605da2c33a9a58009e076c6a6bc33666ba..05023e9c4d5ac5703172a43399014ce318b54491 100644 --- a/src/mol-model/volume/data.ts +++ b/src/mol-model/volume/data.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { SpacegroupCell, Box3D } from '../../mol-math/geometry' -import { Tensor, Mat4, Vec3 } from '../../mol-math/linear-algebra' +import { SpacegroupCell, Box3D } from '../../mol-math/geometry'; +import { Tensor, Mat4, Vec3 } from '../../mol-math/linear-algebra'; import { equalEps } from '../../mol-math/linear-algebra/3d/common'; /** The basic unit cell that contains the data. */ @@ -28,7 +28,7 @@ namespace VolumeData { fractionalBox: Box3D.empty(), data: Tensor.create(Tensor.Space([1, 1, 1], [0, 1, 2]), Tensor.Data1([0])), dataStats: { min: 0, max: 0, mean: 0, sigma: 0 } - } + }; const _scale = Mat4.zero(), _translate = Mat4.zero(); export function getGridToCartesianTransform(volume: VolumeData) { @@ -39,7 +39,7 @@ namespace VolumeData { } export function areEquivalent(volA: VolumeData, volB: VolumeData) { - return volA === volB + return volA === volB; } } @@ -50,33 +50,33 @@ namespace VolumeIsoValue { export type Absolute = Readonly<{ kind: 'absolute', absoluteValue: number }> export function areSame(a: VolumeIsoValue, b: VolumeIsoValue, stats: VolumeData['dataStats']) { - return equalEps(toAbsolute(a, stats).absoluteValue, toAbsolute(b, stats).absoluteValue, stats.sigma / 100) + return equalEps(toAbsolute(a, stats).absoluteValue, toAbsolute(b, stats).absoluteValue, stats.sigma / 100); } export function absolute(value: number): Absolute { return { kind: 'absolute', absoluteValue: value }; } export function relative(value: number): Relative { return { kind: 'relative', relativeValue: value }; } export function calcAbsolute(stats: VolumeData['dataStats'], relativeValue: number): number { - return relativeValue * stats.sigma + stats.mean + return relativeValue * stats.sigma + stats.mean; } export function calcRelative(stats: VolumeData['dataStats'], absoluteValue: number): number { - return stats.sigma === 0 ? 0 : ((absoluteValue - stats.mean) / stats.sigma) + return stats.sigma === 0 ? 0 : ((absoluteValue - stats.mean) / stats.sigma); } export function toAbsolute(value: VolumeIsoValue, stats: VolumeData['dataStats']): Absolute { - return value.kind === 'absolute' ? value : { kind: 'absolute', absoluteValue: VolumeIsoValue.calcAbsolute(stats, value.relativeValue) } + return value.kind === 'absolute' ? value : { kind: 'absolute', absoluteValue: VolumeIsoValue.calcAbsolute(stats, value.relativeValue) }; } export function toRelative(value: VolumeIsoValue, stats: VolumeData['dataStats']): Relative { - return value.kind === 'relative' ? value : { kind: 'relative', relativeValue: VolumeIsoValue.calcRelative(stats, value.absoluteValue) } + return value.kind === 'relative' ? value : { kind: 'relative', relativeValue: VolumeIsoValue.calcRelative(stats, value.absoluteValue) }; } export function toString(value: VolumeIsoValue) { return value.kind === 'relative' ? `${value.relativeValue} σ` - : `${value.absoluteValue}` + : `${value.absoluteValue}`; } } -export { VolumeData, VolumeIsoValue } \ No newline at end of file +export { VolumeData, VolumeIsoValue }; \ No newline at end of file diff --git a/src/mol-plugin-state/actions.ts b/src/mol-plugin-state/actions.ts index ce6c13d4193c80a5749755e8d74048991eca8e86..5cb145b9b849219726bfd7cd1c850d9752d691a9 100644 --- a/src/mol-plugin-state/actions.ts +++ b/src/mol-plugin-state/actions.ts @@ -4,12 +4,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Structure from './actions/structure' -import * as Volume from './actions/volume' -import * as DataFormat from './actions/file' +import * as Structure from './actions/structure'; +import * as Volume from './actions/volume'; +import * as DataFormat from './actions/file'; export const StateActions = { Structure, Volume, DataFormat -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-plugin-state/actions/file.ts b/src/mol-plugin-state/actions/file.ts index 693a315ebd1e6c5d7c877a0545913846443c978f..24de5f1f2f9c87fc5c6d926bac4a5063b2f86b4d 100644 --- a/src/mol-plugin-state/actions/file.ts +++ b/src/mol-plugin-state/actions/file.ts @@ -15,30 +15,30 @@ export const OpenFiles = StateAction.build({ display: { name: 'Open Files', description: 'Load one or more files and optionally create default visuals' }, from: PluginStateObject.Root, params: (a, ctx: PluginContext) => { - const { extensions, options } = ctx.dataFormats + const { extensions, options } = ctx.dataFormats; return { files: PD.FileList({ accept: Array.from(extensions.values()).map(e => `.${e}`).join(',') + ',.gz,.zip', multiple: true }), format: PD.Select('auto', options), visuals: PD.Boolean(true, { description: 'Add default visuals' }), - } + }; } })(({ params, state }, plugin: PluginContext) => Task.create('Open Files', async taskCtx => { plugin.behaviors.layout.leftPanelTabName.next('data'); await state.transaction(async () => { if (params.files === null) { - plugin.log.error('No file(s) selected') - return + plugin.log.error('No file(s) selected'); + return; } for (let i = 0, il = params.files.length; i < il; ++i) { try { - const file = params.files[i] - const info = getFileInfo(file) - const isBinary = plugin.dataFormats.binaryExtensions.has(info.ext) + const file = params.files[i]; + const info = getFileInfo(file); + const isBinary = plugin.dataFormats.binaryExtensions.has(info.ext); const { data } = await plugin.builders.data.readFile({ file, isBinary }); const provider = params.format === 'auto' ? plugin.dataFormats.auto(info, data.cell?.obj!) - : plugin.dataFormats.get(params.format) + : plugin.dataFormats.get(params.format); if (!provider) { plugin.log.warn(`OpenFiles: could not find data provider for '${info.name}.${info.ext}'`); @@ -51,7 +51,7 @@ export const OpenFiles = StateAction.build({ await provider.visuals?.(plugin, parsed); } } catch (e) { - plugin.log.error(e) + plugin.log.error(e); } } }).runInContext(taskCtx); diff --git a/src/mol-plugin-state/actions/structure.ts b/src/mol-plugin-state/actions/structure.ts index 171504fce8e4cd4760885e8e67c60e21ebdeee02..4f5a8c4752172ade1bcf36efd9c617f6bc51f1c1 100644 --- a/src/mol-plugin-state/actions/structure.ts +++ b/src/mol-plugin-state/actions/structure.ts @@ -71,7 +71,7 @@ const DownloadStructure = StateAction.build({ options }, { isFlat: true, label: 'URL' }) }) - } + }; } })(({ params, state }, plugin: PluginContext) => Task.create('Download Structure', async ctx => { plugin.behaviors.layout.leftPanelTabName.next('data'); @@ -83,7 +83,7 @@ const DownloadStructure = StateAction.build({ switch (src.name) { case 'url': downloadParams = [{ url: src.params.url, isBinary: src.params.isBinary }]; - format = src.params.format + format = src.params.format; break; case 'pdb': downloadParams = src.params.provider.server.name === 'pdbe' @@ -98,8 +98,8 @@ const DownloadStructure = StateAction.build({ case 'pdb-dev': downloadParams = getDownloadParams(src.params.id, id => { - const nId = id.toUpperCase().startsWith('PDBDEV_') ? id : `PDBDEV_${id.padStart(8, '0')}` - return `https://pdb-dev.wwpdb.org/cif/${nId.toUpperCase()}.cif` + const nId = id.toUpperCase().startsWith('PDBDEV_') ? id : `PDBDEV_${id.padStart(8, '0')}`; + return `https://pdb-dev.wwpdb.org/cif/${nId.toUpperCase()}.cif`; }, id => id.toUpperCase().startsWith('PDBDEV_') ? id : `PDBDEV_${id.padStart(8, '0')}`, false @@ -113,12 +113,12 @@ const DownloadStructure = StateAction.build({ case 'swissmodel': downloadParams = getDownloadParams(src.params.id, id => `https://swissmodel.expasy.org/repository/uniprot/${id.toUpperCase()}.pdb`, id => `SWISS-MODEL: ${id}`, false); asTrajectory = !!src.params.options.asTrajectory; - format = 'pdb' + format = 'pdb'; break; case 'pubchem': downloadParams = getDownloadParams(src.params.id, id => `https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/CID/${id.trim()}/record/SDF/?record_type=3d`, id => `PubChem: ${id}`, false); asTrajectory = !!src.params.options.asTrajectory; - format = 'mol' + format = 'mol'; break; default: throw new Error(`${(src as any).name} not supported.`); } @@ -160,7 +160,7 @@ function getDownloadParams(src: string, url: (id: string) => string, label: (id: const ids = src.split(',').map(id => id.trim()).filter(id => !!id && (id.length >= 4 || /^[1-9][0-9]*$/.test(id))); const ret: StateTransformer.Params<Download>[] = []; for (const id of ids) { - ret.push({ url: url(id), isBinary, label: label(id) }) + ret.push({ url: url(id), isBinary, label: label(id) }); } return ret; } @@ -200,7 +200,7 @@ export const EnableModelCustomProps = StateAction.build({ display: { name: 'Custom Model Properties', description: 'Enable parameters for custom properties of the model.' }, from: PluginStateObject.Molecule.Model, params(a, ctx: PluginContext) { - return ctx.customModelProperties.getParams(a?.data) + return ctx.customModelProperties.getParams(a?.data); }, isApplicable(a, t, ctx: PluginContext) { return t.transformer !== CustomModelProperties; @@ -211,7 +211,7 @@ export const EnableStructureCustomProps = StateAction.build({ display: { name: 'Custom Structure Properties', description: 'Enable parameters for custom properties of the structure.' }, from: PluginStateObject.Molecule.Structure, params(a, ctx: PluginContext) { - return ctx.customStructureProperties.getParams(a?.data) + return ctx.customStructureProperties.getParams(a?.data); }, isApplicable(a, t, ctx: PluginContext) { return t.transformer !== CustomStructureProperties; @@ -222,18 +222,18 @@ export const AddTrajectory = StateAction.build({ display: { name: 'Add Trajectory', description: 'Add trajectory from existing model/topology and coordinates.' }, from: PluginStateObject.Root, params(a, ctx: PluginContext) { - const state = ctx.state.data + const state = ctx.state.data; const models = [ ...state.selectQ(q => q.rootsOfType(PluginStateObject.Molecule.Model)), ...state.selectQ(q => q.rootsOfType(PluginStateObject.Molecule.Topology)), - ] - const modelOptions = models.map(t => [t.transform.ref, t.obj!.label]) as [string, string][] - const coords = state.selectQ(q => q.rootsOfType(PluginStateObject.Molecule.Coordinates)) - const coordOptions = coords.map(c => [c.transform.ref, c.obj!.label]) as [string, string][] + ]; + const modelOptions = models.map(t => [t.transform.ref, t.obj!.label]) as [string, string][]; + const coords = state.selectQ(q => q.rootsOfType(PluginStateObject.Molecule.Coordinates)); + const coordOptions = coords.map(c => [c.transform.ref, c.obj!.label]) as [string, string][]; return { model: PD.Select(modelOptions.length ? modelOptions[0][0] : '', modelOptions), coordinates: PD.Select(coordOptions.length ? coordOptions[0][0] : '', coordOptions) - } + }; } })(({ params, state }, ctx: PluginContext) => Task.create('Add Trajectory', taskCtx => { return state.transaction(async () => { @@ -248,5 +248,5 @@ export const AddTrajectory = StateAction.build({ await state.updateTree(model).runInContext(taskCtx); const structure = await ctx.builders.structure.createStructure(model.selector); await ctx.builders.structure.representation.applyPreset(structure, 'auto'); - }).runInContext(taskCtx) + }).runInContext(taskCtx); })); \ No newline at end of file diff --git a/src/mol-plugin-state/actions/volume.ts b/src/mol-plugin-state/actions/volume.ts index 6a5383c38ef38216495ed86a060d2646084577a2..178fce410aa4c301df39c929c84c7d467181e530 100644 --- a/src/mol-plugin-state/actions/volume.ts +++ b/src/mol-plugin-state/actions/volume.ts @@ -20,7 +20,7 @@ const DownloadDensity = StateAction.build({ from: PluginStateObject.Root, display: { name: 'Download Density', description: 'Load a density from the provided source and create its default visual.' }, params: (a, ctx: PluginContext) => { - const { options } = ctx.dataFormats + const { options } = ctx.dataFormats; return { source: PD.MappedStatic('pdb-xray', { 'pdb-xray': PD.Group({ @@ -57,7 +57,7 @@ const DownloadDensity = StateAction.build({ ['url', 'URL'] ] }) - } + }; } })(({ params }, plugin: PluginContext) => Task.create('Download Density', async taskCtx => { const src = params.source; @@ -113,16 +113,16 @@ const DownloadDensity = StateAction.build({ switch (src.name) { case 'url': downloadParams = src.params; - provider = src.params.format === 'auto' ? plugin.dataFormats.auto(getFileInfo(downloadParams.url), data.cell?.obj!) : plugin.dataFormats.get(src.params.format) + provider = src.params.format === 'auto' ? plugin.dataFormats.auto(getFileInfo(downloadParams.url), data.cell?.obj!) : plugin.dataFormats.get(src.params.format); break; case 'pdb-xray': provider = src.params.provider.server === 'pdbe' ? plugin.dataFormats.get('ccp4') - : plugin.dataFormats.get('dsn6') + : plugin.dataFormats.get('dsn6'); break; case 'pdb-emd-ds': case 'pdb-xray-ds': - provider = plugin.dataFormats.get('dscif') + provider = plugin.dataFormats.get('dscif'); break; default: throw new Error(`${(src as any).name} not supported.`); } diff --git a/src/mol-plugin-state/animation/built-in.ts b/src/mol-plugin-state/animation/built-in.ts index f3fde2bb93d40f71e35ef8a1dac3943eeb0dfae2..e87c2ed175f06a1f5b8fb379032eab4865092864 100644 --- a/src/mol-plugin-state/animation/built-in.ts +++ b/src/mol-plugin-state/animation/built-in.ts @@ -85,7 +85,7 @@ export const AnimateModelIndex = PluginStateAnimation.create({ if (params.mode.name === 'palindrome') return { kind: 'next', state: { palindromeDirections } }; return { kind: 'next', state: {} }; } -}) +}); export const AnimateAssemblyUnwind = PluginStateAnimation.create({ name: 'built-in.animate-assembly-unwind', @@ -164,7 +164,7 @@ export const AnimateAssemblyUnwind = PluginStateAnimation.create({ if (finished) return { kind: 'finished' }; return { kind: 'next', state: { t: newTime } }; } -}) +}); export const AnimateUnitsExplode = PluginStateAnimation.create({ name: 'built-in.animate-units-explode', @@ -223,7 +223,7 @@ export const AnimateUnitsExplode = PluginStateAnimation.create({ return { kind: 'next', state: { t: newTime } }; } -}) +}); export const AnimateStateInterpolation = PluginStateAnimation.create({ name: 'built-in.animate-state-interpolation', @@ -273,4 +273,4 @@ export const AnimateStateInterpolation = PluginStateAnimation.create({ return { kind: 'next', state: { } }; } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-plugin-state/animation/manager.ts b/src/mol-plugin-state/animation/manager.ts index f21ffc36d203dc1ae0e640f26941b690740605c7..13a57f56c803fc005b325ab3ea79e54162eb071a 100644 --- a/src/mol-plugin-state/animation/manager.ts +++ b/src/mol-plugin-state/animation/manager.ts @@ -9,7 +9,7 @@ import { PluginContext } from '../../mol-plugin/context'; import { PluginStateAnimation } from './model'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; -export { PluginAnimationManager } +export { PluginAnimationManager }; // TODO: pause functionality (this needs to reset if the state tree changes) // TODO: handle unregistered animations on state restore @@ -54,7 +54,7 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana state: {}, startedTime: -1, lastTime: 0 - } + }; this.triggerUpdate(); } diff --git a/src/mol-plugin-state/animation/model.ts b/src/mol-plugin-state/animation/model.ts index a1e2c3664df995941907d7750132eb8ec2f94bd3..c0f16f1fa27795192c3c5f31dbdc4d0a4ae9bac5 100644 --- a/src/mol-plugin-state/animation/model.ts +++ b/src/mol-plugin-state/animation/model.ts @@ -7,7 +7,7 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { PluginContext } from '../../mol-plugin/context'; -export { PluginStateAnimation } +export { PluginStateAnimation }; // TODO: helpers for building animations (once more animations are added) // for example "composite animation" diff --git a/src/mol-plugin-state/builder/structure.ts b/src/mol-plugin-state/builder/structure.ts index 001312e7aafc6de9dd299605d8be2fd0eb769467..322d7ea8f081d5ba394faabe2e9c6995c98245c0 100644 --- a/src/mol-plugin-state/builder/structure.ts +++ b/src/mol-plugin-state/builder/structure.ts @@ -177,7 +177,7 @@ export class StructureBuilder { } return this.tryCreateComponent(structure, transformParams, key, tags); - })) + })); } constructor(public plugin: PluginContext) { diff --git a/src/mol-plugin-state/builder/structure/hierarchy-preset.ts b/src/mol-plugin-state/builder/structure/hierarchy-preset.ts index b29af346e3d5085754cb012594609ed0bb5bfaeb..22b82a091b8bcddca7ab8cedf9cef1af54c25144 100644 --- a/src/mol-plugin-state/builder/structure/hierarchy-preset.ts +++ b/src/mol-plugin-state/builder/structure/hierarchy-preset.ts @@ -27,10 +27,10 @@ export namespace TrajectoryHierarchyPresetProvider { modelProperties: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.CustomModelProperties, void 0, plugin))), structureProperties: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.CustomStructureProperties, void 0, plugin))), representationPreset: PD.Optional(PD.Text<keyof PresetStructureRepresentations>('auto' as const)), - }) + }); } -const CommonParams = TrajectoryHierarchyPresetProvider.CommonParams +const CommonParams = TrajectoryHierarchyPresetProvider.CommonParams; const DefaultParams = (a: PluginStateObject.Molecule.Trajectory | undefined, plugin: PluginContext) => ({ model: PD.Optional(PD.Group(StateTransformer.getParamDefinition(StateTransforms.Model.ModelFromTrajectory, a, plugin))), @@ -46,7 +46,7 @@ const defaultPreset = TrajectoryHierarchyPresetProvider({ description: 'Shows the first assembly or, if that is unavailable, the first deposited model.' }, isApplicable: o => { - return true + return true; }, params: DefaultParams, async apply(trajectory, params, plugin) { @@ -79,7 +79,7 @@ const allModels = TrajectoryHierarchyPresetProvider({ description: 'Shows all models; colored by model-index.' }, isApplicable: o => { - return o.data.length > 1 + return o.data.length > 1; }, params: CommonParams, async apply(trajectory, params, plugin) { @@ -99,7 +99,7 @@ const allModels = TrajectoryHierarchyPresetProvider({ models.push(model); structures.push(structure); - const quality = structure.obj ? getStructureQuality(structure.obj.data, { elementCountFactor: tr.length }) : 'medium' + const quality = structure.obj ? getStructureQuality(structure.obj.data, { elementCountFactor: tr.length }) : 'medium'; await builder.representation.applyPreset(structureProperties, params.representationPreset || 'auto', { globalThemeName: 'model-index', quality }); } @@ -144,7 +144,7 @@ const unitcell = TrajectoryHierarchyPresetProvider({ description: 'Shows the fully populated unitcell.' }, isApplicable: o => { - return Model.hasCrystalSymmetry(o.data[0]) + return Model.hasCrystalSymmetry(o.data[0]); }, params: CrystalSymmetryParams, async apply(trajectory, params, plugin) { @@ -159,7 +159,7 @@ const supercell = TrajectoryHierarchyPresetProvider({ description: 'Shows the supercell, i.e. the central unitcell and all adjacent unitcells.' }, isApplicable: o => { - return Model.hasCrystalSymmetry(o.data[0]) + return Model.hasCrystalSymmetry(o.data[0]); }, params: CrystalSymmetryParams, async apply(trajectory, params, plugin) { diff --git a/src/mol-plugin-state/builder/structure/hierarchy.ts b/src/mol-plugin-state/builder/structure/hierarchy.ts index 23bbda9c27adcf2efceb0dd986c0322190be7d78..a77098da3b6be554b6ff6716ab1d6a59640ff93c 100644 --- a/src/mol-plugin-state/builder/structure/hierarchy.ts +++ b/src/mol-plugin-state/builder/structure/hierarchy.ts @@ -67,7 +67,7 @@ export class TrajectoryHierarchyBuilder { if (p.isApplicable && !p.isApplicable(t, this.plugin)) continue; options.push([p.id, p.display.name]); - map[p.id] = p.params ? PD.Group(p.params(t, this.plugin)) : PD.EmptyGroup() + map[p.id] = p.params ? PD.Group(p.params(t, this.plugin)) : PD.EmptyGroup(); } if (options.length === 0) return PD.MappedStatic('', { '': PD.EmptyGroup() }); return PD.MappedStatic(options[0][0], map, { options }); @@ -82,8 +82,8 @@ export class TrajectoryHierarchyBuilder { } unregisterPreset(provider: TrajectoryHierarchyPresetProvider) { - this.providerMap.delete(provider.id) - arrayRemoveInPlace(this._providers, provider) + this.providerMap.delete(provider.id); + arrayRemoveInPlace(this._providers, provider); } applyPreset<K extends keyof PresetTrajectoryHierarchy>(parent: StateObjectRef<PluginStateObject.Molecule.Trajectory>, preset: K, params?: Partial<TrajectoryHierarchyPresetProvider.Params<PresetTrajectoryHierarchy[K]>>): Promise<TrajectoryHierarchyPresetProvider.State<PresetTrajectoryHierarchy[K]>> | undefined @@ -101,7 +101,7 @@ export class TrajectoryHierarchyBuilder { const prms = params || (provider.params ? PD.getDefaultValues(provider.params(cell.obj, this.plugin) as PD.Params) - : {}) + : {}); const task = Task.create(`${provider.display.name}`, () => provider.apply(cell, prms, this.plugin) as Promise<any>); return this.plugin.runTask(task); diff --git a/src/mol-plugin-state/builder/structure/representation-preset.ts b/src/mol-plugin-state/builder/structure/representation-preset.ts index 2def1be284f8fc8a97c5051888fe6dc1fd972428..34bb792a08f49b31becdc75ce022731e14d25a55 100644 --- a/src/mol-plugin-state/builder/structure/representation-preset.ts +++ b/src/mol-plugin-state/builder/structure/representation-preset.ts @@ -30,7 +30,7 @@ export namespace StructureRepresentationPresetProvider { ignoreHydrogens: PD.Optional(PD.Boolean(false)), quality: PD.Optional(PD.Select<VisualQuality>('auto', VisualQualityOptions)), globalThemeName: PD.Optional(PD.Text<ColorTheme.BuiltIn>('')) - } + }; export type CommonParams = PD.ValuesFor<typeof CommonParams> export function reprBuilder(plugin: PluginContext, params: CommonParams) { @@ -50,9 +50,9 @@ export namespace StructureRepresentationPresetProvider { type _Result = StructureRepresentationPresetProvider.Result -const CommonParams = StructureRepresentationPresetProvider.CommonParams +const CommonParams = StructureRepresentationPresetProvider.CommonParams; type CommonParams = StructureRepresentationPresetProvider.CommonParams -const reprBuilder = StructureRepresentationPresetProvider.reprBuilder +const reprBuilder = StructureRepresentationPresetProvider.reprBuilder; const auto = StructureRepresentationPresetProvider({ id: 'preset-structure-representation-auto', @@ -64,7 +64,7 @@ const auto = StructureRepresentationPresetProvider({ apply(ref, params, plugin) { const structure = StateObjectRef.resolveAndCheck(plugin.state.data, ref)?.obj?.data; if (!structure) return { }; - const size = Structure.getSize(structure) + const size = Structure.getSize(structure); switch (size) { case Structure.Size.Gigantic: @@ -88,7 +88,7 @@ const empty = StructureRepresentationPresetProvider({ } }); -const BuiltInPresetGroupName = 'Basic' +const BuiltInPresetGroupName = 'Basic'; const polymerAndLigand = StructureRepresentationPresetProvider({ id: 'preset-structure-representation-polymer-and-ligand', @@ -167,10 +167,10 @@ const coarseSurface = StructureRepresentationPresetProvider({ const components = { polymer: await presetStaticComponent(plugin, structureCell, 'polymer') - } + }; const structure = structureCell.obj!.data; - const size = Structure.getSize(structure) + const size = Structure.getSize(structure); const gaussianProps = Object.create(null); if (size === Structure.Size.Gigantic) { Object.assign(gaussianProps, { @@ -178,11 +178,11 @@ const coarseSurface = StructureRepresentationPresetProvider({ radiusOffset: 1, smoothness: 0.5, visuals: ['structure-gaussian-surface-mesh'] - }) + }); } else if(size === Structure.Size.Huge) { Object.assign(gaussianProps, { smoothness: 0.5, - }) + }); } const { update, builder, typeParams, color } = reprBuilder(plugin, params); diff --git a/src/mol-plugin-state/builder/structure/representation.ts b/src/mol-plugin-state/builder/structure/representation.ts index ef15aaa5b492920f6fb77501c398f5b5b0c9e2d4..d22d509ae5711cdbfc60848c822c8d2916a824ea 100644 --- a/src/mol-plugin-state/builder/structure/representation.ts +++ b/src/mol-plugin-state/builder/structure/representation.ts @@ -69,7 +69,7 @@ export class StructureRepresentationBuilder { if (p.isApplicable && !p.isApplicable(s, this.plugin)) continue; options.push([p.id, p.display.name]); - map[p.id] = p.params ? PD.Group(p.params(s, this.plugin)) : PD.EmptyGroup() + map[p.id] = p.params ? PD.Group(p.params(s, this.plugin)) : PD.EmptyGroup(); } if (options.length === 0) return PD.MappedStatic('', { '': PD.EmptyGroup() }); return PD.MappedStatic(options[0][0], map, { options }); @@ -84,8 +84,8 @@ export class StructureRepresentationBuilder { } unregisterPreset(provider: StructureRepresentationPresetProvider) { - this.providerMap.delete(provider.id) - arrayRemoveInPlace(this._providers, provider) + this.providerMap.delete(provider.id); + arrayRemoveInPlace(this._providers, provider); } applyPreset<K extends keyof PresetStructureRepresentations>(parent: StateObjectRef<PluginStateObject.Molecule.Structure>, preset: K, params?: StructureRepresentationPresetProvider.Params<PresetStructureRepresentations[K]>): Promise<StructureRepresentationPresetProvider.State<PresetStructureRepresentations[K]>> | undefined @@ -104,7 +104,7 @@ export class StructureRepresentationBuilder { const prms = params || (provider.params ? PD.getDefaultValues(provider.params(cell.obj, this.plugin) as PD.Params) - : {}) + : {}); const task = Task.create(`${provider.display.name}`, () => provider.apply(cell, prms, this.plugin) as Promise<any>); return this.plugin.runTask(task); diff --git a/src/mol-plugin-state/camera.ts b/src/mol-plugin-state/camera.ts index 86b543c6e345e1a6f7278b19140c7dd4f6164109..c3bef6bcdd4874ebe61001f0c31cebb9285a57cb 100644 --- a/src/mol-plugin-state/camera.ts +++ b/src/mol-plugin-state/camera.ts @@ -9,7 +9,7 @@ import { OrderedMap } from 'immutable'; import { UUID } from '../mol-util'; import { StatefulPluginComponent } from './component'; -export { CameraSnapshotManager } +export { CameraSnapshotManager }; class CameraSnapshotManager extends StatefulPluginComponent<{ entries: OrderedMap<string, CameraSnapshotManager.Entry> }> { readonly events = { diff --git a/src/mol-plugin-state/formats/provider.ts b/src/mol-plugin-state/formats/provider.ts index eaa33bfa06698efe82b3f7cdda12604a5dbe1adf..dd3d996d411572f2245dbd698aa60b097dfc13a3 100644 --- a/src/mol-plugin-state/formats/provider.ts +++ b/src/mol-plugin-state/formats/provider.ts @@ -30,12 +30,12 @@ export function guessCifVariant(info: FileInfo, data: Uint8Array | string): cifV try { // TODO: find a way to run msgpackDecode only once // now it is run twice, here and during file parsing - if (msgpackDecode(data as Uint8Array).encoder.startsWith('VolumeServer')) return 'dscif' + if (msgpackDecode(data as Uint8Array).encoder.startsWith('VolumeServer')) return 'dscif'; } catch { } } else if (info.ext === 'cif') { - const str = data as string - if (str.startsWith('data_SERVER\n#\n_density_server_result')) return 'dscif' - if (str.includes('atom_site_fract_x') || str.includes('atom_site.fract_x')) return 'coreCif' + const str = data as string; + if (str.startsWith('data_SERVER\n#\n_density_server_result')) return 'dscif'; + if (str.includes('atom_site_fract_x') || str.includes('atom_site.fract_x')) return 'coreCif'; } - return -1 + return -1; } \ No newline at end of file diff --git a/src/mol-plugin-state/formats/registry.ts b/src/mol-plugin-state/formats/registry.ts index 9ed9f3fdf4e0f3f313f436fcb59b6ec6ba80d002..1314e91f709efd4b0c4da30645ae7b56d5f748c9 100644 --- a/src/mol-plugin-state/formats/registry.ts +++ b/src/mol-plugin-state/formats/registry.ts @@ -25,30 +25,30 @@ export class DataFormatRegistry { } get extensions() { - if (this._extensions) return this._extensions - const extensions = new Set<string>() + if (this._extensions) return this._extensions; + const extensions = new Set<string>(); this._list.forEach(({ provider }) => { - provider.stringExtensions?.forEach(ext => extensions.add(ext)) - provider.binaryExtensions?.forEach(ext => extensions.add(ext)) - }) - this._extensions = extensions - return extensions + provider.stringExtensions?.forEach(ext => extensions.add(ext)); + provider.binaryExtensions?.forEach(ext => extensions.add(ext)); + }); + this._extensions = extensions; + return extensions; } get binaryExtensions() { - if (this._binaryExtensions) return this._binaryExtensions - const binaryExtensions = new Set<string>() - this._list.forEach(({ provider }) => provider.binaryExtensions?.forEach(ext => binaryExtensions.add(ext))) - this._binaryExtensions = binaryExtensions - return binaryExtensions + if (this._binaryExtensions) return this._binaryExtensions; + const binaryExtensions = new Set<string>(); + this._list.forEach(({ provider }) => provider.binaryExtensions?.forEach(ext => binaryExtensions.add(ext))); + this._binaryExtensions = binaryExtensions; + return binaryExtensions; } get options() { - if (this._options) return this._options - const options: [string, string, string][] = [['auto', 'Automatic', '']] - this._list.forEach(({ name, provider }) => options.push([ name, provider.label, provider.category || '' ])) - this._options = options - return options + if (this._options) return this._options; + const options: [string, string, string][] = [['auto', 'Automatic', '']]; + this._list.forEach(({ name, provider }) => options.push([ name, provider.label, provider.category || '' ])); + this._options = options; + return options; } constructor() { @@ -59,21 +59,21 @@ export class DataFormatRegistry { }; private _clear() { - this._extensions = undefined - this._binaryExtensions = undefined - this._options = undefined + this._extensions = undefined; + this._binaryExtensions = undefined; + this._options = undefined; } add(name: string, provider: DataFormatProvider) { - this._clear() - this._list.push({ name, provider }) - this._map.set(name, provider) + this._clear(); + this._list.push({ name, provider }); + this._map.set(name, provider); } remove(name: string) { - this._clear() - this._list.splice(this._list.findIndex(e => e.name === name), 1) - this._map.delete(name) + this._clear(); + this._list.splice(this._list.findIndex(e => e.name === name), 1); + this._map.delete(name); } auto(info: FileInfo, dataStateObject: PluginStateObject.Data.Binary | PluginStateObject.Data.String) { @@ -90,13 +90,13 @@ export class DataFormatRegistry { get(name: string): DataFormatProvider | undefined { if (this._map.has(name)) { - return this._map.get(name)! + return this._map.get(name)!; } else { - throw new Error(`unknown data format name '${name}'`) + throw new Error(`unknown data format name '${name}'`); } } get list() { - return this._list + return this._list; } } \ No newline at end of file diff --git a/src/mol-plugin-state/formats/shape.ts b/src/mol-plugin-state/formats/shape.ts index cc02ee10c1a667708a130af62246f3b7174e25fc..d42465e074258cdabcf7a1e48ed903b399a8299f 100644 --- a/src/mol-plugin-state/formats/shape.ts +++ b/src/mol-plugin-state/formats/shape.ts @@ -30,6 +30,6 @@ export const PlyProvider = DataFormatProvider({ export const BuiltInShapeFormats = [ ['ply', PlyProvider] as const, -] as const +] as const; export type BuildInShapeFormat = (typeof BuiltInShapeFormats)[number][0] \ No newline at end of file diff --git a/src/mol-plugin-state/formats/structure.ts b/src/mol-plugin-state/formats/structure.ts index f534e20da4c09f68de15c62cc0ad558fd2c7fb8e..7a6f24d4030fac07dc63d809f62d451ea26f5b29 100644 --- a/src/mol-plugin-state/formats/structure.ts +++ b/src/mol-plugin-state/formats/structure.ts @@ -44,6 +44,6 @@ export const DcdProvider = DataFormatProvider({ export const BuiltInStructureFormats = [ ['psf', PsfProvider] as const, ['dcd', DcdProvider] as const, -] as const +] as const; export type BuildInStructureFormat = (typeof BuiltInStructureFormats)[number][0] \ No newline at end of file diff --git a/src/mol-plugin-state/formats/trajectory.ts b/src/mol-plugin-state/formats/trajectory.ts index c888550f2c1808fefb31880dd10b630bb5d32141..c76c879d24dc27e55cf0f434583094082a0a0db5 100644 --- a/src/mol-plugin-state/formats/trajectory.ts +++ b/src/mol-plugin-state/formats/trajectory.ts @@ -28,15 +28,15 @@ export const MmcifProvider: TrajectoryFormatProvider = { stringExtensions: ['cif', 'mmcif', 'mcif'], binaryExtensions: ['bcif'], isApplicable: (info, data) => { - if (info.ext === 'mmcif' || info.ext === 'mcif') return true + if (info.ext === 'mmcif' || info.ext === 'mcif') return true; // assume undetermined cif/bcif files are mmCIF - if (info.ext === 'cif' || info.ext === 'bcif') return guessCifVariant(info, data) === -1 - return false + if (info.ext === 'cif' || info.ext === 'bcif') return guessCifVariant(info, data) === -1; + return false; }, parse: async (plugin, data, params) => { const state = plugin.state.data; const cif = state.build().to(data) - .apply(StateTransforms.Data.ParseCif, void 0, { state: { isGhost: true } }) + .apply(StateTransforms.Data.ParseCif, void 0, { state: { isGhost: true } }); const trajectory = await cif .apply(StateTransforms.Model.TrajectoryFromMmCif, void 0, { tags: params?.trajectoryTags }) .commit({ revertOnError: true }); @@ -48,7 +48,7 @@ export const MmcifProvider: TrajectoryFormatProvider = { return { trajectory }; }, visuals: defaultVisuals -} +}; export const CifCoreProvider: TrajectoryFormatProvider = { label: 'cifCore', @@ -56,13 +56,13 @@ export const CifCoreProvider: TrajectoryFormatProvider = { category: Category, stringExtensions: ['cif'], isApplicable: (info, data) => { - if (info.ext === 'cif') return guessCifVariant(info, data) === 'coreCif' - return false + if (info.ext === 'cif') return guessCifVariant(info, data) === 'coreCif'; + return false; }, parse: async (plugin, data, params) => { const state = plugin.state.data; const cif = state.build().to(data) - .apply(StateTransforms.Data.ParseCif, void 0, { state: { isGhost: true } }) + .apply(StateTransforms.Data.ParseCif, void 0, { state: { isGhost: true } }); const trajectory = await cif .apply(StateTransforms.Model.TrajectoryFromCifCore, void 0, { tags: params?.trajectoryTags }) .commit({ revertOnError: true }); @@ -73,7 +73,7 @@ export const CifCoreProvider: TrajectoryFormatProvider = { return { trajectory }; }, visuals: defaultVisuals -} +}; function directTrajectory(transformer: StateTransformer<PluginStateObject.Data.String | PluginStateObject.Data.Binary, PluginStateObject.Molecule.Trajectory>): TrajectoryFormatProvider['parse'] { return async (plugin, data, params) => { @@ -82,7 +82,7 @@ function directTrajectory(transformer: StateTransformer<PluginStateObject.Data.S .apply(transformer, void 0, { tags: params?.trajectoryTags }) .commit({ revertOnError: true }); return { trajectory }; - } + }; } export const PdbProvider: TrajectoryFormatProvider = { @@ -92,7 +92,7 @@ export const PdbProvider: TrajectoryFormatProvider = { stringExtensions: ['pdb', 'ent'], parse: directTrajectory(StateTransforms.Model.TrajectoryFromPDB), visuals: defaultVisuals -} +}; export const GroProvider: TrajectoryFormatProvider = { label: 'GRO', @@ -102,7 +102,7 @@ export const GroProvider: TrajectoryFormatProvider = { binaryExtensions: [], parse: directTrajectory(StateTransforms.Model.TrajectoryFromGRO), visuals: defaultVisuals -} +}; export const Provider3dg: TrajectoryFormatProvider = { label: '3DG', @@ -111,7 +111,7 @@ export const Provider3dg: TrajectoryFormatProvider = { stringExtensions: ['3dg'], parse: directTrajectory(StateTransforms.Model.TrajectoryFrom3DG), visuals: defaultVisuals -} +}; export const MolProvider: TrajectoryFormatProvider = { label: 'MOL', @@ -120,7 +120,7 @@ export const MolProvider: TrajectoryFormatProvider = { stringExtensions: ['mol', 'sdf'], parse: directTrajectory(StateTransforms.Model.TrajectoryFromMOL), visuals: defaultVisuals -} +}; export const BuiltInTrajectoryFormats = [ @@ -130,6 +130,6 @@ export const BuiltInTrajectoryFormats = [ ['gro', GroProvider] as const, ['3dg', Provider3dg] as const, ['mol', MolProvider] as const -] as const +] as const; export type BuiltInTrajectoryFormat = (typeof BuiltInTrajectoryFormats)[number][0] \ No newline at end of file diff --git a/src/mol-plugin-state/formats/volume.ts b/src/mol-plugin-state/formats/volume.ts index a70f3d285264b1dbba6dd5858e6530bda9a0e5f6..1f0aaf121603d261a3e3c4fb2026c800764fba51 100644 --- a/src/mol-plugin-state/formats/volume.ts +++ b/src/mol-plugin-state/formats/volume.ts @@ -66,14 +66,14 @@ export const DscifProvider = DataFormatProvider({ stringExtensions: ['cif'], binaryExtensions: ['bcif'], isApplicable: (info, data) => { - return guessCifVariant(info, data) === 'dscif' ? true : false + return guessCifVariant(info, data) === 'dscif' ? true : false; }, parse: async (plugin, data) => { - const cifCell = await plugin.build().to(data).apply(StateTransforms.Data.ParseCif).commit() + const cifCell = await plugin.build().to(data).apply(StateTransforms.Data.ParseCif).commit(); const b = plugin.build().to(cifCell); const blocks = cifCell.obj!.data.blocks.slice(1); // zero block contains query meta-data - if (blocks.length !== 1 && blocks.length !== 2) throw new Error('unknown number of blocks') + if (blocks.length !== 1 && blocks.length !== 2) throw new Error('unknown number of blocks'); const volumes: StateObjectSelector<PluginStateObject.Volume.Data>[] = []; for (const block of blocks) { @@ -97,8 +97,8 @@ export const DscifProvider = DataFormatProvider({ } if (volumes.length > 1) { - const posParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(plugin, 'isosurface', { isoValue: VolumeIsoValue.relative(3), alpha: 0.3 }, 'uniform', { value: ColorNames.green }) - const negParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(plugin, 'isosurface', { isoValue: VolumeIsoValue.relative(-3), alpha: 0.3 }, 'uniform', { value: ColorNames.red }) + const posParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(plugin, 'isosurface', { isoValue: VolumeIsoValue.relative(3), alpha: 0.3 }, 'uniform', { value: ColorNames.green }); + const negParams = VolumeRepresentation3DHelpers.getDefaultParamsStatic(plugin, 'isosurface', { isoValue: VolumeIsoValue.relative(-3), alpha: 0.3 }, 'uniform', { value: ColorNames.red }); visuals[visuals.length] = tree.to(volumes[1]).apply(StateTransforms.Representation.VolumeRepresentation3D, posParams).selector; visuals[visuals.length] = tree.to(volumes[1]).apply(StateTransforms.Representation.VolumeRepresentation3D, negParams).selector; } @@ -113,6 +113,6 @@ export const BuiltInVolumeFormats = [ ['ccp4', Ccp4Provider] as const, ['dns6', Dsn6Provider] as const, ['dscif', DscifProvider] as const, -] as const +] as const; export type BuildInVolumeFormat = (typeof BuiltInVolumeFormats)[number][0] \ No newline at end of file diff --git a/src/mol-plugin-state/helpers/root-structure.ts b/src/mol-plugin-state/helpers/root-structure.ts index 8b3c7c49fec7040a99a9aed8020ffb34e4697787..850e0aee0eb4bb7cfccb1c1feb286b1c7e9bd997 100644 --- a/src/mol-plugin-state/helpers/root-structure.ts +++ b/src/mol-plugin-state/helpers/root-structure.ts @@ -18,25 +18,25 @@ import { ModelSymmetry } from '../../mol-model-formats/structure/property/symmet export namespace RootStructureDefinition { export function getParams(model?: Model, defaultValue?: 'auto' | 'deposited' | 'assembly' | 'symmetry' | 'symmetry-mates' | 'symmetry-assembly') { - const symmetry = model && ModelSymmetry.Provider.get(model) + const symmetry = model && ModelSymmetry.Provider.get(model); const assemblyIds = symmetry ? symmetry.assemblies.map(a => [a.id, `${a.id}: ${stringToWords(a.details)}`] as [string, string]) : []; const showSymm = !symmetry ? true : !SpacegroupCell.isZero(symmetry.spacegroup.cell); - const operatorOptions: [number, string][] = [] + const operatorOptions: [number, string][] = []; if (symmetry) { - const { operators } = symmetry.spacegroup + const { operators } = symmetry.spacegroup; for (let i = 0, il = operators.length; i < il; i++) { - operatorOptions.push([i, `${i + 1}: ${Spacegroup.getOperatorXyz(operators[i])}`]) + operatorOptions.push([i, `${i + 1}: ${Spacegroup.getOperatorXyz(operators[i])}`]); } } - const asymIdsOptions: [string, string][] = [] + const asymIdsOptions: [string, string][] = []; if (model) { model.properties.structAsymMap.forEach(v => { - const label = v.id === v.auth_id ? v.id : `${v.id} [auth ${v.auth_id}]` - asymIdsOptions.push([v.id, label]) - }) + const label = v.id === v.auth_id ? v.id : `${v.id} [auth ${v.auth_id}]`; + asymIdsOptions.push([v.id, label]); + }); } const modes = { @@ -102,7 +102,7 @@ export namespace RootStructureDefinition { async function buildAssembly(plugin: PluginContext, ctx: RuntimeContext, model: Model, id?: string) { let asm: Assembly | undefined = void 0; - const symmetry = ModelSymmetry.Provider.get(model) + const symmetry = ModelSymmetry.Provider.get(model); // if no id is specified, use the 1st assembly. if (!id && symmetry && symmetry.assemblies.length !== 0) { @@ -154,7 +154,7 @@ export namespace RootStructureDefinition { } export async function create(plugin: PluginContext, ctx: RuntimeContext, model: Model, params?: Params): Promise<SO.Molecule.Structure> { - const symmetry = ModelSymmetry.Provider.get(model) + const symmetry = ModelSymmetry.Provider.get(model); if (!symmetry || !params || params.name === 'deposited') { const s = Structure.ofModel(model); return new SO.Molecule.Structure(s, { label: 'Deposited', description: Structure.elementDescription(s) }); @@ -168,16 +168,16 @@ export namespace RootStructureDefinition { } } if (params.name === 'assembly') { - return buildAssembly(plugin, ctx, model, params.params.id) + return buildAssembly(plugin, ctx, model, params.params.id); } if (params.name === 'symmetry') { - return buildSymmetry(ctx, model, params.params.ijkMin, params.params.ijkMax) + return buildSymmetry(ctx, model, params.params.ijkMin, params.params.ijkMax); } if (params.name === 'symmetry-mates') { - return buildSymmetryMates(ctx, model, params.params.radius) + return buildSymmetryMates(ctx, model, params.params.radius); } if (params.name === 'symmetry-assembly') { - return buildSymmetryAssembly(ctx, model, params.params.generators, symmetry) + return buildSymmetryAssembly(ctx, model, params.params.generators, symmetry); } throw new Error(`Unknown represetation type: ${(params as any).name}`); diff --git a/src/mol-plugin-state/helpers/structure-overpaint.ts b/src/mol-plugin-state/helpers/structure-overpaint.ts index 2049ee21756b5c77938ec8354bc772e4e4ee637f..381567116d0cc2c6c5a064641ba474f4aa6aa3e4 100644 --- a/src/mol-plugin-state/helpers/structure-overpaint.ts +++ b/src/mol-plugin-state/helpers/structure-overpaint.ts @@ -16,34 +16,34 @@ import { StructureComponentRef } from '../manager/structure/hierarchy-state'; import { EmptyLoci, Loci } from '../../mol-model/loci'; type OverpaintEachReprCallback = (update: StateBuilder.Root, repr: StateObjectCell<PluginStateObject.Molecule.Structure.Representation3D, StateTransform<typeof StateTransforms.Representation.StructureRepresentation3D>>, overpaint?: StateObjectCell<any, StateTransform<typeof StateTransforms.Representation.OverpaintStructureRepresentation3DFromBundle>>) => void -const OverpaintManagerTag = 'overpaint-controls' +const OverpaintManagerTag = 'overpaint-controls'; export async function setStructureOverpaint(plugin: PluginContext, components: StructureComponentRef[], color: Color | -1, lociGetter: (structure: Structure) => StructureElement.Loci | EmptyLoci, types?: string[], alpha = 1) { await eachRepr(plugin, components, (update, repr, overpaintCell) => { - if (types && types.length > 0 && !types.includes(repr.params!.values.type.name)) return + if (types && types.length > 0 && !types.includes(repr.params!.values.type.name)) return; - const structure = repr.obj!.data.source.data + const structure = repr.obj!.data.source.data; // always use the root structure to get the loci so the overpaint // stays applicable as long as the root structure does not change - const loci = lociGetter(structure.root) - if (Loci.isEmpty(loci)) return + const loci = lociGetter(structure.root); + if (Loci.isEmpty(loci)) return; const layer = { bundle: StructureElement.Bundle.fromLoci(loci), color: color === -1 ? Color(0) : color, clear: color === -1 - } + }; if (overpaintCell) { - const bundleLayers = [...overpaintCell.params!.values.layers, layer] - const filtered = getFilteredBundle(bundleLayers, structure) - update.to(overpaintCell).update(Overpaint.toBundle(filtered, alpha)) + const bundleLayers = [...overpaintCell.params!.values.layers, layer]; + const filtered = getFilteredBundle(bundleLayers, structure); + update.to(overpaintCell).update(Overpaint.toBundle(filtered, alpha)); } else { - const filtered = getFilteredBundle([layer], structure) + const filtered = getFilteredBundle([layer], structure); update.to(repr.transform.ref) .apply(StateTransforms.Representation.OverpaintStructureRepresentation3DFromBundle, Overpaint.toBundle(filtered, alpha), { tags: OverpaintManagerTag }); } - }) + }); } export async function clearStructureOverpaint(plugin: PluginContext, components: StructureComponentRef[], types?: string[]) { @@ -60,8 +60,8 @@ function eachRepr(plugin: PluginContext, components: StructureComponentRef[], ca const update = state.build(); for (const c of components) { for (const r of c.representations) { - const overpaint = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.OverpaintStructureRepresentation3DFromBundle, r.cell.transform.ref).withTag(OverpaintManagerTag)) - callback(update, r.cell, overpaint[0]) + const overpaint = state.select(StateSelection.Generators.ofTransformer(StateTransforms.Representation.OverpaintStructureRepresentation3DFromBundle, r.cell.transform.ref).withTag(OverpaintManagerTag)); + callback(update, r.cell, overpaint[0]); } } @@ -70,7 +70,7 @@ function eachRepr(plugin: PluginContext, components: StructureComponentRef[], ca /** filter overpaint layers for given structure */ function getFilteredBundle(layers: Overpaint.BundleLayer[], structure: Structure) { - const overpaint = Overpaint.ofBundle(layers, 1, structure.root) - const merged = Overpaint.merge(overpaint) - return Overpaint.filter(merged, structure) + const overpaint = Overpaint.ofBundle(layers, 1, structure.root); + const merged = Overpaint.merge(overpaint); + return Overpaint.filter(merged, structure); } \ No newline at end of file diff --git a/src/mol-plugin-state/helpers/structure-query.ts b/src/mol-plugin-state/helpers/structure-query.ts index f29197da009a8b8b5b0e278980d39f4706b73f41..22bc0b3b4b720cc5953e93750759130c485c6f44 100644 --- a/src/mol-plugin-state/helpers/structure-query.ts +++ b/src/mol-plugin-state/helpers/structure-query.ts @@ -10,7 +10,7 @@ import { Script } from '../../mol-script/script'; import { compile } from '../../mol-script/runtime/query/compiler'; import { PluginStateObject as SO } from '../objects'; -export { StructureQueryHelper } +export { StructureQueryHelper }; namespace StructureQueryHelper { export interface CacheEntry { script?: Script, @@ -37,7 +37,7 @@ namespace StructureQueryHelper { } export function run(entry: CacheEntry, structure: Structure) { - return entry.compiled(new QueryContext(structure)) + return entry.compiled(new QueryContext(structure)); } export function createAndRun(structure: Structure, query: Script | Expression) { diff --git a/src/mol-plugin-state/helpers/structure-representation-params.ts b/src/mol-plugin-state/helpers/structure-representation-params.ts index 8ce837d9636d1ec5011139879c4692a7ecd8b180..621dea1713899d9ddd7cf3be2cfd91854a6447e9 100644 --- a/src/mol-plugin-state/helpers/structure-representation-params.ts +++ b/src/mol-plugin-state/helpers/structure-representation-params.ts @@ -7,7 +7,7 @@ import { Structure } from '../../mol-model/structure'; import { PluginContext } from '../../mol-plugin/context'; import { RepresentationProvider } from '../../mol-repr/representation'; -import { StructureRepresentationRegistry } from '../../mol-repr/structure/registry' +import { StructureRepresentationRegistry } from '../../mol-repr/structure/registry'; import { StateTransformer } from '../../mol-state'; import { ColorTheme } from '../../mol-theme/color'; import { SizeTheme } from '../../mol-theme/size'; @@ -96,7 +96,7 @@ function createParamsByName(ctx: PluginContext, structure: Structure, props: Str } function createParamsProvider(ctx: PluginContext, structure: Structure, props: StructureRepresentationProps = {}): StateTransformer.Params<StructureRepresentation3D> { - const { themes: themeCtx } = ctx.representation.structure + const { themes: themeCtx } = ctx.representation.structure; const themeDataCtx = { structure }; const repr = props.type || ctx.representation.structure.registry.default.provider; diff --git a/src/mol-plugin-state/helpers/structure-selection-query.ts b/src/mol-plugin-state/helpers/structure-selection-query.ts index 2a041d7a4a98534afdd9423fd31989065a7ba942..a53303356f3e90648baf318bb47aa3c8287c7fd3 100644 --- a/src/mol-plugin-state/helpers/structure-selection-query.ts +++ b/src/mol-plugin-state/helpers/structure-selection-query.ts @@ -56,7 +56,7 @@ interface StructureSelectionQueryProps { } function StructureSelectionQuery(label: string, expression: Expression, props: StructureSelectionQueryProps = {}): StructureSelectionQuery { - let _query: StructureQuery + let _query: StructureQuery; return { label, expression, @@ -65,24 +65,24 @@ function StructureSelectionQuery(label: string, expression: Expression, props: S isHidden: !!props.isHidden, referencesCurrent: !!props.referencesCurrent, get query() { - if (!_query) _query = compile<StructureSelection>(expression) - return _query + if (!_query) _query = compile<StructureSelection>(expression); + return _query; }, ensureCustomProperties: props.ensureCustomProperties, async getSelection(plugin, runtime, structure) { - const current = plugin.managers.structure.selection.getStructure(structure) + const current = plugin.managers.structure.selection.getStructure(structure); const currentSelection = current ? StructureSelection.Singletons(structure, current) : StructureSelection.Empty(structure); if (props.ensureCustomProperties) { - await props.ensureCustomProperties({ fetch: plugin.fetch, runtime }, structure) + await props.ensureCustomProperties({ fetch: plugin.fetch, runtime }, structure); } - if (!_query) _query = compile<StructureSelection>(expression) + if (!_query) _query = compile<StructureSelection>(expression); return _query(new QueryContext(structure, { currentSelection })); } - } + }; } -const all = StructureSelectionQuery('All', MS.struct.generator.all(), { category: '' }) -const current = StructureSelectionQuery('Current Selection', MS.internal.generator.current(), { category: '', referencesCurrent: true }) +const all = StructureSelectionQuery('All', MS.struct.generator.all(), { category: '' }); +const current = StructureSelectionQuery('Current Selection', MS.internal.generator.current(), { category: '', referencesCurrent: true }); const polymer = StructureSelectionQuery('Polymer', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -94,7 +94,7 @@ const polymer = StructureSelectionQuery('Polymer', MS.struct.modifier.union([ ]) ]) }) -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); const trace = StructureSelectionQuery('Trace', MS.struct.modifier.union([ MS.struct.combinator.merge([ @@ -114,7 +114,7 @@ const trace = StructureSelectionQuery('Trace', MS.struct.modifier.union([ }) ]) ]) -]), { category: StructureSelectionCategory.Structure }) +]), { category: StructureSelectionCategory.Structure }); // TODO maybe pre-calculate atom properties like backbone/sidechain const backbone = StructureSelectionQuery('Backbone', MS.struct.modifier.union([ @@ -146,7 +146,7 @@ const backbone = StructureSelectionQuery('Backbone', MS.struct.modifier.union([ }) ]) ]) -]), { category: StructureSelectionCategory.Structure }) +]), { category: StructureSelectionCategory.Structure }); const protein = StructureSelectionQuery('Protein', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -158,7 +158,7 @@ const protein = StructureSelectionQuery('Protein', MS.struct.modifier.union([ ]) ]) }) -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); const nucleic = StructureSelectionQuery('Nucleic', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -170,7 +170,7 @@ const nucleic = StructureSelectionQuery('Nucleic', MS.struct.modifier.union([ ]) ]) }) -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); const helix = StructureSelectionQuery('Helix', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -186,7 +186,7 @@ const helix = StructureSelectionQuery('Helix', MS.struct.modifier.union([ MS.core.type.bitflags([SecondaryStructureType.Flag.Helix]) ]) }) -]), { category: StructureSelectionCategory.Structure }) +]), { category: StructureSelectionCategory.Structure }); const beta = StructureSelectionQuery('Beta Strand/Sheet', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -202,13 +202,13 @@ const beta = StructureSelectionQuery('Beta Strand/Sheet', MS.struct.modifier.uni MS.core.type.bitflags([SecondaryStructureType.Flag.Beta]) ]) }) -]), { category: StructureSelectionCategory.Structure }) +]), { category: StructureSelectionCategory.Structure }); const water = StructureSelectionQuery('Water', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'water']) }) -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); const branched = StructureSelectionQuery('Carbohydrate', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -223,20 +223,20 @@ const branched = StructureSelectionQuery('Carbohydrate', MS.struct.modifier.unio ]) ]) }) -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); const branchedPlusConnected = StructureSelectionQuery('Carbohydrate with Connected', MS.struct.modifier.union([ MS.struct.modifier.includeConnected({ 0: branched.expression, 'layer-count': 1, 'as-whole-residues': true }) -]), { category: StructureSelectionCategory.Internal }) +]), { category: StructureSelectionCategory.Internal }); const branchedConnectedOnly = StructureSelectionQuery('Connected to Carbohydrate', MS.struct.modifier.union([ MS.struct.modifier.exceptBy({ 0: branchedPlusConnected.expression, by: branched.expression }) -]), { category: StructureSelectionCategory.Internal }) +]), { category: StructureSelectionCategory.Internal }); const ligand = StructureSelectionQuery('Ligand', MS.struct.modifier.union([ MS.struct.combinator.merge([ @@ -270,7 +270,7 @@ const ligand = StructureSelectionQuery('Ligand', MS.struct.modifier.union([ }) ]) ]), -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); // don't include branched entities as they have their own link representation const ligandPlusConnected = StructureSelectionQuery('Ligand with Connected', MS.struct.modifier.union([ @@ -290,14 +290,14 @@ const ligandPlusConnected = StructureSelectionQuery('Ligand with Connected', MS. ]), by: branched.expression }) -]), { category: StructureSelectionCategory.Internal }) +]), { category: StructureSelectionCategory.Internal }); const ligandConnectedOnly = StructureSelectionQuery('Connected to Ligand', MS.struct.modifier.union([ MS.struct.modifier.exceptBy({ 0: ligandPlusConnected.expression, by: ligand.expression }) -]), { category: StructureSelectionCategory.Internal }) +]), { category: StructureSelectionCategory.Internal }); // residues connected to ligands or branched entities const connectedOnly = StructureSelectionQuery('Connected to Ligand or Carbohydrate', MS.struct.modifier.union([ @@ -305,7 +305,7 @@ const connectedOnly = StructureSelectionQuery('Connected to Ligand or Carbohydra branchedConnectedOnly.expression, ligandConnectedOnly.expression ]), -]), { category: StructureSelectionCategory.Internal }) +]), { category: StructureSelectionCategory.Internal }); const disulfideBridges = StructureSelectionQuery('Disulfide Bridges', MS.struct.modifier.union([ MS.struct.modifier.wholeResidues([ @@ -318,7 +318,7 @@ const disulfideBridges = StructureSelectionQuery('Disulfide Bridges', MS.struct. }) ]) ]) -]), { category: StructureSelectionCategory.Bond }) +]), { category: StructureSelectionCategory.Bond }); const nonStandardPolymer = StructureSelectionQuery('Non-standard Residues in Polymers', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -326,7 +326,7 @@ const nonStandardPolymer = StructureSelectionQuery('Non-standard Residues in Pol 'chain-test': MS.core.rel.eq([MS.ammp('objectPrimitive'), 'atomistic']), 'residue-test': MS.ammp('isNonStandard') }) -]), { category: StructureSelectionCategory.Residue }) +]), { category: StructureSelectionCategory.Residue }); const coarse = StructureSelectionQuery('Coarse Elements', MS.struct.modifier.union([ MS.struct.generator.atomGroups({ @@ -334,15 +334,15 @@ const coarse = StructureSelectionQuery('Coarse Elements', MS.struct.modifier.uni MS.set('sphere', 'gaussian'), MS.ammp('objectPrimitive') ]) }) -]), { category: StructureSelectionCategory.Type }) +]), { category: StructureSelectionCategory.Type }); const ring = StructureSelectionQuery('Rings in Residues', MS.struct.modifier.union([ MS.struct.generator.rings() -]), { category: StructureSelectionCategory.Residue }) +]), { category: StructureSelectionCategory.Residue }); const aromaticRing = StructureSelectionQuery('Aromatic Rings in Residues', MS.struct.modifier.union([ MS.struct.generator.rings({ 'only-aromatic': true }) -]), { category: StructureSelectionCategory.Residue }) +]), { category: StructureSelectionCategory.Residue }); const surroundings = StructureSelectionQuery('Surrounding Residues (5 \u212B) of Selection', MS.struct.modifier.union([ MS.struct.modifier.exceptBy({ @@ -357,7 +357,7 @@ const surroundings = StructureSelectionQuery('Surrounding Residues (5 \u212B) of description: 'Select residues within 5 \u212B of the current selection.', category: StructureSelectionCategory.Manipulate, referencesCurrent: true -}) +}); const complement = StructureSelectionQuery('Inverse / Complement of Selection', MS.struct.modifier.union([ MS.struct.modifier.exceptBy({ @@ -368,7 +368,7 @@ const complement = StructureSelectionQuery('Inverse / Complement of Selection', description: 'Select everything not in the current selection.', category: StructureSelectionCategory.Manipulate, referencesCurrent: true -}) +}); const bonded = StructureSelectionQuery('Residues Bonded to Selection', MS.struct.modifier.union([ MS.struct.modifier.includeConnected({ @@ -378,7 +378,7 @@ const bonded = StructureSelectionQuery('Residues Bonded to Selection', MS.struct description: 'Select residues covalently bonded to current selection.', category: StructureSelectionCategory.Manipulate, referencesCurrent: true -}) +}); const StandardAminoAcids = [ [['HIS'], 'HISTIDINE'], @@ -402,7 +402,7 @@ const StandardAminoAcids = [ [['THR'], 'THREONINE'], [['SEC'], 'SELENOCYSTEINE'], [['PYL'], 'PYRROLYSINE'], -].sort((a, b) => a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) as [string[], string][] +].sort((a, b) => a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) as [string[], string][]; const StandardNucleicBases = [ [['A', 'DA'], 'ADENOSINE'], @@ -411,14 +411,14 @@ const StandardNucleicBases = [ [['G', 'DG'], 'GUANOSINE'], [['I', 'DI'], 'INOSINE'], [['U', 'DU'], 'URIDINE'], -].sort((a, b) => a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) as [string[], string][] +].sort((a, b) => a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) as [string[], string][]; function ResidueQuery([names, label]: [string[], string], category: string) { return StructureSelectionQuery(`${stringToWords(label)} (${names.join(', ')})`, MS.struct.modifier.union([ MS.struct.generator.atomGroups({ 'residue-test': MS.core.set.has([MS.set(...names), MS.ammp('auth_comp_id')]) }) - ]), { category }) + ]), { category }); } export const StructureSelectionQueries = { @@ -447,7 +447,7 @@ export const StructureSelectionQueries = { surroundings, complement, bonded, -} +}; export function applyBuiltInSelection(to: StateBuilder.To<PluginStateObject.Molecule.Structure>, query: keyof typeof StructureSelectionQueries, customTag?: string) { return to.apply(StateTransforms.Model.StructureSelectionFromExpression, @@ -461,17 +461,17 @@ export class StructureSelectionQueryRegistry { version = 1 add(q: StructureSelectionQuery) { - this.list.push(q) - this.options.push([q, q.label, q.category]) - this.version += 1 + this.list.push(q); + this.options.push([q, q.label, q.category]); + this.version += 1; } remove(q: StructureSelectionQuery) { - const idx = this.list.indexOf(q) + const idx = this.list.indexOf(q); if (idx !== -1) { - this.list.splice(idx, 1) - this.options.splice(idx, 1) - this.version += 1 + this.list.splice(idx, 1); + this.options.splice(idx, 1); + this.version += 1; } } @@ -481,7 +481,7 @@ export class StructureSelectionQueryRegistry { ...Object.values(StructureSelectionQueries), ...StandardAminoAcids.map(v => ResidueQuery(v, StructureSelectionCategory.AminoAcid)), ...StandardNucleicBases.map(v => ResidueQuery(v, StructureSelectionCategory.NucleicBase)) - ) - this.options.push(...this.list.map(q => [q, q.label, q.category] as [StructureSelectionQuery, string, string])) + ); + this.options.push(...this.list.map(q => [q, q.label, q.category] as [StructureSelectionQuery, string, string])); } } \ No newline at end of file diff --git a/src/mol-plugin-state/manager/camera.ts b/src/mol-plugin-state/manager/camera.ts index 0bc67d39d552ff1607fdaa95affb0e1e1aded451..abd2df131f7b62398e9eb82bfe407155ecfd3a3d 100644 --- a/src/mol-plugin-state/manager/camera.ts +++ b/src/mol-plugin-state/manager/camera.ts @@ -17,7 +17,7 @@ const DefaultCameraFocusOptions = { minRadius: 5, extraRadius: 6, durationMs: 250 -} +}; export type CameraFocusOptions = typeof DefaultCameraFocusOptions @@ -89,11 +89,11 @@ export class CameraManager { if (options?.principalAxes) { const { origin, dirA, dirC } = options?.principalAxes.boxAxes; const snapshot = this.plugin.canvas3d?.camera.getFocus(origin, radius, dirA, dirC); - this.plugin.canvas3d?.requestCameraReset({ durationMs, snapshot }) + this.plugin.canvas3d?.requestCameraReset({ durationMs, snapshot }); // this.plugin.canvas3d?.camera.focus(origin, radius, durationMs, dirA, dirC); } else { const snapshot = this.plugin.canvas3d?.camera.getFocus(sphere.center, radius); - this.plugin.canvas3d?.requestCameraReset({ durationMs, snapshot }) + this.plugin.canvas3d?.requestCameraReset({ durationMs, snapshot }); // this.plugin.canvas3d?.camera.focus(sphere.center, radius, durationMs); } diff --git a/src/mol-plugin-state/manager/interactivity.ts b/src/mol-plugin-state/manager/interactivity.ts index b6ad3fd6bbe8d16ba66ae12774c98551aa582504..60f84fc332d8268ea0cc9edd13509dc39497919d 100644 --- a/src/mol-plugin-state/manager/interactivity.ts +++ b/src/mol-plugin-state/manager/interactivity.ts @@ -27,7 +27,7 @@ const DefaultInteractivityFocusOptions = { minRadius: 6, extraRadius: 6, durationMs: 250, -} +}; export type InteractivityFocusLociOptions = typeof DefaultInteractivityFocusOptions @@ -65,7 +65,7 @@ class InteractivityManager extends StatefulPluginComponent<InteractivityManagerS namespace InteractivityManager { export const Params = { granularity: PD.Select('residue', Loci.GranularityOptions, { label: 'Picking Level', description: 'Controls if selections are expanded upon picking to whole residues, chains, structures, instances, or left as atoms and coarse elements' }), - } + }; export type Params = typeof Params export type Props = PD.Values<Params> @@ -81,7 +81,7 @@ namespace InteractivityManager { readonly props: Readonly<Props> = PD.getDefaultValues(Params) setProps(props: Partial<Props>) { - Object.assign(this.props, props) + Object.assign(this.props, props); } addProvider(provider: LociMarkProvider) { @@ -94,9 +94,9 @@ namespace InteractivityManager { } protected normalizedLoci(reprLoci: Representation.Loci, applyGranularity = true) { - const { loci, repr } = reprLoci - const granularity = applyGranularity ? this.props.granularity : undefined - return { loci: Loci.normalize(loci, granularity), repr } + const { loci, repr } = reprLoci; + const granularity = applyGranularity ? this.props.granularity : undefined; + return { loci: Loci.normalize(loci, granularity), repr }; } protected mark(current: Representation.Loci, action: MarkerAction) { @@ -104,8 +104,8 @@ namespace InteractivityManager { } constructor(public readonly ctx: PluginContext, props: Partial<Props> = {}) { - this.sel = ctx.managers.structure.selection - this.setProps(props) + this.sel = ctx.managers.structure.selection; + this.setProps(props); } } @@ -116,48 +116,48 @@ namespace InteractivityManager { private isHighlighted(loci: Representation.Loci) { for (const p of this.prev) { - if (Representation.Loci.areEqual(p, loci)) return true + if (Representation.Loci.areEqual(p, loci)) return true; } - return false + return false; } private addHighlight(loci: Representation.Loci) { this.mark(loci, MarkerAction.Highlight); - this.prev.push(loci) + this.prev.push(loci); } clearHighlights = () => { for (const p of this.prev) { this.mark(p, MarkerAction.RemoveHighlight); } - this.prev.length = 0 + this.prev.length = 0; } highlight(current: Representation.Loci, applyGranularity = true) { - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (!this.isHighlighted(normalized)) { - this.addHighlight(normalized) + this.addHighlight(normalized); } } highlightOnly(current: Representation.Loci, applyGranularity = true) { - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (!this.isHighlighted(normalized)) { - this.clearHighlights() - this.addHighlight(normalized) + this.clearHighlights(); + this.addHighlight(normalized); } } highlightOnlyExtend(current: Representation.Loci, applyGranularity = true) { - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { const loci = { loci: this.sel.tryGetRange(normalized.loci) || normalized.loci, repr: normalized.repr - } + }; if (!this.isHighlighted(loci)) { - this.clearHighlights() - this.addHighlight(loci) + this.clearHighlights(); + this.addHighlight(loci); } } } @@ -169,7 +169,7 @@ namespace InteractivityManager { toggle(current: Representation.Loci, applyGranularity = true) { if (Loci.isEmpty(current.loci)) return; - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { this.toggleSel(normalized); } else { @@ -180,7 +180,7 @@ namespace InteractivityManager { toggleExtend(current: Representation.Loci, applyGranularity = true) { if (Loci.isEmpty(current.loci)) return; - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { const loci = this.sel.tryGetRange(normalized.loci) || normalized.loci; this.toggleSel({ loci, repr: normalized.repr }); @@ -188,7 +188,7 @@ namespace InteractivityManager { } select(current: Representation.Loci, applyGranularity = true) { - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { this.sel.modify('add', normalized.loci); } @@ -196,7 +196,7 @@ namespace InteractivityManager { } selectJoin(current: Representation.Loci, applyGranularity = true) { - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { this.sel.modify('intersect', normalized.loci); } @@ -204,8 +204,8 @@ namespace InteractivityManager { } selectOnly(current: Representation.Loci, applyGranularity = true) { - this.deselectAll() - const normalized = this.normalizedLoci(current, applyGranularity) + this.deselectAll(); + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { this.sel.modify('set', normalized.loci); } @@ -213,7 +213,7 @@ namespace InteractivityManager { } deselect(current: Representation.Loci, applyGranularity = true) { - const normalized = this.normalizedLoci(current, applyGranularity) + const normalized = this.normalizedLoci(current, applyGranularity); if (StructureElement.Loci.is(normalized.loci)) { this.sel.modify('remove', normalized.loci); } @@ -226,19 +226,19 @@ namespace InteractivityManager { } deselectAllOnEmpty(current: Representation.Loci) { - if (isEmptyLoci(current.loci)) this.deselectAll() + if (isEmptyLoci(current.loci)) this.deselectAll(); } protected mark(current: Representation.Loci, action: MarkerAction.Select | MarkerAction.Deselect) { - const { loci } = current + const { loci } = current; if (StructureElement.Loci.is(loci)) { // do a full deselect/select for the current structure so visuals that are // marked with granularity unequal to 'element' and join/intersect operations // are handled properly - super.mark({ loci: Structure.Loci(loci.structure) }, MarkerAction.Deselect) - super.mark({ loci: this.sel.getLoci(loci.structure) }, MarkerAction.Select) + super.mark({ loci: Structure.Loci(loci.structure) }, MarkerAction.Deselect); + super.mark({ loci: this.sel.getLoci(loci.structure) }, MarkerAction.Select); } else { - super.mark(current, action) + super.mark(current, action); } } diff --git a/src/mol-plugin-state/manager/loci-label.ts b/src/mol-plugin-state/manager/loci-label.ts index adabbd1c74657094076593b45169b22d24777336..5193912b4bf3ce11ed652f0da69791b1298ba1e3 100644 --- a/src/mol-plugin-state/manager/loci-label.ts +++ b/src/mol-plugin-state/manager/loci-label.ts @@ -24,27 +24,27 @@ export class LociLabelManager { addProvider(provider: LociLabelProvider) { this.providers.push(provider); - this.providers.sort((a, b) => (b.priority || 0) - (a.priority || 0)) - this.isDirty = true - this.showLabels() + this.providers.sort((a, b) => (b.priority || 0) - (a.priority || 0)); + this.isDirty = true; + this.showLabels(); } removeProvider(provider: LociLabelProvider) { this.providers = this.providers.filter(p => p !== provider); - this.isDirty = true - this.showLabels() + this.isDirty = true; + this.showLabels(); } private locis: Representation.Loci[] = [] private mark(loci: Representation.Loci, action: MarkerAction) { - const idx = this.locis.findIndex(l => Representation.Loci.areEqual(loci, l)) + const idx = this.locis.findIndex(l => Representation.Loci.areEqual(loci, l)); if (idx === -1 && action === MarkerAction.Highlight) { - this.locis.push(loci) - this.isDirty = true + this.locis.push(loci); + this.isDirty = true; } else if(idx !== -1 && action === MarkerAction.RemoveHighlight) { - arrayRemoveAtInPlace(this.locis, idx) - this.isDirty = true + arrayRemoveAtInPlace(this.locis, idx); + this.isDirty = true; } } @@ -53,42 +53,42 @@ export class LociLabelManager { private groupedLabels = new Map<string, LociLabel[]>() private showLabels() { - this.ctx.behaviors.labels.highlight.next({ labels: this.getLabels() }) + this.ctx.behaviors.labels.highlight.next({ labels: this.getLabels() }); } private getLabels() { if (this.isDirty) { - this.groupedLabels.clear() - this.labels.length = 0 + this.groupedLabels.clear(); + this.labels.length = 0; for (const provider of this.providers) { for (const loci of this.locis) { - if (Loci.isEmpty(loci.loci)) continue - const label = provider.label(loci.loci, loci.repr) + if (Loci.isEmpty(loci.loci)) continue; + const label = provider.label(loci.loci, loci.repr); if (label) { - const hash = provider.group ? provider.group(label) : label.toString() - const group = this.groupedLabels.get(hash) - if (group) group.push(label) - else this.groupedLabels.set(hash, [label]) + const hash = provider.group ? provider.group(label) : label.toString(); + const group = this.groupedLabels.get(hash); + if (group) group.push(label); + else this.groupedLabels.set(hash, [label]); } } } - this.labels.length = 0 + this.labels.length = 0; this.groupedLabels.forEach((group, hash) => { - const count = group.length + const count = group.length; const entry = count > 1 && group[0] !== group[1] - ? hash : group[0] + ? hash : group[0]; - this.labels.push(count === 1 ? entry : `${entry} <small>|| \u00D7 ${count}</small>`) - }) - this.isDirty = false + this.labels.push(count === 1 ? entry : `${entry} <small>|| \u00D7 ${count}</small>`); + }); + this.isDirty = false; } - return this.labels + return this.labels; } constructor(public ctx: PluginContext) { ctx.managers.interactivity.lociHighlights.addProvider((loci, action) => { - this.mark(loci, action) - this.showLabels() - }) + this.mark(loci, action); + this.showLabels(); + }); } } \ No newline at end of file diff --git a/src/mol-plugin-state/manager/structure/component.ts b/src/mol-plugin-state/manager/structure/component.ts index 87868522ada71f7ed7dd75f41dffc5de39e8d00c..75348ec35d4769a8e3cf87819c8bbfd3c013872a 100644 --- a/src/mol-plugin-state/manager/structure/component.ts +++ b/src/mol-plugin-state/manager/structure/component.ts @@ -164,7 +164,7 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone const mng = this.plugin.managers.structure.selection; mng.clear(); for (const c of components) { - const loci = Structure.toSubStructureElementLoci(c.structure.cell.obj!.data, c.cell.obj?.data!) + const loci = Structure.toSubStructureElementLoci(c.structure.cell.obj!.data, c.cell.obj?.data!); mng.fromLoci('set', loci); } } @@ -203,7 +203,7 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone // TODO: is it ok to use just the index here? Could possible lead to ugly edge cases, but perhaps not worth the trouble to "fix". const repr = c.representations[index]; if (!repr) continue; - setSubtreeVisibility(this.dataState, repr.cell.transform.ref, isHidden) + setSubtreeVisibility(this.dataState, repr.cell.transform.ref, isHidden); } } } @@ -369,7 +369,7 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone nullIfEmpty: true, label: component.cell.obj?.label! }; - builder.to(component.cell).update(params) + builder.to(component.cell).update(params); } } @@ -388,7 +388,7 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone } constructor(public plugin: PluginContext) { - super({ options: PD.getDefaultValues(StructureComponentManager.OptionsParams) }) + super({ options: PD.getDefaultValues(StructureComponentManager.OptionsParams) }); } } @@ -397,11 +397,11 @@ namespace StructureComponentManager { showHydrogens: PD.Boolean(true, { description: 'Toggle display of hydrogen atoms in representations' }), visualQuality: PD.Select('auto', VisualQualityOptions, { description: 'Control the visual/rendering quality of representations' }), interactions: PD.Group(InteractionsProvider.defaultParams, { label: 'Non-covalent Interactions' }), - } + }; export type Options = PD.Values<typeof OptionsParams> export function getAddParams(plugin: PluginContext) { - const { options } = plugin.query.structure.registry + const { options } = plugin.query.structure.registry; return { selection: PD.Select(options[1][0], options), representation: getRepresentationTypesSelect(plugin, plugin.managers.structure.component.pivotStructure, [['none', '< Create Later >']]), diff --git a/src/mol-plugin-state/manager/structure/focus.ts b/src/mol-plugin-state/manager/structure/focus.ts index 7e0736d492a15b6b60d913d68105599f3d7c9d17..b23445a30dc673a5188018f0fec191133cb48a78 100644 --- a/src/mol-plugin-state/manager/structure/focus.ts +++ b/src/mol-plugin-state/manager/structure/focus.ts @@ -65,34 +65,34 @@ export class StructureFocusManager extends StatefulPluginComponent<StructureFocu } set(entry: FocusEntry) { - this.tryAddHistory(entry) + this.tryAddHistory(entry); if (!this.state.current || !StructureElement.Loci.areEqual(this.state.current.loci, entry.loci)) { - this.state.current = entry - this.behaviors.current.next(entry) + this.state.current = entry; + this.behaviors.current.next(entry); } } setFromLoci(anyLoci: Loci) { - const loci = Loci.normalize(anyLoci) + const loci = Loci.normalize(anyLoci); if (!StructureElement.Loci.is(loci) || StructureElement.Loci.isEmpty(loci)) { - this.clear() - return + this.clear(); + return; } - this.set({ loci, label: lociLabel(loci, { reverse: true, hidePrefix: true, htmlStyling: false }) }) + this.set({ loci, label: lociLabel(loci, { reverse: true, hidePrefix: true, htmlStyling: false }) }); } addFromLoci(anyLoci: Loci) { const union = this.state.current && StructureElement.Loci.is(anyLoci) ? StructureElement.Loci.union(anyLoci, this.state.current.loci) - : anyLoci - this.setFromLoci(union) + : anyLoci; + this.setFromLoci(union); } clear() { if (this.state.current) { - this.state.current = undefined - this.behaviors.current.next(void 0) + this.state.current = undefined; + this.behaviors.current.next(void 0); } } @@ -107,20 +107,20 @@ export class StructureFocusManager extends StatefulPluginComponent<StructureFocu super({ history: [] }); plugin.state.data.events.object.removed.subscribe(o => { - if (!PluginStateObject.Molecule.Structure.is(o.obj)) return + if (!PluginStateObject.Molecule.Structure.is(o.obj)) return; if (this.current?.loci.structure === o.obj.data) { - this.clear() + this.clear(); } - const keep: FocusEntry[] = [] + const keep: FocusEntry[] = []; for (const e of this.history) { - if (e.loci.structure === o.obj.data) keep.push(e) + if (e.loci.structure === o.obj.data) keep.push(e); } if (keep.length !== this.history.length) { - this.history.length = 0 - this.history.push(...keep) - this.events.historyUpdated.next() + this.history.length = 0; + this.history.push(...keep); + this.events.historyUpdated.next(); } }); // plugin.state.data.events.object.updated.subscribe(e => this.onUpdate(e.ref, e.oldObj, e.obj)); diff --git a/src/mol-plugin-state/manager/structure/hierarchy-state.ts b/src/mol-plugin-state/manager/structure/hierarchy-state.ts index 988c2640ac934f59777f60c4e098591f9c671583..7c3a9f60595a0b30f2738d3dfaf0cd17e8af6f51 100644 --- a/src/mol-plugin-state/manager/structure/hierarchy-state.ts +++ b/src/mol-plugin-state/manager/structure/hierarchy-state.ts @@ -25,7 +25,7 @@ export interface StructureHierarchy { } export function StructureHierarchy(): StructureHierarchy { - return { trajectories: [], models: [], structures: [], refs: new Map() } + return { trajectories: [], models: [], structures: [], refs: new Map() }; } interface RefBase<K extends string = string, O extends StateObject = StateObject, T extends StateTransformer = StateTransformer> { @@ -258,7 +258,7 @@ const Mapping: [TestCell, ApplyRef, LeaveRef][] = [ // Component Representation [(cell, state) => { - return !cell.state.isGhost && !!state.currentComponent && SO.Molecule.Structure.Representation3D.is(cell.obj) + return !cell.state.isGhost && !!state.currentComponent && SO.Molecule.Structure.Representation3D.is(cell.obj); }, (state, cell) => { if (state.currentComponent) { createOrUpdateRefList(state, cell, state.currentComponent.representations, StructureRepresentationRef, cell, state.currentComponent); @@ -276,7 +276,7 @@ const Mapping: [TestCell, ApplyRef, LeaveRef][] = [ createOrUpdateRefList(state, cell, genericTarget.genericRepresentations, GenericRepresentationRef, cell, genericTarget); } }, noop], -] +]; function isValidCell(cell?: StateObjectCell): cell is StateObjectCell { if (!cell || !cell?.parent || !cell.parent.cells.has(cell.transform.ref)) return false; diff --git a/src/mol-plugin-state/manager/structure/measurement.ts b/src/mol-plugin-state/manager/structure/measurement.ts index 75b201739fac0be94dc658dcbe38c5d6ba645c3f..d7a6125c3bc8051d0ec2ce550e74b2656b038e34 100644 --- a/src/mol-plugin-state/manager/structure/measurement.ts +++ b/src/mol-plugin-state/manager/structure/measurement.ts @@ -15,7 +15,7 @@ import { StatefulPluginComponent } from '../../component'; import { ParamDefinition as PD } from '../../../mol-util/param-definition'; import { MeasurementRepresentationCommonTextParams } from '../../../mol-repr/shape/loci/common'; -export { StructureMeasurementManager } +export { StructureMeasurementManager }; export const MeasurementGroupTag = 'measurement-group'; @@ -24,8 +24,8 @@ export type StructureMeasurementCell = StateObjectCell<PluginStateObject.Shape.R export const StructureMeasurementParams = { distanceUnitLabel: PD.Text('\u212B', { isEssential: true }), textColor: MeasurementRepresentationCommonTextParams.textColor -} -const DefaultStructureMeasurementOptions = PD.getDefaultValues(StructureMeasurementParams) +}; +const DefaultStructureMeasurementOptions = PD.getDefaultValues(StructureMeasurementParams); export type StructureMeasurementOptions = PD.ValuesFor<typeof StructureMeasurementParams> export interface StructureMeasurementManagerState { @@ -102,7 +102,7 @@ class StructureMeasurementManager extends StatefulPluginComponent<StructureMeasu .apply(StateTransforms.Representation.StructureSelectionsDistance3D, { unitLabel: this.state.options.distanceUnitLabel, textColor: this.state.options.textColor - }) + }); const state = this.plugin.state.data; await PluginCommands.State.Update(this.plugin, { state, tree: update, options: { doNotLogTiming: true } }); @@ -132,7 +132,7 @@ class StructureMeasurementManager extends StatefulPluginComponent<StructureMeasu }, { dependsOn }) .apply(StateTransforms.Representation.StructureSelectionsAngle3D, { textColor: this.state.options.textColor - }) + }); const state = this.plugin.state.data; await PluginCommands.State.Update(this.plugin, { state, tree: update, options: { doNotLogTiming: true } }); @@ -165,7 +165,7 @@ class StructureMeasurementManager extends StatefulPluginComponent<StructureMeasu }, { dependsOn }) .apply(StateTransforms.Representation.StructureSelectionsDihedral3D, { textColor: this.state.options.textColor - }) + }); const state = this.plugin.state.data; await PluginCommands.State.Update(this.plugin, { state, tree: update, options: { doNotLogTiming: true } }); @@ -189,7 +189,7 @@ class StructureMeasurementManager extends StatefulPluginComponent<StructureMeasu }, { dependsOn }) .apply(StateTransforms.Representation.StructureSelectionsLabel3D, { textColor: this.state.options.textColor - }) + }); const state = this.plugin.state.data; await PluginCommands.State.Update(this.plugin, { state, tree: update, options: { doNotLogTiming: true } }); @@ -211,7 +211,7 @@ class StructureMeasurementManager extends StatefulPluginComponent<StructureMeasu isTransitive: true, label: 'Orientation' }, { dependsOn }) - .apply(StateTransforms.Representation.StructureSelectionsOrientation3D) + .apply(StateTransforms.Representation.StructureSelectionsOrientation3D); const state = this.plugin.state.data; await PluginCommands.State.Update(this.plugin, { state, tree: update, options: { doNotLogTiming: true } }); diff --git a/src/mol-plugin-state/manager/structure/selection.ts b/src/mol-plugin-state/manager/structure/selection.ts index 8aac59c6eba8d17122c0315c7eb56f8000bf7e72..8cc04223ad9a650087884eefeeb59209466e800e 100644 --- a/src/mol-plugin-state/manager/structure/selection.ts +++ b/src/mol-plugin-state/manager/structure/selection.ts @@ -63,24 +63,24 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure } private calcStats(): SelectionStats { - let structureCount = 0 - let elementCount = 0 - const stats = StructureElement.Stats.create() + let structureCount = 0; + let elementCount = 0; + const stats = StructureElement.Stats.create(); this.entries.forEach(v => { - const { elements } = v.selection + const { elements } = v.selection; if (elements.length) { - structureCount += 1 + structureCount += 1; for (let i = 0, il = elements.length; i < il; ++i) { - elementCount += OrderedSet.size(elements[i].indices) + elementCount += OrderedSet.size(elements[i].indices); } - StructureElement.Stats.add(stats, stats, StructureElement.Stats.ofLoci(v.selection)) + StructureElement.Stats.add(stats, stats, StructureElement.Stats.ofLoci(v.selection)); } - }) + }); - const label = structureElementStatsLabel(stats, { countsOnly: true }) + const label = structureElementStatsLabel(stats, { countsOnly: true }); - return { structureCount, elementCount, label } + return { structureCount, elementCount, label }; } private add(loci: Loci): boolean { @@ -92,7 +92,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure const sel = entry.selection; entry.selection = StructureElement.Loci.union(entry.selection, loci); this.tryAddHistory(loci); - this.referenceLoci = loci + this.referenceLoci = loci; return !StructureElement.Loci.areEqual(sel, entry.selection); } @@ -105,7 +105,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure const sel = entry.selection; entry.selection = StructureElement.Loci.subtract(entry.selection, loci); // this.addHistory(loci); - this.referenceLoci = loci + this.referenceLoci = loci; return !StructureElement.Loci.areEqual(sel, entry.selection); } @@ -118,7 +118,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure const sel = entry.selection; entry.selection = StructureElement.Loci.intersect(entry.selection, loci); // this.addHistory(loci); - this.referenceLoci = loci + this.referenceLoci = loci; return !StructureElement.Loci.areEqual(sel, entry.selection); } @@ -194,7 +194,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure this.entries.delete(ref); // TODO: property update the latest loci this.state.additionsHistory = []; - this.referenceLoci = undefined + this.referenceLoci = undefined; } } @@ -206,7 +206,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure // TODO: property update the latest loci & reference loci this.state.additionsHistory = []; - this.referenceLoci = undefined + this.referenceLoci = undefined; // remap the old selection to be related to the new object if possible. if (Structure.areUnitAndIndicesEqual(oldObj.data, obj.data)) { @@ -267,7 +267,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure const xs = loci.elements[0]; if (!xs) return; - const ref = this.referenceLoci + const ref = this.referenceLoci; if (!ref || !StructureElement.Loci.is(ref) || ref.structure.root !== loci.structure.root) return; let e: StructureElement.Loci['elements'][0] | undefined; @@ -281,7 +281,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure if (xs.unit !== e.unit) return; - return getElementRange(loci.structure.root, e, xs) + return getElementRange(loci.structure.root, e, xs); } private prevHighlight: StructureElement.Loci | undefined = void 0; @@ -305,32 +305,32 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure /** Count of all selected elements */ elementCount() { - let count = 0 + let count = 0; this.entries.forEach(v => { - count += StructureElement.Loci.size(v.selection) - }) - return count + count += StructureElement.Loci.size(v.selection); + }); + return count; } getBoundary() { - const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE) - const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE) + const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE); + const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE); boundaryHelper.reset(); - const boundaries: Boundary[] = [] + const boundaries: Boundary[] = []; this.entries.forEach(v => { - const loci = v.selection + const loci = v.selection; if (!StructureElement.Loci.isEmpty(loci)) { - boundaries.push(StructureElement.Loci.getBoundary(loci)) + boundaries.push(StructureElement.Loci.getBoundary(loci)); } - }) + }); for (let i = 0, il = boundaries.length; i < il; ++i) { const { box, sphere } = boundaries[i]; Vec3.min(min, min, box.min); Vec3.max(max, max, box.max); - boundaryHelper.includePositionRadius(sphere.center, sphere.radius) + boundaryHelper.includePositionRadius(sphere.center, sphere.radius); } boundaryHelper.finishedIncludeStep(); for (let i = 0, il = boundaries.length; i < il; ++i) { @@ -342,14 +342,14 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure } getPrincipalAxes(): PrincipalAxes { - const elementCount = this.elementCount() - const positions = new Float32Array(3 * elementCount) - let offset = 0 + const elementCount = this.elementCount(); + const positions = new Float32Array(3 * elementCount); + let offset = 0; this.entries.forEach(v => { - StructureElement.Loci.toPositionsArray(v.selection, positions, offset) - offset += StructureElement.Loci.size(v.selection) * 3 - }) - return PrincipalAxes.ofPositions(positions) + StructureElement.Loci.toPositionsArray(v.selection, positions, offset); + offset += StructureElement.Loci.size(v.selection) * 3; + }); + return PrincipalAxes.ofPositions(positions); } modify(modifier: StructureSelectionModifier, loci: Loci) { @@ -376,17 +376,17 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure private triggerInteraction(modifier: StructureSelectionModifier, loci: Loci, applyGranularity = true) { switch (modifier) { case 'add': - this.plugin.managers.interactivity.lociSelects.select({ loci }, applyGranularity) - break + this.plugin.managers.interactivity.lociSelects.select({ loci }, applyGranularity); + break; case 'remove': - this.plugin.managers.interactivity.lociSelects.deselect({ loci }, applyGranularity) - break + this.plugin.managers.interactivity.lociSelects.deselect({ loci }, applyGranularity); + break; case 'intersect': - this.plugin.managers.interactivity.lociSelects.selectJoin({ loci }, applyGranularity) - break + this.plugin.managers.interactivity.lociSelects.selectJoin({ loci }, applyGranularity); + break; case 'set': - this.plugin.managers.interactivity.lociSelects.selectOnly({ loci }, applyGranularity) - break + this.plugin.managers.interactivity.lociSelects.selectOnly({ loci }, applyGranularity); + break; } } @@ -400,7 +400,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure const loci = await query.getSelection(this.plugin, runtime, s); this.triggerInteraction(modifier, StructureSelection.toLociWithSourceUnits(loci), applyGranularity); } - })) + })); } fromSelections(ref: StateObjectRef<PluginStateObject.Molecule.Structure.Selections>) { @@ -432,7 +432,7 @@ interface SelectionStats { label: string } -function SelectionStats(): SelectionStats { return { structureCount: 0, elementCount: 0, label: 'Nothing Selected' } }; +function SelectionStats(): SelectionStats { return { structureCount: 0, elementCount: 0, label: 'Nothing Selected' }; }; class SelectionEntry { private _selection: StructureElement.Loci; @@ -441,7 +441,7 @@ class SelectionEntry { get selection() { return this._selection; } set selection(value: StructureElement.Loci) { this._selection = value; - this._structure = void 0 + this._structure = void 0; } get structure(): Structure | undefined { @@ -474,8 +474,8 @@ function remapSelectionEntry(e: SelectionEntry, s: Structure): SelectionEntry { * Assumes `ref` and `ext` belong to the same unit in the same structure */ function getElementRange(structure: Structure, ref: StructureElement.Loci['elements'][0], ext: StructureElement.Loci['elements'][0]) { - const min = Math.min(OrderedSet.min(ref.indices), OrderedSet.min(ext.indices)) - const max = Math.max(OrderedSet.max(ref.indices), OrderedSet.max(ext.indices)) + const min = Math.min(OrderedSet.min(ref.indices), OrderedSet.min(ext.indices)); + const max = Math.max(OrderedSet.max(ref.indices), OrderedSet.max(ext.indices)); return StructureElement.Loci(structure, [{ unit: ref.unit, diff --git a/src/mol-plugin-state/objects.ts b/src/mol-plugin-state/objects.ts index 56ab4699c818310e08d4b0c55de3822f060b3c43..d020f0ec0bef815872bb7434b51b0a0754e6c9b8 100644 --- a/src/mol-plugin-state/objects.ts +++ b/src/mol-plugin-state/objects.ts @@ -46,7 +46,7 @@ export namespace PluginStateObject { } export function CreateBehavior<T extends PluginBehavior>(type: { name: string }) { - return Create<T>({ ...type, typeClass: 'Behavior' }) + return Create<T>({ ...type, typeClass: 'Behavior' }); } export class Root extends Create({ name: 'Root', typeClass: 'Root' }) { } diff --git a/src/mol-plugin-state/snapshots.ts b/src/mol-plugin-state/snapshots.ts index 9ae2b8ad4b4a05107e5fbeb6b95db8525db801a7..d6c325634364753192d2a1b16ca094f8c11339e6 100644 --- a/src/mol-plugin-state/snapshots.ts +++ b/src/mol-plugin-state/snapshots.ts @@ -10,7 +10,7 @@ import { PluginState } from '../mol-plugin/state'; import { StatefulPluginComponent } from './component'; import { PluginContext } from '../mol-plugin/context'; -export { PluginStateSnapshotManager } +export { PluginStateSnapshotManager }; class PluginStateSnapshotManager extends StatefulPluginComponent<{ current?: UUID | undefined, @@ -126,7 +126,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{ async setRemoteSnapshot(snapshot: PluginStateSnapshotManager.RemoteSnapshot): Promise<PluginState.Snapshot | undefined> { this.clear(); - const entries = List<PluginStateSnapshotManager.Entry>().asMutable() + const entries = List<PluginStateSnapshotManager.Entry>().asMutable(); for (const e of snapshot.entries) { this.entryMap.set(e.snapshot.id, e); entries.push(e); diff --git a/src/mol-plugin-state/transforms.ts b/src/mol-plugin-state/transforms.ts index 7a868aad7837d20ddc1bc8dd2e2f9785bc37486f..0c98e21b1790e31653115e608c801b1030defd49 100644 --- a/src/mol-plugin-state/transforms.ts +++ b/src/mol-plugin-state/transforms.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Data from './transforms/data' -import * as Misc from './transforms/misc' -import * as Model from './transforms/model' -import * as Volume from './transforms/volume' -import * as Representation from './transforms/representation' +import * as Data from './transforms/data'; +import * as Misc from './transforms/misc'; +import * as Model from './transforms/model'; +import * as Volume from './transforms/volume'; +import * as Representation from './transforms/representation'; export const StateTransforms = { Data, @@ -16,6 +16,6 @@ export const StateTransforms = { Model, Volume, Representation -} +}; export type StateTransforms = typeof StateTransforms \ No newline at end of file diff --git a/src/mol-plugin-state/transforms/data.ts b/src/mol-plugin-state/transforms/data.ts index b588dd00f0feeda11a281d76d1e5f438fc157be4..10f08680cd820a59ca5ec604af842405989fef06 100644 --- a/src/mol-plugin-state/transforms/data.ts +++ b/src/mol-plugin-state/transforms/data.ts @@ -8,18 +8,18 @@ import { PluginStateTransform } from '../objects'; import { PluginStateObject as SO } from '../objects'; import { Task } from '../../mol-task'; -import { CIF } from '../../mol-io/reader/cif' +import { CIF } from '../../mol-io/reader/cif'; import { PluginContext } from '../../mol-plugin/context'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { StateTransformer, StateObject } from '../../mol-state'; import { readFromFile, ajaxGetMany } from '../../mol-util/data-source'; -import * as CCP4 from '../../mol-io/reader/ccp4/parser' -import * as DSN6 from '../../mol-io/reader/dsn6/parser' -import * as PLY from '../../mol-io/reader/ply/parser' +import * as CCP4 from '../../mol-io/reader/ccp4/parser'; +import * as DSN6 from '../../mol-io/reader/dsn6/parser'; +import * as PLY from '../../mol-io/reader/ply/parser'; import { parsePsf } from '../../mol-io/reader/psf/parser'; import { isTypedArray } from '../../mol-data/db/column-helpers'; -export { Download } +export { Download }; type Download = typeof Download const Download = PluginStateTransform.BuiltIn({ name: 'download', @@ -51,7 +51,7 @@ const Download = PluginStateTransform.BuiltIn({ } }); -export { DownloadBlob } +export { DownloadBlob }; type DownloadBlob = typeof DownloadBlob const DownloadBlob = PluginStateTransform.BuiltIn({ name: 'download-blob', @@ -98,7 +98,7 @@ const DownloadBlob = PluginStateTransform.BuiltIn({ // } }); -export { RawData } +export { RawData }; type RawData = typeof RawData const RawData = PluginStateTransform.BuiltIn({ name: 'raw-data', @@ -130,7 +130,7 @@ const RawData = PluginStateTransform.BuiltIn({ } }); -export { ReadFile } +export { ReadFile }; type ReadFile = typeof ReadFile const ReadFile = PluginStateTransform.BuiltIn({ name: 'read-file', @@ -146,7 +146,7 @@ const ReadFile = PluginStateTransform.BuiltIn({ apply({ params: p }, plugin: PluginContext) { return Task.create('Open File', async ctx => { if (p.file === null) { - plugin.log.error('No file(s) selected') + plugin.log.error('No file(s) selected'); return StateObject.Null; } const data = await readFromFile(p.file, p.isBinary ? 'binary' : 'string').runInContext(ctx); @@ -165,7 +165,7 @@ const ReadFile = PluginStateTransform.BuiltIn({ isSerializable: () => ({ isSerializable: false, reason: 'Cannot serialize user loaded files.' }) }); -export { ParseBlob } +export { ParseBlob }; type ParseBlob = typeof ParseBlob const ParseBlob = PluginStateTransform.BuiltIn({ name: 'parse-blob', @@ -209,7 +209,7 @@ const ParseBlob = PluginStateTransform.BuiltIn({ // } }); -export { ParseCif } +export { ParseCif }; type ParseCif = typeof ParseCif const ParseCif = PluginStateTransform.BuiltIn({ name: 'parse-cif', @@ -226,7 +226,7 @@ const ParseCif = PluginStateTransform.BuiltIn({ } }); -export { ParsePsf } +export { ParsePsf }; type ParsePsf = typeof ParsePsf const ParsePsf = PluginStateTransform.BuiltIn({ name: 'parse-psf', @@ -243,7 +243,7 @@ const ParsePsf = PluginStateTransform.BuiltIn({ } }); -export { ParsePly } +export { ParsePly }; type ParsePly = typeof ParsePly const ParsePly = PluginStateTransform.BuiltIn({ name: 'parse-ply', @@ -260,7 +260,7 @@ const ParsePly = PluginStateTransform.BuiltIn({ } }); -export { ParseCcp4 } +export { ParseCcp4 }; type ParseCcp4 = typeof ParseCcp4 const ParseCcp4 = PluginStateTransform.BuiltIn({ name: 'parse-ccp4', @@ -277,7 +277,7 @@ const ParseCcp4 = PluginStateTransform.BuiltIn({ } }); -export { ParseDsn6 } +export { ParseDsn6 }; type ParseDsn6 = typeof ParseDsn6 const ParseDsn6 = PluginStateTransform.BuiltIn({ name: 'parse-dsn6', @@ -294,7 +294,7 @@ const ParseDsn6 = PluginStateTransform.BuiltIn({ } }); -export { ImportString } +export { ImportString }; type ImportString = typeof ImportString const ImportString = PluginStateTransform.BuiltIn({ name: 'import-string', @@ -320,7 +320,7 @@ const ImportString = PluginStateTransform.BuiltIn({ isSerializable: () => ({ isSerializable: false, reason: 'Cannot serialize user imported strings.' }) }); -export { ImportJson } +export { ImportJson }; type ImportJson = typeof ImportJson const ImportJson = PluginStateTransform.BuiltIn({ name: 'import-json', @@ -346,7 +346,7 @@ const ImportJson = PluginStateTransform.BuiltIn({ isSerializable: () => ({ isSerializable: false, reason: 'Cannot serialize user imported JSON.' }) }); -export { ParseJson } +export { ParseJson }; type ParseJson = typeof ParseJson const ParseJson = PluginStateTransform.BuiltIn({ name: 'parse-json', @@ -357,7 +357,7 @@ const ParseJson = PluginStateTransform.BuiltIn({ apply({ a }) { return Task.create('Parse JSON', async ctx => { const json = await (new Response(a.data)).json(); // async JSON parsing via fetch API - return new SO.Format.Json(json) + return new SO.Format.Json(json); }); } }); \ No newline at end of file diff --git a/src/mol-plugin-state/transforms/helpers.ts b/src/mol-plugin-state/transforms/helpers.ts index f2732fd750d248d55f7b6163c9751e28c04a354f..bc12da993e2710108033229af7670867fb420389 100644 --- a/src/mol-plugin-state/transforms/helpers.ts +++ b/src/mol-plugin-state/transforms/helpers.ts @@ -12,32 +12,32 @@ import { AngleData } from '../../mol-repr/shape/loci/angle'; import { DihedralData } from '../../mol-repr/shape/loci/dihedral'; export function getDistanceDataFromStructureSelections(s: ReadonlyArray<PluginStateObject.Molecule.Structure.SelectionEntry>): DistanceData { - const lociA = s[0].loci - const lociB = s[1].loci - return { pairs: [ { loci: [lociA, lociB] as const }] } + const lociA = s[0].loci; + const lociB = s[1].loci; + return { pairs: [ { loci: [lociA, lociB] as const }] }; } export function getAngleDataFromStructureSelections(s: ReadonlyArray<PluginStateObject.Molecule.Structure.SelectionEntry>): AngleData { - const lociA = s[0].loci - const lociB = s[1].loci - const lociC = s[2].loci - return { triples: [{ loci: [lociA, lociB, lociC] as const }] } + const lociA = s[0].loci; + const lociB = s[1].loci; + const lociC = s[2].loci; + return { triples: [{ loci: [lociA, lociB, lociC] as const }] }; } export function getDihedralDataFromStructureSelections(s: ReadonlyArray<PluginStateObject.Molecule.Structure.SelectionEntry>): DihedralData { - const lociA = s[0].loci - const lociB = s[1].loci - const lociC = s[2].loci - const lociD = s[3].loci - return { quads: [{ loci: [lociA, lociB, lociC, lociD] as const }] } + const lociA = s[0].loci; + const lociB = s[1].loci; + const lociC = s[2].loci; + const lociD = s[3].loci; + return { quads: [{ loci: [lociA, lociB, lociC, lociD] as const }] }; } export function getLabelDataFromStructureSelections(s: ReadonlyArray<PluginStateObject.Molecule.Structure.SelectionEntry>): LabelData { - const loci = s[0].loci - return { infos: [{ loci }] } + const loci = s[0].loci; + return { infos: [{ loci }] }; } export function getOrientationDataFromStructureSelections(s: ReadonlyArray<PluginStateObject.Molecule.Structure.SelectionEntry>): OrientationData { - const loci = s[0].loci - return { locis: [loci] } + const loci = s[0].loci; + return { locis: [loci] }; } \ No newline at end of file diff --git a/src/mol-plugin-state/transforms/model.ts b/src/mol-plugin-state/transforms/model.ts index 2e0839e8fe2743e40aef426116d462d504da3ffc..5e624419f7c140f80f656610202306d98f7c8824 100644 --- a/src/mol-plugin-state/transforms/model.ts +++ b/src/mol-plugin-state/transforms/model.ts @@ -95,13 +95,13 @@ const TopologyFromPsf = PluginStateTransform.BuiltIn({ async function getTrajectory(ctx: RuntimeContext, obj: StateObject, coordinates: Coordinates) { if (obj.type === SO.Molecule.Topology.type) { - const topology = obj.data as Topology + const topology = obj.data as Topology; return await Model.trajectoryFromTopologyAndCoordinates(topology, coordinates).runInContext(ctx); } else if (obj.type === SO.Molecule.Model.type) { - const model = obj.data as Model + const model = obj.data as Model; return Model.trajectoryFromModelAndCoordinates(model, coordinates); } - throw new Error('no model/topology found') + throw new Error('no model/topology found'); } type TrajectoryFromModelAndCoordinates = typeof TrajectoryFromModelAndCoordinates @@ -117,7 +117,7 @@ const TrajectoryFromModelAndCoordinates = PluginStateTransform.BuiltIn({ })({ apply({ params, dependencies }) { return Task.create('Create trajectory from model/topology and coordinates', async ctx => { - const coordinates = dependencies![params.coordinatesRef].data as Coordinates + const coordinates = dependencies![params.coordinatesRef].data as Coordinates; const trajectory = await getTrajectory(ctx, dependencies![params.modelRef], coordinates); const props = { label: 'Trajectory', description: `${trajectory.length} model${trajectory.length === 1 ? '' : 's'}` }; return new SO.Molecule.Trajectory(trajectory, props); @@ -295,7 +295,7 @@ const ModelFromTrajectory = PluginStateTransform.BuiltIn({ if (!a) { return { modelIndex: PD.Numeric(0, {}, { description: 'Zero-based index of the model' }) }; } - return { modelIndex: PD.Converted(plus1, minus1, PD.Numeric(1, { min: 1, max: a.data.length, step: 1 }, { description: 'Model Index' })) } + return { modelIndex: PD.Converted(plus1, minus1, PD.Numeric(1, { min: 1, max: a.data.length, step: 1 }, { description: 'Model Index' })) }; } })({ isApplicable: a => a.data.length > 0, @@ -321,7 +321,7 @@ const StructureFromTrajectory = PluginStateTransform.BuiltIn({ const s = Structure.ofTrajectory(a.data); const props = { label: 'Ensemble', description: Structure.elementDescription(s) }; return new SO.Molecule.Structure(s, props); - }) + }); } }); @@ -339,7 +339,7 @@ const StructureFromModel = PluginStateTransform.BuiltIn({ apply({ a, params }, plugin: PluginContext) { return Task.create('Build Structure', async ctx => { return RootStructureDefinition.create(plugin, ctx, a.data, params && params.type); - }) + }); }, update: ({ a, b, oldParams, newParams }) => { if (!b.data.models.includes(a.data)) return StateTransformer.UpdateResult.Recreate; @@ -711,7 +711,7 @@ export const StructureComplexElementTypes = { 'atomic-sequence': 'atomic-sequence', 'atomic-het': 'atomic-het', 'spheres': 'spheres' -} as const +} as const; export type StructureComplexElementTypes = keyof typeof StructureComplexElementTypes const StructureComplexElementTypeTuples = PD.objectToOptions(StructureComplexElementTypes); @@ -781,7 +781,7 @@ const CustomModelProperties = PluginStateTransform.BuiltIn({ from: SO.Molecule.Model, to: SO.Molecule.Model, params: (a, ctx: PluginContext) => { - return ctx.customModelProperties.getParams(a?.data) + return ctx.customModelProperties.getParams(a?.data); } })({ apply({ a, params }, ctx: PluginContext) { @@ -806,19 +806,19 @@ const CustomModelProperties = PluginStateTransform.BuiltIn({ } }); async function attachModelProps(model: Model, ctx: PluginContext, taskCtx: RuntimeContext, params: ReturnType<CustomModelProperties['createDefaultParams']>) { - const propertyCtx = { runtime: taskCtx, fetch: ctx.fetch } - const { autoAttach, properties } = params + const propertyCtx = { runtime: taskCtx, fetch: ctx.fetch }; + const { autoAttach, properties } = params; for (const name of Object.keys(properties)) { - const property = ctx.customModelProperties.get(name) - const props = properties[name] + const property = ctx.customModelProperties.get(name); + const props = properties[name]; if (autoAttach.includes(name)) { try { - await property.attach(propertyCtx, model, props, true) + await property.attach(propertyCtx, model, props, true); } catch (e) { ctx.log.warn(`Error attaching model prop '${name}': ${e}`); } } else { - property.set(model, props) + property.set(model, props); } } } @@ -831,7 +831,7 @@ const CustomStructureProperties = PluginStateTransform.BuiltIn({ from: SO.Molecule.Structure, to: SO.Molecule.Structure, params: (a, ctx: PluginContext) => { - return ctx.customStructureProperties.getParams(a?.data.root) + return ctx.customStructureProperties.getParams(a?.data.root); } })({ apply({ a, params }, ctx: PluginContext) { @@ -856,19 +856,19 @@ const CustomStructureProperties = PluginStateTransform.BuiltIn({ } }); async function attachStructureProps(structure: Structure, ctx: PluginContext, taskCtx: RuntimeContext, params: ReturnType<CustomStructureProperties['createDefaultParams']>) { - const propertyCtx = { runtime: taskCtx, fetch: ctx.fetch } - const { autoAttach, properties } = params + const propertyCtx = { runtime: taskCtx, fetch: ctx.fetch }; + const { autoAttach, properties } = params; for (const name of Object.keys(properties)) { - const property = ctx.customStructureProperties.get(name) - const props = properties[name] + const property = ctx.customStructureProperties.get(name); + const props = properties[name]; if (autoAttach.includes(name)) { try { - await property.attach(propertyCtx, structure, props, true) + await property.attach(propertyCtx, structure, props, true); } catch (e) { ctx.log.warn(`Error attaching structure prop '${name}': ${e}`); } } else { - property.set(structure, props) + property.set(structure, props); } } } @@ -885,7 +885,7 @@ const ShapeFromPly = PluginStateTransform.BuiltIn({ })({ apply({ a, params }) { return Task.create('Create shape from PLY', async ctx => { - const shape = await shapeFromPly(a.data, params).runInContext(ctx) + const shape = await shapeFromPly(a.data, params).runInContext(ctx); const props = { label: 'Shape' }; return new SO.Shape.Provider(shape, props); }); diff --git a/src/mol-plugin-state/transforms/representation.ts b/src/mol-plugin-state/transforms/representation.ts index 33cfaee080d233c4f023248b77a5c50b376420c6..87c210b0dab3cdd17e7175abc8a86533331c54be 100644 --- a/src/mol-plugin-state/transforms/representation.ts +++ b/src/mol-plugin-state/transforms/representation.ts @@ -35,14 +35,14 @@ import { AngleParams, AngleRepresentation } from '../../mol-repr/shape/loci/angl import { DihedralParams, DihedralRepresentation } from '../../mol-repr/shape/loci/dihedral'; import { ModelSymmetry } from '../../mol-model-formats/structure/property/symmetry'; -export { StructureRepresentation3D } -export { ExplodeStructureRepresentation3D } -export { UnwindStructureAssemblyRepresentation3D } -export { OverpaintStructureRepresentation3DFromScript } -export { OverpaintStructureRepresentation3DFromBundle } -export { TransparencyStructureRepresentation3DFromScript } -export { TransparencyStructureRepresentation3DFromBundle } -export { VolumeRepresentation3D } +export { StructureRepresentation3D }; +export { ExplodeStructureRepresentation3D }; +export { UnwindStructureAssemblyRepresentation3D }; +export { OverpaintStructureRepresentation3DFromScript }; +export { OverpaintStructureRepresentation3DFromBundle }; +export { TransparencyStructureRepresentation3DFromScript }; +export { TransparencyStructureRepresentation3DFromBundle }; +export { VolumeRepresentation3D }; type StructureRepresentation3D = typeof StructureRepresentation3D const StructureRepresentation3D = PluginStateTransform.BuiltIn({ @@ -51,18 +51,18 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ from: SO.Molecule.Structure, to: SO.Molecule.Structure.Representation3D, params: (a, ctx: PluginContext) => { - const { registry, themes: themeCtx } = ctx.representation.structure + const { registry, themes: themeCtx } = ctx.representation.structure; const type = registry.get(registry.default.name); if (!a) { const colorThemeInfo = { help: (value: { name: string, params: {} }) => { - const { name, params } = value - const p = themeCtx.colorThemeRegistry.get(name) - const ct = p.factory({}, params) - return { description: ct.description, legend: ct.legend } + const { name, params } = value; + const p = themeCtx.colorThemeRegistry.get(name); + const ct = p.factory({}, params); + return { description: ct.description, legend: ct.legend }; } - } + }; return { type: PD.Mapped<any>( @@ -80,18 +80,18 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ themeCtx.sizeThemeRegistry.types, name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams({ structure: Structure.Empty })) ) - } + }; } - const dataCtx = { structure: a.data } + const dataCtx = { structure: a.data }; const colorThemeInfo = { help: (value: { name: string, params: {} }) => { - const { name, params } = value - const p = themeCtx.colorThemeRegistry.get(name) - const ct = p.factory(dataCtx, params) - return { description: ct.description, legend: ct.legend } + const { name, params } = value; + const p = themeCtx.colorThemeRegistry.get(name); + const ct = p.factory(dataCtx, params); + return { description: ct.description, legend: ct.legend }; } - } + }; return ({ type: PD.Mapped<any>( @@ -109,7 +109,7 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ themeCtx.sizeThemeRegistry.types, name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams(dataCtx)) ) - }) + }); } })({ canAutoUpdate({ a, oldParams, newParams }) { @@ -120,13 +120,13 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ }, apply({ a, params, cache }, plugin: PluginContext) { return Task.create('Structure Representation', async ctx => { - const propertyCtx = { runtime: ctx, fetch: plugin.fetch } - const provider = plugin.representation.structure.registry.get(params.type.name) - if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data) - const props = params.type.params || {} - const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, provider.getParams) - await Theme.ensureDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, params) - repr.setTheme(Theme.create(plugin.representation.structure.themes, { structure: a.data }, params)) + const propertyCtx = { runtime: ctx, fetch: plugin.fetch }; + const provider = plugin.representation.structure.registry.get(params.type.name); + if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data); + const props = params.type.params || {}; + const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, provider.getParams); + await Theme.ensureDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, params); + repr.setTheme(Theme.create(plugin.representation.structure.themes, { structure: a.data }, params)); // TODO: build this into representation? if (!a.data.coordinateSystem.isIdentity) { @@ -147,11 +147,11 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ if (newParams.type.name !== oldParams.type.name) return StateTransformer.UpdateResult.Recreate; - const provider = plugin.representation.structure.registry.get(newParams.type.name) - const propertyCtx = { runtime: ctx, fetch: plugin.fetch } - if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data) - const props = { ...b.data.repr.props, ...newParams.type.params } - await Theme.ensureDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, newParams) + const provider = plugin.representation.structure.registry.get(newParams.type.name); + const propertyCtx = { runtime: ctx, fetch: plugin.fetch }; + if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data); + const props = { ...b.data.repr.props, ...newParams.type.params }; + await Theme.ensureDependencies(propertyCtx, plugin.representation.structure.themes, { structure: a.data }, newParams); b.data.repr.setTheme(Theme.create(plugin.representation.structure.themes, { structure: a.data }, newParams)); // TODO: build this into representation? @@ -161,7 +161,7 @@ const StructureRepresentation3D = PluginStateTransform.BuiltIn({ } await b.data.repr.createOrUpdate(props, a.data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); }, @@ -281,28 +281,28 @@ const OverpaintStructureRepresentation3DFromScript = PluginStateTransform.BuiltI return true; }, apply({ a, params }) { - const structure = a.data.source.data - const overpaint = Overpaint.ofScript(params.layers, params.alpha, structure) + const structure = a.data.source.data; + const overpaint = Overpaint.ofScript(params.layers, params.alpha, structure); return new SO.Molecule.Structure.Representation3DState({ state: { overpaint }, initialState: { overpaint: Overpaint.Empty }, info: structure, source: a - }, { label: `Overpaint (${overpaint.layers.length} Layers)` }) + }, { label: `Overpaint (${overpaint.layers.length} Layers)` }); }, update({ a, b, newParams, oldParams }) { - const oldStructure = b.data.info as Structure - const newStructure = a.data.source.data - if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate - const oldOverpaint = b.data.state.overpaint! - const newOverpaint = Overpaint.ofScript(newParams.layers, newParams.alpha, newStructure) - if (oldParams.alpha === newParams.alpha && Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged - - b.data.state.overpaint = newOverpaint - b.data.source = a - b.label = `Overpaint (${newOverpaint.layers.length} Layers)` - return StateTransformer.UpdateResult.Updated + const oldStructure = b.data.info as Structure; + const newStructure = a.data.source.data; + if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate; + const oldOverpaint = b.data.state.overpaint!; + const newOverpaint = Overpaint.ofScript(newParams.layers, newParams.alpha, newStructure); + if (oldParams.alpha === newParams.alpha && Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged; + + b.data.state.overpaint = newOverpaint; + b.data.source = a; + b.label = `Overpaint (${newOverpaint.layers.length} Layers)`; + return StateTransformer.UpdateResult.Updated; } }); @@ -332,28 +332,28 @@ const OverpaintStructureRepresentation3DFromBundle = PluginStateTransform.BuiltI return true; }, apply({ a, params }) { - const structure = a.data.source.data - const overpaint = Overpaint.ofBundle(params.layers, params.alpha, structure) + const structure = a.data.source.data; + const overpaint = Overpaint.ofBundle(params.layers, params.alpha, structure); return new SO.Molecule.Structure.Representation3DState({ state: { overpaint }, initialState: { overpaint: Overpaint.Empty }, info: structure, source: a - }, { label: `Overpaint (${overpaint.layers.length} Layers)` }) + }, { label: `Overpaint (${overpaint.layers.length} Layers)` }); }, update({ a, b, newParams, oldParams }) { - const oldStructure = b.data.info as Structure - const newStructure = a.data.source.data - if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate - const oldOverpaint = b.data.state.overpaint! - const newOverpaint = Overpaint.ofBundle(newParams.layers, newParams.alpha, newStructure) - if (oldParams.alpha === newParams.alpha && Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged - - b.data.state.overpaint = newOverpaint - b.data.source = a - b.label = `Overpaint (${newOverpaint.layers.length} Layers)` - return StateTransformer.UpdateResult.Updated + const oldStructure = b.data.info as Structure; + const newStructure = a.data.source.data; + if (newStructure !== oldStructure) return StateTransformer.UpdateResult.Recreate; + const oldOverpaint = b.data.state.overpaint!; + const newOverpaint = Overpaint.ofBundle(newParams.layers, newParams.alpha, newStructure); + if (oldParams.alpha === newParams.alpha && Overpaint.areEqual(oldOverpaint, newOverpaint)) return StateTransformer.UpdateResult.Unchanged; + + b.data.state.overpaint = newOverpaint; + b.data.source = a; + b.label = `Overpaint (${newOverpaint.layers.length} Layers)`; + return StateTransformer.UpdateResult.Updated; } }); @@ -373,27 +373,27 @@ const TransparencyStructureRepresentation3DFromScript = PluginStateTransform.Bui return true; }, apply({ a, params }) { - const structure = a.data.source.data - const transparency = Transparency.ofScript(params.script, params.value, params.variant, structure) + const structure = a.data.source.data; + const transparency = Transparency.ofScript(params.script, params.value, params.variant, structure); return new SO.Molecule.Structure.Representation3DState({ state: { transparency }, initialState: { transparency: Transparency.Empty }, info: structure, source: a - }, { label: `Transparency (${transparency.value})` }) + }, { label: `Transparency (${transparency.value})` }); }, update({ a, b, newParams, oldParams }) { - const structure = b.data.info as Structure - if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate - const oldTransparency = b.data.state.transparency! - const newTransparency = Transparency.ofScript(newParams.script, newParams.value, newParams.variant, structure) - if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged - - b.data.state.transparency = newTransparency - b.data.source = a - b.label = `Transparency (${newTransparency.value})` - return StateTransformer.UpdateResult.Updated + const structure = b.data.info as Structure; + if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + const oldTransparency = b.data.state.transparency!; + const newTransparency = Transparency.ofScript(newParams.script, newParams.value, newParams.variant, structure); + if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged; + + b.data.state.transparency = newTransparency; + b.data.source = a; + b.label = `Transparency (${newTransparency.value})`; + return StateTransformer.UpdateResult.Updated; } }); @@ -413,27 +413,27 @@ const TransparencyStructureRepresentation3DFromBundle = PluginStateTransform.Bui return true; }, apply({ a, params }) { - const structure = a.data.source.data - const transparency = Transparency.ofBundle(params.bundle, params.value, params.variant, structure) + const structure = a.data.source.data; + const transparency = Transparency.ofBundle(params.bundle, params.value, params.variant, structure); return new SO.Molecule.Structure.Representation3DState({ state: { transparency }, initialState: { transparency: Transparency.Empty }, info: structure, source: a - }, { label: `Transparency (${transparency.value})` }) + }, { label: `Transparency (${transparency.value})` }); }, update({ a, b, newParams, oldParams }) { - const structure = b.data.info as Structure - if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate - const oldTransparency = b.data.state.transparency! - const newTransparency = Transparency.ofBundle(newParams.bundle, newParams.value, newParams.variant, structure) - if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged - - b.data.state.transparency = newTransparency - b.data.source = a - b.label = `Transparency (${newTransparency.value})` - return StateTransformer.UpdateResult.Updated + const structure = b.data.info as Structure; + if (a.data.source.data !== structure) return StateTransformer.UpdateResult.Recreate; + const oldTransparency = b.data.state.transparency!; + const newTransparency = Transparency.ofBundle(newParams.bundle, newParams.value, newParams.variant, structure); + if (Transparency.areEqual(oldTransparency, newTransparency)) return StateTransformer.UpdateResult.Unchanged; + + b.data.state.transparency = newTransparency; + b.data.source = a; + b.label = `Transparency (${newTransparency.value})`; + return StateTransformer.UpdateResult.Updated; } }); @@ -445,13 +445,13 @@ export namespace VolumeRepresentation3DHelpers { const themeDataCtx = { volume }; const colorParams = ctx.representation.volume.themes.colorThemeRegistry.get(type.defaultColorTheme.name).getParams(themeDataCtx); - const sizeParams = ctx.representation.volume.themes.sizeThemeRegistry.get(type.defaultSizeTheme.name).getParams(themeDataCtx) - const volumeDefaultParams = PD.getDefaultValues(type.getParams(ctx.representation.volume.themes, volume)) + const sizeParams = ctx.representation.volume.themes.sizeThemeRegistry.get(type.defaultSizeTheme.name).getParams(themeDataCtx); + const volumeDefaultParams = PD.getDefaultValues(type.getParams(ctx.representation.volume.themes, volume)); return ({ type: { name, params: volumeParams ? { ...volumeDefaultParams, ...volumeParams } : volumeDefaultParams }, colorTheme: { name: type.defaultColorTheme.name, params: PD.getDefaultValues(colorParams) }, sizeTheme: { name: type.defaultSizeTheme.name, params: PD.getDefaultValues(sizeParams) } - }) + }); } export function getDefaultParamsStatic(ctx: PluginContext, name: VolumeRepresentationRegistry.BuiltIn, volumeParams?: Partial<PD.Values<PD.Params>>, colorName?: ColorTheme.BuiltIn, colorParams?: Partial<ColorTheme.Props>, sizeName?: SizeTheme.BuiltIn, sizeParams?: Partial<SizeTheme.Props>): StateTransformer.Params<VolumeRepresentation3D> { @@ -462,11 +462,11 @@ export namespace VolumeRepresentation3DHelpers { type: { name, params: volumeParams ? { ...type.defaultValues, ...volumeParams } : type.defaultValues }, colorTheme: { name: type.defaultColorTheme.name, params: colorParams ? { ...colorType.defaultValues, ...colorParams } : colorType.defaultValues }, sizeTheme: { name: type.defaultSizeTheme.name, params: sizeParams ? { ...sizeType.defaultValues, ...sizeParams } : sizeType.defaultValues } - }) + }); } export function getDescription(props: any) { - return props.isoValue && VolumeIsoValue.toString(props.isoValue) + return props.isoValue && VolumeIsoValue.toString(props.isoValue); } } type VolumeRepresentation3D = typeof VolumeRepresentation3D @@ -476,7 +476,7 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ from: SO.Volume.Data, to: SO.Volume.Representation3D, params: (a, ctx: PluginContext) => { - const { registry, themes: themeCtx } = ctx.representation.volume + const { registry, themes: themeCtx } = ctx.representation.volume; const type = registry.get(registry.default.name); if (!a) { @@ -495,10 +495,10 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ themeCtx.sizeThemeRegistry.types, name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams({ volume: VolumeData.One })) ) - } + }; } - const dataCtx = { volume: a.data } + const dataCtx = { volume: a.data }; return ({ type: PD.Mapped<any>( registry.default.name, @@ -514,7 +514,7 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ themeCtx.sizeThemeRegistry.types, name => PD.Group<any>(themeCtx.sizeThemeRegistry.get(name).getParams(dataCtx)) ) - }) + }); } })({ canAutoUpdate({ oldParams, newParams }) { @@ -523,12 +523,12 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Volume Representation', async ctx => { - const propertyCtx = { runtime: ctx, fetch: plugin.fetch } - const provider = plugin.representation.volume.registry.get(params.type.name) - if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data) - const props = params.type.params || {} - const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.volume.themes }, provider.getParams) - repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: a.data }, params)) + const propertyCtx = { runtime: ctx, fetch: plugin.fetch }; + const provider = plugin.representation.volume.registry.get(params.type.name); + if (provider.ensureCustomProperties) await provider.ensureCustomProperties.attach(propertyCtx, a.data); + const props = params.type.params || {}; + const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.volume.themes }, provider.getParams); + repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: a.data }, params)); // TODO set initial state, repr.setState({}) await repr.createOrUpdate(props, a.data).runInContext(ctx); return new SO.Volume.Representation3D({ repr, source: a }, { label: provider.label, description: VolumeRepresentation3DHelpers.getDescription(props) }); @@ -539,14 +539,14 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ if (newParams.type.name !== oldParams.type.name) { const oldProvider = plugin.representation.volume.registry.get(oldParams.type.name); if (oldProvider.ensureCustomProperties) { - oldProvider.ensureCustomProperties.detach(a.data) + oldProvider.ensureCustomProperties.detach(a.data); } return StateTransformer.UpdateResult.Recreate; } - const props = { ...b.data.repr.props, ...newParams.type.params } - b.data.repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: a.data }, newParams)) + const props = { ...b.data.repr.props, ...newParams.type.params }; + b.data.repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: a.data }, newParams)); await b.data.repr.createOrUpdate(props, a.data).runInContext(ctx); - b.description = VolumeRepresentation3DHelpers.getDescription(props) + b.description = VolumeRepresentation3DHelpers.getDescription(props); return StateTransformer.UpdateResult.Updated; }); } @@ -554,7 +554,7 @@ const VolumeRepresentation3D = PluginStateTransform.BuiltIn({ // -export { ShapeRepresentation3D } +export { ShapeRepresentation3D }; type ShapeRepresentation3D = typeof ShapeRepresentation3D const ShapeRepresentation3D = PluginStateTransform.BuiltIn({ name: 'shape-representation-3d', @@ -562,7 +562,7 @@ const ShapeRepresentation3D = PluginStateTransform.BuiltIn({ from: SO.Shape.Provider, to: SO.Shape.Representation3D, params: (a, ctx: PluginContext) => { - return a ? a.data.params : BaseGeometry.Params + return a ? a.data.params : BaseGeometry.Params; } })({ canAutoUpdate() { @@ -570,8 +570,8 @@ const ShapeRepresentation3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Shape Representation', async ctx => { - const props = { ...PD.getDefaultValues(a.data.params), params } - const repr = ShapeRepresentation(a.data.getShape, a.data.geometryUtils) + const props = { ...PD.getDefaultValues(a.data.params), params }; + const repr = ShapeRepresentation(a.data.getShape, a.data.geometryUtils); // TODO set initial state, repr.setState({}) await repr.createOrUpdate(props, a.data.data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: a.data.label }); @@ -579,14 +579,14 @@ const ShapeRepresentation3D = PluginStateTransform.BuiltIn({ }, update({ a, b, oldParams, newParams }, plugin: PluginContext) { return Task.create('Shape Representation', async ctx => { - const props = { ...b.data.repr.props, ...newParams } + const props = { ...b.data.repr.props, ...newParams }; await b.data.repr.createOrUpdate(props, a.data.data).runInContext(ctx); return StateTransformer.UpdateResult.Updated; }); } }); -export { ModelUnitcell3D } +export { ModelUnitcell3D }; type ModelUnitcell3D = typeof ModelUnitcell3D const ModelUnitcell3D = PluginStateTransform.BuiltIn({ name: 'model-unitcell-3d', @@ -603,28 +603,28 @@ const ModelUnitcell3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Model Unitcell', async ctx => { - const symmetry = ModelSymmetry.Provider.get(a.data) - if (!symmetry) return StateObject.Null - const data = getUnitcellData(a.data, symmetry) - const repr = UnitcellRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => UnitcellParams) + const symmetry = ModelSymmetry.Provider.get(a.data); + if (!symmetry) return StateObject.Null; + const data = getUnitcellData(a.data, symmetry); + const repr = UnitcellRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => UnitcellParams); await repr.createOrUpdate(params, data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: `Unitcell`, description: symmetry.spacegroup.name }); }); }, update({ a, b, newParams }) { return Task.create('Model Unitcell', async ctx => { - const symmetry = ModelSymmetry.Provider.get(a.data) - if (!symmetry) return StateTransformer.UpdateResult.Null - const props = { ...b.data.repr.props, ...newParams } - const data = getUnitcellData(a.data, symmetry) + const symmetry = ModelSymmetry.Provider.get(a.data); + if (!symmetry) return StateTransformer.UpdateResult.Null; + const props = { ...b.data.repr.props, ...newParams }; + const data = getUnitcellData(a.data, symmetry); await b.data.repr.createOrUpdate(props, data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); } }); -export { StructureSelectionsDistance3D } +export { StructureSelectionsDistance3D }; type StructureSelectionsDistance3D = typeof StructureSelectionsDistance3D const StructureSelectionsDistance3D = PluginStateTransform.BuiltIn({ name: 'structure-selections-distance-3d', @@ -640,24 +640,24 @@ const StructureSelectionsDistance3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Structure Distance', async ctx => { - const data = getDistanceDataFromStructureSelections(a.data) - const repr = DistanceRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => DistanceParams) + const data = getDistanceDataFromStructureSelections(a.data); + const repr = DistanceRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => DistanceParams); await repr.createOrUpdate(params, data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: `Distance` }); }); }, update({ a, b, oldParams, newParams }, plugin: PluginContext) { return Task.create('Structure Distance', async ctx => { - const props = { ...b.data.repr.props, ...newParams } - const data = getDistanceDataFromStructureSelections(a.data) + const props = { ...b.data.repr.props, ...newParams }; + const data = getDistanceDataFromStructureSelections(a.data); await b.data.repr.createOrUpdate(props, data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); }, }); -export { StructureSelectionsAngle3D } +export { StructureSelectionsAngle3D }; type StructureSelectionsAngle3D = typeof StructureSelectionsAngle3D const StructureSelectionsAngle3D = PluginStateTransform.BuiltIn({ name: 'structure-selections-angle-3d', @@ -673,24 +673,24 @@ const StructureSelectionsAngle3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Structure Angle', async ctx => { - const data = getAngleDataFromStructureSelections(a.data) - const repr = AngleRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => AngleParams) + const data = getAngleDataFromStructureSelections(a.data); + const repr = AngleRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => AngleParams); await repr.createOrUpdate(params, data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: `Angle` }); }); }, update({ a, b, oldParams, newParams }, plugin: PluginContext) { return Task.create('Structure Angle', async ctx => { - const props = { ...b.data.repr.props, ...newParams } - const data = getAngleDataFromStructureSelections(a.data) + const props = { ...b.data.repr.props, ...newParams }; + const data = getAngleDataFromStructureSelections(a.data); await b.data.repr.createOrUpdate(props, data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); }, }); -export { StructureSelectionsDihedral3D } +export { StructureSelectionsDihedral3D }; type StructureSelectionsDihedral3D = typeof StructureSelectionsDihedral3D const StructureSelectionsDihedral3D = PluginStateTransform.BuiltIn({ name: 'structure-selections-dihedral-3d', @@ -706,24 +706,24 @@ const StructureSelectionsDihedral3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Structure Dihedral', async ctx => { - const data = getDihedralDataFromStructureSelections(a.data) - const repr = DihedralRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => DihedralParams) + const data = getDihedralDataFromStructureSelections(a.data); + const repr = DihedralRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => DihedralParams); await repr.createOrUpdate(params, data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: `Dihedral` }); }); }, update({ a, b, oldParams, newParams }, plugin: PluginContext) { return Task.create('Structure Dihedral', async ctx => { - const props = { ...b.data.repr.props, ...newParams } - const data = getDihedralDataFromStructureSelections(a.data) + const props = { ...b.data.repr.props, ...newParams }; + const data = getDihedralDataFromStructureSelections(a.data); await b.data.repr.createOrUpdate(props, data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); }, }); -export { StructureSelectionsLabel3D } +export { StructureSelectionsLabel3D }; type StructureSelectionsLabel3D = typeof StructureSelectionsLabel3D const StructureSelectionsLabel3D = PluginStateTransform.BuiltIn({ name: 'structure-selections-label-3d', @@ -739,24 +739,24 @@ const StructureSelectionsLabel3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Structure Label', async ctx => { - const data = getLabelDataFromStructureSelections(a.data) - const repr = LabelRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => LabelParams) + const data = getLabelDataFromStructureSelections(a.data); + const repr = LabelRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => LabelParams); await repr.createOrUpdate(params, data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: `Label` }); }); }, update({ a, b, oldParams, newParams }, plugin: PluginContext) { return Task.create('Structure Label', async ctx => { - const props = { ...b.data.repr.props, ...newParams } - const data = getLabelDataFromStructureSelections(a.data) + const props = { ...b.data.repr.props, ...newParams }; + const data = getLabelDataFromStructureSelections(a.data); await b.data.repr.createOrUpdate(props, data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); }, }); -export { StructureSelectionsOrientation3D } +export { StructureSelectionsOrientation3D }; type StructureSelectionsOrientation3D = typeof StructureSelectionsOrientation3D const StructureSelectionsOrientation3D = PluginStateTransform.BuiltIn({ name: 'structure-selections-orientation-3d', @@ -772,18 +772,18 @@ const StructureSelectionsOrientation3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Structure Orientation', async ctx => { - const data = getOrientationDataFromStructureSelections(a.data) - const repr = OrientationRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => OrientationParams) + const data = getOrientationDataFromStructureSelections(a.data); + const repr = OrientationRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => OrientationParams); await repr.createOrUpdate(params, data).runInContext(ctx); return new SO.Shape.Representation3D({ repr, source: a }, { label: `Orientation` }); }); }, update({ a, b, oldParams, newParams }, plugin: PluginContext) { return Task.create('Structure Orientation', async ctx => { - const props = { ...b.data.repr.props, ...newParams } - const data = getOrientationDataFromStructureSelections(a.data) + const props = { ...b.data.repr.props, ...newParams }; + const data = getOrientationDataFromStructureSelections(a.data); await b.data.repr.createOrUpdate(props, data).runInContext(ctx); - b.data.source = a + b.data.source = a; return StateTransformer.UpdateResult.Updated; }); }, diff --git a/src/mol-plugin-state/transforms/volume.ts b/src/mol-plugin-state/transforms/volume.ts index f63aa54d363da5ac2fd49f1c029ec3797efce78f..3174a3d0f9ab3f131156dbcc75897659aaa1a883 100644 --- a/src/mol-plugin-state/transforms/volume.ts +++ b/src/mol-plugin-state/transforms/volume.ts @@ -32,7 +32,7 @@ const VolumeFromCcp4 = PluginStateTransform.BuiltIn({ })({ apply({ a, params }) { return Task.create('Create volume from CCP4/MRC/MAP', async ctx => { - const volume = await volumeFromCcp4(a.data, params).runInContext(ctx) + const volume = await volumeFromCcp4(a.data, params).runInContext(ctx); const props = { label: 'Volume' }; return new SO.Volume.Data(volume, props); }); @@ -53,7 +53,7 @@ const VolumeFromDsn6 = PluginStateTransform.BuiltIn({ })({ apply({ a, params }) { return Task.create('Create volume from DSN6/BRIX', async ctx => { - const volume = await volumeFromDsn6(a.data, params).runInContext(ctx) + const volume = await volumeFromDsn6(a.data, params).runInContext(ctx); const props = { label: 'Volume' }; return new SO.Volume.Data(volume, props); }); @@ -84,8 +84,8 @@ const VolumeFromDensityServerCif = PluginStateTransform.BuiltIn({ const header = params.blockHeader || a.data.blocks[1].header; // zero block contains query meta-data const block = a.data.blocks.find(b => b.header === header); if (!block) throw new Error(`Data block '${[header]}' not found.`); - const densityServerCif = CIF.schema.densityServer(block) - const volume = await volumeFromDensityServerData(densityServerCif).runInContext(ctx) + const densityServerCif = CIF.schema.densityServer(block); + const volume = await volumeFromDensityServerData(densityServerCif).runInContext(ctx); const props = { label: densityServerCif.volume_data_3d_info.name.value(0), description: `${densityServerCif.volume_data_3d_info.name.value(0)}` }; return new SO.Volume.Data(volume, props); }); diff --git a/src/mol-plugin-ui/base.tsx b/src/mol-plugin-ui/base.tsx index f633dbba1d4600b24203fcca889aba0b0e2be9d8..7efc7132124ca2407a4f8fd154293766dd99eff0 100644 --- a/src/mol-plugin-ui/base.tsx +++ b/src/mol-plugin-ui/base.tsx @@ -80,7 +80,7 @@ export type CollapsableState = { export abstract class CollapsableControls<P = {}, S = {}, SS = {}> extends PluginUIComponent<P & CollapsableProps, S & CollapsableState, SS> { toggleCollapsed = () => { - this.setState({ isCollapsed: !this.state.isCollapsed } as (S & CollapsableState)) + this.setState({ isCollapsed: !this.state.isCollapsed } as (S & CollapsableState)); } componentDidUpdate(prevProps: P & CollapsableProps) { @@ -109,15 +109,15 @@ export abstract class CollapsableControls<P = {}, S = {}, SS = {}> extends Plugi </Button> </div> {!this.state.isCollapsed && this.renderControls()} - </div> + </div>; } constructor(props: P & CollapsableProps, context?: any) { - super(props, context) + super(props, context); - const state = this.defaultState() - if (props.initiallyCollapsed !== undefined) state.isCollapsed = props.initiallyCollapsed - if (props.header !== undefined) state.header = props.header - this.state = state + const state = this.defaultState(); + if (props.initiallyCollapsed !== undefined) state.isCollapsed = props.initiallyCollapsed; + if (props.header !== undefined) state.header = props.header; + this.state = state; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/camera.tsx b/src/mol-plugin-ui/camera.tsx index 1ce2196eb84f4381243626f684befa642253be37..5838fc60a1735990996e8bea336a1c6e4cbad199 100644 --- a/src/mol-plugin-ui/camera.tsx +++ b/src/mol-plugin-ui/camera.tsx @@ -31,7 +31,7 @@ class CameraSnapshotControls extends PluginUIComponent<{ }, { name: string, desc add = () => { PluginCommands.Camera.Snapshots.Add(this.plugin, this.state); - this.setState({ name: '', description: '' }) + this.setState({ name: '', description: '' }); } clear = () => { @@ -62,7 +62,7 @@ class CameraSnapshotList extends PluginUIComponent<{ }, { }> { remove(id: string) { return () => { PluginCommands.Camera.Snapshots.Remove(this.plugin, { id }); - } + }; } render() { diff --git a/src/mol-plugin-ui/controls.tsx b/src/mol-plugin-ui/controls.tsx index 34661f0cf1c0749cdc7bc55c00f64e117493d6da..af6c6de78d4b5458d9c71ca04992e131e82e218d 100644 --- a/src/mol-plugin-ui/controls.tsx +++ b/src/mol-plugin-ui/controls.tsx @@ -117,7 +117,7 @@ export class StateSnapshotViewportControls extends PluginUIComponent<{}, { isBus // TODO: this needs to be diabled when the state is updating! this.subscribe(this.plugin.state.snapshots.events.changed, () => this.forceUpdate()); this.subscribe(this.plugin.behaviors.state.isBusy, isBusy => this.setState({ isBusy })); - this.subscribe(this.plugin.behaviors.state.isAnimating, isBusy => this.setState({ isBusy })) + this.subscribe(this.plugin.behaviors.state.isAnimating, isBusy => this.setState({ isBusy })); window.addEventListener('keyup', this.keyUp, false); } @@ -253,7 +253,7 @@ export class SelectionViewportControls extends PluginUIComponent { onMouseMove = (e: React.MouseEvent) => { // ignore mouse moves when no button is held - if (e.buttons === 0) e.stopPropagation() + if (e.buttons === 0) e.stopPropagation(); } render() { @@ -288,11 +288,11 @@ export class CustomStructureControls extends PluginUIComponent<{ initiallyCollap } render() { - const controls: JSX.Element[] = [] + const controls: JSX.Element[] = []; this.plugin.customStructureControls.forEach((Controls, key) => { - controls.push(<Controls initiallyCollapsed={this.props.initiallyCollapsed} key={key} />) - }) - return controls.length > 0 ? <>{controls}</> : null + controls.push(<Controls initiallyCollapsed={this.props.initiallyCollapsed} key={key} />); + }); + return controls.length > 0 ? <>{controls}</> : null; } } diff --git a/src/mol-plugin-ui/controls/action-menu.tsx b/src/mol-plugin-ui/controls/action-menu.tsx index 9f1b7d8c2de3fc82f7df4f34f7b9b72d8165576f..47d0bb8c37c6964a393518aa264d02783310302e 100644 --- a/src/mol-plugin-ui/controls/action-menu.tsx +++ b/src/mol-plugin-ui/controls/action-menu.tsx @@ -21,7 +21,7 @@ export class ActionMenu extends React.PureComponent<ActionMenu.Props> { {section} </ControlGroup>} {!cmd.header && section} - </div> + </div>; } } @@ -206,7 +206,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> { isItems(this.props.items) && isItems(prevProps.items) && isHeader(this.props.items[0]) && isHeader(prevProps.items[0]) && this.props.items[0].label === prevProps.items[0].label - ) ? this.state.isExpanded : undefined + ) ? this.state.isExpanded : undefined; this.setState(Section.createState(this.props, isExpanded)); } } @@ -251,7 +251,7 @@ class Section extends React.PureComponent<SectionProps, SectionState> { const { items, onSelect, current } = this.props; if (isHeader(items)) return null; - if (isItem(items)) return <Action item={items} onSelect={onSelect} current={current} multiselect={this.props.multiselect} /> + if (isItem(items)) return <Action item={items} onSelect={onSelect} current={current} multiselect={this.props.multiselect} />; const { header } = this.state; return <> @@ -259,8 +259,8 @@ class Section extends React.PureComponent<SectionProps, SectionState> { <div className={this.props.noOffset ? void 0 : this.props.noAccent ? 'msp-control-offset' : 'msp-accent-offset'}> {(!header || this.state.isExpanded) && items.map((x, i) => { if (isHeader(x)) return null; - if (isItem(x)) return <Action key={i} item={x} onSelect={onSelect} current={current} multiselect={this.props.multiselect} /> - return <Section key={i} items={x} onSelect={onSelect} current={current} multiselect={this.props.multiselect} noAccent /> + if (isItem(x)) return <Action key={i} item={x} onSelect={onSelect} current={current} multiselect={this.props.multiselect} />; + return <Section key={i} items={x} onSelect={onSelect} current={current} multiselect={this.props.multiselect} noAccent />; })} </div> </>; @@ -280,7 +280,7 @@ const Action: React.FC<{ {isCurrent || item.selected ? <b>{item.label}</b> : item.label} {item.addOn} </Button>; -} +}; function isItems(x: any): x is ActionMenu.Items[] { return !!x && Array.isArray(x); diff --git a/src/mol-plugin-ui/controls/color.tsx b/src/mol-plugin-ui/controls/color.tsx index d28d916c57f1264d326ddc7c6e4c57f2c6b3f3ae..76c4d3a913f9499588a986441bae1c8c9e2ef14e 100644 --- a/src/mol-plugin-ui/controls/color.tsx +++ b/src/mol-plugin-ui/controls/color.tsx @@ -99,12 +99,12 @@ export function ColorOptions() { } const DefaultColorSwatchMap = (function () { - const map = new Map<Color, string>() - for (const v of DefaultColorSwatch) map.set(v[1], v[0]) - return map -})() + const map = new Map<Color, string>(); + for (const v of DefaultColorSwatch) map.set(v[1], v[0]); + return map; +})(); export function ColorValueOption(color: Color) { return !DefaultColorSwatchMap.has(color) ? <option key={Color.toHexString(color)} value={color} style={{ background: `${Color.toStyle(color)}` }} > {Color.toRgbString(color)} - </option> : null + </option> : null; } \ No newline at end of file diff --git a/src/mol-plugin-ui/controls/common.tsx b/src/mol-plugin-ui/controls/common.tsx index d0df8ba15e38ad9d45f77481d0991e0e0bb08484..3fe23915c2d97be7ce50a5d3dbde0e101e25e4c7 100644 --- a/src/mol-plugin-ui/controls/common.tsx +++ b/src/mol-plugin-ui/controls/common.tsx @@ -45,7 +45,7 @@ export class ControlGroup extends React.Component<{ {this.state.isExpanded && <div className={groupClassName} style={{ display: this.state.isExpanded ? 'block' : 'none' }}> {this.props.children} </div>} - </div> + </div>; } } @@ -223,7 +223,7 @@ export class NumericInput extends React.PureComponent<{ onChange={this.onChange} onKeyPress={this.props.onEnter || this.props.blurOnEnter ? this.onKeyPress : void 0} disabled={!!this.props.isDisabled} - /> + />; } } @@ -261,7 +261,7 @@ export function SectionHeader(props: { icon?: IconName, title: string | JSX.Elem return <div className='msp-section-header'> {props.icon && <Icon name={props.icon} />} {props.title} <small>{props.desc}</small> - </div> + </div>; } export type ButtonProps = { @@ -322,10 +322,10 @@ export function IconButton(props: { }) { let className = `msp-btn msp-btn-icon${props.small ? '-small' : ''}${props.className ? ' ' + props.className : ''}`; if (typeof props.toggleState !== 'undefined') { - className += ` msp-btn-link-toggle-${props.toggleState ? 'on' : 'off'}` + className += ` msp-btn-link-toggle-${props.toggleState ? 'on' : 'off'}`; } if (props.transparent) { - className += ' msp-transparent-bg' + className += ' msp-transparent-bg'; } const iconStyle = props.small ? { fontSize: '80%' } : void 0; diff --git a/src/mol-plugin-ui/controls/icons.tsx b/src/mol-plugin-ui/controls/icons.tsx index a35df09bf23888af0ea800e111861facfb992855..bd82b9a35cdad8c6fd919d983b81866cad9713f0 100644 --- a/src/mol-plugin-ui/controls/icons.tsx +++ b/src/mol-plugin-ui/controls/icons.tsx @@ -20,8 +20,8 @@ export function Icon(props: { case 'subtract': case 'intersect': case 'set': - return <SvgIcon name={props.name} title={props.title} style={props.style} /> - default: return <FontIcon name={props.name} title={props.title} style={props.style} /> + return <SvgIcon name={props.name} title={props.title} style={props.style} />; + default: return <FontIcon name={props.name} title={props.title} style={props.style} />; } } @@ -73,15 +73,15 @@ function SvgIcon(props: { function getSvg(name: SvgIconName) { switch (name) { - case 'union': return <Union /> - case 'subtract': return <Subtract /> - case 'intersect': return <Intersect /> - case 'set': return <Set /> + case 'union': return <Union />; + case 'subtract': return <Subtract />; + case 'intersect': return <Intersect />; + case 'set': return <Set />; } } -const circleLeft = <circle r="6px" id="circle-left" cy="16px" cx="12px" strokeWidth="0.5"/> -const circleRight = <circle r="6px" id="circle-right" cy="16px" cx="20px" strokeWidth="0.5"/> +const circleLeft = <circle r="6px" id="circle-left" cy="16px" cx="12px" strokeWidth="0.5"/>; +const circleRight = <circle r="6px" id="circle-right" cy="16px" cx="20px" strokeWidth="0.5"/>; function Union() { return <svg width="32px" height="32px" viewBox="0 0 32 32"> diff --git a/src/mol-plugin-ui/controls/legend.tsx b/src/mol-plugin-ui/controls/legend.tsx index 1243de1a7a45d9ea52c8c63336b0cb1219c97cbd..a758f167b8083f8d76e255a9c8165f2bf3fbb146 100644 --- a/src/mol-plugin-ui/controls/legend.tsx +++ b/src/mol-plugin-ui/controls/legend.tsx @@ -14,8 +14,8 @@ export type Legend = React.ComponentClass<LegendProps<any>> export function legendFor(legend: LegendData): Legend | undefined { switch (legend.kind) { - case 'scale-legend': return ScaleLegend - case 'table-legend': return TableLegend + case 'scale-legend': return ScaleLegend; + case 'table-legend': return TableLegend; default: const _: never = legend; console.warn(`${_} has no associated UI component`); @@ -25,28 +25,28 @@ export function legendFor(legend: LegendData): Legend | undefined { export class ScaleLegend extends React.PureComponent<LegendProps<ScaleLegendData>> { render() { - const { legend } = this.props - const colors = legend.colors.map(c => Color.toStyle(c)).join(', ') + const { legend } = this.props; + const colors = legend.colors.map(c => Color.toStyle(c)).join(', '); return <div className='msp-scale-legend'> <div style={{ background: `linear-gradient(to right, ${colors})` }}> <span style={{float: 'left'}}>{legend.minLabel}</span> <span style={{float: 'right'}}>{legend.maxLabel}</span> </div> - </div> + </div>; } } export class TableLegend extends React.PureComponent<LegendProps<TableLegendData>> { render() { - const { legend } = this.props + const { legend } = this.props; return <div className='msp-table-legend'> {legend.table.map((value, i) => { - const [name, color] = value + const [name, color] = value; return <div key={i}> <div className='msp-table-legend-color' style={{backgroundColor: Color.toStyle(color)}}></div> <div className='msp-table-legend-text'>{name}</div> - </div> + </div>; })} - </div> + </div>; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/controls/line-graph/line-graph-component.tsx b/src/mol-plugin-ui/controls/line-graph/line-graph-component.tsx index 0d88187a1839753eac903dc6d42c423d93ab68c6..e6243a1233376aba8dcdca1cfe6c10c5ad29e757 100644 --- a/src/mol-plugin-ui/controls/line-graph/line-graph-component.tsx +++ b/src/mol-plugin-ui/controls/line-graph/line-graph-component.tsx @@ -151,7 +151,7 @@ export default class LineGraphComponent extends React.Component<any, LineGraphCo private handleDrag(event: any) { if(this.selected === undefined){ - return + return; } const pt = this.myRef.createSVGPoint(); @@ -259,7 +259,7 @@ export default class LineGraphComponent extends React.Component<any, LineGraphCo } return a[0] - b[0]; }); - this.setState({points}) + this.setState({points}); this.change(points); } @@ -379,7 +379,7 @@ export default class LineGraphComponent extends React.Component<any, LineGraphCo const x2 = data[i + 1][0]; const y2 = data[i + 1][1]; - lines.push(<line key={`lineOf${i}`} x1={x1} x2={x2} y1={y1} y2={y2} stroke="#cec9ba" strokeWidth="5"/>) + lines.push(<line key={`lineOf${i}`} x1={x1} x2={x2} y1={y1} y2={y2} stroke="#cec9ba" strokeWidth="5"/>); } return lines; diff --git a/src/mol-plugin-ui/controls/line-graph/point-component.tsx b/src/mol-plugin-ui/controls/line-graph/point-component.tsx index 191bc8f9f6a73d63d8c0d2e5c0c4d545dd0417ce..86aba693aa9b0fd0d554198805ca96f7f66b5b9e 100644 --- a/src/mol-plugin-ui/controls/line-graph/point-component.tsx +++ b/src/mol-plugin-ui/controls/line-graph/point-component.tsx @@ -6,7 +6,7 @@ import { Vec2 } from '../../../mol-math/linear-algebra'; export default class PointComponent extends React.Component<any, {show: boolean}> { constructor(props: any) { super(props); - this.state = {show: false} + this.state = {show: false}; this.handleHover = this.handleHover.bind(this); this.handleHoverOff = this.handleHoverOff.bind(this); diff --git a/src/mol-plugin-ui/controls/parameters.tsx b/src/mol-plugin-ui/controls/parameters.tsx index dddf51b97792a1e0b6e0ab1711755cf9102ee7db..0917328b62bbe8f1095e7760f94c10dda4286032 100644 --- a/src/mol-plugin-ui/controls/parameters.tsx +++ b/src/mol-plugin-ui/controls/parameters.tsx @@ -57,7 +57,7 @@ export class ParameterControls<P extends PD.Params> extends React.PureComponent< if (!ctrls) ctrls = []; category = p.category; - ctrls.push(<Control param={p} key={key} onChange={this.onChange} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} name={key} value={values[key]} />) + ctrls.push(<Control param={p} key={key} onChange={this.onChange} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} name={key} value={values[key]} />); } if (!ctrls) return null; @@ -117,7 +117,7 @@ export class ParameterMappingControl<S, T> extends PluginUIComponent<{ mapping: const t = this.props.mapping.getTarget(this.plugin); const values = this.props.mapping.getValues(t, this.plugin); const params = this.props.mapping.params(this.plugin) as any as PD.Params; - return <ParameterControls params={params} values={values} onChange={this.setSettings} /> + return <ParameterControls params={params} values={values} onChange={this.setSettings} />; } } @@ -156,7 +156,7 @@ function classifyParams(params: PD.Params) { const p = params[k]; if (p.isHidden) continue; - if (p.isEssential) addParam(k, p, essentials) + if (p.isEssential) addParam(k, p, essentials); else addParam(k, p, advanced); } @@ -199,15 +199,15 @@ function controlFor(param: PD.Any): ParamControl | undefined { export class ParamHelp<L extends LegendData> extends React.PureComponent<{ legend?: L, description?: string }> { render() { - const { legend, description } = this.props - const Legend = legend && legendFor(legend) + const { legend, description } = this.props; + const Legend = legend && legendFor(legend); return <div className='msp-help-text'> <div> <div className='msp-help-description'><Icon name='help-circle' />{description}</div> {Legend && <div className='msp-help-legend'><Legend legend={legend} /></div>} </div> - </div> + </div>; } } @@ -227,16 +227,16 @@ function renderSimple(options: { props: ParamProps<any>, state: { showHelp: bool const { props, state, control, toggleHelp, addOn } = options; let _className = []; - if (props.param.shortLabel) _className.push('msp-control-label-short') - if (props.param.twoColumns) _className.push('msp-control-col-2') + if (props.param.shortLabel) _className.push('msp-control-label-short'); + if (props.param.twoColumns) _className.push('msp-control-col-2'); const className = _className.join(' '); const label = props.param.label || camelCaseToWords(props.name); const help = props.param.help ? props.param.help(props.value) - : { description: props.param.description, legend: props.param.legend } + : { description: props.param.description, legend: props.param.legend }; const desc = props.param.description; - const hasHelp = help.description || help.legend + const hasHelp = help.description || help.legend; return <> <ControlRow className={className} @@ -341,15 +341,15 @@ export class NumberInputControl extends React.PureComponent<ParamProps<PD.Numeri state = { value: '0' }; update = (value: number) => { - const p = getPrecision(this.props.param.step || 0.01) - value = parseFloat(value.toFixed(p)) + const p = getPrecision(this.props.param.step || 0.01); + value = parseFloat(value.toFixed(p)); this.props.onChange({ param: this.props.param, name: this.props.name, value }); } render() { const placeholder = this.props.param.label || camelCaseToWords(this.props.name); const label = this.props.param.label || camelCaseToWords(this.props.name); - const p = getPrecision(this.props.param.step || 0.01) + const p = getPrecision(this.props.param.step || 0.01); return <ControlRow title={this.props.param.description} label={label} @@ -364,7 +364,7 @@ export class NumberRangeControl extends SimpleParam<PD.Numeric> { renderControl() { const value = typeof this.props.value === 'undefined' ? this.props.param.defaultValue : this.props.value; return <Slider value={value} min={this.props.param.min!} max={this.props.param.max!} - step={this.props.param.step} onChange={this.onChange} disabled={this.props.isDisabled} onEnter={this.props.onEnter} /> + step={this.props.param.step} onChange={this.onChange} disabled={this.props.isDisabled} onEnter={this.props.onEnter} />; } } @@ -433,9 +433,9 @@ export class SelectControl extends React.PureComponent<ParamProps<PD.Select<stri toggle = () => this.setState({ showOptions: !this.state.showOptions }); cycle = () => { - const { options } = this.props.param - const current = options.findIndex(o => o[0] === this.props.value) - const next = current === options.length - 1 ? 0 : current + 1 + const { options } = this.props.param; + const current = options.findIndex(o => o[0] === this.props.value); + const next = current === options.length - 1 ? 0 : current + 1; this.props.onChange({ param: this.props.param, name: this.props.name, value: options[next][0] }); }; @@ -450,12 +450,12 @@ export class SelectControl extends React.PureComponent<ParamProps<PD.Select<stri ? `${ActionMenu.getFirstItem(items)?.label || ''} [Default]` : `[Invalid] ${this.props.value}`; - const toggle = this.props.param.cycle ? this.cycle : this.toggle - const textAlign = this.props.param.cycle ? 'center' : 'left' + const toggle = this.props.param.cycle ? this.cycle : this.toggle; + const textAlign = this.props.param.cycle ? 'center' : 'left'; const icon = this.props.param.cycle ? (this.props.value === 'on' ? 'ok' : this.props.value === 'off' ? 'off' : '') - : '' + : ''; return <ToggleButton disabled={this.props.isDisabled} style={{ textAlign, overflow: 'hidden', textOverflow: 'ellipsis' }} label={label} title={label as string} icon={icon} toggle={toggle} isSelected={this.state.showOptions} />; @@ -509,7 +509,7 @@ export class IntervalControl extends React.PureComponent<ParamProps<PD.Interval> render() { const v = this.props.value; const label = this.props.param.label || camelCaseToWords(this.props.name); - const p = getPrecision(this.props.param.step || 0.01) + const p = getPrecision(this.props.param.step || 0.01); const value = `[${v[0].toFixed(p)}, ${v[1].toFixed(p)}]`; return <> <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{value}</button>} /> @@ -556,21 +556,21 @@ export class ColorControl extends SimpleParam<PD.Color> { } const colorGradientInterpolated = memoize1((colors: Color[]) => { - const styles = colors.map(c => Color.toStyle(c)) - return `linear-gradient(to right, ${styles.join(', ')})` + const styles = colors.map(c => Color.toStyle(c)); + return `linear-gradient(to right, ${styles.join(', ')})`; }); const colorGradientBanded = memoize1((colors: Color[]) => { - const n = colors.length - const styles: string[] = [`${Color.toStyle(colors[0])} ${100 * (1 / n)}%`] + const n = colors.length; + const styles: string[] = [`${Color.toStyle(colors[0])} ${100 * (1 / n)}%`]; for (let i = 1, il = n - 1; i < il; ++i) { styles.push( `${Color.toStyle(colors[i])} ${100 * (i / n)}%`, `${Color.toStyle(colors[i])} ${100 * ((i + 1) / n)}%` - ) + ); } - styles.push(`${Color.toStyle(colors[n - 1])} ${100 * ((n - 1) / n)}%`) - return `linear-gradient(to right, ${styles.join(', ')})` + styles.push(`${Color.toStyle(colors[n - 1])} ${100 * ((n - 1) / n)}%`); + return `linear-gradient(to right, ${styles.join(', ')})`; }); function colorStripStyle(list: PD.ColorList['defaultValue'], right = '0'): React.CSSProperties { @@ -585,7 +585,7 @@ function colorStripStyle(list: PD.ColorList['defaultValue'], right = '0'): React } function colorGradient(colors: Color[], banded: boolean) { - return banded ? colorGradientBanded(colors) : colorGradientInterpolated(colors) + return banded ? colorGradientBanded(colors) : colorGradientInterpolated(colors); } function createColorListHelpers() { @@ -593,7 +593,7 @@ function createColorListHelpers() { const addOn = (l: [ColorListName, any, any]) => { const preset = getColorListFromName(l[0]); return <div style={colorStripStyle({ kind: preset.type !== 'qualitative' ? 'interpolate' : 'set', colors: preset.list })} />; - } + }; return { ColorPresets: { @@ -606,7 +606,7 @@ function createColorListHelpers() { }; } -let _colorListHelpers: ReturnType<typeof createColorListHelpers> +let _colorListHelpers: ReturnType<typeof createColorListHelpers>; function ColorListHelpers() { if (_colorListHelpers) return _colorListHelpers; _colorListHelpers = createColorListHelpers(); @@ -633,7 +633,7 @@ export class ColorListControl extends React.PureComponent<ParamProps<PD.ColorLis </button> <IconButton icon='bookmarks' onClick={this.togglePresets} toggleState={this.state.show === 'presets'} title='Color Presets' style={{ padding: 0, position: 'absolute', right: 0, top: 0, width: '32px' }} /> - </> + </>; } selectPreset: ActionMenu.OnSelect = item => { @@ -652,7 +652,7 @@ export class ColorListControl extends React.PureComponent<ParamProps<PD.ColorLis } isInterpolatedChanged: ParamOnChange = ({ value }) => { - this.update({ kind: value ? 'interpolate' : 'set', colors: this.props.value.colors }) + this.update({ kind: value ? 'interpolate' : 'set', colors: this.props.value.colors }); } renderColors() { @@ -709,7 +709,7 @@ export class Vec3Control extends React.PureComponent<ParamProps<PD.Vec3>, { isEx render() { const v = this.props.value; const label = this.props.param.label || camelCaseToWords(this.props.name); - const p = getPrecision(this.props.param.step || 0.01) + const p = getPrecision(this.props.param.step || 0.01); const value = `[${v[0].toFixed(p)}, ${v[1].toFixed(p)}, ${v[2].toFixed(p)}]`; return <> <ControlRow label={label} control={<button onClick={this.toggleExpanded} disabled={this.props.isDisabled}>{value}</button>} /> @@ -783,7 +783,7 @@ export class FileControl extends React.PureComponent<ParamProps<PD.FileParam>> { return <div className='msp-btn msp-btn-block msp-btn-action msp-loader-msp-btn-file' style={{ marginTop: '1px' }}> {value ? value.name : 'Select a file...'} <input disabled={this.props.isDisabled} onChange={this.onChangeFile} type='file' multiple={false} accept={this.props.param.accept} /> - </div> + </div>; } } @@ -799,19 +799,19 @@ export class FileListControl extends React.PureComponent<ParamProps<PD.FileListP render() { const value = this.props.value; - const names: string[] = [] + const names: string[] = []; if (value) { for (let i = 0, il = value.length; i < il; ++i) { - names.push(value[i].name) + names.push(value[i].name); } } const label = names.length === 0 ? 'Select files...' : names.length === 1 - ? names[0] : `${names.length} files selected` + ? names[0] : `${names.length} files selected`; return <div className='msp-btn msp-btn-block msp-btn-action msp-loader-msp-btn-file' style={{ marginTop: '1px' }}> {label} <input disabled={this.props.isDisabled} onChange={this.onChangeFileList} type='file' multiple={true} accept={this.props.param.accept} /> - </div> + </div>; } } @@ -827,7 +827,7 @@ export class MultiSelectControl extends React.PureComponent<ParamProps<PD.MultiS if (this.props.value.indexOf(key) < 0) this.change(this.props.value.concat(key)); else this.change(this.props.value.filter(v => v !== key)); e.currentTarget.blur(); - } + }; } toggleExpanded = (e: React.MouseEvent<HTMLButtonElement>) => { @@ -848,7 +848,7 @@ export class MultiSelectControl extends React.PureComponent<ParamProps<PD.MultiS const sel = current.indexOf(value) >= 0; return <Button key={value} onClick={this.toggle(value)} disabled={this.props.isDisabled} style={{ marginTop: '1px' }}> <span style={{ float: sel ? 'left' : 'right' }}>{sel ? `✓ ${label}` : `${label} ✗`}</span> - </Button> + </Button>; })} </div>} </>; @@ -927,7 +927,7 @@ export class GroupControl extends React.PureComponent<ParamProps<PD.Group<any>> {this.state.isExpanded && <div className='msp-control-offset'> {controls} </div>} - </div> + </div>; } } @@ -938,13 +938,13 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> // I think there are currently no cases where this could happen in the UI, but still need to watch out.. private valuesCache: { [name: string]: PD.Values<any> } = {} private setValues(name: string, values: PD.Values<any>) { - this.valuesCache[name] = values + this.valuesCache[name] = values; } private getValues(name: string) { if (name in this.valuesCache) { - return this.valuesCache[name] + return this.valuesCache[name]; } else { - return this.props.param.map(name).defaultValue + return this.props.param.map(name).defaultValue; } } @@ -957,7 +957,7 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> } onChangeParam: ParamOnChange = e => { - this.setValues(this.props.value.name, e.value) + this.setValues(this.props.value.name, e.value); this.change({ name: this.props.value.name, params: e.value }); } @@ -976,17 +976,17 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> const label = this.props.param.label || camelCaseToWords(this.props.name); const Mapped = controlFor(param); - const help = this.props.param.help + const help = this.props.param.help; const select = help ? { ...this.props.param.select, help: (name: any) => help({ name, params: this.getValues(name) }) } - : this.props.param.select + : this.props.param.select; const Select = <SelectControl param={select} isDisabled={this.props.isDisabled} onChange={this.onChangeName} onEnter={this.props.onEnter} - name={label} value={value.name} /> + name={label} value={value.name} />; if (!Mapped) { return Select; @@ -998,7 +998,7 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> {Select} <IconButton icon='dot-3' onClick={this.toggleExpanded} toggleState={this.state.isExpanded} title={`${label} Properties`} /> {this.state.isExpanded && <GroupControl inMapped param={param} value={value.params} name={value.name} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} />} - </div> + </div>; } return Select; @@ -1007,7 +1007,7 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> return <> {Select} <Mapped param={param} value={value.params} name={value.name} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> - </> + </>; } } @@ -1162,14 +1162,14 @@ export class ConditionedControl extends React.PureComponent<ParamProps<PD.Condit render() { const value = this.props.value; - const condition = this.props.param.conditionForValue(value) as string + const condition = this.props.param.conditionForValue(value) as string; const param = this.props.param.conditionParams[condition]; const label = this.props.param.label || camelCaseToWords(this.props.name); const Conditioned = controlFor(param); const select = <SelectControl param={this.props.param.select} isDisabled={this.props.isDisabled} onChange={this.onChangeCondition} onEnter={this.props.onEnter} - name={`${label} Kind`} value={condition} /> + name={`${label} Kind`} value={condition} />; if (!Conditioned) { return select; @@ -1178,7 +1178,7 @@ export class ConditionedControl extends React.PureComponent<ParamProps<PD.Condit return <> {select} <Conditioned param={param} value={value} name={label} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> - </> + </>; } } @@ -1196,7 +1196,7 @@ export class ConvertedControl extends React.PureComponent<ParamProps<PD.Converte const Converted = controlFor(this.props.param.converted); if (!Converted) return null; - return <Converted param={this.props.param.converted} value={value} name={this.props.name} onChange={this.onChange} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} /> + return <Converted param={this.props.param.converted} value={value} name={this.props.name} onChange={this.onChange} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} />; } } diff --git a/src/mol-plugin-ui/controls/slider.tsx b/src/mol-plugin-ui/controls/slider.tsx index 12a66eeef40d88d2f402f7d7183fcffe7436651c..3795d5a65d965ea5d65e5a6f2c24566e3909dc57 100644 --- a/src/mol-plugin-ui/controls/slider.tsx +++ b/src/mol-plugin-ui/controls/slider.tsx @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as React from 'react' +import * as React from 'react'; import { NumericInput } from './common'; import { noop } from '../../mol-util'; @@ -106,7 +106,7 @@ export class Slider2 extends React.Component<{ updateMax = (v: number) => { let n = v; if (this.props.step === 1) n = Math.round(n); - if (n < this.state.current[0]) n = this.state.current[0] + if (n < this.state.current[0]) n = this.state.current[0]; else if (n < this.props.min) n = this.props.min; if (n > this.props.max) n = this.props.max; this.props.onChange([this.state.current[0], n]); diff --git a/src/mol-plugin-ui/custom/volume.tsx b/src/mol-plugin-ui/custom/volume.tsx index 9d8ad3dc893fd4f2bbcedbab0744b8cd15d0fa3c..c79567707037e4681a1c6dfe0bdbe53ec8c37de5 100644 --- a/src/mol-plugin-ui/custom/volume.tsx +++ b/src/mol-plugin-ui/custom/volume.tsx @@ -41,7 +41,7 @@ function Channel(props: { const value = Math.round(100 * (channel.isoValue.kind === 'relative' ? channel.isoValue.relativeValue : channel.isoValue.absoluteValue)) / 100; const relMin = (min - mean) / sigma; const relMax = (max - mean) / sigma; - const step = toPrecision(isRelative ? Math.round(((max - min) / sigma)) / 100 : sigma / 100, 2) + const step = toPrecision(isRelative ? Math.round(((max - min) / sigma)) / 100 : sigma / 100, 2); return <ExpandableControlRow label={props.label + (props.isRelative ? ' \u03C3' : '')} @@ -63,7 +63,7 @@ export class VolumeStreamingCustomControls extends PluginUIComponent<StateTransf } changeIso = (name: string, value: number, isRelative: boolean) => { - const old = this.props.params as VolumeStreaming.Params + const old = this.props.params as VolumeStreaming.Params; this.newParams({ ...old, entry: { @@ -107,11 +107,11 @@ export class VolumeStreamingCustomControls extends PluginUIComponent<StateTransf ...channel, isoValue: isRelative ? VolumeIsoValue.toRelative(channel.isoValue, stats) : VolumeIsoValue.toAbsolute(channel.isoValue, stats) - } + }; } changeOption: ParamOnChange = ({ name, value }) => { - const old = this.props.params as VolumeStreaming.Params + const old = this.props.params as VolumeStreaming.Params; if (name === 'entry') { this.newParams({ @@ -177,7 +177,7 @@ export class VolumeStreamingCustomControls extends PluginUIComponent<StateTransf const params = this.props.params as VolumeStreaming.Params; const detailLevel = ((this.props.info.params as VolumeStreaming.ParamDefinition) - .entry.map(params.entry.name) as PD.Group<VolumeStreaming.EntryParamDefinition>).params.detailLevel + .entry.map(params.entry.name) as PD.Group<VolumeStreaming.EntryParamDefinition>).params.detailLevel; const isRelative = ((params.entry.params.channels as any)[pivot].isoValue as VolumeIsoValue).kind === 'relative'; const sampling = b.info.header.sampling[0]; @@ -235,6 +235,6 @@ export class VolumeStreamingCustomControls extends PluginUIComponent<StateTransf {isEM && <Channel label='EM' name='em' channels={params.entry.params.channels} changeIso={this.changeIso} changeParams={this.changeParams} isRelative={isRelative} params={this.props} stats={sampling.valuesInfo[0]} />} <ParameterControls onChange={this.changeOption} params={OptionsParams} values={options} onEnter={this.props.events.onEnter} /> - </> + </>; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/left-panel.tsx b/src/mol-plugin-ui/left-panel.tsx index 678ca2add5eb98b3fedaffe1a85df2b8a386d86b..4b666d58ed31bc0529201aee82cb9794e89afb82 100644 --- a/src/mol-plugin-ui/left-panel.tsx +++ b/src/mol-plugin-ui/left-panel.tsx @@ -97,7 +97,7 @@ class DataIcon extends PluginUIComponent<{ set: (tab: LeftPanelTabName) => void state = { changed: false }; get tab() { - return this.plugin.behaviors.layout.leftPanelTabName.value + return this.plugin.behaviors.layout.leftPanelTabName.value; } componentDidMount() { @@ -129,9 +129,9 @@ class FullSettings extends PluginUIComponent { this.subscribe(this.plugin.canvas3d!.camera.stateChanged, state => { if (state.radiusMax !== undefined || state.radius !== undefined) { - this.forceUpdate() + this.forceUpdate(); } - }) + }); } icon(name: IconName, onClick: (e: React.MouseEvent<HTMLButtonElement>) => void, title: string, isOn = true) { @@ -146,7 +146,7 @@ class FullSettings extends PluginUIComponent { </>} <SectionHeader title='Behavior' /> <StateTree state={this.plugin.state.behaviors} /> - </> + </>; } } diff --git a/src/mol-plugin-ui/plugin.tsx b/src/mol-plugin-ui/plugin.tsx index 3cf28088d07f857ca6cac06b0fd3ec9a337d32da..895fd0e7f5ca080cae8ef715a8aed0223f9d4788 100644 --- a/src/mol-plugin-ui/plugin.tsx +++ b/src/mol-plugin-ui/plugin.tsx @@ -24,7 +24,7 @@ export class Plugin extends React.Component<{ plugin: PluginContext }, {}> { <div className='msp-layout-static'> {element} </div> - </div> + </div>; } render() { @@ -63,39 +63,39 @@ class Layout extends PluginUIComponent { const layout = this.plugin.layout.state; const controls = (this.plugin.spec.layout && this.plugin.spec.layout.controls) || { }; - const classList: string[] = [] + const classList: string[] = []; if (controls.top === 'none' || !layout.showControls || layout.regionState.top === 'hidden') { - classList.push('msp-layout-hide-top') + classList.push('msp-layout-hide-top'); } if (controls.left === 'none' || !layout.showControls || layout.regionState.left === 'hidden') { - classList.push('msp-layout-hide-left') + classList.push('msp-layout-hide-left'); } else if (layout.regionState.left === 'collapsed') { - classList.push('msp-layout-collapse-left') + classList.push('msp-layout-collapse-left'); } if (controls.right === 'none' || !layout.showControls || layout.regionState.right === 'hidden') { - classList.push('msp-layout-hide-right') + classList.push('msp-layout-hide-right'); } if (controls.bottom === 'none' || !layout.showControls || layout.regionState.bottom === 'hidden') { - classList.push('msp-layout-hide-bottom') + classList.push('msp-layout-hide-bottom'); } - return classList.join(' ') + return classList.join(' '); } get layoutClassName() { const layout = this.plugin.layout.state; - const classList: string[] = ['msp-plugin-content'] + const classList: string[] = ['msp-plugin-content']; if (layout.isExpanded) { - classList.push('msp-layout-expanded') + classList.push('msp-layout-expanded'); } else { - classList.push('msp-layout-standard', `msp-layout-standard-${layout.controlsDisplay}`) + classList.push('msp-layout-standard', `msp-layout-standard-${layout.controlsDisplay}`); } - return classList.join(' ') + return classList.join(' '); } render() { diff --git a/src/mol-plugin-ui/sequence.tsx b/src/mol-plugin-ui/sequence.tsx index 3ab5dacbdd35f3663119fc3b1205e68797f0141f..6032974b7a4da8ef18799cc62b575029c0ce12fb 100644 --- a/src/mol-plugin-ui/sequence.tsx +++ b/src/mol-plugin-ui/sequence.tsx @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as React from 'react' +import * as React from 'react'; import { PluginUIComponent } from './base'; import { PluginStateObject as PSO } from '../mol-plugin-state/objects'; import { Sequence } from './sequence/sequence'; @@ -23,165 +23,165 @@ import { elementLabel } from '../mol-theme/label'; import { Icon } from './controls/icons'; import { StructureSelectionManager } from '../mol-plugin-state/manager/structure/selection'; -const MaxDisplaySequenceLength = 5000 +const MaxDisplaySequenceLength = 5000; function opKey(l: StructureElement.Location) { - const ids = SP.unit.pdbx_struct_oper_list_ids(l) - const ncs = SP.unit.struct_ncs_oper_id(l) - const hkl = SP.unit.hkl(l) - const spgrOp = SP.unit.spgrOp(l) - return `${ids.sort().join(',')}|${ncs}|${hkl}|${spgrOp}` + const ids = SP.unit.pdbx_struct_oper_list_ids(l); + const ncs = SP.unit.struct_ncs_oper_id(l); + const hkl = SP.unit.hkl(l); + const spgrOp = SP.unit.spgrOp(l); + return `${ids.sort().join(',')}|${ncs}|${hkl}|${spgrOp}`; } function splitModelEntityId(modelEntityId: string) { - const [ modelIdx, entityId ] = modelEntityId.split('|') - return [ parseInt(modelIdx), entityId ] + const [ modelIdx, entityId ] = modelEntityId.split('|'); + return [ parseInt(modelIdx), entityId ]; } function getSequenceWrapper(state: SequenceViewState, structureSelection: StructureSelectionManager): SequenceWrapper.Any | string { - const { structure, modelEntityId, chainGroupId, operatorKey } = state - const l = StructureElement.Location.create(structure) - const [ modelIdx, entityId ] = splitModelEntityId(modelEntityId) + const { structure, modelEntityId, chainGroupId, operatorKey } = state; + const l = StructureElement.Location.create(structure); + const [ modelIdx, entityId ] = splitModelEntityId(modelEntityId); - const units: Unit[] = [] + const units: Unit[] = []; for (const unit of structure.units) { - StructureElement.Location.set(l, structure, unit, unit.elements[0]) - if (structure.getModelIndex(unit.model) !== modelIdx) continue - if (SP.entity.id(l) !== entityId) continue - if (unit.chainGroupId !== chainGroupId) continue - if (opKey(l) !== operatorKey) continue + StructureElement.Location.set(l, structure, unit, unit.elements[0]); + if (structure.getModelIndex(unit.model) !== modelIdx) continue; + if (SP.entity.id(l) !== entityId) continue; + if (unit.chainGroupId !== chainGroupId) continue; + if (opKey(l) !== operatorKey) continue; - units.push(unit) + units.push(unit); } if (units.length > 0) { - const data = { structure, units } - const unit = units[0] + const data = { structure, units }; + const unit = units[0]; - let sw: SequenceWrapper<any> + let sw: SequenceWrapper<any>; if (unit.polymerElements.length) { - const l = StructureElement.Location.create(structure, unit, unit.elements[0]) - const entitySeq = unit.model.sequence.byEntityKey[SP.entity.key(l)] + const l = StructureElement.Location.create(structure, unit, unit.elements[0]); + const entitySeq = unit.model.sequence.byEntityKey[SP.entity.key(l)]; // check if entity sequence is available if (entitySeq && entitySeq.sequence.length <= MaxDisplaySequenceLength) { - sw = new PolymerSequenceWrapper(data) + sw = new PolymerSequenceWrapper(data); } else { - const polymerElementCount = units.reduce((a, v) => a + v.polymerElements.length, 0) + const polymerElementCount = units.reduce((a, v) => a + v.polymerElements.length, 0); if (Unit.isAtomic(unit) || polymerElementCount > MaxDisplaySequenceLength) { - sw = new ChainSequenceWrapper(data) + sw = new ChainSequenceWrapper(data); } else { - sw = new ElementSequenceWrapper(data) + sw = new ElementSequenceWrapper(data); } } } else if (Unit.isAtomic(unit)) { - const residueCount = units.reduce((a, v) => a + (v as Unit.Atomic).residueCount, 0) + const residueCount = units.reduce((a, v) => a + (v as Unit.Atomic).residueCount, 0); if (residueCount > MaxDisplaySequenceLength) { - sw = new ChainSequenceWrapper(data) + sw = new ChainSequenceWrapper(data); } else { - sw = new HeteroSequenceWrapper(data) + sw = new HeteroSequenceWrapper(data); } } else { - console.warn('should not happen, expecting coarse units to be polymeric') - sw = new ChainSequenceWrapper(data) + console.warn('should not happen, expecting coarse units to be polymeric'); + sw = new ChainSequenceWrapper(data); } - sw.markResidue(structureSelection.getLoci(structure), MarkerAction.Select) - return sw + sw.markResidue(structureSelection.getLoci(structure), MarkerAction.Select); + return sw; } else { - return 'No sequence available' + return 'No sequence available'; } } function getModelEntityOptions(structure: Structure) { - const options: [string, string][] = [] - const l = StructureElement.Location.create(structure) - const seen = new Set<string>() + const options: [string, string][] = []; + const l = StructureElement.Location.create(structure); + const seen = new Set<string>(); for (const unit of structure.units) { - StructureElement.Location.set(l, structure, unit, unit.elements[0]) - const id = SP.entity.id(l) - const modelIdx = structure.getModelIndex(unit.model) - const key = `${modelIdx}|${id}` - if (seen.has(key)) continue + StructureElement.Location.set(l, structure, unit, unit.elements[0]); + const id = SP.entity.id(l); + const modelIdx = structure.getModelIndex(unit.model); + const key = `${modelIdx}|${id}`; + if (seen.has(key)) continue; - let description = SP.entity.pdbx_description(l).join(', ') + let description = SP.entity.pdbx_description(l).join(', '); if (structure.models.length) { if (structure.representativeModel) { // indicates model trajectory - description += ` (Model ${structure.models[modelIdx].modelNum})` + description += ` (Model ${structure.models[modelIdx].modelNum})`; } else if (description.startsWith('Polymer ')) { // indicates generic entity name - description += ` (${structure.models[modelIdx].entry})` + description += ` (${structure.models[modelIdx].entry})`; } } - const label = `${id}: ${description}` - options.push([ key, label ]) - seen.add(key) + const label = `${id}: ${description}`; + options.push([ key, label ]); + seen.add(key); } - if (options.length === 0) options.push(['', 'No entities']) - return options + if (options.length === 0) options.push(['', 'No entities']); + return options; } function getChainOptions(structure: Structure, modelEntityId: string) { - const options: [number, string][] = [] - const l = StructureElement.Location.create(structure) - const seen = new Set<number>() - const [ modelIdx, entityId ] = splitModelEntityId(modelEntityId) + const options: [number, string][] = []; + const l = StructureElement.Location.create(structure); + const seen = new Set<number>(); + const [ modelIdx, entityId ] = splitModelEntityId(modelEntityId); for (const unit of structure.units) { - StructureElement.Location.set(l, structure, unit, unit.elements[0]) - if (structure.getModelIndex(unit.model) !== modelIdx) continue - if (SP.entity.id(l) !== entityId) continue + StructureElement.Location.set(l, structure, unit, unit.elements[0]); + if (structure.getModelIndex(unit.model) !== modelIdx) continue; + if (SP.entity.id(l) !== entityId) continue; - const id = unit.chainGroupId - if (seen.has(id)) continue + const id = unit.chainGroupId; + if (seen.has(id)) continue; // TODO handle special case // - more than one chain in a unit - let label = elementLabel(l, { granularity: 'chain', hidePrefix: true, htmlStyling: false }) + let label = elementLabel(l, { granularity: 'chain', hidePrefix: true, htmlStyling: false }); - options.push([ id, label ]) - seen.add(id) + options.push([ id, label ]); + seen.add(id); } - if (options.length === 0) options.push([-1, 'No units']) - return options + if (options.length === 0) options.push([-1, 'No units']); + return options; } function getOperatorOptions(structure: Structure, modelEntityId: string, chainGroupId: number) { - const options: [string, string][] = [] - const l = StructureElement.Location.create(structure) - const seen = new Set<string>() - const [ modelIdx, entityId ] = splitModelEntityId(modelEntityId) + const options: [string, string][] = []; + const l = StructureElement.Location.create(structure); + const seen = new Set<string>(); + const [ modelIdx, entityId ] = splitModelEntityId(modelEntityId); for (const unit of structure.units) { - StructureElement.Location.set(l, structure, unit, unit.elements[0]) - if (structure.getModelIndex(unit.model) !== modelIdx) continue - if (SP.entity.id(l) !== entityId) continue - if (unit.chainGroupId !== chainGroupId) continue + StructureElement.Location.set(l, structure, unit, unit.elements[0]); + if (structure.getModelIndex(unit.model) !== modelIdx) continue; + if (SP.entity.id(l) !== entityId) continue; + if (unit.chainGroupId !== chainGroupId) continue; - const id = opKey(l) - if (seen.has(id)) continue + const id = opKey(l); + if (seen.has(id)) continue; - const label = unit.conformation.operator.name - options.push([ id, label ]) - seen.add(id) + const label = unit.conformation.operator.name; + options.push([ id, label ]); + seen.add(id); } - if (options.length === 0) options.push(['', 'No operators']) - return options + if (options.length === 0) options.push(['', 'No operators']); + return options; } function getStructureOptions(state: State) { - const options: [string, string][] = [] + const options: [string, string][] = []; - const structures = state.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure)) + const structures = state.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure)); for (const s of structures) { - options.push([s.transform.ref, s.obj!.data.label]) + options.push([s.transform.ref, s.obj!.data.label]); } - if (options.length === 0) options.push(['', 'No structure']) - return options + if (options.length === 0) options.push(['', 'No structure']); + return options; } type SequenceViewState = { @@ -196,23 +196,23 @@ export class SequenceView extends PluginUIComponent<{ }, SequenceViewState> { state = { structure: Structure.Empty, structureRef: '', modelEntityId: '', chainGroupId: -1, operatorKey: '' } componentDidMount() { - if (this.plugin.state.data.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure)).length > 0) this.setState(this.getInitialState()) + if (this.plugin.state.data.select(StateSelection.Generators.rootsOfType(PSO.Molecule.Structure)).length > 0) this.setState(this.getInitialState()); this.subscribe(this.plugin.events.state.object.updated, ({ ref, obj }) => { if (ref === this.state.structureRef && obj && obj.type === PSO.Molecule.Structure.type && obj.data !== this.state.structure) { - this.setState(this.getInitialState()) + this.setState(this.getInitialState()); } }); this.subscribe(this.plugin.events.state.object.created, ({ obj }) => { if (obj && obj.type === PSO.Molecule.Structure.type) { - this.setState(this.getInitialState()) + this.setState(this.getInitialState()); } }); this.subscribe(this.plugin.events.state.object.removed, ({ obj }) => { if (obj && obj.type === PSO.Molecule.Structure.type && obj.data === this.state.structure) { - this.setState(this.getInitialState()) + this.setState(this.getInitialState()); } }); } @@ -225,35 +225,35 @@ export class SequenceView extends PluginUIComponent<{ }, SequenceViewState> { } private getSequenceWrapper() { - return getSequenceWrapper(this.state, this.plugin.managers.structure.selection) + return getSequenceWrapper(this.state, this.plugin.managers.structure.selection); } private getInitialState(): SequenceViewState { - const structureRef = getStructureOptions(this.plugin.state.data)[0][0] - const structure = this.getStructure(structureRef) - let modelEntityId = getModelEntityOptions(structure)[0][0] - let chainGroupId = getChainOptions(structure, modelEntityId)[0][0] - let operatorKey = getOperatorOptions(structure, modelEntityId, chainGroupId)[0][0] + const structureRef = getStructureOptions(this.plugin.state.data)[0][0]; + const structure = this.getStructure(structureRef); + let modelEntityId = getModelEntityOptions(structure)[0][0]; + let chainGroupId = getChainOptions(structure, modelEntityId)[0][0]; + let operatorKey = getOperatorOptions(structure, modelEntityId, chainGroupId)[0][0]; if (this.state.structure && this.state.structure === structure) { - modelEntityId = this.state.modelEntityId - chainGroupId = this.state.chainGroupId - operatorKey = this.state.operatorKey + modelEntityId = this.state.modelEntityId; + chainGroupId = this.state.chainGroupId; + operatorKey = this.state.operatorKey; } - return { structure, structureRef, modelEntityId, chainGroupId, operatorKey } + return { structure, structureRef, modelEntityId, chainGroupId, operatorKey }; } private get params() { - const { structure, modelEntityId, chainGroupId } = this.state - const structureOptions = getStructureOptions(this.plugin.state.data) - const entityOptions = getModelEntityOptions(structure) - const chainOptions = getChainOptions(structure, modelEntityId) - const operatorOptions = getOperatorOptions(structure, modelEntityId, chainGroupId) + const { structure, modelEntityId, chainGroupId } = this.state; + const structureOptions = getStructureOptions(this.plugin.state.data); + const entityOptions = getModelEntityOptions(structure); + const chainOptions = getChainOptions(structure, modelEntityId); + const operatorOptions = getOperatorOptions(structure, modelEntityId, chainGroupId); return { structure: PD.Select(structureOptions[0][0], structureOptions, { shortLabel: true }), entity: PD.Select(entityOptions[0][0], entityOptions, { shortLabel: true }), chain: PD.Select(chainOptions[0][0], chainOptions, { shortLabel: true, twoColumns: true, label: 'Chain' }), operator: PD.Select(operatorOptions[0][0], operatorOptions, { shortLabel: true, twoColumns: true }) - } + }; } private get values(): PD.Values<SequenceView['params']> { @@ -262,33 +262,33 @@ export class SequenceView extends PluginUIComponent<{ }, SequenceViewState> { entity: this.state.modelEntityId, chain: this.state.chainGroupId, operator: this.state.operatorKey - } + }; } private setParamProps = (p: { param: PD.Base<any>, name: string, value: any }) => { - const state = { ...this.state } + const state = { ...this.state }; switch (p.name) { case 'structure': - state.structureRef = p.value - state.structure = this.getStructure(p.value) - state.modelEntityId = getModelEntityOptions(state.structure)[0][0] - state.chainGroupId = getChainOptions(state.structure, state.modelEntityId)[0][0] - state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0] - break + state.structureRef = p.value; + state.structure = this.getStructure(p.value); + state.modelEntityId = getModelEntityOptions(state.structure)[0][0]; + state.chainGroupId = getChainOptions(state.structure, state.modelEntityId)[0][0]; + state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0]; + break; case 'entity': - state.modelEntityId = p.value - state.chainGroupId = getChainOptions(state.structure, state.modelEntityId)[0][0] - state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0] - break + state.modelEntityId = p.value; + state.chainGroupId = getChainOptions(state.structure, state.modelEntityId)[0][0]; + state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0]; + break; case 'chain': - state.chainGroupId = p.value - state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0] - break + state.chainGroupId = p.value; + state.operatorKey = getOperatorOptions(state.structure, state.modelEntityId, state.chainGroupId)[0][0]; + break; case 'operator': - state.operatorKey = p.value - break + state.operatorKey = p.value; + break; } - this.setState(state) + this.setState(state); } render() { @@ -303,7 +303,7 @@ export class SequenceView extends PluginUIComponent<{ }, SequenceViewState> { </div>; } - const sequenceWrapper = this.getSequenceWrapper() + const sequenceWrapper = this.getSequenceWrapper(); const params = this.params; const values = this.values; diff --git a/src/mol-plugin-ui/sequence/chain.ts b/src/mol-plugin-ui/sequence/chain.ts index af12258cdcd74ebaae338faaff9e6904f048eb21..34508c231f4a3b4cc2b6d3084e561a63eeee7ce4 100644 --- a/src/mol-plugin-ui/sequence/chain.ts +++ b/src/mol-plugin-ui/sequence/chain.ts @@ -17,73 +17,73 @@ export class ChainSequenceWrapper extends SequenceWrapper<StructureUnit> { private loci: StructureElement.Loci residueLabel(seqIdx: number) { - return this.label + return this.label; } residueColor(seqIdx: number) { - return ColorNames.black + return ColorNames.black; } residueClass(seqIdx: number) { - return 'msp-sequence-present' + return 'msp-sequence-present'; } mark(loci: Loci, action: MarkerAction) { - let changed = false - const { structure } = this.data + let changed = false; + const { structure } = this.data; if (StructureElement.Loci.is(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - loci = StructureElement.Loci.remap(loci, structure) + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + loci = StructureElement.Loci.remap(loci, structure); for (const e of loci.elements) { - const indices = this.unitIndices.get(e.unit.id) + const indices = this.unitIndices.get(e.unit.id); if (indices) { if (OrderedSet.isSubset(indices, e.indices)) { - if (applyMarkerAction(this.markerArray, Interval.ofSingleton(0), action)) changed = true + if (applyMarkerAction(this.markerArray, Interval.ofSingleton(0), action)) changed = true; } } } } else if (Structure.isLoci(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; - if (applyMarkerAction(this.markerArray, Interval.ofSingleton(0), action)) changed = true + if (applyMarkerAction(this.markerArray, Interval.ofSingleton(0), action)) changed = true; } - return changed + return changed; } getLoci(seqIdx: number) { - return this.loci + return this.loci; } constructor(data: StructureUnit) { - let residueCount = 0 - let elementCount = 0 - const counts: string[] = [] - const l = StructureElement.Location.create(data.structure) + let residueCount = 0; + let elementCount = 0; + const counts: string[] = []; + const l = StructureElement.Location.create(data.structure); - const unitIndices = new Map<number, Interval<StructureElement.UnitIndex>>() - const lociElements: StructureElement.Loci['elements'][0][] = [] + const unitIndices = new Map<number, Interval<StructureElement.UnitIndex>>(); + const lociElements: StructureElement.Loci['elements'][0][] = []; for (let i = 0, il = data.units.length; i < il; ++i) { - const unit = data.units[i] - StructureElement.Location.set(l, data.structure, unit, unit.elements[0]) - const entitySeq = unit.model.sequence.byEntityKey[StructureProperties.entity.key(l)] - if (entitySeq) residueCount += entitySeq.sequence.length - elementCount += unit.elements.length + const unit = data.units[i]; + StructureElement.Location.set(l, data.structure, unit, unit.elements[0]); + const entitySeq = unit.model.sequence.byEntityKey[StructureProperties.entity.key(l)]; + if (entitySeq) residueCount += entitySeq.sequence.length; + elementCount += unit.elements.length; - const indices = Interval.ofBounds(0, unit.elements.length) - unitIndices.set(unit.id, indices) - lociElements.push({ unit, indices }) + const indices = Interval.ofBounds(0, unit.elements.length); + unitIndices.set(unit.id, indices); + lociElements.push({ unit, indices }); } - if (residueCount > 0) counts.push(`${residueCount} residues`) - counts.push(`${elementCount} elements`) + if (residueCount > 0) counts.push(`${residueCount} residues`); + counts.push(`${elementCount} elements`); - const length = 1 - const markerArray = new Uint8Array(length) + const length = 1; + const markerArray = new Uint8Array(length); - super(data, markerArray, length) + super(data, markerArray, length); - this.label = `Whole Chain (${counts.join(', ')})` - this.unitIndices = unitIndices - this.loci = StructureElement.Loci(this.data.structure, lociElements) + this.label = `Whole Chain (${counts.join(', ')})`; + this.unitIndices = unitIndices; + this.loci = StructureElement.Loci(this.data.structure, lociElements); } } \ No newline at end of file diff --git a/src/mol-plugin-ui/sequence/element.ts b/src/mol-plugin-ui/sequence/element.ts index d75d5e4900054a4ce97857c3102917d789f8ae82..18d3ce5ba198256c9f07e82aab7c1f35d608fb69 100644 --- a/src/mol-plugin-ui/sequence/element.ts +++ b/src/mol-plugin-ui/sequence/element.ts @@ -15,74 +15,74 @@ export class ElementSequenceWrapper extends SequenceWrapper<StructureUnit> { private unitIndices: Map<number, Interval<StructureElement.UnitIndex>> residueLabel(seqIdx: number) { - return 'X' + return 'X'; } residueColor(seqIdx: number) { - return ColorNames.black + return ColorNames.black; } residueClass(seqIdx: number) { - return 'msp-sequence-present' + return 'msp-sequence-present'; } mark(loci: Loci, action: MarkerAction) { - let changed = false - const { structure, units } = this.data + let changed = false; + const { structure, units } = this.data; if (StructureElement.Loci.is(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - loci = StructureElement.Loci.remap(loci, structure) + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + loci = StructureElement.Loci.remap(loci, structure); for (const e of loci.elements) { - const indices = this.unitIndices.get(e.unit.id) + const indices = this.unitIndices.get(e.unit.id); if (indices) { if (OrderedSet.isSubset(indices, e.indices)) { - if (applyMarkerAction(this.markerArray, e.indices, action)) changed = true + if (applyMarkerAction(this.markerArray, e.indices, action)) changed = true; } } } } else if (Structure.isLoci(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; for (let i = 0, il = units.length; i < il; ++i) { - const indices = this.unitIndices.get(units[i].id)! - if (applyMarkerAction(this.markerArray, indices, action)) changed = true + const indices = this.unitIndices.get(units[i].id)!; + if (applyMarkerAction(this.markerArray, indices, action)) changed = true; } } - return changed + return changed; } getLoci(seqIdx: number) { - const { units } = this.data - const lociElements: StructureElement.Loci['elements'][0][] = [] - let offset = 0 + const { units } = this.data; + const lociElements: StructureElement.Loci['elements'][0][] = []; + let offset = 0; for (let i = 0, il = units.length; i < il; ++i) { - const unit = units[i] + const unit = units[i]; if (seqIdx < offset + unit.elements.length) { - lociElements.push({ unit, indices: Interval.ofSingleton(seqIdx - offset) }) - break + lociElements.push({ unit, indices: Interval.ofSingleton(seqIdx - offset) }); + break; } - offset += unit.elements.length + offset += unit.elements.length; } - return StructureElement.Loci(this.data.structure, lociElements) + return StructureElement.Loci(this.data.structure, lociElements); } constructor(data: StructureUnit) { - let length = 0 + let length = 0; - const unitIndices = new Map<number, Interval<StructureElement.UnitIndex>>() - const lociElements: StructureElement.Loci['elements'][0][] = [] + const unitIndices = new Map<number, Interval<StructureElement.UnitIndex>>(); + const lociElements: StructureElement.Loci['elements'][0][] = []; for (let i = 0, il = data.units.length; i < il; ++i) { - const unit = data.units[i] - length += unit.elements.length + const unit = data.units[i]; + length += unit.elements.length; - const indices = Interval.ofBounds(0, unit.elements.length) - unitIndices.set(unit.id, indices) - lociElements.push({ unit, indices }) + const indices = Interval.ofBounds(0, unit.elements.length); + unitIndices.set(unit.id, indices); + lociElements.push({ unit, indices }); } - const markerArray = new Uint8Array(length) + const markerArray = new Uint8Array(length); - super(data, markerArray, length) + super(data, markerArray, length); - this.unitIndices = unitIndices + this.unitIndices = unitIndices; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/sequence/hetero.ts b/src/mol-plugin-ui/sequence/hetero.ts index 8f0fcb23e77b29448c0cfb7c727dd3e49ba137fe..aaa036e0f7e0f4c1d9ba6fd08f6fc396d3f2598b 100644 --- a/src/mol-plugin-ui/sequence/hetero.ts +++ b/src/mol-plugin-ui/sequence/hetero.ts @@ -19,83 +19,83 @@ export class HeteroSequenceWrapper extends SequenceWrapper<StructureUnit> { private readonly seqToUnit: Map<number, Unit> residueLabel(seqIdx: number) { - return this.sequence[seqIdx] + return this.sequence[seqIdx]; } residueColor(seqIdx: number) { - return ColorNames.black + return ColorNames.black; } residueClass(seqIdx: number) { - return 'msp-sequence-present' + return 'msp-sequence-present'; } mark(loci: Loci, action: MarkerAction) { - let changed = false - const { structure } = this.data + let changed = false; + const { structure } = this.data; if (StructureElement.Loci.is(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - loci = StructureElement.Loci.remap(loci, structure) + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + loci = StructureElement.Loci.remap(loci, structure); for (const e of loci.elements) { - const unit = this.unitMap.get(e.unit.id) + const unit = this.unitMap.get(e.unit.id); if (unit) { - const { index: residueIndex } = e.unit.model.atomicHierarchy.residueAtomSegments + const { index: residueIndex } = e.unit.model.atomicHierarchy.residueAtomSegments; OrderedSet.forEach(e.indices, v => { - const seqIdx = this.sequenceIndices.get(residueIndex[unit.elements[v]]) - if (seqIdx !== undefined && applyMarkerAction(this.markerArray, Interval.ofSingleton(seqIdx), action)) changed = true - }) + const seqIdx = this.sequenceIndices.get(residueIndex[unit.elements[v]]); + if (seqIdx !== undefined && applyMarkerAction(this.markerArray, Interval.ofSingleton(seqIdx), action)) changed = true; + }); } } } else if (Structure.isLoci(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; - if (applyMarkerAction(this.markerArray, Interval.ofBounds(0, this.length), action)) changed = true + if (applyMarkerAction(this.markerArray, Interval.ofBounds(0, this.length), action)) changed = true; } - return changed + return changed; } getLoci(seqIdx: number) { - const elements: StructureElement.Loci['elements'][0][] = [] - const rI = this.residueIndices.get(seqIdx) + const elements: StructureElement.Loci['elements'][0][] = []; + const rI = this.residueIndices.get(seqIdx); if (rI !== undefined) { - const unit = this.seqToUnit.get(seqIdx)! - const { offsets } = unit.model.atomicHierarchy.residueAtomSegments - const start = SortedArray.findPredecessorIndex(unit.elements, offsets[rI]) - const end = SortedArray.findPredecessorIndex(unit.elements, offsets[rI + 1]) - elements.push({ unit, indices: Interval.ofBounds(start, end) }) + const unit = this.seqToUnit.get(seqIdx)!; + const { offsets } = unit.model.atomicHierarchy.residueAtomSegments; + const start = SortedArray.findPredecessorIndex(unit.elements, offsets[rI]); + const end = SortedArray.findPredecessorIndex(unit.elements, offsets[rI + 1]); + elements.push({ unit, indices: Interval.ofBounds(start, end) }); } - return StructureElement.Loci(this.data.structure, elements) + return StructureElement.Loci(this.data.structure, elements); } constructor(data: StructureUnit) { - const sequence: string[] = [] - const sequenceIndices = new Map<ResidueIndex, number>() - const residueIndices = new Map<number, ResidueIndex>() - const seqToUnit = new Map<number, Unit>() + const sequence: string[] = []; + const sequenceIndices = new Map<ResidueIndex, number>(); + const residueIndices = new Map<number, ResidueIndex>(); + const seqToUnit = new Map<number, Unit>(); for (let i = 0, il = data.units.length; i < il; ++i) { - const unit = data.units[i] - const { residueAtomSegments, residues } = unit.model.atomicHierarchy - const residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements) + const unit = data.units[i]; + const { residueAtomSegments, residues } = unit.model.atomicHierarchy; + const residueIt = Segmentation.transientSegments(residueAtomSegments, unit.elements); while (residueIt.hasNext) { - const { index } = residueIt.move() - sequenceIndices.set(index, sequence.length) - residueIndices.set(sequence.length, index) - seqToUnit.set(sequence.length, unit) - sequence.push(residues.label_comp_id.value(index)) + const { index } = residueIt.move(); + sequenceIndices.set(index, sequence.length); + residueIndices.set(sequence.length, index); + seqToUnit.set(sequence.length, unit); + sequence.push(residues.label_comp_id.value(index)); } } - const length = sequence.length - const markerArray = new Uint8Array(length) + const length = sequence.length; + const markerArray = new Uint8Array(length); - super(data, markerArray, length) + super(data, markerArray, length); - this.unitMap = new Map() - for (const unit of data.units) this.unitMap.set(unit.id, unit) + this.unitMap = new Map(); + for (const unit of data.units) this.unitMap.set(unit.id, unit); - this.sequence = sequence - this.sequenceIndices = sequenceIndices - this.residueIndices = residueIndices - this.seqToUnit = seqToUnit + this.sequence = sequence; + this.sequenceIndices = sequenceIndices; + this.residueIndices = residueIndices; + this.seqToUnit = seqToUnit; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/sequence/polymer.ts b/src/mol-plugin-ui/sequence/polymer.ts index cc17ca8a3fd2aaba9e691acde2d0e9a93ddf9add..5042f26a5362a3da61a30b416b865dbb2d540b5b 100644 --- a/src/mol-plugin-ui/sequence/polymer.ts +++ b/src/mol-plugin-ui/sequence/polymer.ts @@ -23,32 +23,32 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> { private readonly asymId: string private seqId(seqIdx: number) { - return this.sequence.seqId.value(seqIdx) + return this.sequence.seqId.value(seqIdx); } residueLabel(seqIdx: number) { - return this.sequence.label.value(seqIdx) + return this.sequence.label.value(seqIdx); } residueColor(seqIdx: number) { return this.missing.has(this.modelNum, this.asymId, this.seqId(seqIdx)) ? ColorNames.grey - : ColorNames.black + : ColorNames.black; } residueClass(seqIdx: number) { return this.missing.has(this.modelNum, this.asymId, this.seqId(seqIdx)) ? 'msp-sequence-missing' - : 'msp-sequence-present' + : 'msp-sequence-present'; } mark(loci: Loci, action: MarkerAction): boolean { - let changed = false - const { structure } = this.data + let changed = false; + const { structure } = this.data; if (StructureElement.Loci.is(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - loci = StructureElement.Loci.remap(loci, structure) + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + loci = StructureElement.Loci.remap(loci, structure); - const { offset } = this.sequence + const { offset } = this.sequence; for (const e of loci.elements) { if (!this.unitMap.has(e.unit.id)) continue; @@ -59,10 +59,10 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> { } } } else if (Structure.isLoci(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - if (applyMarkerAction(this.markerArray, this.observed, action)) changed = true + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + if (applyMarkerAction(this.markerArray, this.observed, action)) changed = true; } - return changed + return changed; } getLoci(seqIdx: number) { @@ -71,28 +71,28 @@ export class PolymerSequenceWrapper extends SequenceWrapper<StructureUnit> { } constructor(data: StructureUnit) { - const l = StructureElement.Location.create(data.structure, data.units[0], data.units[0].elements[0]) - const entitySeq = data.units[0].model.sequence.byEntityKey[SP.entity.key(l)] + const l = StructureElement.Location.create(data.structure, data.units[0], data.units[0].elements[0]); + const entitySeq = data.units[0].model.sequence.byEntityKey[SP.entity.key(l)]; - const length = entitySeq.sequence.length - const markerArray = new Uint8Array(length) + const length = entitySeq.sequence.length; + const markerArray = new Uint8Array(length); - super(data, markerArray, length) + super(data, markerArray, length); - this.unitMap = new Map() - for (const unit of data.units) this.unitMap.set(unit.id, unit) + this.unitMap = new Map(); + for (const unit of data.units) this.unitMap.set(unit.id, unit); - this.sequence = entitySeq.sequence - this.missing = data.units[0].model.properties.missingResidues + this.sequence = entitySeq.sequence; + this.missing = data.units[0].model.properties.missingResidues; - this.modelNum = data.units[0].model.modelNum - this.asymId = Unit.isAtomic(data.units[0]) ? SP.chain.label_asym_id(l) : SP.coarse.asym_id(l) + this.modelNum = data.units[0].model.modelNum; + this.asymId = Unit.isAtomic(data.units[0]) ? SP.chain.label_asym_id(l) : SP.coarse.asym_id(l); - const missing: number[] = [] + const missing: number[] = []; for (let i = 0; i < length; ++i) { - if (this.missing.has(this.modelNum, this.asymId, this.seqId(i))) missing.push(i) + if (this.missing.has(this.modelNum, this.asymId, this.seqId(i))) missing.push(i); } - this.observed = OrderedSet.subtract(Interval.ofBounds(0, length), SortedArray.ofSortedArray(missing)) + this.observed = OrderedSet.subtract(Interval.ofBounds(0, length), SortedArray.ofSortedArray(missing)); } } @@ -102,16 +102,16 @@ function createResidueQuery(chainGroupId: number, operatorName: string, label_se return ( SP.unit.chainGroupId(ctx.element) === chainGroupId && SP.unit.operator_name(ctx.element) === operatorName - ) + ); }, residueTest: ctx => { if (ctx.element.unit.kind === Unit.Kind.Atomic) { - return SP.residue.label_seq_id(ctx.element) === label_seq_id + return SP.residue.label_seq_id(ctx.element) === label_seq_id; } else { return ( SP.coarse.seq_id_begin(ctx.element) <= label_seq_id && SP.coarse.seq_id_end(ctx.element) >= label_seq_id - ) + ); } } }); @@ -124,7 +124,7 @@ function applyMarkerAtomic(e: StructureElement.Loci.Element, action: MarkerActio let changed = false; OrderedSet.forEachSegment(e.indices, i => index[elements[i]], rI => { - const seqId = label_seq_id.value(rI) + const seqId = label_seq_id.value(rI); changed = applyMarkerActionAtPosition(markerArray, seqId - 1 - offset, action) || changed; }); return changed; diff --git a/src/mol-plugin-ui/sequence/sequence.tsx b/src/mol-plugin-ui/sequence/sequence.tsx index 195bbd152c42dbece74d20807a4d3d3e8ff00f1d..653ccc1e0460c77f95227377261d6abc48de58af 100644 --- a/src/mol-plugin-ui/sequence/sequence.tsx +++ b/src/mol-plugin-ui/sequence/sequence.tsx @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as React from 'react' +import * as React from 'react'; import { PluginUIComponent } from '../base'; import { MarkerAction } from '../../mol-util/marker-action'; import { ButtonsType, ModifiersKeys, getButtons, getModifiers, getButton } from '../../mol-util/input/input-observer'; @@ -23,7 +23,7 @@ type SequenceProps = { } /** Note, if this is changed, the CSS for `msp-sequence-number` needs adjustment too */ -const MaxSequenceNumberSize = 5 +const MaxSequenceNumberSize = 5; // TODO: this is somewhat inefficient and should be done using a canvas. export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { @@ -32,31 +32,31 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { private highlightQueue = new Subject<{ seqIdx: number, buttons: number, button: number, modifiers: ModifiersKeys }>(); private lociHighlightProvider = (loci: Representation.Loci, action: MarkerAction) => { - const changed = this.props.sequenceWrapper.markResidue(loci.loci, action) + const changed = this.props.sequenceWrapper.markResidue(loci.loci, action); if (changed) this.updateMarker(); } private lociSelectionProvider = (loci: Representation.Loci, action: MarkerAction) => { - const changed = this.props.sequenceWrapper.markResidue(loci.loci, action) + const changed = this.props.sequenceWrapper.markResidue(loci.loci, action); if (changed) this.updateMarker(); } private get sequenceNumberPeriod() { if (this.props.sequenceNumberPeriod !== undefined) { - return this.props.sequenceNumberPeriod as number + return this.props.sequenceNumberPeriod as number; } - if (this.props.sequenceWrapper.length > 10) return 10 - const lastSeqNum = this.getSequenceNumber(this.props.sequenceWrapper.length - 1) - if (lastSeqNum.length > 1) return 5 - return 1 + if (this.props.sequenceWrapper.length > 10) return 10; + const lastSeqNum = this.getSequenceNumber(this.props.sequenceWrapper.length - 1); + if (lastSeqNum.length > 1) return 5; + return 1; } componentDidMount() { - this.plugin.managers.interactivity.lociHighlights.addProvider(this.lociHighlightProvider) - this.plugin.managers.interactivity.lociSelects.addProvider(this.lociSelectionProvider) + this.plugin.managers.interactivity.lociHighlights.addProvider(this.lociHighlightProvider); + this.plugin.managers.interactivity.lociSelects.addProvider(this.lociSelectionProvider); this.subscribe(debounceTime<{ seqIdx: number, buttons: number, button: number, modifiers: ModifiersKeys }>(15)(this.highlightQueue), (e) => { - const loci = this.getLoci(e.seqIdx < 0 ? void 0 : e.seqIdx) + const loci = this.getLoci(e.seqIdx < 0 ? void 0 : e.seqIdx); this.hover(loci, e.buttons, e.button, e.modifiers); }); @@ -66,14 +66,14 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { componentWillUnmount() { super.componentWillUnmount(); - this.plugin.managers.interactivity.lociHighlights.removeProvider(this.lociHighlightProvider) - this.plugin.managers.interactivity.lociSelects.removeProvider(this.lociSelectionProvider) + this.plugin.managers.interactivity.lociHighlights.removeProvider(this.lociHighlightProvider); + this.plugin.managers.interactivity.lociSelects.removeProvider(this.lociSelectionProvider); } getLoci(seqIdx: number | undefined) { if (seqIdx !== undefined) { const loci = this.props.sequenceWrapper.getLoci(seqIdx); - if (!StructureElement.Loci.isEmpty(loci)) return loci + if (!StructureElement.Loci.isEmpty(loci)) return loci; } } @@ -83,27 +83,27 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { if (el && el.getAttribute) { seqIdx = el.hasAttribute('data-seqid') ? +el.getAttribute('data-seqid')! : undefined; } - return seqIdx + return seqIdx; } hover(loci: StructureElement.Loci | undefined, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys) { - const ev = { current: Representation.Loci.Empty, buttons, button, modifiers } + const ev = { current: Representation.Loci.Empty, buttons, button, modifiers }; if (loci !== undefined && !StructureElement.Loci.isEmpty(loci)) { ev.current = { loci }; } - this.plugin.behaviors.interaction.hover.next(ev) + this.plugin.behaviors.interaction.hover.next(ev); } click(loci: StructureElement.Loci | undefined, buttons: ButtonsType, button: ButtonsType.Flag, modifiers: ModifiersKeys) { - const ev = { current: Representation.Loci.Empty, buttons, button, modifiers } + const ev = { current: Representation.Loci.Empty, buttons, button, modifiers }; if (loci !== undefined && !StructureElement.Loci.isEmpty(loci)) { ev.current = { loci }; } - this.plugin.behaviors.interaction.click.next(ev) + this.plugin.behaviors.interaction.click.next(ev); } contextMenu = (e: React.MouseEvent) => { - e.preventDefault() + e.preventDefault(); } private mouseDownLoci: StructureElement.Loci | undefined = undefined @@ -111,11 +111,11 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { mouseDown = (e: React.MouseEvent) => { e.stopPropagation(); - const seqIdx = this.getSeqIdx(e) - const loci = this.getLoci(seqIdx) - const buttons = getButtons(e.nativeEvent) - const button = getButton(e.nativeEvent) - const modifiers = getModifiers(e.nativeEvent) + const seqIdx = this.getSeqIdx(e); + const loci = this.getLoci(seqIdx); + const buttons = getButtons(e.nativeEvent); + const button = getButton(e.nativeEvent); + const modifiers = getModifiers(e.nativeEvent); this.click(loci, buttons, button, modifiers); this.mouseDownLoci = loci; @@ -125,20 +125,20 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { e.stopPropagation(); // ignore mouse-up events without a bound loci - if (this.mouseDownLoci === undefined) return + if (this.mouseDownLoci === undefined) return; - const seqIdx = this.getSeqIdx(e) - const loci = this.getLoci(seqIdx) + const seqIdx = this.getSeqIdx(e); + const loci = this.getLoci(seqIdx); if (loci && !StructureElement.Loci.areEqual(this.mouseDownLoci, loci)) { - const buttons = getButtons(e.nativeEvent) - const button = getButton(e.nativeEvent) - const modifiers = getModifiers(e.nativeEvent) + const buttons = getButtons(e.nativeEvent); + const button = getButton(e.nativeEvent); + const modifiers = getModifiers(e.nativeEvent); - const ref = this.mouseDownLoci.elements[0] - const ext = loci.elements[0] - const min = Math.min(OrderedSet.min(ref.indices), OrderedSet.min(ext.indices)) - const max = Math.max(OrderedSet.max(ref.indices), OrderedSet.max(ext.indices)) + const ref = this.mouseDownLoci.elements[0]; + const ext = loci.elements[0]; + const min = Math.min(OrderedSet.min(ref.indices), OrderedSet.min(ext.indices)); + const max = Math.max(OrderedSet.max(ref.indices), OrderedSet.max(ext.indices)); const range = StructureElement.Loci(loci.structure, [{ unit: ref.unit, @@ -152,7 +152,7 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { private getBackgroundColor(marker: number) { // TODO: make marker color configurable - if (typeof marker === 'undefined') console.error('unexpected marker value') + if (typeof marker === 'undefined') console.error('unexpected marker value'); return marker === 0 ? '' : marker % 2 === 0 ? 'rgb(51, 255, 25)' /* selected */ : 'rgb(255, 102, 153)' /* highlighted */; } @@ -167,31 +167,31 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { } private getSequenceNumberClass(seqIdx: number, seqNum: string, label: string) { - const classList = ['msp-sequence-number'] + const classList = ['msp-sequence-number']; if (seqNum.startsWith('-')) { - if (label.length > 1 && seqIdx > 0) classList.push('msp-sequence-number-long-negative') - else classList.push('msp-sequence-number-negative') + if (label.length > 1 && seqIdx > 0) classList.push('msp-sequence-number-long-negative'); + else classList.push('msp-sequence-number-negative'); } else { - if (label.length > 1 && seqIdx > 0) classList.push('msp-sequence-number-long') + if (label.length > 1 && seqIdx > 0) classList.push('msp-sequence-number-long'); } - return classList.join(' ') + return classList.join(' '); } private location = StructureElement.Location.create(void 0); private getSequenceNumber(seqIdx: number) { - let seqNum = '' - const loci = this.props.sequenceWrapper.getLoci(seqIdx) + let seqNum = ''; + const loci = this.props.sequenceWrapper.getLoci(seqIdx); const l = StructureElement.Loci.getFirstLocation(loci, this.location); if (l) { if (Unit.isAtomic(l.unit)) { - const seqId = StructureProperties.residue.auth_seq_id(l) - const insCode = StructureProperties.residue.pdbx_PDB_ins_code(l) - seqNum = `${seqId}${insCode ? insCode : ''}` + const seqId = StructureProperties.residue.auth_seq_id(l); + const insCode = StructureProperties.residue.pdbx_PDB_ins_code(l); + seqNum = `${seqId}${insCode ? insCode : ''}`; } else if (Unit.isCoarse(l.unit)) { - seqNum = `${seqIdx + 1}` + seqNum = `${seqIdx + 1}`; } } - return seqNum + return seqNum; } private padSeqNum(n: string) { @@ -199,8 +199,8 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { return n; } private getSequenceNumberSpan(seqIdx: number, label: string) { - const seqNum = this.getSequenceNumber(seqIdx) - return <span key={`marker-${seqIdx}`} className={this.getSequenceNumberClass(seqIdx, seqNum, label)}>{this.padSeqNum(seqNum)}</span> + const seqNum = this.getSequenceNumber(seqIdx); + return <span key={`marker-${seqIdx}`} className={this.getSequenceNumberClass(seqIdx, seqNum, label)}>{this.padSeqNum(seqNum)}</span>; } private updateMarker() { @@ -235,15 +235,15 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { mouseMove = (e: React.MouseEvent) => { e.stopPropagation(); - const buttons = getButtons(e.nativeEvent) - const button = getButton(e.nativeEvent) - const modifiers = getModifiers(e.nativeEvent) + const buttons = getButtons(e.nativeEvent); + const button = getButton(e.nativeEvent); + const modifiers = getModifiers(e.nativeEvent); const el = e.target as HTMLElement; if (!el || !el.getAttribute) { if (this.lastMouseOverSeqIdx === -1) return; this.lastMouseOverSeqIdx = -1; - this.highlightQueue.next({ seqIdx: -1, buttons, button, modifiers }) + this.highlightQueue.next({ seqIdx: -1, buttons, button, modifiers }); return; } const seqIdx = el.hasAttribute('data-seqid') ? +el.getAttribute('data-seqid')! : -1; @@ -252,10 +252,10 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { } else { this.lastMouseOverSeqIdx = seqIdx; if (this.mouseDownLoci !== undefined) { - const loci = this.getLoci(seqIdx) - this.hover(loci, ButtonsType.Flag.None, ButtonsType.Flag.None, { ...modifiers, shift: true }) + const loci = this.getLoci(seqIdx); + this.hover(loci, ButtonsType.Flag.None, ButtonsType.Flag.None, { ...modifiers, shift: true }); } else { - this.highlightQueue.next({ seqIdx, buttons, button, modifiers }) + this.highlightQueue.next({ seqIdx, buttons, button, modifiers }); } } } @@ -266,30 +266,30 @@ export class Sequence<P extends SequenceProps> extends PluginUIComponent<P> { if (this.lastMouseOverSeqIdx === -1) return; this.lastMouseOverSeqIdx = -1; - const buttons = getButtons(e.nativeEvent) - const button = getButton(e.nativeEvent) - const modifiers = getModifiers(e.nativeEvent) - this.highlightQueue.next({ seqIdx: -1, buttons, button, modifiers }) + const buttons = getButtons(e.nativeEvent); + const button = getButton(e.nativeEvent); + const modifiers = getModifiers(e.nativeEvent); + this.highlightQueue.next({ seqIdx: -1, buttons, button, modifiers }); } render() { - const sw = this.props.sequenceWrapper + const sw = this.props.sequenceWrapper; const elems: JSX.Element[] = []; const hasNumbers = !this.props.hideSequenceNumbers, period = this.sequenceNumberPeriod; for (let i = 0, il = sw.length; i < il; ++i) { - const label = sw.residueLabel(i) + const label = sw.residueLabel(i); // add sequence number before name so the html element do not get separated by a line-break if (hasNumbers && i % period === 0 && i < il) { - elems[elems.length] = this.getSequenceNumberSpan(i, label) + elems[elems.length] = this.getSequenceNumberSpan(i, label); } elems[elems.length] = this.residue(i, label, sw.markerArray[i]); } // calling .updateMarker here is neccesary to ensure existing // residue spans are updated as react won't update them - this.updateMarker() + this.updateMarker(); return <div className='msp-sequence-wrapper msp-sequence-wrapper-non-empty' diff --git a/src/mol-plugin-ui/sequence/wrapper.ts b/src/mol-plugin-ui/sequence/wrapper.ts index 2bd41ede93e5a7aec09835f2e98994a41b1ebb52..fd206229db7087fad7fbd2b6995f250c63fd672f 100644 --- a/src/mol-plugin-ui/sequence/wrapper.ts +++ b/src/mol-plugin-ui/sequence/wrapper.ts @@ -12,7 +12,7 @@ import { Color } from '../../mol-util/color'; export type StructureUnit = { structure: Structure, units: Unit[] } -export { SequenceWrapper } +export { SequenceWrapper }; abstract class SequenceWrapper<D> { abstract residueLabel(seqIdx: number): string @@ -25,7 +25,7 @@ abstract class SequenceWrapper<D> { markResidue(loci: Loci, action: MarkerAction) { if (isEveryLoci(loci)) { - return applyMarkerAction(this.markerArray, Interval.ofLength(this.length), action) + return applyMarkerAction(this.markerArray, Interval.ofLength(this.length), action); } else { return this.mark(loci, action); } diff --git a/src/mol-plugin-ui/state/animation.tsx b/src/mol-plugin-ui/state/animation.tsx index 9abf17b8e646956fd9db54d4b79e417840019764..1ed41d96c85ce12a5b559cfef2468eca32e7f051 100644 --- a/src/mol-plugin-ui/state/animation.tsx +++ b/src/mol-plugin-ui/state/animation.tsx @@ -17,7 +17,7 @@ export class AnimationControlsWrapper extends PluginUIComponent<{ }> { return <div className='msp-controls-section'> <div className='msp-section-header'><Icon name='code' /> Animations</div> <AnimationControls /> - </div> + </div>; } } diff --git a/src/mol-plugin-ui/state/common.tsx b/src/mol-plugin-ui/state/common.tsx index fdf573e2f928c88a355e017f81330c394b13d633..064a11598640de31060c71230ab6b0efe4ae50bc 100644 --- a/src/mol-plugin-ui/state/common.tsx +++ b/src/mol-plugin-ui/state/common.tsx @@ -86,7 +86,7 @@ namespace StateTransformParameters { initialValues, params, isEmpty: areParamsEmpty(params) - } + }; } } @@ -169,7 +169,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS if (this.state.busy !== b) this.busy.next(b); }); this.subscribe(this.busy, busy => { - if (this.state.busy !== busy) this.setState({ busy }) + if (this.state.busy !== busy) this.setState({ busy }); }); } @@ -229,7 +229,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS params = <> <ParamEditor info={info} a={a} b={b} events={this.events} params={this.state.params} isDisabled={this.state.busy} /> {applyControl} - </> + </>; } const ctrl = <div className={wrapClass} style={{ marginBottom: this.props.noMargin ? 0 : void 0 }}> @@ -257,7 +257,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS {this.props.simpleApply?.header} </Button> {!info.isEmpty && <ToggleButton icon='cog' label='' title='Options' toggle={this.toggleExpanded} isSelected={!this.state.isCollapsed} disabled={this.state.busy} style={{ flex: '0 0 40px', padding: 0 }} />} - </div> + </div>; if (this.state.isCollapsed) return apply; @@ -270,7 +270,7 @@ abstract class TransformControlBase<P, S extends TransformControlBase.ComponentS return <> {apply} <ParamEditor info={info} a={a} b={b} events={this.events} params={this.state.params} isDisabled={this.state.busy} /> - </> + </>; } render() { diff --git a/src/mol-plugin-ui/state/snapshots.tsx b/src/mol-plugin-ui/state/snapshots.tsx index cb5359de3a0a34aa56af1bc43d78713f934bcb26..a3e425c64aedbeb948456c9e258f26c9d76b47da 100644 --- a/src/mol-plugin-ui/state/snapshots.tsx +++ b/src/mol-plugin-ui/state/snapshots.tsx @@ -210,10 +210,10 @@ export class RemoteStateSnapshots extends PluginUIComponent< }); } - this.setState({ entries: entries.asImmutable(), isBusy: false }) + this.setState({ entries: entries.asImmutable(), isBusy: false }); } catch (e) { this.plugin.log.error('Fetching Remote Snapshots: ' + e); - this.setState({ entries: OrderedMap(), isBusy: false }) + this.setState({ entries: OrderedMap(), isBusy: false }); } } diff --git a/src/mol-plugin-ui/state/tree.tsx b/src/mol-plugin-ui/state/tree.tsx index b939576c7cc859f604e52dea3fe1cdd8d3049a6a..93f23a12788c2cc2153db3771b47d46dd79fac90 100644 --- a/src/mol-plugin-ui/state/tree.tsx +++ b/src/mol-plugin-ui/state/tree.tsx @@ -6,7 +6,7 @@ import * as React from 'react'; import { PluginStateObject } from '../../mol-plugin-state/objects'; -import { State, StateTree as _StateTree, StateObject, StateTransform, StateObjectCell, StateAction } from '../../mol-state' +import { State, StateTree as _StateTree, StateObject, StateTransform, StateObjectCell, StateAction } from '../../mol-state'; import { PluginCommands } from '../../mol-plugin/commands'; import { PluginUIComponent, _Props, _State } from '../base'; import { Icon } from '../controls/icons'; @@ -44,7 +44,7 @@ export class StateTree extends PluginUIComponent<{ state: State }, { showActions return <div style={{ margin: '10px', cursor: 'default' }}> <p>Nothing to see here.</p> <p>Structures can be loaded from the <Icon name='home' /> tab.</p> - </div> + </div>; } return <StateTreeNode cell={this.props.state.cells.get(ref)!} depth={0} />; } @@ -297,13 +297,13 @@ class StateTreeNodeLabel extends PluginUIComponent<{ cell: StateObjectCell, dept const children = cell.parent!.tree.children.get(this.ref); const cellState = cell.state; - const expand = <IconButton icon={cellState.isCollapsed ? 'expand' : 'collapse'} flex='20px' disabled={disabled} onClick={this.toggleExpanded} transparent className='msp-no-hover-outline' style={{ visibility: children.size > 0 ? 'visible' : 'hidden' }} /> + const expand = <IconButton icon={cellState.isCollapsed ? 'expand' : 'collapse'} flex='20px' disabled={disabled} onClick={this.toggleExpanded} transparent className='msp-no-hover-outline' style={{ visibility: children.size > 0 ? 'visible' : 'hidden' }} />; const remove = !cell.state.isLocked ? <IconButton icon='remove' onClick={this.remove} disabled={disabled} small toggleState={false} /> : void 0; const visibility = <IconButton icon='visual-visibility' toggleState={!cellState.isHidden} disabled={disabled} small onClick={this.toggleVisible} />; const marginStyle: React.CSSProperties = { marginLeft: `${this.props.depth * 8}px` - } + }; const row = <div className={`msp-flex-row msp-tree-row${isCurrent ? ' msp-tree-row-current' : ''}`} onMouseEnter={this.highlight} onMouseLeave={this.clearHighlight} style={marginStyle}> {expand} @@ -320,7 +320,7 @@ class StateTreeNodeLabel extends PluginUIComponent<{ cell: StateObjectCell, dept <ControlGroup header={`Apply ${this.state.currentAction.definition.display.name}`} initialExpanded={true} hideExpander={true} hideOffset={false} onHeaderClick={this.hideApply} topRightIcon='off' headerLeftMargin={`${this.props.depth * 8 + 21}px`}> <ApplyActionControl onApply={this.hideApply} state={this.props.cell.parent!} action={this.state.currentAction} nodeRef={this.props.cell.transform.ref} hideHeader noMargin /> </ControlGroup> - </div> + </div>; } if (this.state.action === 'options') { @@ -332,7 +332,7 @@ class StateTreeNodeLabel extends PluginUIComponent<{ cell: StateObjectCell, dept {actions && <div style={{ marginLeft: `${this.props.depth * 8 + 21}px`, marginTop: '-1px' }}> <ActionMenu items={actions} onSelect={this.selectAction} /> </div>} - </div> + </div>; } return row; diff --git a/src/mol-plugin-ui/state/update-transform.tsx b/src/mol-plugin-ui/state/update-transform.tsx index 5edf852ed7b0a515bd01114400e9f102809a2438..b0f1aa2dc20d25b0e5f8b31a1f88c16e85bade1b 100644 --- a/src/mol-plugin-ui/state/update-transform.tsx +++ b/src/mol-plugin-ui/state/update-transform.tsx @@ -56,7 +56,7 @@ class UpdateTransformControl extends TransformControlBase<UpdateTransformControl } canAutoApply(newParams: any) { - const autoUpdate = this.props.transform.transformer.definition.canAutoUpdate + const autoUpdate = this.props.transform.transformer.definition.canAutoUpdate; if (!autoUpdate) return false; const { state } = this.props; @@ -76,7 +76,7 @@ class UpdateTransformControl extends TransformControlBase<UpdateTransformControl if (this.props.transform.ref !== ref || this.props.state !== state) return; if (this.state.params !== this.props.transform.params) { this._getInfo = memoizeLatest((t: StateTransform) => StateTransformParameters.infoFromTransform(this.plugin, this.props.state, t)); - this.setState({ params: this.props.transform.params, isInitial: true }) + this.setState({ params: this.props.transform.params, isInitial: true }); } }); } diff --git a/src/mol-plugin-ui/structure/components.tsx b/src/mol-plugin-ui/structure/components.tsx index a0e34263521094ee3ff7e4131c55aafe6930f5ef..76ffe5036cfc67581b5108c0cd741e9e1dce6fd5 100644 --- a/src/mol-plugin-ui/structure/components.tsx +++ b/src/mol-plugin-ui/structure/components.tsx @@ -58,7 +58,7 @@ class ComponentEditorControls extends PurePluginUIComponent<{}, ComponentEditorC }; get isDisabled() { - return this.state.isBusy || this.state.isEmpty + return this.state.isBusy || this.state.isEmpty; } componentDidMount() { @@ -67,7 +67,7 @@ class ComponentEditorControls extends PurePluginUIComponent<{}, ComponentEditorC isEmpty: c.structures.length === 0 })); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - this.setState({ isBusy: v, action: this.state.action !== 'options' ? void 0 : 'options' }) + this.setState({ isBusy: v, action: this.state.action !== 'options' ? void 0 : 'options' }); }); this.subscribe(this.plugin.state.data.events.historyUpdated, ({ state }) => { this.setState({ canUndo: state.canUndo }); @@ -84,7 +84,7 @@ class ComponentEditorControls extends PurePluginUIComponent<{}, ComponentEditorC hideAction = () => this.setState({ action: void 0 }); get presetControls() { - return <ActionMenu items={this.presetActions} onSelect={this.applyPreset} /> + return <ActionMenu items={this.presetActions} onSelect={this.applyPreset} />; } get presetActions() { @@ -185,7 +185,7 @@ class ComponentOptionsControls extends PurePluginUIComponent<{ isDisabled: boole class ComponentListControls extends PurePluginUIComponent { componentDidMount() { this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, () => { - this.forceUpdate() + this.forceUpdate(); }); } diff --git a/src/mol-plugin-ui/structure/focus.tsx b/src/mol-plugin-ui/structure/focus.tsx index 3d8a45b780b786d670ff7a100c862b89a4656ca2..f030b8fdc0ca9011e6efe7d6d0446dba49d6d805 100644 --- a/src/mol-plugin-ui/structure/focus.tsx +++ b/src/mol-plugin-ui/structure/focus.tsx @@ -25,71 +25,71 @@ interface StructureFocusControlsState { } function addSymmetryGroupEntries(entries: Map<string, FocusEntry[]>, location: StructureElement.Location, unitSymmetryGroup: Unit.SymmetryGroup) { - const idx = SortedArray.indexOf(location.unit.elements, location.element) as UnitIndex + const idx = SortedArray.indexOf(location.unit.elements, location.element) as UnitIndex; const base = StructureElement.Loci.extendToWholeResidues( StructureElement.Loci(location.structure, [ { unit: location.unit, indices: OrderedSet.ofSingleton(idx) } ]) - ) - const name = StructureProperties.entity.pdbx_description(location).join(', ') + ); + const name = StructureProperties.entity.pdbx_description(location).join(', '); for (const u of unitSymmetryGroup.units) { const loci = StructureElement.Loci(base.structure, [ { unit: u, indices: base.elements[0].indices } - ]) + ]); - let label = lociLabel(loci, { reverse: true, hidePrefix: true, htmlStyling: false, granularity: 'residue' }) - if (!label) label = lociLabel(loci, { hidePrefix: false, htmlStyling: false }) + let label = lociLabel(loci, { reverse: true, hidePrefix: true, htmlStyling: false, granularity: 'residue' }); + if (!label) label = lociLabel(loci, { hidePrefix: false, htmlStyling: false }); if (unitSymmetryGroup.units.length > 1) { - label += ` | ${loci.elements[0].unit.conformation.operator.name}` + label += ` | ${loci.elements[0].unit.conformation.operator.name}`; } - const item: FocusEntry = { label, category: name, loci } + const item: FocusEntry = { label, category: name, loci }; - if (entries.has(name)) entries.get(name)!.push(item) - else entries.set(name, [item]) + if (entries.has(name)) entries.get(name)!.push(item); + else entries.set(name, [item]); } } function getFocusEntries(structure: Structure) { - const entityEntries = new Map<string, FocusEntry[]>() - const l = StructureElement.Location.create(structure) + const entityEntries = new Map<string, FocusEntry[]>(); + const l = StructureElement.Location.create(structure); for (const ug of structure.unitSymmetryGroups) { - l.unit = ug.units[0] - l.element = ug.elements[0] - const entityType = StructureProperties.entity.type(l) - const isMultiChain = Unit.Traits.is(l.unit.traits, Unit.Trait.MultiChain) - const isPolymer = entityType === 'non-polymer' - const isBranched = entityType === 'branched' + l.unit = ug.units[0]; + l.element = ug.elements[0]; + const entityType = StructureProperties.entity.type(l); + const isMultiChain = Unit.Traits.is(l.unit.traits, Unit.Trait.MultiChain); + const isPolymer = entityType === 'non-polymer'; + const isBranched = entityType === 'branched'; if (isPolymer && !isMultiChain) { - addSymmetryGroupEntries(entityEntries, l, ug) + addSymmetryGroupEntries(entityEntries, l, ug); } else if (isBranched || (isPolymer && isMultiChain)) { - const u = l.unit - const { index: residueIndex } = u.model.atomicHierarchy.residueAtomSegments - let prev = -1 + const u = l.unit; + const { index: residueIndex } = u.model.atomicHierarchy.residueAtomSegments; + let prev = -1; for (let i = 0, il = u.elements.length; i < il; ++i) { - const eI = u.elements[i] - const rI = residueIndex[eI] + const eI = u.elements[i]; + const rI = residueIndex[eI]; if(rI !== prev) { - l.element = eI - addSymmetryGroupEntries(entityEntries, l, ug) - prev = rI + l.element = eI; + addSymmetryGroupEntries(entityEntries, l, ug); + prev = rI; } } } } - const entries: FocusEntry[] = [] + const entries: FocusEntry[] = []; entityEntries.forEach((e, name) => { if (e.length === 1) { - entries.push({ label: `${name}: ${e[0].label}`, loci: e[0].loci }) + entries.push({ label: `${name}: ${e[0].label}`, loci: e[0].loci }); } else { - entries.push(...e) + entries.push(...e); } - }) + }); - return entries + return entries; } export class StructureFocusControls extends PluginUIComponent<{}, StructureFocusControlsState> { @@ -107,20 +107,20 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus }); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - this.setState({ isBusy: v, showAction: false }) - }) + this.setState({ isBusy: v, showAction: false }); + }); } get isDisabled() { - return this.state.isBusy || this.actionItems.length === 0 + return this.state.isBusy || this.actionItems.length === 0; } getSelectionItems = memoizeLatest((structures: ReadonlyArray<StructureRef>) => { - const presetItems: ActionMenu.Items[] = [] + const presetItems: ActionMenu.Items[] = []; for (const s of structures) { - const d = s.cell.obj?.data + const d = s.cell.obj?.data; if (d) { - const entries = getFocusEntries(d) + const entries = getFocusEntries(d); if (entries.length > 0) { presetItems.push([ ActionMenu.Header(d.label, { description: d.label }), @@ -129,7 +129,7 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus category: f => f.category, description: f => f.label }) - ]) + ]); } } } @@ -137,8 +137,8 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus }); get actionItems() { - const historyItems: ActionMenu.Items[] = [] - const { history } = this.plugin.managers.structure.focus + const historyItems: ActionMenu.Items[] = []; + const { history } = this.plugin.managers.structure.focus; if (history.length > 0) { historyItems.push([ ActionMenu.Header('History', { description: 'Previously focused on items.' }), @@ -147,24 +147,24 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus description: f => { return f.category && f.label !== f.category ? `${f.category} | ${f.label}` - : f.label + : f.label; } }) - ]) + ]); } const presetItems: ActionMenu.Items[] = this.getSelectionItems(this.plugin.managers.structure.hierarchy.selection.structures); if (presetItems.length === 1) { - const item = presetItems[0] as ActionMenu.Items[] - const header = item[0] as ActionMenu.Header - header.initiallyExpanded = true + const item = presetItems[0] as ActionMenu.Items[]; + const header = item[0] as ActionMenu.Header; + header.initiallyExpanded = true; } - const items: ActionMenu.Items[] = [] - if (presetItems.length > 0) items.push(...presetItems) - if (historyItems.length > 0) items.push(...historyItems) + const items: ActionMenu.Items[] = []; + if (presetItems.length > 0) items.push(...presetItems); + if (historyItems.length > 0) items.push(...historyItems); - return items + return items; } selectAction: ActionMenu.OnSelect = (item, e) => { @@ -172,18 +172,18 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus this.setState({ showAction: false }); return; } - const f = item.value as FocusEntry + const f = item.value as FocusEntry; if (e?.shiftKey) { - this.plugin.managers.structure.focus.addFromLoci(f.loci) + this.plugin.managers.structure.focus.addFromLoci(f.loci); } else { - this.plugin.managers.structure.focus.set(f) + this.plugin.managers.structure.focus.set(f); } } toggleAction = () => this.setState({ showAction: !this.state.showAction }) focus = () => { - const { current } = this.plugin.managers.structure.focus + const { current } = this.plugin.managers.structure.focus; if (current) this.plugin.managers.camera.focusLoci(current.loci); } @@ -193,12 +193,12 @@ export class StructureFocusControls extends PluginUIComponent<{}, StructureFocus } highlightCurrent = () => { - const { current } = this.plugin.managers.structure.focus + const { current } = this.plugin.managers.structure.focus; if (current) this.plugin.managers.interactivity.lociHighlights.highlightOnly({ loci: current.loci }, false); } clearHighlights = () => { - this.plugin.managers.interactivity.lociHighlights.clearHighlights() + this.plugin.managers.interactivity.lociHighlights.clearHighlights(); } getToggleBindingLabel() { diff --git a/src/mol-plugin-ui/structure/generic.tsx b/src/mol-plugin-ui/structure/generic.tsx index c76a97e0d27900f7b2e8a3197a9aeabeb3ab12b9..9f9acfcaf11277241041d6e8bbb2b0ba8da6fcfd 100644 --- a/src/mol-plugin-ui/structure/generic.tsx +++ b/src/mol-plugin-ui/structure/generic.tsx @@ -37,16 +37,16 @@ export class GenericEntryListControls extends PurePluginUIComponent { } get customControls(): JSX.Element[] | null { - const controls: JSX.Element[] = [] + const controls: JSX.Element[] = []; this.plugin.genericRepresentationControls.forEach((provider, key) => { - const [refs, labelMultiple] = provider(this.plugin.managers.structure.hierarchy.selection) + const [refs, labelMultiple] = provider(this.plugin.managers.structure.hierarchy.selection); if (refs.length > 0) { controls.push(<div key={key}> <GenericEntry refs={refs} labelMultiple={labelMultiple} /> - </div>) + </div>); } - }) - return controls.length > 0 ? controls : null + }); + return controls.length > 0 ? controls : null; } render() { @@ -55,7 +55,7 @@ export class GenericEntryListControls extends PurePluginUIComponent { {this.unitcell} {this.customControls} </div> - </> + </>; } } @@ -111,7 +111,7 @@ export class GenericEntry<T extends HierarchyRef> extends PurePluginUIComponent< continue; } - const l = uc.cell.obj?.data.repr.getLoci() + const l = uc.cell.obj?.data.repr.getLoci(); if (l) loci.push(l); } this.plugin.managers.camera.focusLoci(loci); diff --git a/src/mol-plugin-ui/structure/measurements.tsx b/src/mol-plugin-ui/structure/measurements.tsx index 6bd76cbedb5f056c1132f2a85578ff1075fc4804..6bab12c4fe2fc92a582c5cd2ee64a341962842c7 100644 --- a/src/mol-plugin-ui/structure/measurements.tsx +++ b/src/mol-plugin-ui/structure/measurements.tsx @@ -29,14 +29,14 @@ export class StructureMeasurementsControls extends CollapsableControls { isCollapsed: false, header: 'Measurements', brand: { name: 'Msr', accent: 'gray' as const } - } + }; } renderControls() { return <> <MeasurementControls /> <MeasurementList /> - </> + </>; } } @@ -50,7 +50,7 @@ export class MeasurementList extends PurePluginUIComponent { renderGroup(cells: ReadonlyArray<StructureMeasurementCell>, header: string) { const group: JSX.Element[] = []; for (const cell of cells) { - if (cell.obj) group.push(<MeasurementEntry key={cell.obj.id} cell={cell} />) + if (cell.obj) group.push(<MeasurementEntry key={cell.obj.id} cell={cell} />); } return group.length ? <ExpandGroup header={header} initiallyExpanded={true}>{group}</ExpandGroup> : null; } @@ -164,7 +164,7 @@ export class MeasurementControls extends PurePluginUIComponent<{}, { isBusy: boo {entries.length === 0 && <div className='msp-control-offset msp-help-text'> <div className='msp-help-description'><Icon name='help-circle' />Add one or more selections</div> </div>} - </> + </>; } render() { @@ -175,7 +175,7 @@ export class MeasurementControls extends PurePluginUIComponent<{}, { isBusy: boo </div> {this.state.action === 'add' && this.add()} {this.state.action === 'options' && <MeasurementsOptions />} - </> + </>; } } @@ -188,8 +188,8 @@ class MeasurementsOptions extends PurePluginUIComponent<{}, { isDisabled: boolea }); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - console.log('isBusy', 'measurement opt', v) - this.setState({ isDisabled: v }) + console.log('isBusy', 'measurement opt', v); + this.setState({ isDisabled: v }); }); } @@ -250,7 +250,7 @@ class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasuremen const selections = this.selections; if (!selections) return; - const sphere = Loci.getBundleBoundingSphere(toLociBundle(selections.data)) + const sphere = Loci.getBundleBoundingSphere(toLociBundle(selections.data)); if (sphere) { this.plugin.managers.camera.focusSphere(sphere); } @@ -259,16 +259,16 @@ class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasuremen get label() { const selections = this.selections; switch (selections?.data.length) { - case 1: return lociLabel(selections.data[0].loci, { condensed: true }) - case 2: return distanceLabel(toLociBundle(selections.data), { condensed: true, unitLabel: this.plugin.managers.structure.measurement.state.options.distanceUnitLabel }) - case 3: return angleLabel(toLociBundle(selections.data), { condensed: true }) - case 4: return dihedralLabel(toLociBundle(selections.data), { condensed: true }) - default: return '' + case 1: return lociLabel(selections.data[0].loci, { condensed: true }); + case 2: return distanceLabel(toLociBundle(selections.data), { condensed: true, unitLabel: this.plugin.managers.structure.measurement.state.options.distanceUnitLabel }); + case 3: return angleLabel(toLociBundle(selections.data), { condensed: true }); + case 4: return dihedralLabel(toLociBundle(selections.data), { condensed: true }); + default: return ''; } } get actions(): ActionMenu.Items { - this.props.cell.sourceRef + this.props.cell.sourceRef; return [ActionMenu.Item('Select This', () => this.plugin.managers.structure.selection.fromSelections(this.props.cell.sourceRef!), { icon: 'set' })]; } @@ -300,10 +300,10 @@ class MeasurementEntry extends PurePluginUIComponent<{ cell: StructureMeasuremen </ExpandGroup> </div> </>} - </> + </>; } } function toLociBundle(data: FiniteArray<{ loci: Loci }, any>): { loci: FiniteArray<Loci, any> } { - return { loci: (data.map(d => d.loci) as unknown as FiniteArray<Loci, any>) } + return { loci: (data.map(d => d.loci) as unknown as FiniteArray<Loci, any>) }; } \ No newline at end of file diff --git a/src/mol-plugin-ui/structure/selection.tsx b/src/mol-plugin-ui/structure/selection.tsx index 1e77f854847331cce0f01f652a28944b734fd517..000f44cf52af2c4c54fac759695e870f12b92204 100644 --- a/src/mol-plugin-ui/structure/selection.tsx +++ b/src/mol-plugin-ui/structure/selection.tsx @@ -21,7 +21,7 @@ import { InteractivityManager } from '../../mol-plugin-state/manager/interactivi const StructureSelectionParams = { granularity: InteractivityManager.Params.granularity, -} +}; // interface StructureSelectionControlsState extends CollapsableState { // isEmpty: boolean, @@ -114,11 +114,11 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str }); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - this.setState({ isBusy: v, action: void 0 }) + this.setState({ isBusy: v, action: void 0 }); }); this.subscribe(this.plugin.managers.interactivity.events.propsUpdated, () => { - this.forceUpdate() + this.forceUpdate(); }); } @@ -127,7 +127,7 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str } set = (modifier: StructureSelectionModifier, selectionQuery: StructureSelectionQuery) => { - this.plugin.managers.structure.selection.fromSelectionQuery(modifier, selectionQuery, false) + this.plugin.managers.structure.selection.fromSelectionQuery(modifier, selectionQuery, false); } selectQuery: ActionMenu.OnSelect = item => { @@ -138,13 +138,13 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str const q = this.state.action! as StructureSelectionModifier; this.setState({ action: void 0 }, () => { this.set(q, item.value as StructureSelectionQuery); - }) + }); } private queriesItems: ActionMenu.Items[] = [] private queriesVersion = -1 get queries () { - const { registry } = this.plugin.query.structure + const { registry } = this.plugin.query.structure; if (registry.version !== this.queriesVersion) { this.queriesItems = ActionMenu.createItems(registry.list, { filter: q => q !== StructureSelectionQueries.current, @@ -152,9 +152,9 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str category: q => q.category, description: q => q.description }); - this.queriesVersion = registry.version + this.queriesVersion = registry.version; } - return this.queriesItems + return this.queriesItems; } private showAction(q: StructureSelectionActionsControlsState['action']) { @@ -193,7 +193,7 @@ export class StructureSelectionActionsControls extends PluginUIComponent<{}, Str <ApplyColorControls /> </ControlGroup> </div>} - </> + </>; } } @@ -205,7 +205,7 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnE componentDidMount() { this.subscribe(this.plugin.managers.structure.selection.events.changed, () => { - this.forceUpdate() + this.forceUpdate(); }); this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, c => { @@ -216,20 +216,20 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnE }); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - this.setState({ isBusy: v }) - }) + this.setState({ isBusy: v }); + }); } get isDisabled() { - return this.state.isBusy || this.state.isEmpty + return this.state.isBusy || this.state.isEmpty; } get stats() { - const stats = this.plugin.managers.structure.selection.stats + const stats = this.plugin.managers.structure.selection.stats; if (stats.structureCount === 0 || stats.elementCount === 0) { - return 'Nothing Selected' + return 'Nothing Selected'; } else { - return `${stripTags(stats.label)} Selected` + return `${stripTags(stats.label)} Selected`; } } @@ -245,7 +245,7 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnE this.plugin.managers.interactivity.lociHighlights.clearHighlights(); this.plugin.managers.structure.selection.entries.forEach(e => { this.plugin.managers.interactivity.lociHighlights.highlight({ loci: e.selection }, false); - }) + }); } clearHighlight = () => { @@ -253,7 +253,7 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnE } render() { - const stats = this.plugin.managers.structure.selection.stats + const stats = this.plugin.managers.structure.selection.stats; const empty = stats.structureCount === 0 || stats.elementCount === 0; if (empty && this.props.hideOnEmpty) return null; @@ -266,7 +266,7 @@ export class StructureSelectionStatsControls extends PluginUIComponent<{ hideOnE </Button> {!empty && <IconButton onClick={this.clear} icon='cancel' title='Clear' className='msp-form-control' flex />} </div> - </> + </>; } } diff --git a/src/mol-plugin-ui/structure/source.tsx b/src/mol-plugin-ui/structure/source.tsx index 79f50e402059a544e9eecd44b1023590aed48e52..ba48a38c439a1c0cf48e6cdff007d824311f1ae5 100644 --- a/src/mol-plugin-ui/structure/source.tsx +++ b/src/mol-plugin-ui/structure/source.tsx @@ -34,7 +34,7 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo componentDidMount() { this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, () => this.forceUpdate()); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - this.setState({ isBusy: v }) + this.setState({ isBusy: v }); }); } @@ -97,7 +97,7 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo ret.push([ ActionMenu.Header('Models'), ...current.models.map(this.item) - ]) + ]); } if (current.trajectories.length === 1 && current.models.length === 1) { @@ -147,9 +147,9 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo if (models.length === 1) { const model = models[0].cell.obj?.data; if (model?.trajectoryInfo.size! > 1) { - return `${t?.cell.obj?.label} | Model ${model?.trajectoryInfo.index! + 1} of ${model?.trajectoryInfo.size}` + return `${t?.cell.obj?.label} | Model ${model?.trajectoryInfo.index! + 1} of ${model?.trajectoryInfo.size}`; } else { - return `${t?.cell.obj?.label} | Model` + return `${t?.cell.obj?.label} | Model`; } } @@ -183,7 +183,7 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo for (const r of (i.value as HierarchyRef[])) refs.push(r); } - this.plugin.managers.structure.hierarchy.updateCurrent(refs, items[0].selected ? 'remove' : 'add') + this.plugin.managers.structure.hierarchy.updateCurrent(refs, items[0].selected ? 'remove' : 'add'); } toggleHierarchy = () => this.setState({ show: this.state.show !== 'hierarchy' ? 'hierarchy' : void 0 }); @@ -192,9 +192,9 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo get presetActions() { const actions: ActionMenu.Item[] = []; const { trajectories } = this.plugin.managers.structure.hierarchy.selection; - if (trajectories.length !== 1) return actions + if (trajectories.length !== 1) return actions; - const providers = this.plugin.builders.structure.hierarchy.getPresets(trajectories[0].cell.obj) + const providers = this.plugin.builders.structure.hierarchy.getPresets(trajectories[0].cell.obj); for (const p of providers) { actions.push(ActionMenu.Item(p.display.name, p, { description: p.display.description })); } @@ -228,7 +228,7 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo const params = m.cell.params?.definition; if (!params) return null; - return <ParameterControls params={params} values={m.cell.params?.values} onChangeValues={this.updateStructureModel} isDisabled={this.state.isBusy} /> + return <ParameterControls params={params} values={m.cell.params?.values} onChangeValues={this.updateStructureModel} isDisabled={this.state.isBusy} />; } updateStructure = (params: any) => { @@ -244,7 +244,7 @@ export class StructureSourceControls extends CollapsableControls<{}, StructureSo const params = s.cell.params?.definition; if (!params || !s.cell.parent) return null; - return <UpdateTransformControl state={s.cell.parent} transform={s.cell.transform} customHeader='none' customUpdate={this.updateStructure} noMargin autoHideApply /> + return <UpdateTransformControl state={s.cell.parent} transform={s.cell.transform} customHeader='none' customUpdate={this.updateStructure} noMargin autoHideApply />; } renderControls() { diff --git a/src/mol-plugin-ui/structure/volume.tsx b/src/mol-plugin-ui/structure/volume.tsx index 180c0b1e1e452d51635a8047e0a5db4b83add2ed..1d8d0f41b5e4eac71a01c20744a69dcc08df69f3 100644 --- a/src/mol-plugin-ui/structure/volume.tsx +++ b/src/mol-plugin-ui/structure/volume.tsx @@ -38,13 +38,13 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea this.setState({ isHidden: !this.canEnable(), description: StructureHierarchyManager.getSelectedStructuresDescription(this.plugin) - }) + }); }); this.subscribe(this.plugin.events.state.cell.stateUpdated, e => { if (StateTransform.hasTag(e.cell.transform, VolumeStreaming.RootTag)) this.forceUpdate(); }); this.subscribe(this.plugin.behaviors.state.isBusy, v => { - this.setState({ isBusy: v }) + this.setState({ isBusy: v }); }); } @@ -72,7 +72,7 @@ export class VolumeStreamingControls extends CollapsableControls<{}, VolumeStrea ? { header: 'Error enabling', icon: 'alert' as const, title: rootCell.errorText } : rootCell && rootCell.obj?.data.entries.length === 0 ? { header: 'Error enabling', icon: 'alert' as const, title: 'No entry for streaming found' } - : { header: 'Enable', icon: 'check' as const, title: 'Enable' } + : { header: 'Enable', icon: 'check' as const, title: 'Enable' }; return <ApplyActionControl state={pivot.cell.parent} action={InitVolumeStreaming} initiallyCollapsed={true} nodeRef={pivot.cell.transform.ref} simpleApply={simpleApply} />; } diff --git a/src/mol-plugin-ui/task.tsx b/src/mol-plugin-ui/task.tsx index dbfbd8192d201c3858e4039c720759e89dc9b5a3..68f8f2879c64506a3b1fda49d2de94f4fe358573 100644 --- a/src/mol-plugin-ui/task.tsx +++ b/src/mol-plugin-ui/task.tsx @@ -15,11 +15,11 @@ import { IconButton } from './controls/common'; export class BackgroundTaskProgress extends PluginUIComponent<{ }, { tracked: OrderedMap<number, TaskManager.ProgressEvent> }> { componentDidMount() { this.subscribe(this.plugin.events.task.progress.pipe(filter(e => e.level !== 'none')), e => { - this.setState({ tracked: this.state.tracked.set(e.id, e) }) + this.setState({ tracked: this.state.tracked.set(e.id, e) }); }); this.subscribe(this.plugin.events.task.finished, ({ id }) => { - this.setState({ tracked: this.state.tracked.delete(id) }) - }) + this.setState({ tracked: this.state.tracked.delete(id) }); + }); } state = { tracked: OrderedMap<number, TaskManager.ProgressEvent>() }; diff --git a/src/mol-plugin-ui/toast.tsx b/src/mol-plugin-ui/toast.tsx index 62b396c18200e6e18045284b48f59904dd3292dd..4d12432865f3104d400f50d129730472ac699c72 100644 --- a/src/mol-plugin-ui/toast.tsx +++ b/src/mol-plugin-ui/toast.tsx @@ -50,7 +50,7 @@ export class Toasts extends PluginUIComponent { const entries: PluginToastManager.Entry[] = []; state.entries.forEach((t, k) => entries.push(t!)); - entries.sort(function (x, y) { return x.serialNumber - y.serialNumber; }) + entries.sort(function (x, y) { return x.serialNumber - y.serialNumber; }); return <div className='msp-toast-container'> {entries.map(e => <ToastEntry key={e.serialNumber} entry={e} />)} diff --git a/src/mol-plugin-ui/viewport.tsx b/src/mol-plugin-ui/viewport.tsx index ad334477a3939fbd8b4ca4fd2af370b7b341a6e1..757468995420ea2dcb7cae805d797b0c96fbc678 100644 --- a/src/mol-plugin-ui/viewport.tsx +++ b/src/mol-plugin-ui/viewport.tsx @@ -82,7 +82,7 @@ export class ViewportControls extends PluginUIComponent<ViewportControlsProps, V onMouseMove = (e: React.MouseEvent) => { // ignore mouse moves when no button is held - if (e.buttons === 0) e.stopPropagation() + if (e.buttons === 0) e.stopPropagation(); } render() { @@ -119,7 +119,7 @@ export class ViewportControls extends PluginUIComponent<ViewportControlsProps, V <SimpleSettingsControl /> </ControlGroup> </div>} - </div> + </div>; } } @@ -131,7 +131,7 @@ export const Logo = () => <div className='msp-logo-image' /> </div> </div> - </div> + </div>; interface ViewportState { noWebGl: boolean @@ -148,7 +148,7 @@ export class Viewport extends PluginUIComponent<{ }, ViewportState> { }; private handleLogo = () => { - this.setState({ showLogo: !this.plugin.canvas3d?.reprCount.value }) + this.setState({ showLogo: !this.plugin.canvas3d?.reprCount.value }); } private handleResize = () => { @@ -191,7 +191,7 @@ export class Viewport extends PluginUIComponent<{ }, ViewportState> { <p>This can be caused by an outdated browser, graphics card driver issue, or bad weather. Sometimes, just restarting the browser helps.</p> <p>For a list of supported browsers, refer to <a href='http://caniuse.com/#feat=webgl' target='_blank'>http://caniuse.com/#feat=webgl</a>.</p> </div> - </div> + </div>; } render() { diff --git a/src/mol-plugin-ui/viewport/help.tsx b/src/mol-plugin-ui/viewport/help.tsx index 49c18b146b6831207a4f4f7f48805a9305d6e8b3..c4583a83ae03bec3f11a4e669733487a2fdc22e3 100644 --- a/src/mol-plugin-ui/viewport/help.tsx +++ b/src/mol-plugin-ui/viewport/help.tsx @@ -14,26 +14,26 @@ import { Icon } from '../controls/icons'; import { Button } from '../controls/common'; function getBindingsList(bindings: { [k: string]: Binding }) { - return Object.keys(bindings).map(k => [k, bindings[k]] as [string, Binding]) + return Object.keys(bindings).map(k => [k, bindings[k]] as [string, Binding]); } export class BindingsHelp extends React.PureComponent<{ bindings: { [k: string]: Binding } }> { getBindingComponents() { - const bindingsList = getBindingsList(this.props.bindings) + const bindingsList = getBindingsList(this.props.bindings); return <> {bindingsList.map(value => { - const [name, binding] = value + const [name, binding] = value; return !Binding.isEmpty(binding) ? <div key={name} style={{ marginBottom: '6px' }}> <b>{binding.action}</b><br /><span dangerouslySetInnerHTML={{ __html: Binding.format(binding, name) }} /> </div> - : null + : null; })} - </> + </>; } render() { - return <HelpText>{this.getBindingComponents()}</HelpText> + return <HelpText>{this.getBindingComponents()}</HelpText>; } } @@ -41,7 +41,7 @@ class HelpText extends React.PureComponent { render() { return <div className='msp-help-text'> <div>{this.props.children}</div> - </div> + </div>; } } @@ -64,7 +64,7 @@ class HelpGroup extends React.PureComponent<{ header: string, initiallyExpanded? {this.state.isExpanded && <div className='msp-control-offset' style={{ display: this.state.isExpanded ? 'block' : 'none' }}> {this.props.children} </div>} - </div> + </div>; } } @@ -78,11 +78,11 @@ export class ViewportHelpContent extends PluginUIComponent { } render() { - const interactionBindings: { [k: string]: Binding } = {} + const interactionBindings: { [k: string]: Binding } = {}; this.plugin.spec.behaviors.forEach(b => { - const { bindings } = b.defaultParams - if (bindings) Object.assign(interactionBindings, bindings) - }) + const { bindings } = b.defaultParams; + if (bindings) Object.assign(interactionBindings, bindings); + }); return <> {this.plugin.canvas3d && <HelpGroup key='trackball' header='Moving in 3D'> <BindingsHelp bindings={this.plugin.canvas3d.props.trackball.bindings} /> @@ -90,7 +90,7 @@ export class ViewportHelpContent extends PluginUIComponent { <HelpGroup key='interactions' header='Select, Highlight, Focus'> <BindingsHelp bindings={interactionBindings} /> </HelpGroup> - </> + </>; } } @@ -100,21 +100,21 @@ export class HelpContent extends PluginUIComponent { } private formatTriggers(binding: Binding) { - return binding.triggers.map(t => Binding.Trigger.format(t)).join(' or ') + return binding.triggers.map(t => Binding.Trigger.format(t)).join(' or '); } private getTriggerFor(transformer: StateTransformer, name: string) { - const state = this.plugin.state.behaviors - const selections = state.select(StateSelection.Generators.ofTransformer(transformer)) - const params = selections.length === 1 ? selections[0].params : undefined - const bindings = params ? params.values.bindings : {} - const binding: Binding = name in bindings ? bindings[name] : Binding.Empty - return this.formatTriggers(binding) + const state = this.plugin.state.behaviors; + const selections = state.select(StateSelection.Generators.ofTransformer(transformer)); + const params = selections.length === 1 ? selections[0].params : undefined; + const bindings = params ? params.values.bindings : {}; + const binding: Binding = name in bindings ? bindings[name] : Binding.Empty; + return this.formatTriggers(binding); } render() { - const selectToggleTriggers = this.getTriggerFor(SelectLoci, 'clickSelectToggle') - const focusTriggers = this.getTriggerFor(FocusLoci, 'clickFocus') + const selectToggleTriggers = this.getTriggerFor(SelectLoci, 'clickSelectToggle'); + const focusTriggers = this.getTriggerFor(FocusLoci, 'clickFocus'); // TODO: interactive help, for example for density @@ -159,6 +159,6 @@ export class HelpContent extends PluginUIComponent { <HelpSection header='Mouse Controls' /> <ViewportHelpContent /> - </div> + </div>; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/viewport/screenshot.tsx b/src/mol-plugin-ui/viewport/screenshot.tsx index 8aa7b95ce82942cb83cd3b2b394e9fc9ec7c9cc5..6e7d1760705e833ad8d2309097b44e19e9491dd6 100644 --- a/src/mol-plugin-ui/viewport/screenshot.tsx +++ b/src/mol-plugin-ui/viewport/screenshot.tsx @@ -70,7 +70,7 @@ export class DownloadScreenshotControls extends PluginUIComponent<{ close: () => private handlePreview() { if (this.state.showPreview) { - this.preview() + this.preview(); } } @@ -87,19 +87,19 @@ export class DownloadScreenshotControls extends PluginUIComponent<{ close: () => this.plugin.helpers.viewportScreenshot!.imagePass.setProps({ multiSample: { mode: 'on', sampleLevel: 2 }, postprocessing: this.plugin.canvas3d?.props.postprocessing - }) + }); this.updateQueue.next(); - }) + }); this.subscribe(debounceTime(250)(this.plugin.canvas3d.didDraw), () => { if (this.state.isDisabled) return; this.updateQueue.next(); - }) + }); this.subscribe(this.plugin.state.data.behaviors.isUpdating, v => { - this.setState({ isDisabled: v }) + this.setState({ isDisabled: v }); if (!v) this.updateQueue.next(); - }) + }); this.handlePreview(); } @@ -128,6 +128,6 @@ export class DownloadScreenshotControls extends PluginUIComponent<{ close: () => <Button icon='export' onClick={this.openTab} disabled={this.state.isDisabled}>Open in new Tab</Button> </div> <ParameterControls params={this.plugin.helpers.viewportScreenshot!.params} values={this.plugin.helpers.viewportScreenshot!.values} onChange={this.setProps} isDisabled={this.state.isDisabled} /> - </div> + </div>; } } \ No newline at end of file diff --git a/src/mol-plugin-ui/viewport/simple-settings.tsx b/src/mol-plugin-ui/viewport/simple-settings.tsx index 6473fa707929da404b13d7e6b38189adb2d160bc..7952d669daa2f8d36452d7b94ff7d92d05918a82 100644 --- a/src/mol-plugin-ui/viewport/simple-settings.tsx +++ b/src/mol-plugin-ui/viewport/simple-settings.tsx @@ -25,9 +25,9 @@ export class SimpleSettingsControl extends PluginUIComponent { this.subscribe(this.plugin.canvas3d!.camera.stateChanged, state => { if (state.radiusMax !== undefined || state.radius !== undefined) { - this.forceUpdate() + this.forceUpdate(); } - }) + }); } render() { @@ -35,7 +35,7 @@ export class SimpleSettingsControl extends PluginUIComponent { return <> <ParameterMappingControl mapping={SimpleSettingsMapping} /> <ViewportHelpContent /> - </> + </>; } } @@ -43,7 +43,7 @@ const LayoutOptions = { 'sequence': 'Sequence', 'log': 'Log', 'left': 'Left Panel' -} +}; type LayoutOptions = keyof typeof LayoutOptions const SimpleSettingsParams = { @@ -69,20 +69,20 @@ const SimpleSettingsParams = { type SimpleSettingsParams = typeof SimpleSettingsParams const SimpleSettingsMapping = ParamMapping({ params: (ctx: PluginContext) => { - const params = PD.clone(SimpleSettingsParams) - const controls = ctx.spec.layout?.controls + const params = PD.clone(SimpleSettingsParams); + const controls = ctx.spec.layout?.controls; if (controls) { - const options: [LayoutOptions, string][] = [] - if (controls.top !== 'none') options.push(['sequence', LayoutOptions.sequence]) - if (controls.bottom !== 'none') options.push(['log', LayoutOptions.log]) - if (controls.left !== 'none') options.push(['left', LayoutOptions.left]) - params.layout.options = options + const options: [LayoutOptions, string][] = []; + if (controls.top !== 'none') options.push(['sequence', LayoutOptions.sequence]); + if (controls.bottom !== 'none') options.push(['log', LayoutOptions.log]); + if (controls.left !== 'none') options.push(['left', LayoutOptions.left]); + params.layout.options = options; } - return params + return params; }, target(ctx: PluginContext) { - const c = ctx.spec.layout?.controls - const r = ctx.layout.state.regionState + const c = ctx.spec.layout?.controls; + const r = ctx.layout.state.regionState; const layout: SimpleSettingsParams['layout']['defaultValue'] = []; if (r.top !== 'hidden' && (!c || c.top !== 'none')) layout.push('sequence'); if (r.bottom !== 'hidden' && (!c || c.bottom !== 'none')) layout.push('log'); @@ -118,11 +118,11 @@ const SimpleSettingsMapping = ParamMapping({ canvas.camera = s.camera; canvas.transparentBackground = s.background.transparent; canvas.renderer.backgroundColor = s.background.color; - canvas.renderer.style = s.lighting.renderStyle + canvas.renderer.style = s.lighting.renderStyle; canvas.postprocessing.occlusion = s.lighting.occlusion; canvas.postprocessing.outline = s.lighting.outline; - canvas.cameraFog = s.lighting.fog - canvas.cameraClipping = s.clipping + canvas.cameraFog = s.lighting.fog; + canvas.cameraClipping = s.clipping; props.layout = s.layout; }, @@ -141,4 +141,4 @@ const SimpleSettingsMapping = ParamMapping({ PluginCommands.State.SetCurrentObject(ctx, { state: ctx.state.data, ref: StateTransform.RootRef }); } } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-plugin/behavior.ts b/src/mol-plugin/behavior.ts index 976e78982558424c4fa084fac2596efc672389f1..fbe472e03b716eef1715edb35ab9808e756e69b2 100644 --- a/src/mol-plugin/behavior.ts +++ b/src/mol-plugin/behavior.ts @@ -4,26 +4,26 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './behavior/behavior' +export * from './behavior/behavior'; -import * as StaticState from './behavior/static/state' -import * as StaticRepresentation from './behavior/static/representation' -import * as StaticCamera from './behavior/static/camera' -import * as StaticMisc from './behavior/static/misc' +import * as StaticState from './behavior/static/state'; +import * as StaticRepresentation from './behavior/static/representation'; +import * as StaticCamera from './behavior/static/camera'; +import * as StaticMisc from './behavior/static/misc'; -import * as DynamicRepresentation from './behavior/dynamic/representation' -import * as DynamicCamera from './behavior/dynamic/camera' -import * as DynamicCustomProps from './behavior/dynamic/custom-props' +import * as DynamicRepresentation from './behavior/dynamic/representation'; +import * as DynamicCamera from './behavior/dynamic/camera'; +import * as DynamicCustomProps from './behavior/dynamic/custom-props'; export const BuiltInPluginBehaviors = { State: StaticState, Representation: StaticRepresentation, Camera: StaticCamera, Misc: StaticMisc -} +}; export const PluginBehaviors = { Representation: DynamicRepresentation, Camera: DynamicCamera, CustomProps: DynamicCustomProps -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-plugin/behavior/behavior.ts b/src/mol-plugin/behavior/behavior.ts index f4bab6836780d8de80b9857f7d276d1d8b42ea47..86b809fb40e0742a052977e9d4b6abf3f25e7521 100644 --- a/src/mol-plugin/behavior/behavior.ts +++ b/src/mol-plugin/behavior/behavior.ts @@ -13,7 +13,7 @@ import { Observable } from 'rxjs'; import { ParamDefinition } from '../../mol-util/param-definition'; import { shallowEqualObjects } from '../../mol-util'; -export { PluginBehavior } +export { PluginBehavior }; interface PluginBehavior<P = unknown> { register(ref: StateTransform.Ref): void, @@ -87,7 +87,7 @@ namespace PluginBehavior { if (!b.data.update) return StateTransformer.UpdateResult.Unchanged; const updated = await b.data.update(newParams); return updated ? StateTransformer.UpdateResult.Updated : StateTransformer.UpdateResult.Unchanged; - }) + }); }, canAutoUpdate: params.canAutoUpdate }); @@ -108,7 +108,7 @@ namespace PluginBehavior { } // TODO can't be private due to bug with generating declerations, see https://github.com/Microsoft/TypeScript/issues/17293 constructor(/** private */ public ctx: PluginContext) { } - } + }; } export abstract class Handler<P = { }> implements PluginBehavior<P> { diff --git a/src/mol-plugin/behavior/dynamic/camera.ts b/src/mol-plugin/behavior/dynamic/camera.ts index 654de55aca37d9fb29f72be176cfbf5e979e578e..6ac9f4b34cb43e47ea7fc730bfedbfd47cb91bbf 100644 --- a/src/mol-plugin/behavior/dynamic/camera.ts +++ b/src/mol-plugin/behavior/dynamic/camera.ts @@ -12,9 +12,9 @@ import { ButtonsType, ModifiersKeys } from '../../../mol-util/input/input-observ import { Binding } from '../../../mol-util/binding'; import { PluginCommands } from '../../commands'; -const B = ButtonsType -const M = ModifiersKeys -const Trigger = Binding.Trigger +const B = ButtonsType; +const M = ModifiersKeys; +const Trigger = Binding.Trigger; const DefaultFocusLociBindings = { clickCenterFocus: Binding([ @@ -24,14 +24,14 @@ const DefaultFocusLociBindings = { Trigger(B.Flag.Auxilary, M.create()), Trigger(B.Flag.Primary, M.create({ alt: true })) ], 'Camera center and focus', 'Click element using ${triggers}'), -} +}; const FocusLociParams = { minRadius: PD.Numeric(8, { min: 1, max: 50, step: 1 }), extraRadius: PD.Numeric(4, { min: 1, max: 50, step: 1 }, { description: 'Value added to the bounding-sphere radius of the Loci' }), durationMs: PD.Numeric(250, { min: 0, max: 1000, step: 1 }, { description: 'Camera transition duration' }), bindings: PD.Value(DefaultFocusLociBindings, { isHidden: true }), -} +}; type FocusLociProps = PD.Values<typeof FocusLociParams> export const FocusLoci = PluginBehavior.create<FocusLociProps>({ @@ -47,11 +47,11 @@ export const FocusLoci = PluginBehavior.create<FocusLociProps>({ : this.params.bindings.clickCenterFocus; if (Binding.match(binding, button, modifiers)) { - const loci = Loci.normalize(current.loci, this.ctx.managers.interactivity.props.granularity) + const loci = Loci.normalize(current.loci, this.ctx.managers.interactivity.props.granularity); if (Loci.isEmpty(loci)) { - PluginCommands.Camera.Reset(this.ctx, { }) + PluginCommands.Camera.Reset(this.ctx, { }); } else { - this.ctx.managers.camera.focusLoci(loci, this.params) + this.ctx.managers.camera.focusLoci(loci, this.params); } } }); diff --git a/src/mol-plugin/behavior/dynamic/custom-props.ts b/src/mol-plugin/behavior/dynamic/custom-props.ts index 91586c5cfe9ac4294e0b5896f769604f5cee8e2e..027908349af19969461dfb202e255b8ca28e3aeb 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props.ts @@ -5,13 +5,13 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export { AccessibleSurfaceArea } from './custom-props/computed/accessible-surface-area' -export { Interactions } from './custom-props/computed/interactions' -export { SecondaryStructure } from './custom-props/computed/secondary-structure' -export { ValenceModel } from './custom-props/computed/valence-model' +export { AccessibleSurfaceArea } from './custom-props/computed/accessible-surface-area'; +export { Interactions } from './custom-props/computed/interactions'; +export { SecondaryStructure } from './custom-props/computed/secondary-structure'; +export { ValenceModel } from './custom-props/computed/valence-model'; -export { CrossLinkRestraint } from './custom-props/integrative/cross-link-restraint' +export { CrossLinkRestraint } from './custom-props/integrative/cross-link-restraint'; -export { PDBeStructureQualityReport } from './custom-props/pdbe/structure-quality-report' -export { RCSBAssemblySymmetry } from './custom-props/rcsb/assembly-symmetry' -export { RCSBValidationReport } from './custom-props/rcsb/validation-report' \ No newline at end of file +export { PDBeStructureQualityReport } from './custom-props/pdbe/structure-quality-report'; +export { RCSBAssemblySymmetry } from './custom-props/rcsb/assembly-symmetry'; +export { RCSBValidationReport } from './custom-props/rcsb/validation-report'; \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/custom-props/computed/accessible-surface-area.ts b/src/mol-plugin/behavior/dynamic/custom-props/computed/accessible-surface-area.ts index 2a890f8ce782b8361df306094e9483708cf72c70..06bc52745878f8666464f6e914d00c5d1d5a0207 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/computed/accessible-surface-area.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/computed/accessible-surface-area.ts @@ -24,8 +24,8 @@ export const AccessibleSurfaceArea = PluginBehavior.create<{ autoAttach: boolean private labelProvider = { label: (loci: Loci): string | undefined => { - if (!this.params.showTooltip) return - return accessibleSurfaceAreaLabel(loci) + if (!this.params.showTooltip) return; + return accessibleSurfaceAreaLabel(loci); } } @@ -33,7 +33,7 @@ export const AccessibleSurfaceArea = PluginBehavior.create<{ autoAttach: boolean let updated = ( this.params.autoAttach !== p.autoAttach || this.params.showTooltip !== p.showTooltip - ) + ); this.params.autoAttach = p.autoAttach; this.params.showTooltip = p.showTooltip; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); @@ -44,10 +44,10 @@ export const AccessibleSurfaceArea = PluginBehavior.create<{ autoAttach: boolean DefaultQueryRuntimeTable.addCustomProp(this.provider.descriptor); this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach); - this.ctx.representation.structure.themes.colorThemeRegistry.add(AccessibleSurfaceAreaColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.add(AccessibleSurfaceAreaColorThemeProvider); this.ctx.managers.lociLabels.addProvider(this.labelProvider); - this.ctx.query.structure.registry.add(isBuried) - this.ctx.query.structure.registry.add(isAccessible) + this.ctx.query.structure.registry.add(isBuried); + this.ctx.query.structure.registry.add(isAccessible); } unregister() { @@ -55,10 +55,10 @@ export const AccessibleSurfaceArea = PluginBehavior.create<{ autoAttach: boolean // DefaultQueryRuntimeTable.removeCustomProp(this.provider.descriptor); this.ctx.customStructureProperties.unregister(this.provider.descriptor.name); - this.ctx.representation.structure.themes.colorThemeRegistry.remove(AccessibleSurfaceAreaColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.remove(AccessibleSurfaceAreaColorThemeProvider); this.ctx.managers.lociLabels.removeProvider(this.labelProvider); - this.ctx.query.structure.registry.remove(isBuried) - this.ctx.query.structure.registry.remove(isAccessible) + this.ctx.query.structure.registry.remove(isBuried); + this.ctx.query.structure.registry.remove(isAccessible); } }, params: () => ({ @@ -73,32 +73,32 @@ function accessibleSurfaceAreaLabel(loci: Loci): string | undefined { if(loci.kind === 'element-loci') { if (loci.elements.length === 0) return; - const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value + const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value; if (!accessibleSurfaceArea || loci.structure.customPropertyDescriptors.hasReference(AccessibleSurfaceAreaProvider.descriptor)) return; - const { getSerialIndex } = loci.structure.root.serialMapping - const { area, serialResidueIndex } = accessibleSurfaceArea - const seen = new Set<number>() - let cummulativeArea = 0 + const { getSerialIndex } = loci.structure.root.serialMapping; + const { area, serialResidueIndex } = accessibleSurfaceArea; + const seen = new Set<number>(); + let cummulativeArea = 0; for (const { indices, unit } of loci.elements) { - const { elements } = unit + const { elements } = unit; OrderedSet.forEach(indices, idx => { - const rSI = serialResidueIndex[getSerialIndex(unit, elements[idx])] + const rSI = serialResidueIndex[getSerialIndex(unit, elements[idx])]; if (rSI !== -1 && !seen.has(rSI)) { - cummulativeArea += area[rSI] - seen.add(rSI) + cummulativeArea += area[rSI]; + seen.add(rSI); } - }) + }); } - if (seen.size === 0) return - const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues sum' : 'Residue'})</small>` + if (seen.size === 0) return; + const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues sum' : 'Residue'})</small>`; return `Accessible Surface Area ${residueCount}: ${cummulativeArea.toFixed(2)} \u212B<sup>2</sup>`; } else if(loci.kind === 'structure-loci') { - const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value + const accessibleSurfaceArea = AccessibleSurfaceAreaProvider.get(loci.structure).value; if (!accessibleSurfaceArea || loci.structure.customPropertyDescriptors.hasReference(AccessibleSurfaceAreaProvider.descriptor)) return; return `Accessible Surface Area <small>(Whole Structure)</small>: ${arraySum(accessibleSurfaceArea.area).toFixed(2)} \u212B<sup>2</sup>`; @@ -120,9 +120,9 @@ const isBuried = StructureSelectionQuery('Buried Protein Residues', MS.struct.mo description: 'Select buried protein residues.', category: StructureSelectionCategory.Residue, ensureCustomProperties: (ctx, structure) => { - return AccessibleSurfaceAreaProvider.attach(ctx, structure) + return AccessibleSurfaceAreaProvider.attach(ctx, structure); } -}) +}); const isAccessible = StructureSelectionQuery('Accessible Protein Residues', MS.struct.modifier.union([ MS.struct.modifier.wholeResidues([ @@ -137,6 +137,6 @@ const isAccessible = StructureSelectionQuery('Accessible Protein Residues', MS.s description: 'Select accessible protein residues.', category: StructureSelectionCategory.Residue, ensureCustomProperties: (ctx, structure) => { - return AccessibleSurfaceAreaProvider.attach(ctx, structure) + return AccessibleSurfaceAreaProvider.attach(ctx, structure); } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/custom-props/computed/interactions.ts b/src/mol-plugin/behavior/dynamic/custom-props/computed/interactions.ts index 73216c4192f941e0427e939ade28cb16c1f53155..d8e988adb9a415b27b199705e5f4713e1595ac96 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/computed/interactions.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/computed/interactions.ts @@ -26,16 +26,16 @@ export const Interactions = PluginBehavior.create<{ autoAttach: boolean, showToo private provider = InteractionsProvider private getStructures(structure: Structure) { - const structures: Structure[] = [] - const root = this.ctx.helpers.substructureParent.get(structure) + const structures: Structure[] = []; + const root = this.ctx.helpers.substructureParent.get(structure); if (root) { - const state = this.ctx.state.data + const state = this.ctx.state.data; const selections = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure, root.transform.ref)); for (const s of selections) { - if (s.obj) arraySetAdd(structures, s.obj.data) + if (s.obj) arraySetAdd(structures, s.obj.data); } } - return structures + return structures; } private labelProvider = { @@ -46,39 +46,39 @@ export const Interactions = PluginBehavior.create<{ autoAttach: boolean, showToo case 'element-loci': if (loci.elements.length === 0) return void 0; - const labels: string[] = [] - const structures = this.getStructures(loci.structure) + const labels: string[] = []; + const structures = this.getStructures(loci.structure); for (const s of structures) { - const interactions = this.provider.get(s).value + const interactions = this.provider.get(s).value; if (!interactions) continue; - const l = StructureElement.Loci.remap(loci, s) - if (l.elements.length !== 1) continue + const l = StructureElement.Loci.remap(loci, s); + if (l.elements.length !== 1) continue; - const e = l.elements[0] - if (OrderedSet.size(e.indices) !== 1) continue + const e = l.elements[0]; + if (OrderedSet.size(e.indices) !== 1) continue; - const features = interactions.unitsFeatures.get(e.unit.id) + const features = interactions.unitsFeatures.get(e.unit.id); if (!features) continue; - const typeLabels: string[] = [] - const groupLabels: string[] = [] - const label: string[] = [] + const typeLabels: string[] = []; + const groupLabels: string[] = []; + const label: string[] = []; - const idx = OrderedSet.start(e.indices) - const { types, groups, elementsIndex: { indices, offsets } } = features + const idx = OrderedSet.start(e.indices); + const { types, groups, elementsIndex: { indices, offsets } } = features; for (let i = offsets[idx], il = offsets[idx + 1]; i < il; ++i) { - const f = indices[i] - const type = types[f] - const group = groups[f] - if (type) typeLabels.push(featureTypeLabel(type)) - if (group) groupLabels.push(featureGroupLabel(group)) + const f = indices[i]; + const type = types[f]; + const group = groups[f]; + if (type) typeLabels.push(featureTypeLabel(type)); + if (group) groupLabels.push(featureGroupLabel(group)); } - if (typeLabels.length) label.push(`<small>Types</small> ${typeLabels.join(', ')}`) - if (groupLabels.length) label.push(`<small>Groups</small> ${groupLabels.join(', ')}`) - if (label.length) labels.push(`Interaction Feature: ${label.join(' | ')}`) + if (typeLabels.length) label.push(`<small>Types</small> ${typeLabels.join(', ')}`); + if (groupLabels.length) label.push(`<small>Groups</small> ${groupLabels.join(', ')}`); + if (label.length) labels.push(`Interaction Feature: ${label.join(' | ')}`); } return labels.length ? labels.join('<br/>') : undefined; @@ -92,7 +92,7 @@ export const Interactions = PluginBehavior.create<{ autoAttach: boolean, showToo let updated = ( this.params.autoAttach !== p.autoAttach || this.params.showTooltip !== p.showTooltip - ) + ); this.params.autoAttach = p.autoAttach; this.params.showTooltip = p.showTooltip; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); @@ -101,16 +101,16 @@ export const Interactions = PluginBehavior.create<{ autoAttach: boolean, showToo register(): void { this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach); - this.ctx.representation.structure.themes.colorThemeRegistry.add(InteractionTypeColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.add(InteractionTypeColorThemeProvider); this.ctx.managers.lociLabels.addProvider(this.labelProvider); - this.ctx.representation.structure.registry.add(InteractionsRepresentationProvider) + this.ctx.representation.structure.registry.add(InteractionsRepresentationProvider); } unregister() { this.ctx.customStructureProperties.unregister(this.provider.descriptor.name); - this.ctx.representation.structure.themes.colorThemeRegistry.remove(InteractionTypeColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.remove(InteractionTypeColorThemeProvider); this.ctx.managers.lociLabels.removeProvider(this.labelProvider); - this.ctx.representation.structure.registry.remove(InteractionsRepresentationProvider) + this.ctx.representation.structure.registry.remove(InteractionsRepresentationProvider); } }, params: () => ({ diff --git a/src/mol-plugin/behavior/dynamic/custom-props/computed/secondary-structure.ts b/src/mol-plugin/behavior/dynamic/custom-props/computed/secondary-structure.ts index 2bffed8945ddf20191a0250cbf534b2893066c0d..46392f082b5f290983d4192cfabd10c830ee817f 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/computed/secondary-structure.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/computed/secondary-structure.ts @@ -18,7 +18,7 @@ export const SecondaryStructure = PluginBehavior.create<{ autoAttach: boolean }> update(p: { autoAttach: boolean, showTooltip: boolean }) { let updated = ( this.params.autoAttach !== p.autoAttach - ) + ); this.params.autoAttach = p.autoAttach; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); return updated; diff --git a/src/mol-plugin/behavior/dynamic/custom-props/computed/valence-model.ts b/src/mol-plugin/behavior/dynamic/custom-props/computed/valence-model.ts index 7ed25b8c30eae68ff5253de92f45c80aad9afa6b..b982494259cb1818eba7334bbec6fe6963d49c97 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/computed/valence-model.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/computed/valence-model.ts @@ -23,16 +23,16 @@ export const ValenceModel = PluginBehavior.create<{ autoAttach: boolean, showToo private provider = ValenceModelProvider private getStructures(structure: Structure) { - const structures: Structure[] = [] - const root = this.ctx.helpers.substructureParent.get(structure) + const structures: Structure[] = []; + const root = this.ctx.helpers.substructureParent.get(structure); if (root) { - const state = this.ctx.state.data + const state = this.ctx.state.data; const selections = state.select(StateSelection.Generators.ofType(PluginStateObject.Molecule.Structure, root.transform.ref)); for (const s of selections) { - if (s.obj) arraySetAdd(structures, s.obj.data) + if (s.obj) arraySetAdd(structures, s.obj.data); } } - return structures + return structures; } private labelProvider = { @@ -43,29 +43,29 @@ export const ValenceModel = PluginBehavior.create<{ autoAttach: boolean, showToo case 'element-loci': if (loci.elements.length === 0) return void 0; - const labels: string[] = [] - const structures = this.getStructures(loci.structure) + const labels: string[] = []; + const structures = this.getStructures(loci.structure); for (const s of structures) { - const valenceModel = this.provider.get(s).value + const valenceModel = this.provider.get(s).value; if (!valenceModel) continue; - const l = StructureElement.Loci.remap(loci, s) - if (l.elements.length !== 1) continue + const l = StructureElement.Loci.remap(loci, s); + if (l.elements.length !== 1) continue; - const e = l.elements[0] - if (OrderedSet.size(e.indices) !== 1) continue + const e = l.elements[0]; + if (OrderedSet.size(e.indices) !== 1) continue; - const vm = valenceModel.get(e.unit.id) + const vm = valenceModel.get(e.unit.id); if (!vm) continue; - const idx = OrderedSet.start(e.indices) - const charge = vm.charge[idx] - const idealGeometry = vm.idealGeometry[idx] - const implicitH = vm.implicitH[idx] - const totalH = vm.totalH[idx] + const idx = OrderedSet.start(e.indices); + const charge = vm.charge[idx]; + const idealGeometry = vm.idealGeometry[idx]; + const implicitH = vm.implicitH[idx]; + const totalH = vm.totalH[idx]; - labels.push(`Valence Model: <small>Charge</small> ${charge} | <small>Ideal Geometry</small> ${geometryLabel(idealGeometry)} | <small>Implicit H</small> ${implicitH} | <small>Total H</small> ${totalH}`) + labels.push(`Valence Model: <small>Charge</small> ${charge} | <small>Ideal Geometry</small> ${geometryLabel(idealGeometry)} | <small>Implicit H</small> ${implicitH} | <small>Total H</small> ${totalH}`); } return labels.length ? labels.join('<br/>') : undefined; @@ -79,7 +79,7 @@ export const ValenceModel = PluginBehavior.create<{ autoAttach: boolean, showToo let updated = ( this.params.autoAttach !== p.autoAttach || this.params.showTooltip !== p.showTooltip - ) + ); this.params.autoAttach = p.autoAttach; this.params.showTooltip = p.showTooltip; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); diff --git a/src/mol-plugin/behavior/dynamic/custom-props/integrative/cross-link-restraint.ts b/src/mol-plugin/behavior/dynamic/custom-props/integrative/cross-link-restraint.ts index a38e38da7ef8740c87c09bf4a0b2ea605018c1e6..8fb480b3e2d3a61e183e96ebe6ae47539726fd80 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/integrative/cross-link-restraint.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/integrative/cross-link-restraint.ts @@ -20,17 +20,17 @@ export const CrossLinkRestraint = PluginBehavior.create<{ }>({ private provider = ModelCrossLinkRestraint.Provider register(): void { - this.provider.formatRegistry.add('mmCIF', crossLinkRestraintFromMmcif) + this.provider.formatRegistry.add('mmCIF', crossLinkRestraintFromMmcif); - this.ctx.representation.structure.themes.colorThemeRegistry.add(CrossLinkColorThemeProvider) - this.ctx.representation.structure.registry.add(CrossLinkRestraintRepresentationProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.add(CrossLinkColorThemeProvider); + this.ctx.representation.structure.registry.add(CrossLinkRestraintRepresentationProvider); } unregister() { - this.provider.formatRegistry.remove('mmCIF') + this.provider.formatRegistry.remove('mmCIF'); - this.ctx.representation.structure.themes.colorThemeRegistry.remove(CrossLinkColorThemeProvider) - this.ctx.representation.structure.registry.remove(CrossLinkRestraintRepresentationProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.remove(CrossLinkColorThemeProvider); + this.ctx.representation.structure.registry.remove(CrossLinkRestraintRepresentationProvider); } } }); @@ -39,5 +39,5 @@ function crossLinkRestraintFromMmcif(model: Model) { if (!MmcifFormat.is(model.sourceData)) return; const { ihm_cross_link_restraint } = model.sourceData.data.db; if (ihm_cross_link_restraint._rowCount === 0) return; - return ModelCrossLinkRestraint.fromTable(ihm_cross_link_restraint, model) + return ModelCrossLinkRestraint.fromTable(ihm_cross_link_restraint, model); } \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts b/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts index 5c640dbc8b275f15c116c2b07bce4cead41ddf0e..d20ceccbcda08a57995a8f41dbdf0a36ea25e618 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/pdbe/structure-quality-report.ts @@ -48,11 +48,11 @@ export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: bo this.ctx.customModelProperties.register(this.provider, this.params.autoAttach); this.ctx.managers.lociLabels.addProvider(this.labelPDBeValidation); - this.ctx.representation.structure.themes.colorThemeRegistry.add(StructureQualityReportColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.add(StructureQualityReportColorThemeProvider); } update(p: { autoAttach: boolean, showTooltip: boolean }) { - let updated = this.params.autoAttach !== p.autoAttach + let updated = this.params.autoAttach !== p.autoAttach; this.params.autoAttach = p.autoAttach; this.params.showTooltip = p.showTooltip; this.ctx.customModelProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); @@ -62,7 +62,7 @@ export const PDBeStructureQualityReport = PluginBehavior.create<{ autoAttach: bo unregister() { this.ctx.customModelProperties.unregister(StructureQualityReportProvider.descriptor.name); this.ctx.managers.lociLabels.removeProvider(this.labelPDBeValidation); - this.ctx.representation.structure.themes.colorThemeRegistry.remove(StructureQualityReportColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.remove(StructureQualityReportColorThemeProvider); } }, params: () => ({ diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts index 34aafbe151d4c7a34d7883f4faf11226a3a787dd..a091f4c3f9e861b181f31888ce34fb1efae9ed14 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/assembly-symmetry.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ParamDefinition as PD } from '../../../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../../../mol-util/param-definition'; import { AssemblySymmetryProvider, AssemblySymmetry, AssemblySymmetryDataProvider } from '../../../../../mol-model-props/rcsb/assembly-symmetry'; import { PluginBehavior } from '../../../behavior'; import { AssemblySymmetryParams, AssemblySymmetryRepresentation } from '../../../../../mol-model-props/rcsb/representations/assembly-symmetry'; @@ -17,7 +17,7 @@ import { GenericRepresentationRef } from '../../../../../mol-plugin-state/manage import { AssemblySymmetryControls } from './ui/assembly-symmetry'; import { StructureRepresentationPresetProvider, PresetStructureRepresentations } from '../../../../../mol-plugin-state/builder/structure/representation-preset'; -const Tag = AssemblySymmetry.Tag +const Tag = AssemblySymmetry.Tag; export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean }>({ name: 'rcsb-assembly-symmetry-prop', @@ -30,37 +30,37 @@ export const RCSBAssemblySymmetry = PluginBehavior.create<{ autoAttach: boolean private provider = AssemblySymmetryProvider register(): void { - this.ctx.state.data.actions.add(InitAssemblySymmetry3D) + this.ctx.state.data.actions.add(InitAssemblySymmetry3D); this.ctx.customStructureProperties.register(this.provider, this.params.autoAttach); - this.ctx.representation.structure.themes.colorThemeRegistry.add(AssemblySymmetryClusterColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.add(AssemblySymmetryClusterColorThemeProvider); this.ctx.genericRepresentationControls.set(Tag.Representation, selection => { - const refs: GenericRepresentationRef[] = [] + const refs: GenericRepresentationRef[] = []; selection.structures.forEach(structure => { - const symmRepr = structure.genericRepresentations?.filter(r => r.cell.transform.transformer.id === AssemblySymmetry3D.id)[0] - if (symmRepr) refs.push(symmRepr) - }) - return [refs, 'Symmetries'] - }) - this.ctx.customStructureControls.set(Tag.Representation, AssemblySymmetryControls as any) - this.ctx.builders.structure.representation.registerPreset(AssemblySymmetryPreset) + const symmRepr = structure.genericRepresentations?.filter(r => r.cell.transform.transformer.id === AssemblySymmetry3D.id)[0]; + if (symmRepr) refs.push(symmRepr); + }); + return [refs, 'Symmetries']; + }); + this.ctx.customStructureControls.set(Tag.Representation, AssemblySymmetryControls as any); + this.ctx.builders.structure.representation.registerPreset(AssemblySymmetryPreset); } update(p: { autoAttach: boolean }) { - let updated = this.params.autoAttach !== p.autoAttach + let updated = this.params.autoAttach !== p.autoAttach; this.params.autoAttach = p.autoAttach; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); return updated; } unregister() { - this.ctx.state.data.actions.remove(InitAssemblySymmetry3D) + this.ctx.state.data.actions.remove(InitAssemblySymmetry3D); this.ctx.customStructureProperties.unregister(this.provider.descriptor.name); - this.ctx.representation.structure.themes.colorThemeRegistry.remove(AssemblySymmetryClusterColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.remove(AssemblySymmetryClusterColorThemeProvider); - this.ctx.genericRepresentationControls.delete(Tag.Representation) - this.ctx.customStructureControls.delete(Tag.Representation) - this.ctx.builders.structure.representation.unregisterPreset(AssemblySymmetryPreset) + this.ctx.genericRepresentationControls.delete(Tag.Representation); + this.ctx.customStructureControls.delete(Tag.Representation); + this.ctx.builders.structure.representation.unregisterPreset(AssemblySymmetryPreset); } }, params: () => ({ @@ -80,21 +80,21 @@ export const InitAssemblySymmetry3D = StateAction.build({ isApplicable: (a) => AssemblySymmetry.isApplicable(a.data) })(({ a, ref, state }, plugin: PluginContext) => Task.create('Init Assembly Symmetry', async ctx => { try { - const propCtx = { runtime: ctx, fetch: plugin.fetch } - await AssemblySymmetryDataProvider.attach(propCtx, a.data) - const assemblySymmetryData = AssemblySymmetryDataProvider.get(a.data).value - const symmetryIndex = assemblySymmetryData ? AssemblySymmetry.firstNonC1(assemblySymmetryData) : -1 - await AssemblySymmetryProvider.attach(propCtx, a.data, { symmetryIndex }) + const propCtx = { runtime: ctx, fetch: plugin.fetch }; + await AssemblySymmetryDataProvider.attach(propCtx, a.data); + const assemblySymmetryData = AssemblySymmetryDataProvider.get(a.data).value; + const symmetryIndex = assemblySymmetryData ? AssemblySymmetry.firstNonC1(assemblySymmetryData) : -1; + await AssemblySymmetryProvider.attach(propCtx, a.data, { symmetryIndex }); } catch(e) { - plugin.log.error(`Assembly Symmetry: ${e}`) - return + plugin.log.error(`Assembly Symmetry: ${e}`); + return; } const tree = state.build().to(ref) .applyOrUpdateTagged(AssemblySymmetry.Tag.Representation, AssemblySymmetry3D); await state.updateTree(tree).runInContext(ctx); })); -export { AssemblySymmetry3D } +export { AssemblySymmetry3D }; type AssemblySymmetry3D = typeof AssemblySymmetry3D const AssemblySymmetry3D = PluginStateTransform.BuiltIn({ @@ -108,7 +108,7 @@ const AssemblySymmetry3D = PluginStateTransform.BuiltIn({ params: (a) => { return { ...AssemblySymmetryParams, - } + }; } })({ canAutoUpdate({ oldParams, newParams }) { @@ -116,36 +116,36 @@ const AssemblySymmetry3D = PluginStateTransform.BuiltIn({ }, apply({ a, params }, plugin: PluginContext) { return Task.create('Assembly Symmetry', async ctx => { - await AssemblySymmetryProvider.attach({ runtime: ctx, fetch: plugin.fetch }, a.data) - const assemblySymmetry = AssemblySymmetryProvider.get(a.data).value + await AssemblySymmetryProvider.attach({ runtime: ctx, fetch: plugin.fetch }, a.data); + const assemblySymmetry = AssemblySymmetryProvider.get(a.data).value; if (!assemblySymmetry || assemblySymmetry.symbol === 'C1') { return StateObject.Null; } - const repr = AssemblySymmetryRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => AssemblySymmetryParams) + const repr = AssemblySymmetryRepresentation({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.structure.themes }, () => AssemblySymmetryParams); await repr.createOrUpdate(params, a.data).runInContext(ctx); - const { type, kind, symbol } = assemblySymmetry + const { type, kind, symbol } = assemblySymmetry; return new PluginStateObject.Shape.Representation3D({ repr, source: a }, { label: kind, description: `${type} (${symbol})` }); }); }, update({ a, b, newParams }, plugin: PluginContext) { return Task.create('Assembly Symmetry', async ctx => { - await AssemblySymmetryProvider.attach({ runtime: ctx, fetch: plugin.fetch }, a.data) - const assemblySymmetry = AssemblySymmetryProvider.get(a.data).value + await AssemblySymmetryProvider.attach({ runtime: ctx, fetch: plugin.fetch }, a.data); + const assemblySymmetry = AssemblySymmetryProvider.get(a.data).value; if (!assemblySymmetry || assemblySymmetry.symbol === 'C1') { // this should NOT be StateTransformer.UpdateResult.Null // because that keeps the old object - return StateTransformer.UpdateResult.Recreate + return StateTransformer.UpdateResult.Recreate; } - const props = { ...b.data.repr.props, ...newParams } + const props = { ...b.data.repr.props, ...newParams }; await b.data.repr.createOrUpdate(props, a.data).runInContext(ctx); - const { type, kind, symbol } = assemblySymmetry - b.label = kind - b.description = `${type} (${symbol})` + const { type, kind, symbol } = assemblySymmetry; + b.label = kind; + b.description = `${type} (${symbol})`; return StateTransformer.UpdateResult.Updated; }); }, isApplicable(a) { - return AssemblySymmetry.isApplicable(a.data) + return AssemblySymmetry.isApplicable(a.data); } }); @@ -153,7 +153,7 @@ const AssemblySymmetry3D = PluginStateTransform.BuiltIn({ export const AssemblySymmetryPresetParams = { ...StructureRepresentationPresetProvider.CommonParams, -} +}; export const AssemblySymmetryPreset = StructureRepresentationPresetProvider({ id: 'preset-structure-representation-rcsb-assembly-symmetry', @@ -162,7 +162,7 @@ export const AssemblySymmetryPreset = StructureRepresentationPresetProvider({ description: 'Shows Assembly Symmetry axes and cage; colors structure according to assembly symmetry cluster membership. Data calculated with BioJava, obtained via RCSB PDB.' }, isApplicable(a) { - return AssemblySymmetry.isApplicable(a.data) + return AssemblySymmetry.isApplicable(a.data); }, params: () => AssemblySymmetryPresetParams, async apply(ref, params, plugin) { @@ -172,16 +172,16 @@ export const AssemblySymmetryPreset = StructureRepresentationPresetProvider({ if (!AssemblySymmetryDataProvider.get(structure).value) { await plugin.runTask(Task.create('Assembly Symmetry', async runtime => { - const propCtx = { runtime, fetch: plugin.fetch } - await AssemblySymmetryDataProvider.attach(propCtx, structure) - const assemblySymmetryData = AssemblySymmetryDataProvider.get(structure).value - const symmetryIndex = assemblySymmetryData ? AssemblySymmetry.firstNonC1(assemblySymmetryData) : -1 - await AssemblySymmetryProvider.attach(propCtx, structure, { symmetryIndex }) - })) + const propCtx = { runtime, fetch: plugin.fetch }; + await AssemblySymmetryDataProvider.attach(propCtx, structure); + const assemblySymmetryData = AssemblySymmetryDataProvider.get(structure).value; + const symmetryIndex = assemblySymmetryData ? AssemblySymmetry.firstNonC1(assemblySymmetryData) : -1; + await AssemblySymmetryProvider.attach(propCtx, structure, { symmetryIndex }); + })); } const assemblySymmetry = await tryCreateAssemblySymmetry(plugin, structureCell); - const globalThemeName = assemblySymmetry.isOk ? Tag.Cluster as any : undefined + const globalThemeName = assemblySymmetry.isOk ? Tag.Cluster as any : undefined; const preset = await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName }, plugin); return { components: preset.components, representations: { ...preset.representations, assemblySymmetry } }; diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/ui/assembly-symmetry.tsx b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/ui/assembly-symmetry.tsx index 8931de1f6c53b9bc7a4d652d1eda63779d32689d..8ae2f8b390ef123cfb943f22235837440f2f02d1 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/ui/assembly-symmetry.tsx +++ b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/ui/assembly-symmetry.tsx @@ -37,7 +37,7 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy this.setState({ isHidden: !this.canEnable(), description: StructureHierarchyManager.getSelectedStructuresDescription(this.plugin) - }) + }); }); this.subscribe(this.plugin.events.state.cell.stateUpdated, e => { if (e.cell.transform.transformer === AssemblySymmetry3D) this.forceUpdate(); @@ -70,25 +70,25 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy } get params() { - const structure = this.pivot.cell.obj?.data - const params = PD.clone(structure ? AssemblySymmetryProvider.getParams(structure) : AssemblySymmetryProvider.defaultParams) - params.serverUrl.isHidden = true - params.symmetryIndex.options = [[-1, 'Off'], ...params.symmetryIndex.options] - return params + const structure = this.pivot.cell.obj?.data; + const params = PD.clone(structure ? AssemblySymmetryProvider.getParams(structure) : AssemblySymmetryProvider.defaultParams); + params.serverUrl.isHidden = true; + params.symmetryIndex.options = [[-1, 'Off'], ...params.symmetryIndex.options]; + return params; } get values() { - const structure = this.pivot.cell.obj?.data + const structure = this.pivot.cell.obj?.data; if (structure) { - return AssemblySymmetryProvider.props(structure) + return AssemblySymmetryProvider.props(structure); } else { - return { ...PD.getDefaultValues(AssemblySymmetryProvider.defaultParams), symmetryIndex: -1 } + return { ...PD.getDefaultValues(AssemblySymmetryProvider.defaultParams), symmetryIndex: -1 }; } } async updateAssemblySymmetry(values: AssemblySymmetryProps) { - const s = this.pivot - const currValues = AssemblySymmetryProvider.props(s.cell.obj!.data) + const s = this.pivot; + const currValues = AssemblySymmetryProvider.props(s.cell.obj!.data); if (PD.areEqual(AssemblySymmetryProvider.defaultParams, currValues, values)) return; if (s.properties) { @@ -108,17 +108,17 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy if (values.symmetryIndex === -1) { const name = components[0]?.representations[0]?.cell.transform.params?.colorTheme.name; if (name === AssemblySymmetry.Tag.Cluster) { - await this.plugin.managers.structure.component.updateRepresentationsTheme(components, { color: 'default' }) + await this.plugin.managers.structure.component.updateRepresentationsTheme(components, { color: 'default' }); } } else { - tryCreateAssemblySymmetry(this.plugin, s.cell) - await this.plugin.managers.structure.component.updateRepresentationsTheme(components, { color: AssemblySymmetry.Tag.Cluster as any }) + tryCreateAssemblySymmetry(this.plugin, s.cell); + await this.plugin.managers.structure.component.updateRepresentationsTheme(components, { color: AssemblySymmetry.Tag.Cluster as any }); } } } paramsOnChange = (options: AssemblySymmetryProps) => { - this.updateAssemblySymmetry(options) + this.updateAssemblySymmetry(options); } get hasAssemblySymmetry3D() { @@ -126,13 +126,13 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy } get enable() { - return !this.hasAssemblySymmetry3D && this.values.symmetryIndex !== -1 + return !this.hasAssemblySymmetry3D && this.values.symmetryIndex !== -1; } get noSymmetries() { - const structure = this.pivot.cell.obj?.data - const data = structure && AssemblySymmetryDataProvider.get(structure).value - return data && data.filter(sym => sym.symbol !== 'C1').length === 0 + const structure = this.pivot.cell.obj?.data; + const data = structure && AssemblySymmetryDataProvider.get(structure).value; + return data && data.filter(sym => sym.symbol !== 'C1').length === 0; } renderParams() { @@ -152,5 +152,5 @@ export class AssemblySymmetryControls extends CollapsableControls<{}, AssemblySy const EnableAssemblySymmetry3D = StateAction.build({ from: PluginStateObject.Molecule.Structure, })(({ a, ref, state }, plugin: PluginContext) => Task.create('Enable Assembly Symmetry', async ctx => { - await AssemblySymmetryPreset.apply(ref, Object.create(null), plugin) + await AssemblySymmetryPreset.apply(ref, Object.create(null), plugin); })); \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts index da8ff9dfb3c4f73134fe62bded4ba98fb2f03f81..0ff1e55dea53661630e2b087934b901c7e101b23 100644 --- a/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts +++ b/src/mol-plugin/behavior/dynamic/custom-props/rcsb/validation-report.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { ParamDefinition as PD } from '../../../../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../../../../mol-util/param-definition'; import { PluginBehavior } from '../../../behavior'; import { ValidationReport, ValidationReportProvider } from '../../../../../mol-model-props/rcsb/validation-report'; import { RandomCoilIndexColorThemeProvider } from '../../../../../mol-model-props/rcsb/themes/random-coil-index'; @@ -34,12 +34,12 @@ export const RCSBValidationReport = PluginBehavior.create<{ autoAttach: boolean, private labelProvider = { label: (loci: Loci): string | undefined => { - if (!this.params.showTooltip) return + if (!this.params.showTooltip) return; return [ geometryQualityLabel(loci), densityFitLabel(loci), randomCoilIndexLabel(loci) - ].filter(l => !!l).join('</br>') + ].filter(l => !!l).join('</br>'); } } @@ -50,20 +50,20 @@ export const RCSBValidationReport = PluginBehavior.create<{ autoAttach: boolean, this.ctx.managers.lociLabels.addProvider(this.labelProvider); - this.ctx.representation.structure.themes.colorThemeRegistry.add(DensityFitColorThemeProvider) - this.ctx.representation.structure.themes.colorThemeRegistry.add(GeometryQualityColorThemeProvider) - this.ctx.representation.structure.themes.colorThemeRegistry.add(RandomCoilIndexColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.add(DensityFitColorThemeProvider); + this.ctx.representation.structure.themes.colorThemeRegistry.add(GeometryQualityColorThemeProvider); + this.ctx.representation.structure.themes.colorThemeRegistry.add(RandomCoilIndexColorThemeProvider); - this.ctx.representation.structure.registry.add(ClashesRepresentationProvider) - this.ctx.query.structure.registry.add(hasClash) + this.ctx.representation.structure.registry.add(ClashesRepresentationProvider); + this.ctx.query.structure.registry.add(hasClash); - this.ctx.builders.structure.representation.registerPreset(ValidationReportGeometryQualityPreset) - this.ctx.builders.structure.representation.registerPreset(ValidationReportDensityFitPreset) - this.ctx.builders.structure.representation.registerPreset(ValidationReportRandomCoilIndexPreset) + this.ctx.builders.structure.representation.registerPreset(ValidationReportGeometryQualityPreset); + this.ctx.builders.structure.representation.registerPreset(ValidationReportDensityFitPreset); + this.ctx.builders.structure.representation.registerPreset(ValidationReportRandomCoilIndexPreset); } update(p: { autoAttach: boolean, showTooltip: boolean }) { - let updated = this.params.autoAttach !== p.autoAttach + let updated = this.params.autoAttach !== p.autoAttach; this.params.autoAttach = p.autoAttach; this.params.showTooltip = p.showTooltip; this.ctx.customStructureProperties.setDefaultAutoAttach(this.provider.descriptor.name, this.params.autoAttach); @@ -78,16 +78,16 @@ export const RCSBValidationReport = PluginBehavior.create<{ autoAttach: boolean, this.ctx.managers.lociLabels.removeProvider(this.labelProvider); - this.ctx.representation.structure.themes.colorThemeRegistry.remove(DensityFitColorThemeProvider) - this.ctx.representation.structure.themes.colorThemeRegistry.remove(GeometryQualityColorThemeProvider) - this.ctx.representation.structure.themes.colorThemeRegistry.remove(RandomCoilIndexColorThemeProvider) + this.ctx.representation.structure.themes.colorThemeRegistry.remove(DensityFitColorThemeProvider); + this.ctx.representation.structure.themes.colorThemeRegistry.remove(GeometryQualityColorThemeProvider); + this.ctx.representation.structure.themes.colorThemeRegistry.remove(RandomCoilIndexColorThemeProvider); - this.ctx.representation.structure.registry.remove(ClashesRepresentationProvider) - this.ctx.query.structure.registry.remove(hasClash) + this.ctx.representation.structure.registry.remove(ClashesRepresentationProvider); + this.ctx.query.structure.registry.remove(hasClash); - this.ctx.builders.structure.representation.unregisterPreset(ValidationReportGeometryQualityPreset) - this.ctx.builders.structure.representation.unregisterPreset(ValidationReportDensityFitPreset) - this.ctx.builders.structure.representation.unregisterPreset(ValidationReportRandomCoilIndexPreset) + this.ctx.builders.structure.representation.unregisterPreset(ValidationReportGeometryQualityPreset); + this.ctx.builders.structure.representation.unregisterPreset(ValidationReportDensityFitPreset); + this.ctx.builders.structure.representation.unregisterPreset(ValidationReportRandomCoilIndexPreset); } }, params: () => ({ @@ -101,78 +101,78 @@ export const RCSBValidationReport = PluginBehavior.create<{ autoAttach: boolean, function geometryQualityLabel(loci: Loci): string | undefined { if (loci.kind === 'element-loci') { - if (loci.elements.length === 0) return + if (loci.elements.length === 0) return; if (loci.elements.length === 1 && OrderedSet.size(loci.elements[0].indices) === 1) { - const { unit, indices } = loci.elements[0] + const { unit, indices } = loci.elements[0]; - const validationReport = ValidationReportProvider.get(unit.model).value - if (!validationReport) return - if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) return + const validationReport = ValidationReportProvider.get(unit.model).value; + if (!validationReport) return; + if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) return; - const { bondOutliers, angleOutliers } = validationReport - const eI = unit.elements[OrderedSet.start(indices)] - const issues = new Set<string>() + const { bondOutliers, angleOutliers } = validationReport; + const eI = unit.elements[OrderedSet.start(indices)]; + const issues = new Set<string>(); - const bonds = bondOutliers.index.get(eI) - if (bonds) bonds.forEach(b => issues.add(bondOutliers.data[b].tag)) + const bonds = bondOutliers.index.get(eI); + if (bonds) bonds.forEach(b => issues.add(bondOutliers.data[b].tag)); - const angles = angleOutliers.index.get(eI) - if (angles) angles.forEach(a => issues.add(angleOutliers.data[a].tag)) + const angles = angleOutliers.index.get(eI); + if (angles) angles.forEach(a => issues.add(angleOutliers.data[a].tag)); if (issues.size === 0) { return `Geometry Quality <small>(1 Atom)</small>: no issues`; } - const summary: string[] = [] - issues.forEach(name => summary.push(name)) + const summary: string[] = []; + issues.forEach(name => summary.push(name)); return `Geometry Quality <small>(1 Atom)</small>: ${summary.join(', ')}`; } - let hasValidationReport = false - const seen = new Set<number>() - const cummulativeIssues = new Map<string, number>() + let hasValidationReport = false; + const seen = new Set<number>(); + const cummulativeIssues = new Map<string, number>(); for (const { indices, unit } of loci.elements) { - const validationReport = ValidationReportProvider.get(unit.model).value - if (!validationReport) continue - if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) continue - hasValidationReport = true + const validationReport = ValidationReportProvider.get(unit.model).value; + if (!validationReport) continue; + if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) continue; + hasValidationReport = true; - const { geometryIssues } = validationReport - const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index - const { elements } = unit + const { geometryIssues } = validationReport; + const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; + const { elements } = unit; OrderedSet.forEach(indices, idx => { - const eI = elements[idx] + const eI = elements[idx]; - const rI = residueIndex[eI] - const residueKey = cantorPairing(rI, unit.id) + const rI = residueIndex[eI]; + const residueKey = cantorPairing(rI, unit.id); if (!seen.has(residueKey)) { - const issues = geometryIssues.get(rI) + const issues = geometryIssues.get(rI); if (issues) { issues.forEach(name => { - const count = cummulativeIssues.get(name) || 0 - cummulativeIssues.set(name, count + 1) - }) + const count = cummulativeIssues.get(name) || 0; + cummulativeIssues.set(name, count + 1); + }); } - seen.add(residueKey) + seen.add(residueKey); } - }) + }); } - if (!hasValidationReport) return + if (!hasValidationReport) return; - const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues' : 'Residue'})</small>` + const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues' : 'Residue'})</small>`; if (cummulativeIssues.size === 0) { return `Geometry Quality ${residueCount}: no issues`; } - const summary: string[] = [] + const summary: string[] = []; cummulativeIssues.forEach((count, name) => { - summary.push(`${name}${count > 1 ? ` \u00D7 ${count}` : ''}`) - }) + summary.push(`${name}${count > 1 ? ` \u00D7 ${count}` : ''}`); + }); return `Geometry Quality ${residueCount}: ${summary.join(', ')}`; } } @@ -181,58 +181,58 @@ function densityFitLabel(loci: Loci): string | undefined { if (loci.kind === 'element-loci') { if (loci.elements.length === 0) return; - const seen = new Set<number>() - const rsrzSeen = new Set<number>() - const rsccSeen = new Set<number>() - let rsrzSum = 0 - let rsccSum = 0 + const seen = new Set<number>(); + const rsrzSeen = new Set<number>(); + const rsccSeen = new Set<number>(); + let rsrzSum = 0; + let rsccSum = 0; for (const { indices, unit } of loci.elements) { - const validationReport = ValidationReportProvider.get(unit.model).value - if (!validationReport) continue - if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) continue + const validationReport = ValidationReportProvider.get(unit.model).value; + if (!validationReport) continue; + if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) continue; - const { rsrz, rscc } = validationReport - const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index - const { elements } = unit + const { rsrz, rscc } = validationReport; + const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; + const { elements } = unit; OrderedSet.forEach(indices, idx => { - const eI = elements[idx] - const rI = residueIndex[eI] + const eI = elements[idx]; + const rI = residueIndex[eI]; - const residueKey = cantorPairing(rI, unit.id) + const residueKey = cantorPairing(rI, unit.id); if (!seen.has(residueKey)) { - const rsrzValue = rsrz.get(rI) - const rsccValue = rscc.get(rI) + const rsrzValue = rsrz.get(rI); + const rsccValue = rscc.get(rI); if (rsrzValue !== undefined) { - rsrzSum += rsrzValue - rsrzSeen.add(residueKey) + rsrzSum += rsrzValue; + rsrzSeen.add(residueKey); } else if (rsccValue !== undefined) { - rsccSum += rsccValue - rsccSeen.add(residueKey) + rsccSum += rsccValue; + rsccSeen.add(residueKey); } - seen.add(residueKey) + seen.add(residueKey); } - }) + }); } - if (seen.size === 0) return + if (seen.size === 0) return; - const summary: string[] = [] + const summary: string[] = []; if (rsrzSeen.size) { - const rsrzCount = `<small>(${rsrzSeen.size} ${rsrzSeen.size > 1 ? 'Residues avg.' : 'Residue'})</small>` - const rsrzAvg = rsrzSum / rsrzSeen.size - summary.push(`Real Space R ${rsrzCount}: ${rsrzAvg.toFixed(2)}`) + const rsrzCount = `<small>(${rsrzSeen.size} ${rsrzSeen.size > 1 ? 'Residues avg.' : 'Residue'})</small>`; + const rsrzAvg = rsrzSum / rsrzSeen.size; + summary.push(`Real Space R ${rsrzCount}: ${rsrzAvg.toFixed(2)}`); } if (rsccSeen.size) { - const rsccCount = `<small>(${rsccSeen.size} ${rsccSeen.size > 1 ? 'Residues avg.' : 'Residue'})</small>` - const rsccAvg = rsccSum / rsccSeen.size - summary.push(`Real Space Correlation Coefficient ${rsccCount}: ${rsccAvg.toFixed(2)}`) + const rsccCount = `<small>(${rsccSeen.size} ${rsccSeen.size > 1 ? 'Residues avg.' : 'Residue'})</small>`; + const rsccAvg = rsccSum / rsccSeen.size; + summary.push(`Real Space Correlation Coefficient ${rsccCount}: ${rsccAvg.toFixed(2)}`); } if (summary.length) { - return summary.join('</br>') + return summary.join('</br>'); } } } @@ -241,39 +241,39 @@ function randomCoilIndexLabel(loci: Loci): string | undefined { if (loci.kind === 'element-loci') { if (loci.elements.length === 0) return; - const seen = new Set<number>() - let sum = 0 + const seen = new Set<number>(); + let sum = 0; for (const { indices, unit } of loci.elements) { - const validationReport = ValidationReportProvider.get(unit.model).value - if (!validationReport) continue - if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) continue + const validationReport = ValidationReportProvider.get(unit.model).value; + if (!validationReport) continue; + if (!unit.model.customProperties.hasReference(ValidationReportProvider.descriptor)) continue; - const { rci } = validationReport - const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index - const { elements } = unit + const { rci } = validationReport; + const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; + const { elements } = unit; OrderedSet.forEach(indices, idx => { - const eI = elements[idx] - const rI = residueIndex[eI] + const eI = elements[idx]; + const rI = residueIndex[eI]; - const residueKey = cantorPairing(rI, unit.id) + const residueKey = cantorPairing(rI, unit.id); if (!seen.has(residueKey)) { - const rciValue = rci.get(rI) + const rciValue = rci.get(rI); if (rciValue !== undefined) { - sum += rciValue - seen.add(residueKey) + sum += rciValue; + seen.add(residueKey); } } - }) + }); } - if (seen.size === 0) return + if (seen.size === 0) return; - const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues avg.' : 'Residue'})</small>` - const rciAvg = sum / seen.size + const residueCount = `<small>(${seen.size} ${seen.size > 1 ? 'Residues avg.' : 'Residue'})</small>`; + const rciAvg = sum / seen.size; - return `Random Coil Index ${residueCount}: ${rciAvg.toFixed(2)}` + return `Random Coil Index ${residueCount}: ${rciAvg.toFixed(2)}`; } } @@ -292,9 +292,9 @@ const hasClash = StructureSelectionQuery('Residues with Clashes', MS.struct.modi description: 'Select residues with clashes in the wwPDB validation report.', category: StructureSelectionCategory.Residue, ensureCustomProperties: (ctx, structure) => { - return ValidationReportProvider.attach(ctx, structure.models[0]) + return ValidationReportProvider.attach(ctx, structure.models[0]); } -}) +}); // @@ -305,22 +305,22 @@ export const ValidationReportGeometryQualityPreset = StructureRepresentationPres description: 'Color structure based on geometry quality; show geometry clashes. Data from wwPDB Validation Report, obtained via RCSB PDB.' }, isApplicable(a) { - return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) + return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]); }, params: () => StructureRepresentationPresetProvider.CommonParams, async apply(ref, params, plugin) { const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref); - const model = structureCell?.obj?.data.model + const model = structureCell?.obj?.data.model; if (!structureCell || !model) return {}; await plugin.runTask(Task.create('Validation Report', async runtime => { - await ValidationReportProvider.attach({ fetch: plugin.fetch, runtime }, model) - })) + await ValidationReportProvider.attach({ fetch: plugin.fetch, runtime }, model); + })); - const colorTheme = GeometryQualityColorThemeProvider.name as any - const { components, representations } = await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin) + const colorTheme = GeometryQualityColorThemeProvider.name as any; + const { components, representations } = await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin); - const clashes = await plugin.builders.structure.tryCreateComponentFromExpression(structureCell, hasClash.expression, 'clashes', { label: 'Clashes' }) + const clashes = await plugin.builders.structure.tryCreateComponentFromExpression(structureCell, hasClash.expression, 'clashes', { label: 'Clashes' }); const { update, builder, typeParams, color } = StructureRepresentationPresetProvider.reprBuilder(plugin, params); let clashesBallAndStick, clashesSnfg3d; @@ -341,20 +341,20 @@ export const ValidationReportDensityFitPreset = StructureRepresentationPresetPro description: 'Color structure based on density fit. Data from wwPDB Validation Report, obtained via RCSB PDB.' }, isApplicable(a) { - return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) && Model.hasXrayMap(a.data.models[0]) + return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) && Model.hasXrayMap(a.data.models[0]); }, params: () => StructureRepresentationPresetProvider.CommonParams, async apply(ref, params, plugin) { const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref); - const model = structureCell?.obj?.data.model + const model = structureCell?.obj?.data.model; if (!structureCell || !model) return {}; await plugin.runTask(Task.create('Validation Report', async runtime => { - await ValidationReportProvider.attach({ fetch: plugin.fetch, runtime }, model) - })) + await ValidationReportProvider.attach({ fetch: plugin.fetch, runtime }, model); + })); - const colorTheme = DensityFitColorThemeProvider.name as any - return await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin) + const colorTheme = DensityFitColorThemeProvider.name as any; + return await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin); } }); @@ -365,19 +365,19 @@ export const ValidationReportRandomCoilIndexPreset = StructureRepresentationPres description: 'Color structure based on Random Coil Index. Data from wwPDB Validation Report, obtained via RCSB PDB.' }, isApplicable(a) { - return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) && Model.isFromNmr(a.data.models[0]) + return a.data.models.length === 1 && ValidationReport.isApplicable(a.data.models[0]) && Model.isFromNmr(a.data.models[0]); }, params: () => StructureRepresentationPresetProvider.CommonParams, async apply(ref, params, plugin) { const structureCell = StateObjectRef.resolveAndCheck(plugin.state.data, ref); - const model = structureCell?.obj?.data.model + const model = structureCell?.obj?.data.model; if (!structureCell || !model) return {}; await plugin.runTask(Task.create('Validation Report', async runtime => { - await ValidationReportProvider.attach({ fetch: plugin.fetch, runtime }, model) - })) + await ValidationReportProvider.attach({ fetch: plugin.fetch, runtime }, model); + })); - const colorTheme = RandomCoilIndexColorThemeProvider.name as any - return await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin) + const colorTheme = RandomCoilIndexColorThemeProvider.name as any; + return await PresetStructureRepresentations.auto.apply(ref, { ...params, globalThemeName: colorTheme }, plugin); } }); \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/representation.ts b/src/mol-plugin/behavior/dynamic/representation.ts index 88494345213c5352da8ea9191042b01500ff05e9..45a80d79dfe6b3389313aa6da1acec2b95e49668 100644 --- a/src/mol-plugin/behavior/dynamic/representation.ts +++ b/src/mol-plugin/behavior/dynamic/representation.ts @@ -21,19 +21,19 @@ import { arrayMax } from '../../../mol-util/array'; import { Representation } from '../../../mol-repr/representation'; import { LociLabel } from '../../../mol-plugin-state/manager/loci-label'; -const B = ButtonsType -const M = ModifiersKeys -const Trigger = Binding.Trigger +const B = ButtonsType; +const M = ModifiersKeys; +const Trigger = Binding.Trigger; // const DefaultHighlightLociBindings = { hoverHighlightOnly: Binding([Trigger(B.Flag.None)], 'Highlight', 'Hover element using ${triggers}'), hoverHighlightOnlyExtend: Binding([Trigger(B.Flag.None, M.create({ shift: true }))], 'Extend highlight', 'From selected to hovered element along polymer using ${triggers}'), -} +}; const HighlightLociParams = { bindings: PD.Value(DefaultHighlightLociBindings, { isHidden: true }), -} +}; type HighlightLociProps = PD.Values<typeof HighlightLociParams> export const HighlightLoci = PluginBehavior.create({ @@ -42,31 +42,31 @@ export const HighlightLoci = PluginBehavior.create({ ctor: class extends PluginBehavior.Handler<HighlightLociProps> { private lociMarkProvider = (interactionLoci: Representation.Loci, action: MarkerAction) => { if (!this.ctx.canvas3d) return; - this.ctx.canvas3d.mark({ loci: interactionLoci.loci }, action) + this.ctx.canvas3d.mark({ loci: interactionLoci.loci }, action); } register() { this.subscribeObservable(this.ctx.behaviors.interaction.hover, ({ current, buttons, modifiers }) => { - if (!this.ctx.canvas3d || this.ctx.isBusy) return - let matched = false + if (!this.ctx.canvas3d || this.ctx.isBusy) return; + let matched = false; if (Binding.match(this.params.bindings.hoverHighlightOnly, buttons, modifiers)) { - this.ctx.managers.interactivity.lociHighlights.highlightOnly(current) - matched = true + this.ctx.managers.interactivity.lociHighlights.highlightOnly(current); + matched = true; } if (Binding.match(this.params.bindings.hoverHighlightOnlyExtend, buttons, modifiers)) { - this.ctx.managers.interactivity.lociHighlights.highlightOnlyExtend(current) - matched = true + this.ctx.managers.interactivity.lociHighlights.highlightOnlyExtend(current); + matched = true; } if (!matched) { - this.ctx.managers.interactivity.lociHighlights.highlightOnly({ repr: current.repr, loci: EmptyLoci }) + this.ctx.managers.interactivity.lociHighlights.highlightOnly({ repr: current.repr, loci: EmptyLoci }); } }); - this.ctx.managers.interactivity.lociHighlights.addProvider(this.lociMarkProvider) + this.ctx.managers.interactivity.lociHighlights.addProvider(this.lociMarkProvider); } unregister() { - this.ctx.managers.interactivity.lociHighlights.removeProvider(this.lociMarkProvider) + this.ctx.managers.interactivity.lociHighlights.removeProvider(this.lociMarkProvider); } }, params: () => HighlightLociParams, @@ -82,10 +82,10 @@ const DefaultSelectLociBindings = { clickToggle: Binding([Trigger(B.Flag.Primary, M.create())], 'Toggle selection', '${triggers} on element'), clickDeselect: Binding.Empty, clickDeselectAllOnEmpty: Binding([Trigger(B.Flag.Primary, M.create())], 'Deselect all', 'Click on nothing using ${triggers}'), -} +}; const SelectLociParams = { bindings: PD.Value(DefaultSelectLociBindings, { isHidden: true }), -} +}; type SelectLociProps = PD.Values<typeof SelectLociParams> export const SelectLoci = PluginBehavior.create({ @@ -95,25 +95,25 @@ export const SelectLoci = PluginBehavior.create({ private spine: StateTreeSpine.Impl private lociMarkProvider = (reprLoci: Representation.Loci, action: MarkerAction) => { if (!this.ctx.canvas3d) return; - this.ctx.canvas3d.mark({ loci: reprLoci.loci }, action) + this.ctx.canvas3d.mark({ loci: reprLoci.loci }, action); } private applySelectMark(ref: string, clear?: boolean) { - const cell = this.ctx.state.data.cells.get(ref) + const cell = this.ctx.state.data.cells.get(ref); if (cell && SO.isRepresentation3D(cell.obj)) { - this.spine.current = cell - const so = this.spine.getRootOfType(SO.Molecule.Structure) + this.spine.current = cell; + const so = this.spine.getRootOfType(SO.Molecule.Structure); if (so) { if (clear) { - this.lociMarkProvider({ loci: Structure.Loci(so.data) }, MarkerAction.Deselect) + this.lociMarkProvider({ loci: Structure.Loci(so.data) }, MarkerAction.Deselect); } - const loci = this.ctx.managers.structure.selection.getLoci(so.data) - this.lociMarkProvider({ loci }, MarkerAction.Select) + const loci = this.ctx.managers.structure.selection.getLoci(so.data); + this.lociMarkProvider({ loci }, MarkerAction.Select); } } } register() { - const lociIsEmpty = (current: Representation.Loci) => Loci.isEmpty(current.loci) - const lociIsNotEmpty = (current: Representation.Loci) => !Loci.isEmpty(current.loci) + const lociIsEmpty = (current: Representation.Loci) => Loci.isEmpty(current.loci); + const lociIsNotEmpty = (current: Representation.Loci) => !Loci.isEmpty(current.loci); const actions: [keyof typeof DefaultSelectLociBindings, (current: Representation.Loci) => void, ((current: Representation.Loci) => boolean) | undefined][] = [ ['clickSelect', current => this.ctx.managers.interactivity.lociSelects.select(current), lociIsNotEmpty], @@ -130,7 +130,7 @@ export const SelectLoci = PluginBehavior.create({ const k = x.triggers.length === 0 ? 0 : arrayMax(x.triggers.map(t => M.size(t.modifiers))); const l = y.triggers.length === 0 ? 0 : arrayMax(y.triggers.map(t => M.size(t.modifiers))); return l - k; - }) + }); this.subscribeObservable(this.ctx.behaviors.interaction.click, ({ current, button, modifiers }) => { if (!this.ctx.canvas3d || this.ctx.isBusy || !this.ctx.selectionMode) return; @@ -143,25 +143,25 @@ export const SelectLoci = PluginBehavior.create({ } } }); - this.ctx.managers.interactivity.lociSelects.addProvider(this.lociMarkProvider) + this.ctx.managers.interactivity.lociSelects.addProvider(this.lociMarkProvider); this.subscribeObservable(this.ctx.events.state.object.created, ({ ref }) => this.applySelectMark(ref)); // re-apply select-mark to all representation of an updated structure this.subscribeObservable(this.ctx.events.state.object.updated, ({ ref }) => { - const cell = this.ctx.state.data.cells.get(ref) + const cell = this.ctx.state.data.cells.get(ref); if (cell && SO.Molecule.Structure.is(cell.obj)) { - const reprs = this.ctx.state.data.select(StateSelection.Generators.ofType(SO.Molecule.Structure.Representation3D, ref)) - for (const repr of reprs) this.applySelectMark(repr.transform.ref, true) + const reprs = this.ctx.state.data.select(StateSelection.Generators.ofType(SO.Molecule.Structure.Representation3D, ref)); + for (const repr of reprs) this.applySelectMark(repr.transform.ref, true); } }); } unregister() { - this.ctx.managers.interactivity.lociSelects.removeProvider(this.lociMarkProvider) + this.ctx.managers.interactivity.lociSelects.removeProvider(this.lociMarkProvider); } constructor(ctx: PluginContext, params: SelectLociProps) { - super(ctx, params) - this.spine = new StateTreeSpine.Impl(ctx.state.data.cells) + super(ctx, params); + this.spine = new StateTreeSpine.Impl(ctx.state.data.cells); } }, params: () => SelectLociParams, @@ -176,15 +176,15 @@ export const DefaultLociLabelProvider = PluginBehavior.create({ ctor: class implements PluginBehavior<undefined> { private f = { label: (loci: Loci) => { - const label: string[] = [] + const label: string[] = []; if (StructureElement.Loci.is(loci) && loci.elements.length === 1) { - const { unit: u } = loci.elements[0] - const l = StructureElement.Location.create(loci.structure, u, u.elements[0]) - const name = StructureProperties.entity.pdbx_description(l).join(', ') - label.push(name) + const { unit: u } = loci.elements[0]; + const l = StructureElement.Location.create(loci.structure, u, u.elements[0]); + const name = StructureProperties.entity.pdbx_description(l).join(', '); + label.push(name); } - label.push(lociLabel(loci)) - return label.filter(l => !!l).join('</br>') + label.push(lociLabel(loci)); + return label.filter(l => !!l).join('</br>'); }, group: (label: LociLabel) => label.toString().replace(/Model [0-9]+/g, 'Models'), priority: 100 @@ -213,10 +213,10 @@ const DefaultFocusLociBindings = { Trigger(B.Flag.Secondary, M.create({ shift: true })), Trigger(B.Flag.Primary, M.create({ control: true, shift: true })) ], 'Representation Focus Add', 'Click element using ${triggers}'), -} +}; const FocusLociParams = { bindings: PD.Value(DefaultFocusLociBindings, { isHidden: true }), -} +}; type FocusLociProps = PD.Values<typeof FocusLociParams> export const FocusLoci = PluginBehavior.create<FocusLociProps>({ @@ -228,27 +228,27 @@ export const FocusLoci = PluginBehavior.create<FocusLociProps>({ const { clickFocus, clickFocusAdd, clickFocusSelectMode, clickFocusAddSelectMode } = this.params.bindings; const binding = this.ctx.selectionMode ? clickFocusSelectMode : clickFocus; - const matched = Binding.match(binding, button, modifiers) + const matched = Binding.match(binding, button, modifiers); const bindingAdd = this.ctx.selectionMode ? clickFocusAddSelectMode : clickFocusAdd; - const matchedAdd = Binding.match(bindingAdd, button, modifiers) + const matchedAdd = Binding.match(bindingAdd, button, modifiers); if (matched || matchedAdd) { - const loci = Loci.normalize(current.loci, 'residue') - const entry = this.ctx.managers.structure.focus.current + const loci = Loci.normalize(current.loci, 'residue'); + const entry = this.ctx.managers.structure.focus.current; if (entry && Loci.areEqual(entry.loci, loci)) { - this.ctx.managers.structure.focus.clear() + this.ctx.managers.structure.focus.clear(); } else { if (matched) { - this.ctx.managers.structure.focus.setFromLoci(loci) + this.ctx.managers.structure.focus.setFromLoci(loci); } else { - this.ctx.managers.structure.focus.addFromLoci(loci) + this.ctx.managers.structure.focus.addFromLoci(loci); } if (isEmptyLoci(loci)) { - this.ctx.managers.camera.reset() + this.ctx.managers.camera.reset(); } } - return + return; } }); } diff --git a/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts b/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts index 0a41479a1e8fc23c35193361a741413e4622d52b..51fd3ec24c14a5ddaea34147d02dd25c53e13b11 100644 --- a/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts +++ b/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts @@ -41,7 +41,7 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => { }) }) }; -} +}; type StructureFocusRepresentationProps = PD.ValuesFor<ReturnType<typeof StructureFocusRepresentationParams>> @@ -53,7 +53,7 @@ export enum StructureFocusRepresentationTags { SurrNciRepr = 'structure-focus-surr-nci-repr' } -const TagSet: Set<StructureFocusRepresentationTags> = new Set([StructureFocusRepresentationTags.TargetSel, StructureFocusRepresentationTags.TargetRepr, StructureFocusRepresentationTags.SurrSel, StructureFocusRepresentationTags.SurrRepr, StructureFocusRepresentationTags.SurrNciRepr]) +const TagSet: Set<StructureFocusRepresentationTags> = new Set([StructureFocusRepresentationTags.TargetSel, StructureFocusRepresentationTags.TargetRepr, StructureFocusRepresentationTags.SurrSel, StructureFocusRepresentationTags.SurrRepr, StructureFocusRepresentationTags.SurrNciRepr]); export class StructureFocusRepresentationBehavior extends PluginBehavior.WithSubscribers<StructureFocusRepresentationProps> { private get surrLabel() { return `[Focus] Surroundings (${this.params.expandRadius} Ã…)`; } @@ -125,8 +125,8 @@ export class StructureFocusRepresentationBehavior extends PluginBehavior.WithSub const parent = this.plugin.helpers.substructureParent.get(loci.structure); if (!parent || !parent.obj) return; - const residueLoci = StructureElement.Loci.extendToWholeResidues(StructureElement.Loci.remap(loci, parent.obj!.data)) - const residueBundle = StructureElement.Bundle.fromLoci(residueLoci) + const residueLoci = StructureElement.Loci.extendToWholeResidues(StructureElement.Loci.remap(loci, parent.obj!.data)); + const residueBundle = StructureElement.Bundle.fromLoci(residueLoci); const surroundings = MS.struct.modifier.includeSurroundings({ 0: StructureElement.Bundle.toExpression(residueBundle), @@ -146,8 +146,8 @@ export class StructureFocusRepresentationBehavior extends PluginBehavior.WithSub register(ref: string): void { this.subscribeObservable(this.plugin.managers.structure.focus.behaviors.current, (entry) => { - if (entry) this.focus(entry.loci) - else this.clear(StateTransform.RootRef) + if (entry) this.focus(entry.loci); + else this.clear(StateTransform.RootRef); }); } diff --git a/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts b/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts index 83b5e4d47a60c369b598c2058d05c0289da5cce9..06ff54c14e89f0033a02ce61994d8d057089cfc8 100644 --- a/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts +++ b/src/mol-plugin/behavior/dynamic/volume-streaming/behavior.ts @@ -27,7 +27,7 @@ import { EmptyLoci, Loci, isEmptyLoci } from '../../../../mol-model/loci'; export class VolumeStreaming extends PluginStateObject.CreateBehavior<VolumeStreaming.Behavior>({ name: 'Volume Streaming' }) { } export namespace VolumeStreaming { - export const RootTag = 'volume-streaming-info' + export const RootTag = 'volume-streaming-info'; export interface ChannelParams { isoValue: VolumeIsoValue, @@ -54,13 +54,13 @@ export namespace VolumeStreaming { export function createParams(options: { data?: VolumeServerInfo.Data, defaultView?: ViewTypes, channelParams?: DefaultChannelParams } = { }) { const { data, defaultView, channelParams } = options; - const map = new Map<string, VolumeServerInfo.EntryData>() - if (data) data.entries.forEach(d => map.set(d.dataId, d)) - const names = data ? data.entries.map(d => [d.dataId, d.dataId] as [string, string]) : [] - const defaultKey = data ? data.entries[0].dataId : '' + const map = new Map<string, VolumeServerInfo.EntryData>(); + if (data) data.entries.forEach(d => map.set(d.dataId, d)); + const names = data ? data.entries.map(d => [d.dataId, d.dataId] as [string, string]) : []; + const defaultKey = data ? data.entries[0].dataId : ''; return { entry: PD.Mapped<EntryParams>(defaultKey, names, name => PD.Group(createEntryParams({ entryData: map.get(name)!, defaultView, structure: data && data.structure, channelParams }))), - } + }; } export type EntryParamDefinition = typeof createEntryParams extends (...args: any[]) => (infer T) ? T : never @@ -113,7 +113,7 @@ export namespace VolumeStreaming { type ChannelsData = { [name in 'EM' | '2FO-FC' | 'FO-FC']?: VolumeData } export type ChannelType = 'em' | '2fo-fc' | 'fo-fc(+ve)' | 'fo-fc(-ve)' - export const ChannelTypeOptions: [ChannelType, string][] = [['em', 'em'], ['2fo-fc', '2fo-fc'], ['fo-fc(+ve)', 'fo-fc(+ve)'], ['fo-fc(-ve)', 'fo-fc(-ve)']] + export const ChannelTypeOptions: [ChannelType, string][] = [['em', 'em'], ['2fo-fc', '2fo-fc'], ['fo-fc(+ve)', 'fo-fc(+ve)'], ['fo-fc(-ve)', 'fo-fc(-ve)']]; export interface ChannelInfo { data: VolumeData, color: Color, @@ -135,7 +135,7 @@ export namespace VolumeStreaming { channels: Channels = {} public get info () { - return this.infoMap.get(this.params.entry.name)! + return this.infoMap.get(this.params.entry.name)!; } private async queryData(box?: Box3D) { @@ -236,12 +236,12 @@ export namespace VolumeStreaming { }); this.subscribeObservable(this.plugin.managers.structure.focus.behaviors.current, (entry) => { - const loci = entry ? entry.loci : EmptyLoci + const loci = entry ? entry.loci : EmptyLoci; if (this.params.entry.params.view.name !== 'selection-box') { this.lastLoci = loci; } else { - this.updateInteraction(loci) + this.updateInteraction(loci); } }); } @@ -256,10 +256,10 @@ export namespace VolumeStreaming { const root = this.getStructureRoot(); if (!root || root.obj?.data !== parent.obj?.data) return Box3D.empty(); - const extendedLoci = StructureElement.Loci.extendToWholeResidues(loci) - const box = StructureElement.Loci.getBoundary(extendedLoci).box + const extendedLoci = StructureElement.Loci.extendToWholeResidues(loci); + const box = StructureElement.Loci.getBoundary(extendedLoci).box; if (StructureElement.Loci.size(extendedLoci) === 1) { - Box3D.expand(box, box, Vec3.create(1, 1, 1)) + Box3D.expand(box, box, Vec3.create(1, 1, 1)); } return box; } @@ -353,8 +353,8 @@ export namespace VolumeStreaming { constructor(public plugin: PluginContext, public data: VolumeServerInfo.Data) { super(plugin, {} as any); - this.infoMap = new Map<string, VolumeServerInfo.EntryData>() - this.data.entries.forEach(info => this.infoMap.set(info.dataId, info)) + this.infoMap = new Map<string, VolumeServerInfo.EntryData>(); + this.data.entries.forEach(info => this.infoMap.set(info.dataId, info)); } } } \ No newline at end of file diff --git a/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts b/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts index c4a44118c52c170a42ccfb5e7f4b7b2fa9c6bc2c..fd1bd1db6354d8b83e6c8b0c272981e1434e7eef 100644 --- a/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts +++ b/src/mol-plugin/behavior/dynamic/volume-streaming/transformers.ts @@ -30,7 +30,7 @@ function addEntry(entries: InfoEntryProps[], method: VolumeServerInfo.Kind, data ? { name: 'em', params: { isoValue: VolumeIsoValue.absolute(emDefaultContourLevel || 0) } } : { name: 'x-ray', params: { } }, dataId - }) + }); } export const InitVolumeStreaming = StateAction.build({ @@ -57,10 +57,10 @@ export const InitVolumeStreaming = StateAction.build({ return a.data.models.length === 1 && Model.hasDensityMap(a.data.models[0]); } })(({ ref, state, params }, plugin: PluginContext) => Task.create('Volume Streaming', async taskCtx => { - const entries: InfoEntryProps[] = [] + const entries: InfoEntryProps[] = []; for (let i = 0, il = params.entries.length; i < il; ++i) { - let dataId = params.entries[i].id.toLowerCase() + let dataId = params.entries[i].id.toLowerCase(); let emDefaultContourLevel: number | undefined; if (params.method === 'em') { @@ -68,29 +68,29 @@ export const InitVolumeStreaming = StateAction.build({ // and continue the loop if (!dataId.toUpperCase().startsWith('EMD')) { await taskCtx.update('Getting EMDB info...'); - const emdbIds = await getEmdbIds(plugin, taskCtx, dataId) + const emdbIds = await getEmdbIds(plugin, taskCtx, dataId); for (let j = 0, jl = emdbIds.length; j < jl; ++j) { - const emdbId = emdbIds[j] + const emdbId = emdbIds[j]; let contourLevel: number | undefined; try { - contourLevel = await getContourLevel(params.options.emContourProvider, plugin, taskCtx, emdbId) + contourLevel = await getContourLevel(params.options.emContourProvider, plugin, taskCtx, emdbId); } catch (e) { - console.info(`Could not get map info for ${emdbId}: ${e}`) + console.info(`Could not get map info for ${emdbId}: ${e}`); continue; } - addEntry(entries, params.method, emdbId, contourLevel || 0) + addEntry(entries, params.method, emdbId, contourLevel || 0); } continue; } try { emDefaultContourLevel = await getContourLevel(params.options.emContourProvider, plugin, taskCtx, dataId); } catch (e) { - console.info(`Could not get map info for ${dataId}: ${e}`) + console.info(`Could not get map info for ${dataId}: ${e}`); continue; } } - addEntry(entries, params.method, dataId, emDefaultContourLevel || 0) + addEntry(entries, params.method, dataId, emDefaultContourLevel || 0); } const infoTree = state.build().to(ref) @@ -161,10 +161,10 @@ const InfoEntryParams = { }), 'x-ray': PD.Group({ }) }) -} +}; type InfoEntryProps = PD.Values<typeof InfoEntryParams> -export { CreateVolumeStreamingInfo } +export { CreateVolumeStreamingInfo }; type CreateVolumeStreamingInfo = typeof CreateVolumeStreamingInfo const CreateVolumeStreamingInfo = PluginStateTransform.BuiltIn({ name: 'create-volume-streaming-info', @@ -181,9 +181,9 @@ const CreateVolumeStreamingInfo = PluginStateTransform.BuiltIn({ } })({ apply: ({ a, params }, plugin: PluginContext) => Task.create('', async taskCtx => { - const entries: VolumeServerInfo.EntryData[] = [] + const entries: VolumeServerInfo.EntryData[] = []; for (let i = 0, il = params.entries.length; i < il; ++i) { - const e = params.entries[i] + const e = params.entries[i]; const dataId = e.dataId; const emDefaultContourLevel = e.source.name === 'em' ? e.source.params.isoValue : VolumeIsoValue.relative(1); await taskCtx.update('Getting server header...'); @@ -193,7 +193,7 @@ const CreateVolumeStreamingInfo = PluginStateTransform.BuiltIn({ kind: e.source.name, header, emDefaultContourLevel - }) + }); } const data: VolumeServerInfo.Data = { @@ -205,7 +205,7 @@ const CreateVolumeStreamingInfo = PluginStateTransform.BuiltIn({ }) }); -export { CreateVolumeStreamingBehavior } +export { CreateVolumeStreamingBehavior }; type CreateVolumeStreamingBehavior = typeof CreateVolumeStreamingBehavior const CreateVolumeStreamingBehavior = PluginStateTransform.BuiltIn({ name: 'create-volume-streaming-behavior', @@ -230,9 +230,9 @@ const CreateVolumeStreamingBehavior = PluginStateTransform.BuiltIn({ return Task.create('Update Volume Streaming', async _ => { if (oldParams.entry.name !== newParams.entry.name) { if ('em' in newParams.entry.params.channels) { - const { emDefaultContourLevel } = b.data.infoMap.get(newParams.entry.name)! + const { emDefaultContourLevel } = b.data.infoMap.get(newParams.entry.name)!; if (emDefaultContourLevel) { - newParams.entry.params.channels['em'].isoValue = emDefaultContourLevel + newParams.entry.params.channels['em'].isoValue = emDefaultContourLevel; } } } @@ -243,7 +243,7 @@ const CreateVolumeStreamingBehavior = PluginStateTransform.BuiltIn({ } }); -export { VolumeStreamingVisual } +export { VolumeStreamingVisual }; type VolumeStreamingVisual = typeof VolumeStreamingVisual const VolumeStreamingVisual = PluginStateTransform.BuiltIn({ name: 'create-volume-streaming-visual', @@ -261,9 +261,9 @@ const VolumeStreamingVisual = PluginStateTransform.BuiltIn({ const params = createVolumeProps(a.data, srcParams.channel); const provider = VolumeRepresentationRegistry.BuiltIn.isosurface; - const props = params.type.params || {} - const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.volume.themes }, provider.getParams) - repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: channel.data }, params)) + const props = params.type.params || {}; + const repr = provider.factory({ webgl: plugin.canvas3d?.webgl, ...plugin.representation.volume.themes }, provider.getParams); + repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: channel.data }, params)); await repr.createOrUpdate(props, channel.data).runInContext(ctx); return new SO.Volume.Representation3D({ repr, source: a }, { label: `${Math.round(channel.isoValue.relativeValue * 100) / 100} σ [${srcParams.channel}]` }); }), @@ -276,7 +276,7 @@ const VolumeStreamingVisual = PluginStateTransform.BuiltIn({ const params = createVolumeProps(a.data, newParams.channel); const props = { ...b.data.repr.props, ...params.type.params }; - b.data.repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: channel.data }, params)) + b.data.repr.setTheme(Theme.create(plugin.representation.volume.themes, { volume: channel.data }, params)); await b.data.repr.createOrUpdate(props, channel.data).runInContext(ctx); return StateTransformer.UpdateResult.Updated; }) diff --git a/src/mol-plugin/behavior/dynamic/volume-streaming/util.ts b/src/mol-plugin/behavior/dynamic/volume-streaming/util.ts index a15b8fd7b45e7b1092653bdecf008e13b2b84ab6..13ba6cf784fc3991600613c8b497c2cf321360c2 100644 --- a/src/mol-plugin/behavior/dynamic/volume-streaming/util.ts +++ b/src/mol-plugin/behavior/dynamic/volume-streaming/util.ts @@ -20,63 +20,63 @@ export function getStreamingMethod(s?: Structure, defaultKind: VolumeServerInfo. // Prefer EMDB entries over structure-factors (SF) e.g. for 'ELECTRON CRYSTALLOGRAPHY' entries // like 6AXZ or 6KJ3 for which EMDB entries are available but map calculation from SF is hard. - if (Model.hasEmMap(model)) return 'em' - if (Model.hasXrayMap(model)) return 'x-ray' + if (Model.hasEmMap(model)) return 'em'; + if (Model.hasXrayMap(model)) return 'x-ray'; // Fallbacks based on experimental method - if (Model.isFromEm(model)) return 'em' - if (Model.isFromXray(model)) return 'x-ray' + if (Model.isFromEm(model)) return 'em'; + if (Model.isFromXray(model)) return 'x-ray'; return defaultKind; } /** Returns EMD ID when available, otherwise falls back to PDB ID */ export function getEmIds(model: Model): string[] { - const ids: string[] = [] - if (!MmcifFormat.is(model.sourceData)) return [ model.entryId ] + const ids: string[] = []; + if (!MmcifFormat.is(model.sourceData)) return [ model.entryId ]; - const { db_id, db_name, content_type } = model.sourceData.data.db.pdbx_database_related - if (!db_name.isDefined) return [ model.entryId ] + const { db_id, db_name, content_type } = model.sourceData.data.db.pdbx_database_related; + if (!db_name.isDefined) return [ model.entryId ]; for (let i = 0, il = db_name.rowCount; i < il; ++i) { if (db_name.value(i).toUpperCase() === 'EMDB' && content_type.value(i) === 'associated EM volume') { - ids.push(db_id.value(i)) + ids.push(db_id.value(i)); } } - return ids + return ids; } export function getXrayIds(model: Model): string[] { - return [ model.entryId ] + return [ model.entryId ]; } export function getIds(method: VolumeServerInfo.Kind, s?: Structure): string[] { - if (!s || !s.models.length) return [] - const model = s.models[0] + if (!s || !s.models.length) return []; + const model = s.models[0]; switch (method) { - case 'em': return getEmIds(model) - case 'x-ray': return getXrayIds(model) + case 'em': return getEmIds(model); + case 'x-ray': return getXrayIds(model); } } export async function getContourLevel(provider: 'emdb' | 'pdbe', plugin: PluginContext, taskCtx: RuntimeContext, emdbId: string) { switch (provider) { - case 'emdb': return getContourLevelEmdb(plugin, taskCtx, emdbId) - case 'pdbe': return getContourLevelPdbe(plugin, taskCtx, emdbId) + case 'emdb': return getContourLevelEmdb(plugin, taskCtx, emdbId); + case 'pdbe': return getContourLevelPdbe(plugin, taskCtx, emdbId); } } export async function getContourLevelEmdb(plugin: PluginContext, taskCtx: RuntimeContext, emdbId: string) { const emdbHeaderServer = plugin.config.get(PluginConfig.VolumeStreaming.EmdbHeaderServer); const header = await plugin.fetch({ url: `${emdbHeaderServer}/${emdbId.toUpperCase()}/header/${emdbId.toLowerCase()}.xml`, type: 'xml' }).runInContext(taskCtx); - const map = header.getElementsByTagName('map')[0] - const contourLevel = parseFloat(map.getElementsByTagName('contourLevel')[0].textContent!) + const map = header.getElementsByTagName('map')[0]; + const contourLevel = parseFloat(map.getElementsByTagName('contourLevel')[0].textContent!); return contourLevel; } export async function getContourLevelPdbe(plugin: PluginContext, taskCtx: RuntimeContext, emdbId: string) { - emdbId = emdbId.toUpperCase() + emdbId = emdbId.toUpperCase(); // TODO: parametrize to a differnt URL? in plugin settings perhaps const header = await plugin.fetch({ url: `https://www.ebi.ac.uk/pdbe/api/emdb/entry/map/${emdbId}`, type: 'json' }).runInContext(taskCtx); const emdbEntry = header?.[emdbId]; @@ -104,5 +104,5 @@ export async function getEmdbIds(plugin: PluginContext, taskCtx: RuntimeContext, throw new Error(`No related EMDB entry found for '${pdbId}'.`); } - return emdbIds + return emdbIds; } \ No newline at end of file diff --git a/src/mol-plugin/behavior/static/camera.ts b/src/mol-plugin/behavior/static/camera.ts index 8249af54c72b26aeb9266cc63e8a32362146e8c8..d08b56ff09eec52a6a8f4c7852331edc20e790d6 100644 --- a/src/mol-plugin/behavior/static/camera.ts +++ b/src/mol-plugin/behavior/static/camera.ts @@ -18,20 +18,20 @@ export function registerDefault(ctx: PluginContext) { export function Reset(ctx: PluginContext) { PluginCommands.Camera.Reset.subscribe(ctx, options => { ctx.managers.camera.reset(options?.snapshot, options?.durationMs); - }) + }); } export function SetSnapshot(ctx: PluginContext) { PluginCommands.Camera.SetSnapshot.subscribe(ctx, ({ snapshot, durationMs }) => { ctx.managers.camera.setSnapshot(snapshot, durationMs); - }) + }); } export function Focus(ctx: PluginContext) { PluginCommands.Camera.Focus.subscribe(ctx, ({ center, radius, durationMs }) => { ctx.managers.camera.focusSphere({ center, radius }, { durationMs }); ctx.events.canvas3d.settingsUpdated.next(); - }) + }); } export function Snapshots(ctx: PluginContext) { diff --git a/src/mol-plugin/behavior/static/representation.ts b/src/mol-plugin/behavior/static/representation.ts index 6948933c61e11e45e6c66512e9740778a482929e..1867af9ec1cd63f6731fcc3ad3404ac1c6eac71e 100644 --- a/src/mol-plugin/behavior/static/representation.ts +++ b/src/mol-plugin/behavior/static/representation.ts @@ -83,7 +83,7 @@ export function UpdateRepresentationVisibility(ctx: PluginContext) { updateVisibility(cell, cell.obj.data.repr); ctx.canvas3d?.syncVisibility(); ctx.canvas3d?.requestDraw(true); - }) + }); } function updateVisibility(cell: StateObjectCell, r: Representation<any>) { diff --git a/src/mol-plugin/behavior/static/state.ts b/src/mol-plugin/behavior/static/state.ts index 2012fc44d7343dea284d00760b7bba49e6299206..744dcde444d9b07661ee8660b817220232468783 100644 --- a/src/mol-plugin/behavior/static/state.ts +++ b/src/mol-plugin/behavior/static/state.ts @@ -114,7 +114,7 @@ export function Highlight(ctx: PluginContext) { if (SO.Molecule.Structure.is(cell.obj)) { ctx.managers.interactivity.lociHighlights.highlight({ loci: Structure.Loci(cell.obj.data) }, false); } else if (cell && SO.isRepresentation3D(cell.obj)) { - const { repr } = cell.obj.data + const { repr } = cell.obj.data; ctx.managers.interactivity.lociHighlights.highlight({ loci: repr.getLoci(), repr }, false); } else if (SO.Molecule.Structure.Selections.is(cell.obj)) { for (const entry of cell.obj.data) { @@ -182,7 +182,7 @@ export function Snapshots(ctx: PluginContext) { PluginCommands.State.Snapshots.DownloadToFile.subscribe(ctx, ({ name }) => { const json = JSON.stringify(ctx.state.getSnapshot(), null, 2); const blob = new Blob([json], {type : 'application/json;charset=utf-8'}); - download(blob, `mol-star_state_${(name || getFormattedTime())}.json`) + download(blob, `mol-star_state_${(name || getFormattedTime())}.json`); }); PluginCommands.State.Snapshots.OpenFile.subscribe(ctx, async ({ file }) => { diff --git a/src/mol-plugin/command.ts b/src/mol-plugin/command.ts index dbc514a85be97894bd9002ccec135a91933be46b..70b797df238d5e90733de0352a3846eca6153227 100644 --- a/src/mol-plugin/command.ts +++ b/src/mol-plugin/command.ts @@ -7,7 +7,7 @@ import { PluginContext } from './context'; import { UUID } from '../mol-util'; -export { PluginCommand, PluginCommandManager } +export { PluginCommand, PluginCommandManager }; interface PluginCommand<T = unknown> { (ctx: PluginContext, params?: T): Promise<void>, @@ -57,7 +57,7 @@ class PluginCommandManager { } actions.pop(); } - } + }; } diff --git a/src/mol-plugin/commands.ts b/src/mol-plugin/commands.ts index be1b855480a69be6d808cf14a05209beb3d543d8..9cae3ed02a8e0d5781dfc96818f6962c71c8d902 100644 --- a/src/mol-plugin/commands.ts +++ b/src/mol-plugin/commands.ts @@ -73,4 +73,4 @@ export const PluginCommands = { SetSettings: PluginCommand<{ settings: Partial<Canvas3DProps> | ((old: Canvas3DProps) => Partial<Canvas3DProps> | void) }>(), ResetSettings: PluginCommand<{ }>() } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-plugin/config.ts b/src/mol-plugin/config.ts index 782c404aefc28aabb6cd266100754da8aa7bd410..f63b5dc835d748fad98c0fd5f7f8bc61dbbbb525 100644 --- a/src/mol-plugin/config.ts +++ b/src/mol-plugin/config.ts @@ -30,7 +30,7 @@ export const PluginConfig = { CanStream: item('volume-streaming.can-stream', (s: Structure, plugin: PluginContext) => { return s.models.length === 1 && (Model.hasDensityMap(s.models[0]) // the following test is to include e.g. 'updated' files from PDBe - || (!Model.isFromPdbArchive(s.models[0]) && s.models[0].entryId.length === 4)) + || (!Model.isFromPdbArchive(s.models[0]) && s.models[0].entryId.length === 4)); }), EmdbHeaderServer: item('volume-streaming.emdb-header-server', 'https://ftp.wwpdb.org/pub/emdb/structures'), }, @@ -38,7 +38,7 @@ export const PluginConfig = { ShowExpand: item('viewer.show-expand-button', true), ShowSelectionMode: item('viewer.show-selection-model-button', true) } -} +}; export class PluginConfigManager { private _config = new Map<PluginConfigItem<any>, unknown>(); diff --git a/src/mol-plugin/context.ts b/src/mol-plugin/context.ts index 0009f66874e40495ae93ab646f07c7b593c8fe6b..9324decda152708a399d20988295d04eb24154d6 100644 --- a/src/mol-plugin/context.ts +++ b/src/mol-plugin/context.ts @@ -177,8 +177,8 @@ export class PluginContext { if (this.spec.layout && this.spec.layout.initial) this.layout.setProps(this.spec.layout.initial); (this.canvas3d as Canvas3D) = Canvas3D.fromCanvas(canvas); - this.events.canvas3d.initialized.next() - this.events.canvas3d.initialized.isStopped = true // TODO is this a good way? + this.events.canvas3d.initialized.next(); + this.events.canvas3d.initialized.isStopped = true; // TODO is this a good way? const renderer = this.canvas3d!.props.renderer; PluginCommands.Canvas3D.SetSettings(this, { settings: { renderer: { ...renderer, backgroundColor: Color(0xFCFBF9) } } }); this.canvas3d!.animate(); @@ -254,7 +254,7 @@ export class PluginContext { let timeout: any = void 0; const setBusy = () => { isBusy.next(true); - } + }; merge(this.behaviors.state.isUpdating, this.behaviors.state.isAnimating).subscribe(v => { const isUpdating = this.behaviors.state.isUpdating.value; @@ -277,7 +277,7 @@ export class PluginContext { if (!v) { this.managers.interactivity?.lociSelects.deselectAll(); } - }) + }); } private initBuiltInBehavior() { diff --git a/src/mol-plugin/index.ts b/src/mol-plugin/index.ts index 9b0e4d9d4ac447b920f6a30cdad7da9fa56db2e2..2a245b06ff54ac080d86f9c36a049e061fe2d2f6 100644 --- a/src/mol-plugin/index.ts +++ b/src/mol-plugin/index.ts @@ -93,7 +93,7 @@ export const DefaultPluginSpec: PluginSpec = { [PluginConfig.State.DefaultServer, 'https://webchem.ncbr.muni.cz/molstar-state'], [PluginConfig.VolumeStreaming.DefaultServer, 'https://ds.litemol.org'] ]) -} +}; export function createPlugin(target: HTMLElement, spec?: PluginSpec): PluginContext { const ctx = new PluginContext(spec || DefaultPluginSpec); diff --git a/src/mol-plugin/layout.ts b/src/mol-plugin/layout.ts index e4050b8e585bb6b8ccccc117a7f57534c55b65eb..bdefee135d14fd514b1fb04420383047d8d056d1 100644 --- a/src/mol-plugin/layout.ts +++ b/src/mol-plugin/layout.ts @@ -30,7 +30,7 @@ export const PluginLayoutStateParams = { bottom: PD.Select('full', simpleRegionStateOptions), }), controlsDisplay: PD.Value<PluginLayoutControlsDisplay>('outside', { isHidden: true }) -} +}; export type PluginLayoutStateProps = PD.Values<typeof PluginLayoutStateParams> export type LeftPanelTabName = 'none' | 'root' | 'data' | 'states' | 'settings' | 'help' @@ -164,7 +164,7 @@ export class PluginLayout extends StatefulPluginComponent<PluginLayoutStateProps head.appendChild(v); } - const s = body.style + const s = body.style; s.top = t.top!; s.bottom = t.bottom!; s.left = t.left!; @@ -192,7 +192,7 @@ export class PluginLayout extends StatefulPluginComponent<PluginLayoutStateProps } } } catch (e) { - const msg = 'Layout change error, you might have to reload the page.' + const msg = 'Layout change error, you might have to reload the page.'; this.context.log.error(msg); console.error(msg, e); } diff --git a/src/mol-plugin/spec.ts b/src/mol-plugin/spec.ts index a900a6f85a8f15eb2d3425d3631238daec40e6cf..14f8d9f44cadab3c3caf8f2b71e296f0b25f6ad2 100644 --- a/src/mol-plugin/spec.ts +++ b/src/mol-plugin/spec.ts @@ -11,7 +11,7 @@ import { PluginLayoutStateProps } from './layout'; import { PluginStateAnimation } from '../mol-plugin-state/animation/model'; import { PluginConfigItem } from './config'; -export { PluginSpec } +export { PluginSpec }; interface PluginSpec { actions: PluginSpec.Action[], diff --git a/src/mol-plugin/state.ts b/src/mol-plugin/state.ts index d9bc28c7511dd34d4966640412de0d102bf228c1..2ec8ed78359aacb2af3b79f805397dd324e27caa 100644 --- a/src/mol-plugin/state.ts +++ b/src/mol-plugin/state.ts @@ -18,7 +18,7 @@ import { ParamDefinition as PD } from '../mol-util/param-definition'; import { UUID } from '../mol-util'; import { InteractivityManager } from '../mol-plugin-state/manager/interactivity'; import { produce } from 'immer'; -export { PluginState } +export { PluginState }; class PluginState { private ev = RxEventHelper.create(); @@ -88,7 +88,7 @@ class PluginState { } updateBehavior<T extends StateTransformer>(behavior: T, params: (old: StateTransformer.Params<T>) => (void | StateTransformer.Params<T>)) { - const tree = this.behaviors.build() + const tree = this.behaviors.build(); if (!this.behaviors.tree.transforms.has(behavior.id)) { const defaultParams = behavior.createDefaultParams(void 0 as any, this.plugin); tree.to(PluginBehavior.getCategoryId(behavior)).apply(behavior, produce(defaultParams, params) as any, { ref: behavior.id }); diff --git a/src/mol-plugin/util/task-manager.ts b/src/mol-plugin/util/task-manager.ts index 812f35d92de6197d14ea522871d0ef883b52574b..9e419b03f0235f5858535d58041c94d66c59b9ac 100644 --- a/src/mol-plugin/util/task-manager.ts +++ b/src/mol-plugin/util/task-manager.ts @@ -10,7 +10,7 @@ import { now } from '../../mol-util/now'; import { CreateObservableCtx, ExecuteInContext } from '../../mol-task/execution/observable'; import { arrayRemoveInPlace } from '../../mol-util/array'; -export { TaskManager } +export { TaskManager }; class TaskManager { private ev = RxEventHelper.create(); @@ -91,6 +91,6 @@ namespace TaskManager { } i++; } - }) + }); } } \ No newline at end of file diff --git a/src/mol-plugin/util/toast.ts b/src/mol-plugin/util/toast.ts index f83d107f846da59c66c450a0712cf38088eed5f0..5062eb4b8294fba1bcb596c3cf662c78d1e3a2b2 100644 --- a/src/mol-plugin/util/toast.ts +++ b/src/mol-plugin/util/toast.ts @@ -38,7 +38,7 @@ export class PluginToastManager extends StatefulPluginComponent<{ private serialId = 0; private findByKey(key: string): PluginToastManager.Entry | undefined { - return this.state.entries.find(e => !!e && e.key === key) + return this.state.entries.find(e => !!e && e.key === key); } private show(toast: PluginToast) { diff --git a/src/mol-plugin/util/viewport-screenshot.ts b/src/mol-plugin/util/viewport-screenshot.ts index c569e57988b2871cd5131e667ece8d986c8ba14e..677ed8b75d88912dc5fa85f60907cbb176eca7fd 100644 --- a/src/mol-plugin/util/viewport-screenshot.ts +++ b/src/mol-plugin/util/viewport-screenshot.ts @@ -17,7 +17,7 @@ import { SyncRuntimeContext } from '../../mol-task/execution/synchronous'; import { CameraHelperParams, CameraHelperProps } from '../../mol-canvas3d/helper/camera-helper'; import { SetUtils } from '../../mol-util/set'; -export { ViewportScreenshotHelper } +export { ViewportScreenshotHelper }; namespace ViewportScreenshotHelper { export type ResolutionSettings = PD.Values<ReturnType<ViewportScreenshotHelper['createParams']>>['resolution'] @@ -26,7 +26,7 @@ namespace ViewportScreenshotHelper { class ViewportScreenshotHelper { private createParams() { - const max = Math.min(this.plugin.canvas3d ? this.plugin.canvas3d.webgl.maxRenderbufferSize : 4096, 4096) + const max = Math.min(this.plugin.canvas3d ? this.plugin.canvas3d.webgl.maxRenderbufferSize : 4096, 4096); return { resolution: PD.MappedStatic('viewport', { viewport: PD.Group({}), @@ -48,7 +48,7 @@ class ViewportScreenshotHelper { }), transparent: PD.Boolean(false), axes: CameraHelperParams.axes, - } + }; } private _params: ReturnType<ViewportScreenshotHelper['createParams']> = void 0 as any; get params() { @@ -81,7 +81,7 @@ class ViewportScreenshotHelper { case 'hd': return { width: 1280, height: 720 }; case 'full-hd': return { width: 1920, height: 1080 }; case 'ultra-hd': return { width: 3840, height: 2160 }; - default: return { width: this.currentResolution.params.width, height: this.currentResolution.params.height } + default: return { width: this.currentResolution.params.width, height: this.currentResolution.params.height }; } } @@ -95,16 +95,16 @@ class ViewportScreenshotHelper { drawPass: { cameraHelper: { axes: this.axes } }, multiSample: { mode: 'on', sampleLevel: 2 }, postprocessing: this.plugin.canvas3d!.props.postprocessing - }) + }); return this._imagePass; } getFilename() { - const models = this.plugin.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Model)).map(s => s.obj!.data) - const uniqueIds = new Set<string>() - models.forEach(m => uniqueIds.add(m.entryId.toUpperCase())) - const idString = SetUtils.toArray(uniqueIds).join('-') - return `${idString || 'molstar-image'}.png` + const models = this.plugin.state.data.select(StateSelection.Generators.rootsOfType(PluginStateObject.Molecule.Model)).map(s => s.obj!.data); + const uniqueIds = new Set<string>(); + models.forEach(m => uniqueIds.add(m.entryId.toUpperCase())); + const idString = SetUtils.toArray(uniqueIds).join('-'); + return `${idString || 'molstar-image'}.png`; } private canvas = function () { @@ -138,7 +138,7 @@ class ViewportScreenshotHelper { const { width, height } = this.getSize(); if (width <= 0 || height <= 0) return; - await ctx.update('Rendering image...') + await ctx.update('Rendering image...'); this.imagePass.setProps({ drawPass: { cameraHelper: { axes: this.axes } }, transparentBackground: this.transparent, @@ -146,35 +146,35 @@ class ViewportScreenshotHelper { }); const imageData = this.imagePass.getImageData(width, height); - await ctx.update('Encoding image...') - const canvas = this.canvas - canvas.width = imageData.width - canvas.height = imageData.height - const canvasCtx = canvas.getContext('2d') - if (!canvasCtx) throw new Error('Could not create canvas 2d context') - canvasCtx.putImageData(imageData, 0, 0) + await ctx.update('Encoding image...'); + const canvas = this.canvas; + canvas.width = imageData.width; + canvas.height = imageData.height; + const canvasCtx = canvas.getContext('2d'); + if (!canvasCtx) throw new Error('Could not create canvas 2d context'); + canvasCtx.putImageData(imageData, 0, 0); return; } private downloadTask() { return Task.create('Download Image', async ctx => { this.draw(ctx); - await ctx.update('Downloading image...') - const blob = await canvasToBlob(this.canvas, 'png') - download(blob, this.getFilename()) - }) + await ctx.update('Downloading image...'); + const blob = await canvasToBlob(this.canvas, 'png'); + download(blob, this.getFilename()); + }); } downloadCurrent() { return this.plugin.runTask(Task.create('Download Image', async ctx => { - await ctx.update('Downloading image...') - const blob = await canvasToBlob(this.canvas, 'png') - download(blob, this.getFilename()) + await ctx.update('Downloading image...'); + const blob = await canvasToBlob(this.canvas, 'png'); + download(blob, this.getFilename()); })); } async imageData() { - await this.draw(SyncRuntimeContext) + await this.draw(SyncRuntimeContext); return this.canvas.toDataURL(); } diff --git a/src/mol-plugin/version.ts b/src/mol-plugin/version.ts index a91782d7aca1f7e6cd91d311e8ea5d74813c25fc..949807afaef319e2d8acf25d7b409b35275a317a 100644 --- a/src/mol-plugin/version.ts +++ b/src/mol-plugin/version.ts @@ -6,10 +6,10 @@ */ /** version from package.json, to be filled in at bundle build time */ -declare const __VERSION__: string +declare const __VERSION__: string; export const PLUGIN_VERSION = __VERSION__; /** unix time stamp, to be filled in at bundle build time */ -declare const __VERSION_TIMESTAMP__: number +declare const __VERSION_TIMESTAMP__: number; export const PLUGIN_VERSION_TIMESTAMP = __VERSION_TIMESTAMP__; export const PLUGIN_VERSION_DATE = new Date(PLUGIN_VERSION_TIMESTAMP); \ No newline at end of file diff --git a/src/mol-repr/representation.ts b/src/mol-repr/representation.ts index 819bc7efc112766beb1e3cb8d60c99cd16257d9d..cd34ef28cf4c81acba6bb95d57a5646c301513d4 100644 --- a/src/mol-repr/representation.ts +++ b/src/mol-repr/representation.ts @@ -71,7 +71,7 @@ export const EmptyRepresentationProvider = { factory: () => Representation.Empty, getParams: () => ({}), defaultValues: {} -} +}; function getTypes(list: { name: string, provider: RepresentationProvider<any, any, any> }[]) { return list.map(e => [e.name, e.provider.label] as [string, string]); @@ -83,7 +83,7 @@ export class RepresentationRegistry<D, S extends Representation.State> { private _name = new Map<RepresentationProvider<D, any, any>, string>() get default() { return this._list[0]; } - get types(): [string, string][] { return getTypes(this._list) } + get types(): [string, string][] { return getTypes(this._list); } constructor() {}; @@ -92,9 +92,9 @@ export class RepresentationRegistry<D, S extends Representation.State> { throw new Error(`${provider.name} already registered.`); } - this._list.push({ name: provider.name, provider }) - this._map.set(provider.name, provider) - this._name.set(provider, provider.name) + this._list.push({ name: provider.name, provider }); + this._map.set(provider.name, provider); + this._name.set(provider, provider.name); } getName(provider: RepresentationProvider<D, any, any>): string { @@ -105,7 +105,7 @@ export class RepresentationRegistry<D, S extends Representation.State> { remove(provider: RepresentationProvider<D, any, any>) { const name = provider.name; - this._list.splice(this._list.findIndex(e => e.name === name), 1) + this._list.splice(this._list.findIndex(e => e.name === name), 1); const p = this._map.get(name); if (p) { this._map.delete(name); @@ -114,11 +114,11 @@ export class RepresentationRegistry<D, S extends Representation.State> { } get<P extends PD.Params>(name: string): RepresentationProvider<D, P, S> { - return this._map.get(name) || EmptyRepresentationProvider as unknown as RepresentationProvider<D, P, S> + return this._map.get(name) || EmptyRepresentationProvider as unknown as RepresentationProvider<D, P, S>; } get list() { - return this._list + return this._list; } getApplicableList(data: D) { @@ -126,13 +126,13 @@ export class RepresentationRegistry<D, S extends Representation.State> { } getApplicableTypes(data: D) { - return getTypes(this.getApplicableList(data)) + return getTypes(this.getApplicableList(data)); } } // -export { Representation } +export { Representation }; interface Representation<D, P extends PD.Params = {}, S extends Representation.State = Representation.State> { readonly label: string readonly updated: Subject<number> @@ -181,23 +181,23 @@ namespace Representation { markerActions: MarkerActions } export function createState(): State { - return { visible: true, alphaFactor: 1, pickable: true, syncManually: false, transform: Mat4.identity(), overpaint: Overpaint.Empty, transparency: Transparency.Empty, markerActions: MarkerActions.All } + return { visible: true, alphaFactor: 1, pickable: true, syncManually: false, transform: Mat4.identity(), overpaint: Overpaint.Empty, transparency: Transparency.Empty, markerActions: MarkerActions.All }; } export function updateState(state: State, update: Partial<State>) { - if (update.visible !== undefined) state.visible = update.visible - if (update.alphaFactor !== undefined) state.alphaFactor = update.alphaFactor - if (update.pickable !== undefined) state.pickable = update.pickable - if (update.overpaint !== undefined) state.overpaint = update.overpaint - if (update.transparency !== undefined) state.transparency = update.transparency - if (update.syncManually !== undefined) state.syncManually = update.syncManually - if (update.transform !== undefined) Mat4.copy(state.transform, update.transform) - if (update.markerActions !== undefined) state.markerActions = update.markerActions + if (update.visible !== undefined) state.visible = update.visible; + if (update.alphaFactor !== undefined) state.alphaFactor = update.alphaFactor; + if (update.pickable !== undefined) state.pickable = update.pickable; + if (update.overpaint !== undefined) state.overpaint = update.overpaint; + if (update.transparency !== undefined) state.transparency = update.transparency; + if (update.syncManually !== undefined) state.syncManually = update.syncManually; + if (update.transform !== undefined) Mat4.copy(state.transform, update.transform); + if (update.markerActions !== undefined) state.markerActions = update.markerActions; } export interface StateBuilder<S extends State> { create(): S update(state: S, update: Partial<S>): void } - export const StateBuilder: StateBuilder<State> = { create: createState, update: updateState } + export const StateBuilder: StateBuilder<State> = { create: createState, update: updateState }; export type Any = Representation<any, any, any> export const Empty: Any = { @@ -208,165 +208,165 @@ namespace Representation { getLoci: () => EmptyLoci, mark: () => false, destroy: () => {} - } + }; export type Def<D, P extends PD.Params = {}, S extends State = State> = { [k: string]: RepresentationFactory<D, P, S> } export function createMulti<D, P extends PD.Params = {}, S extends State = State>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<D, P>, stateBuilder: StateBuilder<S>, reprDefs: Def<D, P>): Representation<D, P, S> { - let version = 0 - const updated = new Subject<number>() - const currentState = stateBuilder.create() - let currentTheme = Theme.createEmpty() + let version = 0; + const updated = new Subject<number>(); + const currentState = stateBuilder.create(); + let currentTheme = Theme.createEmpty(); - let currentParams: P - let currentProps: PD.Values<P> - let currentData: D + let currentParams: P; + let currentProps: PD.Values<P>; + let currentData: D; - const reprMap: { [k: number]: string } = {} + const reprMap: { [k: number]: string } = {}; const reprList: Representation<D, P>[] = Object.keys(reprDefs).map((name, i) => { - reprMap[i] = name - const repr = reprDefs[name](ctx, getParams) - repr.setState(currentState) - return repr - }) + reprMap[i] = name; + const repr = reprDefs[name](ctx, getParams); + repr.setState(currentState); + return repr; + }); return { label, updated, get groupCount() { - let groupCount = 0 + let groupCount = 0; if (currentProps) { - const { visuals } = currentProps + const { visuals } = currentProps; for (let i = 0, il = reprList.length; i < il; ++i) { if (!visuals || visuals.includes(reprMap[i])) { - groupCount += reprList[i].groupCount + groupCount += reprList[i].groupCount; } } } - return groupCount + return groupCount; }, get renderObjects() { - const renderObjects: GraphicsRenderObject[] = [] + const renderObjects: GraphicsRenderObject[] = []; if (currentProps) { - const { visuals } = currentProps + const { visuals } = currentProps; for (let i = 0, il = reprList.length; i < il; ++i) { if (!visuals || visuals.includes(reprMap[i])) { - renderObjects.push(...reprList[i].renderObjects) + renderObjects.push(...reprList[i].renderObjects); } } } - return renderObjects + return renderObjects; }, - get props() { return currentProps }, - get params() { return currentParams }, + get props() { return currentProps; }, + get params() { return currentParams; }, createOrUpdate: (props: Partial<P> = {}, data?: D) => { if (data && data !== currentData) { - currentParams = getParams(ctx, data) - currentData = data - if (!currentProps) currentProps = PD.getDefaultValues(currentParams) as P + currentParams = getParams(ctx, data); + currentData = data; + if (!currentProps) currentProps = PD.getDefaultValues(currentParams) as P; } - const qualityProps = getQualityProps(Object.assign({}, currentProps, props), currentData) - Object.assign(currentProps, props, qualityProps) + const qualityProps = getQualityProps(Object.assign({}, currentProps, props), currentData); + Object.assign(currentProps, props, qualityProps); - const { visuals } = currentProps + const { visuals } = currentProps; return Task.create(`Creating or updating '${label}' representation`, async runtime => { for (let i = 0, il = reprList.length; i < il; ++i) { if (!visuals || visuals.includes(reprMap[i])) { - await reprList[i].createOrUpdate(currentProps, currentData).runInContext(runtime) + await reprList[i].createOrUpdate(currentProps, currentData).runInContext(runtime); } } - updated.next(version++) - }) + updated.next(version++); + }); }, - get state() { return currentState }, - get theme() { return currentTheme }, + get state() { return currentState; }, + get theme() { return currentTheme; }, getLoci: (pickingId?: PickingId) => { - const { visuals } = currentProps + const { visuals } = currentProps; for (let i = 0, il = reprList.length; i < il; ++i) { if (!visuals || visuals.includes(reprMap[i])) { - const loci = reprList[i].getLoci(pickingId) - if (!isEmptyLoci(loci)) return loci + const loci = reprList[i].getLoci(pickingId); + if (!isEmptyLoci(loci)) return loci; } } - return EmptyLoci + return EmptyLoci; }, mark: (loci: ModelLoci, action: MarkerAction) => { - let marked = false + let marked = false; for (let i = 0, il = reprList.length; i < il; ++i) { - marked = reprList[i].mark(loci, action) || marked + marked = reprList[i].mark(loci, action) || marked; } - return marked + return marked; }, setState: (state: Partial<S>) => { - stateBuilder.update(currentState, state) + stateBuilder.update(currentState, state); for (let i = 0, il = reprList.length; i < il; ++i) { - reprList[i].setState(currentState) + reprList[i].setState(currentState); } }, setTheme: (theme: Theme) => { for (let i = 0, il = reprList.length; i < il; ++i) { - reprList[i].setTheme(theme) + reprList[i].setTheme(theme); } }, destroy() { for (let i = 0, il = reprList.length; i < il; ++i) { - reprList[i].destroy() + reprList[i].destroy(); } } - } + }; } export function fromRenderObject(label: string, renderObject: GraphicsRenderObject): Representation<GraphicsRenderObject, BaseGeometry.Params> { - let version = 0 - const updated = new Subject<number>() - const currentState = Representation.createState() - const currentTheme = Theme.createEmpty() + let version = 0; + const updated = new Subject<number>(); + const currentState = Representation.createState(); + const currentTheme = Theme.createEmpty(); - const currentParams = PD.clone(BaseGeometry.Params) - const currentProps = PD.getDefaultValues(BaseGeometry.Params) + const currentParams = PD.clone(BaseGeometry.Params); + const currentProps = PD.getDefaultValues(BaseGeometry.Params); return { label, updated, - get groupCount() { return renderObject.values.uGroupCount.ref.value }, - get renderObjects() { return [renderObject] }, - get props() { return currentProps }, - get params() { return currentParams }, + get groupCount() { return renderObject.values.uGroupCount.ref.value; }, + get renderObjects() { return [renderObject]; }, + get props() { return currentProps; }, + get params() { return currentParams; }, createOrUpdate: (props: Partial<PD.Values<BaseGeometry.Params>> = {}) => { - const qualityProps = getQualityProps(Object.assign({}, currentProps, props)) - Object.assign(currentProps, props, qualityProps) + const qualityProps = getQualityProps(Object.assign({}, currentProps, props)); + Object.assign(currentProps, props, qualityProps); return Task.create(`Updating '${label}' representation`, async runtime => { // TODO - updated.next(version++) - }) + updated.next(version++); + }); }, - get state() { return currentState }, - get theme() { return currentTheme }, + get state() { return currentState; }, + get theme() { return currentTheme; }, getLoci: () => { // TODO - return EmptyLoci + return EmptyLoci; }, mark: (loci: ModelLoci, action: MarkerAction) => { // TODO - return false + return false; }, setState: (state: Partial<State>) => { - if (state.visible !== undefined) Visual.setVisibility(renderObject, state.visible) - if (state.alphaFactor !== undefined) Visual.setAlphaFactor(renderObject, state.alphaFactor) - if (state.pickable !== undefined) Visual.setPickable(renderObject, state.pickable) + if (state.visible !== undefined) Visual.setVisibility(renderObject, state.visible); + if (state.alphaFactor !== undefined) Visual.setAlphaFactor(renderObject, state.alphaFactor); + if (state.pickable !== undefined) Visual.setPickable(renderObject, state.pickable); if (state.overpaint !== undefined) { // TODO } if (state.transparency !== undefined) { // TODO } - if (state.transform !== undefined) Visual.setTransform(renderObject, state.transform) + if (state.transform !== undefined) Visual.setTransform(renderObject, state.transform); - Representation.updateState(currentState, state) + Representation.updateState(currentState, state); }, setTheme: () => { }, destroy() { } - } + }; } } \ No newline at end of file diff --git a/src/mol-repr/shape/loci/angle.ts b/src/mol-repr/shape/loci/angle.ts index 2bda93ad9ff785ebc5d7ec608841379348596db2..bddd9719e6814b1094fb101a49a2faa14d9558bc 100644 --- a/src/mol-repr/shape/loci/angle.ts +++ b/src/mol-repr/shape/loci/angle.ts @@ -32,7 +32,7 @@ export interface AngleData { const SharedParams = { color: PD.Color(ColorNames.lightgreen), arcScale: PD.Numeric(0.7, { min: 0.01, max: 1, step: 0.01 }) -} +}; const LinesParams = { ...Lines.Params, @@ -40,16 +40,16 @@ const LinesParams = { lineSizeAttenuation: PD.Boolean(true), linesSize: PD.Numeric(0.04, { min: 0.01, max: 5, step: 0.01 }), dashLength: PD.Numeric(0.04, { min: 0.01, max: 0.2, step: 0.01 }), -} +}; const VectorsParams = { ...LinesParams -} +}; type VectorsParams = typeof VectorsParams const ArcParams = { ...LinesParams -} +}; type ArcParams = typeof ArcParams const SectorParams = { @@ -57,7 +57,7 @@ const SectorParams = { ...SharedParams, ignoreLight: PD.Boolean(true), sectorOpacity: PD.Numeric(0.75, { min: 0, max: 1, step: 0.01 }), -} +}; type SectorParams = typeof SectorParams const TextParams = { @@ -65,7 +65,7 @@ const TextParams = { borderWidth: PD.Numeric(0.2, { min: 0, max: 0.5, step: 0.01 }), textColor: PD.Color(ColorNames.black), textSize: PD.Numeric(0.4, { min: 0.1, max: 5, step: 0.1 }), -} +}; type TextParams = typeof TextParams const AngleVisuals = { @@ -73,7 +73,7 @@ const AngleVisuals = { 'arc': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<AngleData, ArcParams>) => ShapeRepresentation(getArcShape, Lines.Utils, { modifyState: s => ({ ...s, pickable: false }) }), 'sector': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<AngleData, SectorParams>) => ShapeRepresentation(getSectorShape, Mesh.Utils, { modifyProps: p => ({ ...p, alpha: p.sectorOpacity }), modifyState: s => ({ ...s, markerActions: MarkerActions.Highlighting }) }), 'text': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<AngleData, TextParams>) => ShapeRepresentation(getTextShape, Text.Utils, { modifyState: s => ({ ...s, markerActions: MarkerAction.None }) }), -} +}; export const AngleParams = { ...VectorsParams, @@ -81,7 +81,7 @@ export const AngleParams = { ...SectorParams, ...TextParams, visuals: PD.MultiSelect(['vectors', 'sector', 'text'], PD.objectToOptions(AngleVisuals)), -} +}; export type AngleParams = typeof AngleParams export type AngleProps = PD.Values<AngleParams> @@ -99,152 +99,152 @@ function getAngleState() { radius: 0, angle: 0, - } + }; } type AngleState = ReturnType<typeof getAngleState> -const tmpVec = Vec3() -const tmpMat = Mat4() +const tmpVec = Vec3(); +const tmpMat = Mat4(); function setAngleState(triple: Loci.Bundle<3>, state: AngleState, arcScale: number) { - const { sphereA, sphereB, sphereC } = state - const { arcDirA, arcDirC, arcNormal } = state + const { sphereA, sphereB, sphereC } = state; + const { arcDirA, arcDirC, arcNormal } = state; - const [lociA, lociB, lociC] = triple.loci - Loci.getBoundingSphere(lociA, sphereA) - Loci.getBoundingSphere(lociB, sphereB) - Loci.getBoundingSphere(lociC, sphereC) + const [lociA, lociB, lociC] = triple.loci; + Loci.getBoundingSphere(lociA, sphereA); + Loci.getBoundingSphere(lociB, sphereB); + Loci.getBoundingSphere(lociC, sphereC); - Vec3.sub(arcDirA, sphereA.center, sphereB.center) - Vec3.sub(arcDirC, sphereC.center, sphereB.center) - Vec3.cross(arcNormal, arcDirA, arcDirC) + Vec3.sub(arcDirA, sphereA.center, sphereB.center); + Vec3.sub(arcDirC, sphereC.center, sphereB.center); + Vec3.cross(arcNormal, arcDirA, arcDirC); - const len = Math.min(Vec3.magnitude(arcDirA), Vec3.magnitude(arcDirC)) - const radius = len * arcScale + const len = Math.min(Vec3.magnitude(arcDirA), Vec3.magnitude(arcDirC)); + const radius = len * arcScale; - state.radius = radius - state.angle = Vec3.angle(arcDirA, arcDirC) + state.radius = radius; + state.angle = Vec3.angle(arcDirA, arcDirC); - return state + return state; } function getCircle(state: AngleState, segmentLength?: number) { - const { radius, angle } = state - const segments = segmentLength ? arcLength(angle, radius) / segmentLength : 32 + const { radius, angle } = state; + const segments = segmentLength ? arcLength(angle, radius) / segmentLength : 32; - Mat4.targetTo(tmpMat, state.sphereB.center, state.sphereA.center, state.arcNormal) - Mat4.setTranslation(tmpMat, state.sphereB.center) - Mat4.mul(tmpMat, tmpMat, Mat4.rotY180) + Mat4.targetTo(tmpMat, state.sphereB.center, state.sphereA.center, state.arcNormal); + Mat4.setTranslation(tmpMat, state.sphereB.center); + Mat4.mul(tmpMat, tmpMat, Mat4.rotY180); - const circle = Circle({ radius, thetaLength: angle, segments }) - return transformPrimitive(circle, tmpMat) + const circle = Circle({ radius, thetaLength: angle, segments }); + return transformPrimitive(circle, tmpMat); } -const tmpState = getAngleState() +const tmpState = getAngleState(); function getAngleName(data: AngleData) { - return data.triples.length === 1 ? `Angle ${angleLabel(data.triples[0], { measureOnly: true })}` : `${data.triples.length} Angles` + return data.triples.length === 1 ? `Angle ${angleLabel(data.triples[0], { measureOnly: true })}` : `${data.triples.length} Angles`; } // function buildVectorsLines(data: AngleData, props: AngleProps, lines?: Lines): Lines { - const builder = LinesBuilder.create(128, 64, lines) + const builder = LinesBuilder.create(128, 64, lines); for (let i = 0, il = data.triples.length; i < il; ++i) { - setAngleState(data.triples[i], tmpState, props.arcScale) - builder.addFixedLengthDashes(tmpState.sphereB.center, tmpState.sphereA.center, props.dashLength, i) - builder.addFixedLengthDashes(tmpState.sphereB.center, tmpState.sphereC.center, props.dashLength, i) + setAngleState(data.triples[i], tmpState, props.arcScale); + builder.addFixedLengthDashes(tmpState.sphereB.center, tmpState.sphereA.center, props.dashLength, i); + builder.addFixedLengthDashes(tmpState.sphereB.center, tmpState.sphereC.center, props.dashLength, i); } - return builder.getLines() + return builder.getLines(); } function getVectorsShape(ctx: RuntimeContext, data: AngleData, props: AngleProps, shape?: Shape<Lines>) { const lines = buildVectorsLines(data, props, shape && shape.geometry); - const name = getAngleName(data) - return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => '') + const name = getAngleName(data); + return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => ''); } // function buildArcLines(data: AngleData, props: AngleProps, lines?: Lines): Lines { - const builder = LinesBuilder.create(128, 64, lines) + const builder = LinesBuilder.create(128, 64, lines); for (let i = 0, il = data.triples.length; i < il; ++i) { - setAngleState(data.triples[i], tmpState, props.arcScale) - const circle = getCircle(tmpState, props.dashLength) - const { indices, vertices } = circle + setAngleState(data.triples[i], tmpState, props.arcScale); + const circle = getCircle(tmpState, props.dashLength); + const { indices, vertices } = circle; for (let j = 0, jl = indices.length; j < jl; j += 3) { - if (j % 2 === 1) continue // draw every other segment to get dashes - const start = indices[j] * 3 - const end = indices[j + 1] * 3 - const startX = vertices[start] - const startY = vertices[start + 1] - const startZ = vertices[start + 2] - const endX = vertices[end] - const endY = vertices[end + 1] - const endZ = vertices[end + 2] - builder.add(startX, startY, startZ, endX, endY, endZ, i) + if (j % 2 === 1) continue; // draw every other segment to get dashes + const start = indices[j] * 3; + const end = indices[j + 1] * 3; + const startX = vertices[start]; + const startY = vertices[start + 1]; + const startZ = vertices[start + 2]; + const endX = vertices[end]; + const endY = vertices[end + 1]; + const endZ = vertices[end + 2]; + builder.add(startX, startY, startZ, endX, endY, endZ, i); } } - return builder.getLines() + return builder.getLines(); } function getArcShape(ctx: RuntimeContext, data: AngleData, props: AngleProps, shape?: Shape<Lines>) { const lines = buildArcLines(data, props, shape && shape.geometry); - const name = getAngleName(data) - return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => '') + const name = getAngleName(data); + return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => ''); } // function buildSectorMesh(data: AngleData, props: AngleProps, mesh?: Mesh): Mesh { - const state = MeshBuilder.createState(128, 64, mesh) + const state = MeshBuilder.createState(128, 64, mesh); for (let i = 0, il = data.triples.length; i < il; ++i) { - setAngleState(data.triples[i], tmpState, props.arcScale) - const circle = getCircle(tmpState) - state.currentGroup = i - MeshBuilder.addPrimitive(state, Mat4.id, circle) - MeshBuilder.addPrimitiveFlipped(state, Mat4.id, circle) + setAngleState(data.triples[i], tmpState, props.arcScale); + const circle = getCircle(tmpState); + state.currentGroup = i; + MeshBuilder.addPrimitive(state, Mat4.id, circle); + MeshBuilder.addPrimitiveFlipped(state, Mat4.id, circle); } - return MeshBuilder.getMesh(state) + return MeshBuilder.getMesh(state); } function getSectorShape(ctx: RuntimeContext, data: AngleData, props: AngleProps, shape?: Shape<Mesh>) { const mesh = buildSectorMesh(data, props, shape && shape.geometry); - const name = getAngleName(data) - const getLabel = (groupId: number ) => angleLabel(data.triples[groupId]) - return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel) + const name = getAngleName(data); + const getLabel = (groupId: number ) => angleLabel(data.triples[groupId]); + return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel); } // function buildText(data: AngleData, props: AngleProps, text?: Text): Text { - const builder = TextBuilder.create(props, 128, 64, text) + const builder = TextBuilder.create(props, 128, 64, text); for (let i = 0, il = data.triples.length; i < il; ++i) { - setAngleState(data.triples[i], tmpState, props.arcScale) + setAngleState(data.triples[i], tmpState, props.arcScale); - Vec3.add(tmpVec, tmpState.arcDirA, tmpState.arcDirC) - Vec3.setMagnitude(tmpVec, tmpVec, tmpState.radius) - Vec3.add(tmpVec, tmpState.sphereB.center, tmpVec) + Vec3.add(tmpVec, tmpState.arcDirA, tmpState.arcDirC); + Vec3.setMagnitude(tmpVec, tmpVec, tmpState.radius); + Vec3.add(tmpVec, tmpState.sphereB.center, tmpVec); - const angle = radToDeg(tmpState.angle).toFixed(2) - const label = `${angle}\u00B0` - const radius = Math.max(2, tmpState.sphereA.radius, tmpState.sphereB.radius, tmpState.sphereC.radius) - const scale = radius / 2 - builder.add(label, tmpVec[0], tmpVec[1], tmpVec[2], 0.1, scale, i) + const angle = radToDeg(tmpState.angle).toFixed(2); + const label = `${angle}\u00B0`; + const radius = Math.max(2, tmpState.sphereA.radius, tmpState.sphereB.radius, tmpState.sphereC.radius); + const scale = radius / 2; + builder.add(label, tmpVec[0], tmpVec[1], tmpVec[2], 0.1, scale, i); } - return builder.getText() + return builder.getText(); } function getTextShape(ctx: RuntimeContext, data: AngleData, props: AngleProps, shape?: Shape<Text>) { const text = buildText(data, props, shape && shape.geometry); - const name = getAngleName(data) - const getLabel = (groupId: number ) => angleLabel(data.triples[groupId]) - return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel) + const name = getAngleName(data); + const getLabel = (groupId: number ) => angleLabel(data.triples[groupId]); + return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel); } // export type AngleRepresentation = Representation<AngleData, AngleParams> export function AngleRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<AngleData, AngleParams>): AngleRepresentation { - return Representation.createMulti('Angle', ctx, getParams, Representation.StateBuilder, AngleVisuals as unknown as Representation.Def<AngleData, AngleParams>) + return Representation.createMulti('Angle', ctx, getParams, Representation.StateBuilder, AngleVisuals as unknown as Representation.Def<AngleData, AngleParams>); } \ No newline at end of file diff --git a/src/mol-repr/shape/loci/common.ts b/src/mol-repr/shape/loci/common.ts index 62af3319d44ef4ded03a746ba616bc5b3acc76a5..4ca2ed7d5321a61dae87f531ec4ca4e474faa159 100644 --- a/src/mol-repr/shape/loci/common.ts +++ b/src/mol-repr/shape/loci/common.ts @@ -11,4 +11,4 @@ import { ColorNames } from '../../../mol-util/color/names'; export const MeasurementRepresentationCommonTextParams = { textColor: PD.Color(ColorNames.black, { isEssential: true }), textSize: PD.Numeric(0.5, { min: 0.1, max: 5, step: 0.1 }, { isEssential: true }), -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-repr/shape/loci/dihedral.ts b/src/mol-repr/shape/loci/dihedral.ts index 411918172284da3df6ce1b90a996e629f0d91fbd..42ac197682d170967d6a155b9e00c0b09b7c93ee 100644 --- a/src/mol-repr/shape/loci/dihedral.ts +++ b/src/mol-repr/shape/loci/dihedral.ts @@ -33,7 +33,7 @@ export interface DihedralData { const SharedParams = { color: PD.Color(ColorNames.lightgreen), arcScale: PD.Numeric(0.7, { min: 0.01, max: 1, step: 0.01 }) -} +}; const LinesParams = { ...Lines.Params, @@ -41,21 +41,21 @@ const LinesParams = { lineSizeAttenuation: PD.Boolean(true), linesSize: PD.Numeric(0.04, { min: 0.01, max: 5, step: 0.01 }), dashLength: PD.Numeric(0.04, { min: 0.01, max: 0.2, step: 0.01 }), -} +}; const VectorsParams = { ...LinesParams -} +}; type VectorsParams = typeof VectorsParams const ExtendersParams = { ...LinesParams -} +}; type ExtendersParams = typeof ExtendersParams const ArcParams = { ...LinesParams -} +}; type ArcParams = typeof ArcParams const SectorParams = { @@ -63,14 +63,14 @@ const SectorParams = { ...SharedParams, ignoreLight: PD.Boolean(true), sectorOpacity: PD.Numeric(0.75, { min: 0, max: 1, step: 0.01 }), -} +}; type SectorParams = typeof SectorParams const TextParams = { ...Text.Params, borderWidth: PD.Numeric(0.2, { min: 0, max: 0.5, step: 0.01 }), ...MeasurementRepresentationCommonTextParams -} +}; type TextParams = typeof TextParams const DihedralVisuals = { @@ -79,7 +79,7 @@ const DihedralVisuals = { 'arc': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<DihedralData, ArcParams>) => ShapeRepresentation(getArcShape, Lines.Utils, { modifyState: s => ({ ...s, pickable: false }) }), 'sector': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<DihedralData, SectorParams>) => ShapeRepresentation(getSectorShape, Mesh.Utils, { modifyProps: p => ({ ...p, alpha: p.sectorOpacity }), modifyState: s => ({ ...s, markerActions: MarkerActions.Highlighting }) }), 'text': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<DihedralData, TextParams>) => ShapeRepresentation(getTextShape, Text.Utils, { modifyState: s => ({ ...s, markerActions: MarkerAction.None }) }), -} +}; export const DihedralParams = { ...VectorsParams, @@ -88,7 +88,7 @@ export const DihedralParams = { ...SectorParams, ...TextParams, visuals: PD.MultiSelect(['extenders', 'sector', 'text'], PD.objectToOptions(DihedralVisuals)), -} +}; export type DihedralParams = typeof DihedralParams export type DihedralProps = PD.Values<DihedralParams> @@ -116,196 +116,196 @@ function getDihedralState() { radius: 0, angle: 0, - } + }; } type DihedralState = ReturnType<typeof getDihedralState> -const tmpVec = Vec3() -const tmpMat = Mat4() +const tmpVec = Vec3(); +const tmpMat = Mat4(); // TODO improper dihedrals are not handled correctly function setDihedralState(quad: Loci.Bundle<4>, state: DihedralState, arcScale: number) { - const { sphereA, sphereB, sphereC, sphereD, dirBA, dirCD, projA, projD } = state - const { arcPointA, arcPointD, arcDirA, arcDirD, arcCenter, arcNormal } = state - - const [lociA, lociB, lociC, lociD] = quad.loci - Loci.getBoundingSphere(lociA, sphereA) - Loci.getBoundingSphere(lociB, sphereB) - Loci.getBoundingSphere(lociC, sphereC) - Loci.getBoundingSphere(lociD, sphereD) - - Vec3.add(arcCenter, sphereB.center, sphereC.center) - Vec3.scale(arcCenter, arcCenter, 0.5) - - Vec3.sub(dirBA, sphereA.center, sphereB.center) - Vec3.sub(dirCD, sphereD.center, sphereC.center) - Vec3.add(arcPointA, arcCenter, dirBA) - Vec3.add(arcPointD, arcCenter, dirCD) - - Vec3.sub(arcNormal, sphereC.center, sphereB.center) - Vec3.orthogonalize(arcDirA, arcNormal, dirBA) - Vec3.orthogonalize(arcDirD, arcNormal, dirCD) - - Vec3.projectPointOnVector(projA, arcPointA, arcDirA, arcCenter) - Vec3.projectPointOnVector(projD, arcPointD, arcDirD, arcCenter) - const len = Math.min(Vec3.distance(projA, arcCenter), Vec3.distance(projD, arcCenter)) - const radius = len * arcScale - - Vec3.setMagnitude(arcDirA, arcDirA, radius) - Vec3.setMagnitude(arcDirD, arcDirD, radius) - Vec3.add(arcPointA, arcCenter, arcDirA) - Vec3.add(arcPointD, arcCenter, arcDirD) - state.radius = radius - state.angle = Vec3.angle(arcDirA, arcDirD) - - Vec3.matchDirection(tmpVec, arcNormal, Vec3.sub(tmpVec, arcPointA, sphereA.center)) - const angleA = Vec3.angle(dirBA, tmpVec) - const lenA = radius / Math.cos(angleA > halfPI ? angleA - halfPI : angleA) - Vec3.add(projA, sphereB.center, Vec3.setMagnitude(tmpVec, dirBA, lenA)) - - Vec3.matchDirection(tmpVec, arcNormal, Vec3.sub(tmpVec, arcPointD, sphereD.center)) - const angleD = Vec3.angle(dirCD, tmpVec) - const lenD = radius / Math.cos(angleD > halfPI ? angleD - halfPI : angleD) - Vec3.add(projD, sphereC.center, Vec3.setMagnitude(tmpVec, dirCD, lenD)) - - return state + const { sphereA, sphereB, sphereC, sphereD, dirBA, dirCD, projA, projD } = state; + const { arcPointA, arcPointD, arcDirA, arcDirD, arcCenter, arcNormal } = state; + + const [lociA, lociB, lociC, lociD] = quad.loci; + Loci.getBoundingSphere(lociA, sphereA); + Loci.getBoundingSphere(lociB, sphereB); + Loci.getBoundingSphere(lociC, sphereC); + Loci.getBoundingSphere(lociD, sphereD); + + Vec3.add(arcCenter, sphereB.center, sphereC.center); + Vec3.scale(arcCenter, arcCenter, 0.5); + + Vec3.sub(dirBA, sphereA.center, sphereB.center); + Vec3.sub(dirCD, sphereD.center, sphereC.center); + Vec3.add(arcPointA, arcCenter, dirBA); + Vec3.add(arcPointD, arcCenter, dirCD); + + Vec3.sub(arcNormal, sphereC.center, sphereB.center); + Vec3.orthogonalize(arcDirA, arcNormal, dirBA); + Vec3.orthogonalize(arcDirD, arcNormal, dirCD); + + Vec3.projectPointOnVector(projA, arcPointA, arcDirA, arcCenter); + Vec3.projectPointOnVector(projD, arcPointD, arcDirD, arcCenter); + const len = Math.min(Vec3.distance(projA, arcCenter), Vec3.distance(projD, arcCenter)); + const radius = len * arcScale; + + Vec3.setMagnitude(arcDirA, arcDirA, radius); + Vec3.setMagnitude(arcDirD, arcDirD, radius); + Vec3.add(arcPointA, arcCenter, arcDirA); + Vec3.add(arcPointD, arcCenter, arcDirD); + state.radius = radius; + state.angle = Vec3.angle(arcDirA, arcDirD); + + Vec3.matchDirection(tmpVec, arcNormal, Vec3.sub(tmpVec, arcPointA, sphereA.center)); + const angleA = Vec3.angle(dirBA, tmpVec); + const lenA = radius / Math.cos(angleA > halfPI ? angleA - halfPI : angleA); + Vec3.add(projA, sphereB.center, Vec3.setMagnitude(tmpVec, dirBA, lenA)); + + Vec3.matchDirection(tmpVec, arcNormal, Vec3.sub(tmpVec, arcPointD, sphereD.center)); + const angleD = Vec3.angle(dirCD, tmpVec); + const lenD = radius / Math.cos(angleD > halfPI ? angleD - halfPI : angleD); + Vec3.add(projD, sphereC.center, Vec3.setMagnitude(tmpVec, dirCD, lenD)); + + return state; } function getCircle(state: DihedralState, segmentLength?: number) { - const { radius, angle } = state - const segments = segmentLength ? arcLength(angle, radius) / segmentLength : 32 + const { radius, angle } = state; + const segments = segmentLength ? arcLength(angle, radius) / segmentLength : 32; - Mat4.targetTo(tmpMat, state.arcCenter, angle > halfPI ? state.arcPointA : state.arcPointD, state.arcNormal) - Mat4.setTranslation(tmpMat, state.arcCenter) - Mat4.mul(tmpMat, tmpMat, Mat4.rotY180) + Mat4.targetTo(tmpMat, state.arcCenter, angle > halfPI ? state.arcPointA : state.arcPointD, state.arcNormal); + Mat4.setTranslation(tmpMat, state.arcCenter); + Mat4.mul(tmpMat, tmpMat, Mat4.rotY180); - const circle = Circle({ radius, thetaLength: angle, segments }) - return transformPrimitive(circle, tmpMat) + const circle = Circle({ radius, thetaLength: angle, segments }); + return transformPrimitive(circle, tmpMat); } -const tmpState = getDihedralState() +const tmpState = getDihedralState(); function getDihedralName(data: DihedralData) { - return data.quads.length === 1 ? `Dihedral ${dihedralLabel(data.quads[0], { measureOnly: true })}` : `${data.quads.length} Dihedrals` + return data.quads.length === 1 ? `Dihedral ${dihedralLabel(data.quads[0], { measureOnly: true })}` : `${data.quads.length} Dihedrals`; } // function buildVectorsLines(data: DihedralData, props: DihedralProps, lines?: Lines): Lines { - const builder = LinesBuilder.create(128, 64, lines) + const builder = LinesBuilder.create(128, 64, lines); for (let i = 0, il = data.quads.length; i < il; ++i) { - setDihedralState(data.quads[i], tmpState, props.arcScale) - builder.addFixedLengthDashes(tmpState.arcCenter, tmpState.arcPointA, props.dashLength, i) - builder.addFixedLengthDashes(tmpState.arcCenter, tmpState.arcPointD, props.dashLength, i) + setDihedralState(data.quads[i], tmpState, props.arcScale); + builder.addFixedLengthDashes(tmpState.arcCenter, tmpState.arcPointA, props.dashLength, i); + builder.addFixedLengthDashes(tmpState.arcCenter, tmpState.arcPointD, props.dashLength, i); } - return builder.getLines() + return builder.getLines(); } function getVectorsShape(ctx: RuntimeContext, data: DihedralData, props: DihedralProps, shape?: Shape<Lines>) { const lines = buildVectorsLines(data, props, shape && shape.geometry); - const name = getDihedralName(data) - return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => '') + const name = getDihedralName(data); + return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => ''); } // function buildExtendersLines(data: DihedralData, props: DihedralProps, lines?: Lines): Lines { - const builder = LinesBuilder.create(128, 64, lines) + const builder = LinesBuilder.create(128, 64, lines); for (let i = 0, il = data.quads.length; i < il; ++i) { - setDihedralState(data.quads[i], tmpState, props.arcScale) - builder.addFixedLengthDashes(tmpState.arcPointA, tmpState.projA, props.dashLength, i) - builder.addFixedLengthDashes(tmpState.arcPointD, tmpState.projD, props.dashLength, i) + setDihedralState(data.quads[i], tmpState, props.arcScale); + builder.addFixedLengthDashes(tmpState.arcPointA, tmpState.projA, props.dashLength, i); + builder.addFixedLengthDashes(tmpState.arcPointD, tmpState.projD, props.dashLength, i); } - return builder.getLines() + return builder.getLines(); } function getExtendersShape(ctx: RuntimeContext, data: DihedralData, props: DihedralProps, shape?: Shape<Lines>) { const lines = buildExtendersLines(data, props, shape && shape.geometry); - const name = getDihedralName(data) - return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => '') + const name = getDihedralName(data); + return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => ''); } // function buildArcLines(data: DihedralData, props: DihedralProps, lines?: Lines): Lines { - const builder = LinesBuilder.create(128, 64, lines) + const builder = LinesBuilder.create(128, 64, lines); for (let i = 0, il = data.quads.length; i < il; ++i) { - setDihedralState(data.quads[i], tmpState, props.arcScale) - const circle = getCircle(tmpState, props.dashLength) - const { indices, vertices } = circle + setDihedralState(data.quads[i], tmpState, props.arcScale); + const circle = getCircle(tmpState, props.dashLength); + const { indices, vertices } = circle; for (let j = 0, jl = indices.length; j < jl; j += 3) { - if (j % 2 === 1) continue // draw every other segment to get dashes - const start = indices[j] * 3 - const end = indices[j + 1] * 3 - const startX = vertices[start] - const startY = vertices[start + 1] - const startZ = vertices[start + 2] - const endX = vertices[end] - const endY = vertices[end + 1] - const endZ = vertices[end + 2] - builder.add(startX, startY, startZ, endX, endY, endZ, i) + if (j % 2 === 1) continue; // draw every other segment to get dashes + const start = indices[j] * 3; + const end = indices[j + 1] * 3; + const startX = vertices[start]; + const startY = vertices[start + 1]; + const startZ = vertices[start + 2]; + const endX = vertices[end]; + const endY = vertices[end + 1]; + const endZ = vertices[end + 2]; + builder.add(startX, startY, startZ, endX, endY, endZ, i); } } - return builder.getLines() + return builder.getLines(); } function getArcShape(ctx: RuntimeContext, data: DihedralData, props: DihedralProps, shape?: Shape<Lines>) { const lines = buildArcLines(data, props, shape && shape.geometry); - const name = getDihedralName(data) - return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => '') + const name = getDihedralName(data); + return Shape.create(name, data, lines, () => props.color, () => props.linesSize, () => ''); } // function buildSectorMesh(data: DihedralData, props: DihedralProps, mesh?: Mesh): Mesh { - const state = MeshBuilder.createState(128, 64, mesh) + const state = MeshBuilder.createState(128, 64, mesh); for (let i = 0, il = data.quads.length; i < il; ++i) { - setDihedralState(data.quads[i], tmpState, props.arcScale) - const circle = getCircle(tmpState) - state.currentGroup = i - MeshBuilder.addPrimitive(state, Mat4.id, circle) - MeshBuilder.addPrimitiveFlipped(state, Mat4.id, circle) + setDihedralState(data.quads[i], tmpState, props.arcScale); + const circle = getCircle(tmpState); + state.currentGroup = i; + MeshBuilder.addPrimitive(state, Mat4.id, circle); + MeshBuilder.addPrimitiveFlipped(state, Mat4.id, circle); } - return MeshBuilder.getMesh(state) + return MeshBuilder.getMesh(state); } function getSectorShape(ctx: RuntimeContext, data: DihedralData, props: DihedralProps, shape?: Shape<Mesh>) { const mesh = buildSectorMesh(data, props, shape && shape.geometry); - const name = getDihedralName(data) - const getLabel = (groupId: number ) => dihedralLabel(data.quads[groupId]) - return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel) + const name = getDihedralName(data); + const getLabel = (groupId: number ) => dihedralLabel(data.quads[groupId]); + return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel); } // function buildText(data: DihedralData, props: DihedralProps, text?: Text): Text { - const builder = TextBuilder.create(props, 128, 64, text) + const builder = TextBuilder.create(props, 128, 64, text); for (let i = 0, il = data.quads.length; i < il; ++i) { - setDihedralState(data.quads[i], tmpState, props.arcScale) + setDihedralState(data.quads[i], tmpState, props.arcScale); - Vec3.add(tmpVec, tmpState.arcDirA, tmpState.arcDirD) - Vec3.setMagnitude(tmpVec, tmpVec, tmpState.radius) - Vec3.add(tmpVec, tmpState.arcCenter, tmpVec) + Vec3.add(tmpVec, tmpState.arcDirA, tmpState.arcDirD); + Vec3.setMagnitude(tmpVec, tmpVec, tmpState.radius); + Vec3.add(tmpVec, tmpState.arcCenter, tmpVec); - const angle = radToDeg(tmpState.angle).toFixed(2) - const label = `${angle}\u00B0` - const radius = Math.max(2, tmpState.sphereA.radius, tmpState.sphereB.radius, tmpState.sphereC.radius, tmpState.sphereD.radius) - const scale = radius / 2 - builder.add(label, tmpVec[0], tmpVec[1], tmpVec[2], 0.1, scale, i) + const angle = radToDeg(tmpState.angle).toFixed(2); + const label = `${angle}\u00B0`; + const radius = Math.max(2, tmpState.sphereA.radius, tmpState.sphereB.radius, tmpState.sphereC.radius, tmpState.sphereD.radius); + const scale = radius / 2; + builder.add(label, tmpVec[0], tmpVec[1], tmpVec[2], 0.1, scale, i); } - return builder.getText() + return builder.getText(); } function getTextShape(ctx: RuntimeContext, data: DihedralData, props: DihedralProps, shape?: Shape<Text>) { const text = buildText(data, props, shape && shape.geometry); - const name = getDihedralName(data) - const getLabel = (groupId: number ) => dihedralLabel(data.quads[groupId]) - return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel) + const name = getDihedralName(data); + const getLabel = (groupId: number ) => dihedralLabel(data.quads[groupId]); + return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel); } // export type DihedralRepresentation = Representation<DihedralData, DihedralParams> export function DihedralRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<DihedralData, DihedralParams>): DihedralRepresentation { - return Representation.createMulti('Dihedral', ctx, getParams, Representation.StateBuilder, DihedralVisuals as unknown as Representation.Def<DihedralData, DihedralParams>) + return Representation.createMulti('Dihedral', ctx, getParams, Representation.StateBuilder, DihedralVisuals as unknown as Representation.Def<DihedralData, DihedralParams>); } \ No newline at end of file diff --git a/src/mol-repr/shape/loci/distance.ts b/src/mol-repr/shape/loci/distance.ts index 5e94c9a475fe8a6d0309ee14f7791710b227bc41..77a4c3273875f984243d591deedb431ef21b57f2 100644 --- a/src/mol-repr/shape/loci/distance.ts +++ b/src/mol-repr/shape/loci/distance.ts @@ -27,7 +27,7 @@ export interface DistanceData { const SharedParams = { unitLabel: PD.Text('\u212B', { isEssential: true }) -} +}; const LineParams = { ...Lines.Params, @@ -36,7 +36,7 @@ const LineParams = { linesColor: PD.Color(ColorNames.lightgreen, { isEssential: true }), linesSize: PD.Numeric(0.075, { min: 0.01, max: 5, step: 0.01 }), dashLength: PD.Numeric(0.2, { min: 0.01, max: 0.2, step: 0.01 }), -} +}; type LineParams = typeof LineParams const TextParams = { @@ -44,19 +44,19 @@ const TextParams = { ...SharedParams, borderWidth: PD.Numeric(0.2, { min: 0, max: 0.5, step: 0.01 }), ...MeasurementRepresentationCommonTextParams -} +}; type TextParams = typeof TextParams const DistanceVisuals = { 'lines': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<DistanceData, LineParams>) => ShapeRepresentation(getLinesShape, Lines.Utils, { modifyState: s => ({ ...s, markerActions: MarkerActions.Highlighting }) }), 'text': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<DistanceData, TextParams>) => ShapeRepresentation(getTextShape, Text.Utils, { modifyState: s => ({ ...s, markerActions: MarkerAction.None }) }), -} +}; export const DistanceParams = { ...LineParams, ...TextParams, visuals: PD.MultiSelect(['lines', 'text'], PD.objectToOptions(DistanceVisuals)), -} +}; export type DistanceParams = typeof DistanceParams export type DistanceProps = PD.Values<DistanceParams> @@ -69,73 +69,73 @@ function getDistanceState() { center: Vec3(), distance: 0, - } + }; } type DistanceState = ReturnType<typeof getDistanceState> function setDistanceState(pair: Loci.Bundle<2>, state: DistanceState) { - const { sphereA, sphereB, center } = state + const { sphereA, sphereB, center } = state; - const [lociA, lociB] = pair.loci - Loci.getBoundingSphere(lociA, sphereA) - Loci.getBoundingSphere(lociB, sphereB) + const [lociA, lociB] = pair.loci; + Loci.getBoundingSphere(lociA, sphereA); + Loci.getBoundingSphere(lociB, sphereB); - Vec3.add(center, sphereA.center, sphereB.center) - Vec3.scale(center, center, 0.5) - state.distance = Vec3.distance(sphereA.center, sphereB.center) + Vec3.add(center, sphereA.center, sphereB.center); + Vec3.scale(center, center, 0.5); + state.distance = Vec3.distance(sphereA.center, sphereB.center); - return state + return state; } -const tmpState = getDistanceState() +const tmpState = getDistanceState(); function getDistanceName(data: DistanceData, unitLabel: string) { - return data.pairs.length === 1 ? `Distance ${distanceLabel(data.pairs[0], { unitLabel, measureOnly: true })}` : `${data.pairs.length} Distances` + return data.pairs.length === 1 ? `Distance ${distanceLabel(data.pairs[0], { unitLabel, measureOnly: true })}` : `${data.pairs.length} Distances`; } // function buildLines(data: DistanceData, props: DistanceProps, lines?: Lines): Lines { - const builder = LinesBuilder.create(128, 64, lines) + const builder = LinesBuilder.create(128, 64, lines); for (let i = 0, il = data.pairs.length; i < il; ++i) { - setDistanceState(data.pairs[i], tmpState) - builder.addFixedLengthDashes(tmpState.sphereA.center, tmpState.sphereB.center, props.dashLength, i) + setDistanceState(data.pairs[i], tmpState); + builder.addFixedLengthDashes(tmpState.sphereA.center, tmpState.sphereB.center, props.dashLength, i); } - return builder.getLines() + return builder.getLines(); } function getLinesShape(ctx: RuntimeContext, data: DistanceData, props: DistanceProps, shape?: Shape<Lines>) { const lines = buildLines(data, props, shape && shape.geometry); - const name = getDistanceName(data, props.unitLabel) - const getLabel = (groupId: number ) => distanceLabel(data.pairs[groupId], props) - return Shape.create(name, data, lines, () => props.linesColor, () => props.linesSize, getLabel) + const name = getDistanceName(data, props.unitLabel); + const getLabel = (groupId: number ) => distanceLabel(data.pairs[groupId], props); + return Shape.create(name, data, lines, () => props.linesColor, () => props.linesSize, getLabel); } // function buildText(data: DistanceData, props: DistanceProps, text?: Text): Text { - const builder = TextBuilder.create(props, 128, 64, text) + const builder = TextBuilder.create(props, 128, 64, text); for (let i = 0, il = data.pairs.length; i < il; ++i) { - setDistanceState(data.pairs[i], tmpState) - const { center, distance, sphereA, sphereB } = tmpState - const label = `${distance.toFixed(2)} ${props.unitLabel}` - const radius = Math.max(2, sphereA.radius, sphereB.radius) - const scale = radius / 2 - builder.add(label, center[0], center[1], center[2], 1, scale, i) + setDistanceState(data.pairs[i], tmpState); + const { center, distance, sphereA, sphereB } = tmpState; + const label = `${distance.toFixed(2)} ${props.unitLabel}`; + const radius = Math.max(2, sphereA.radius, sphereB.radius); + const scale = radius / 2; + builder.add(label, center[0], center[1], center[2], 1, scale, i); } - return builder.getText() + return builder.getText(); } function getTextShape(ctx: RuntimeContext, data: DistanceData, props: DistanceProps, shape?: Shape<Text>) { const text = buildText(data, props, shape && shape.geometry); - const name = getDistanceName(data, props.unitLabel) - const getLabel = (groupId: number ) => distanceLabel(data.pairs[groupId], props) - return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel) + const name = getDistanceName(data, props.unitLabel); + const getLabel = (groupId: number ) => distanceLabel(data.pairs[groupId], props); + return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel); } // export type DistanceRepresentation = Representation<DistanceData, DistanceParams> export function DistanceRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<DistanceData, DistanceParams>): DistanceRepresentation { - return Representation.createMulti('Distance', ctx, getParams, Representation.StateBuilder, DistanceVisuals as unknown as Representation.Def<DistanceData, DistanceParams>) + return Representation.createMulti('Distance', ctx, getParams, Representation.StateBuilder, DistanceVisuals as unknown as Representation.Def<DistanceData, DistanceParams>); } \ No newline at end of file diff --git a/src/mol-repr/shape/loci/label.ts b/src/mol-repr/shape/loci/label.ts index 36fca46fd9f2c160c31a3a3a984f3bf27fe36bef..89ac82a750aaa1080c4d657bfbcd9a2b1bcd0260 100644 --- a/src/mol-repr/shape/loci/label.ts +++ b/src/mol-repr/shape/loci/label.ts @@ -25,60 +25,60 @@ const TextParams = { borderWidth: PD.Numeric(0.2, { min: 0, max: 0.5, step: 0.01 }), ...MeasurementRepresentationCommonTextParams, offsetZ: PD.Numeric(2, { min: 0, max: 10, step: 0.1 }), -} +}; type TextParams = typeof TextParams const LabelVisuals = { 'text': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<LabelData, TextParams>) => ShapeRepresentation(getTextShape, Text.Utils, { modifyState: s => ({ ...s, pickable: false }) }), -} +}; export const LabelParams = { ...TextParams, visuals: PD.MultiSelect(['text'], PD.objectToOptions(LabelVisuals)), -} +}; export type LabelParams = typeof LabelParams export type LabelProps = PD.Values<LabelParams> // -const tmpSphere = Sphere3D() +const tmpSphere = Sphere3D(); function label(info: { loci: Loci, label?: string }, condensed = false) { - return info.label || lociLabel(info.loci, { hidePrefix: true, htmlStyling: false, condensed }) + return info.label || lociLabel(info.loci, { hidePrefix: true, htmlStyling: false, condensed }); } function getLabelName(data: LabelData) { - return data.infos.length === 1 ? label(data.infos[0]) : `${data.infos.length} Labels` + return data.infos.length === 1 ? label(data.infos[0]) : `${data.infos.length} Labels`; } // function buildText(data: LabelData, props: LabelProps, text?: Text): Text { - const builder = TextBuilder.create(props, 128, 64, text) + const builder = TextBuilder.create(props, 128, 64, text); for (let i = 0, il = data.infos.length; i < il; ++i) { - const info = data.infos[i] - const sphere = Loci.getBoundingSphere(info.loci, tmpSphere) - if (!sphere) continue - const { center, radius } = sphere - const text = label(info, true) - builder.add(text, center[0], center[1], center[2], radius / 0.9, Math.max(1, radius), i) + const info = data.infos[i]; + const sphere = Loci.getBoundingSphere(info.loci, tmpSphere); + if (!sphere) continue; + const { center, radius } = sphere; + const text = label(info, true); + builder.add(text, center[0], center[1], center[2], radius / 0.9, Math.max(1, radius), i); } - return builder.getText() + return builder.getText(); } function getTextShape(ctx: RuntimeContext, data: LabelData, props: LabelProps, shape?: Shape<Text>) { const text = buildText(data, props, shape && shape.geometry); - const name = getLabelName(data) + const name = getLabelName(data); const getLabel = function (groupId: number) { - return label(data.infos[groupId]) - } - return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel) + return label(data.infos[groupId]); + }; + return Shape.create(name, data, text, () => props.textColor, () => props.textSize, getLabel); } // export type LabelRepresentation = Representation<LabelData, LabelParams> export function LabelRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<LabelData, LabelParams>): LabelRepresentation { - return Representation.createMulti('Label', ctx, getParams, Representation.StateBuilder, LabelVisuals as unknown as Representation.Def<LabelData, LabelParams>) + return Representation.createMulti('Label', ctx, getParams, Representation.StateBuilder, LabelVisuals as unknown as Representation.Def<LabelData, LabelParams>); } \ No newline at end of file diff --git a/src/mol-repr/shape/loci/orientation.ts b/src/mol-repr/shape/loci/orientation.ts index f99830edb6a2ba5a14d5e8917295a062291db58c..52b92c7fdae544bf138b3d8f0daea5543385cfe8 100644 --- a/src/mol-repr/shape/loci/orientation.ts +++ b/src/mol-repr/shape/loci/orientation.ts @@ -28,31 +28,31 @@ export interface OrientationData { const SharedParams = { color: PD.Color(ColorNames.orange), scale: PD.Numeric(2, { min: 0.1, max: 10, step: 0.1 }) -} +}; const AxesParams = { ...Mesh.Params, ...SharedParams -} +}; type AxesParams = typeof AxesParams const BoxParams = { ...Mesh.Params, ...SharedParams -} +}; type BoxParams = typeof BoxParams const EllipsoidParams = { ...Mesh.Params, ...SharedParams -} +}; type EllipsoidParams = typeof EllipsoidParams const OrientationVisuals = { 'axes': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<OrientationData, AxesParams>) => ShapeRepresentation(getAxesShape, Mesh.Utils), 'box': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<OrientationData, BoxParams>) => ShapeRepresentation(getBoxShape, Mesh.Utils), 'ellipsoid': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<OrientationData, EllipsoidParams>) => ShapeRepresentation(getEllipsoidShape, Mesh.Utils), -} +}; export const OrientationParams = { ...AxesParams, @@ -60,101 +60,101 @@ export const OrientationParams = { visuals: PD.MultiSelect(['box'], PD.objectToOptions(OrientationVisuals)), color: PD.Color(ColorNames.orange), scale: PD.Numeric(2, { min: 0.1, max: 5, step: 0.1 }) -} +}; export type OrientationParams = typeof OrientationParams export type OrientationProps = PD.Values<OrientationParams> // function orientationLabel(loci: Loci) { - const label = lociLabel(loci, { countsOnly: true }) - return `Principal Axes of ${label}` + const label = lociLabel(loci, { countsOnly: true }); + return `Principal Axes of ${label}`; } function getOrientationName(data: OrientationData) { - return data.locis.length === 1 ? orientationLabel(data.locis[0]) : `${data.locis.length} Orientations` + return data.locis.length === 1 ? orientationLabel(data.locis[0]) : `${data.locis.length} Orientations`; } // function buildAxesMesh(data: OrientationData, props: OrientationProps, mesh?: Mesh): Mesh { - const state = MeshBuilder.createState(256, 128, mesh) + const state = MeshBuilder.createState(256, 128, mesh); for (let i = 0, il = data.locis.length; i < il; ++i) { - const principalAxes = Loci.getPrincipalAxes(data.locis[i]) + const principalAxes = Loci.getPrincipalAxes(data.locis[i]); if (principalAxes) { - state.currentGroup = i - addAxes(state, principalAxes.momentsAxes, props.scale, 2, 20) + state.currentGroup = i; + addAxes(state, principalAxes.momentsAxes, props.scale, 2, 20); } } - return MeshBuilder.getMesh(state) + return MeshBuilder.getMesh(state); } function getAxesShape(ctx: RuntimeContext, data: OrientationData, props: OrientationProps, shape?: Shape<Mesh>) { const mesh = buildAxesMesh(data, props, shape && shape.geometry); - const name = getOrientationName(data) + const name = getOrientationName(data); const getLabel = function (groupId: number ) { - return orientationLabel(data.locis[groupId]) - } - return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel) + return orientationLabel(data.locis[groupId]); + }; + return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel); } // function buildBoxMesh(data: OrientationData, props: OrientationProps, mesh?: Mesh): Mesh { - const state = MeshBuilder.createState(256, 128, mesh) + const state = MeshBuilder.createState(256, 128, mesh); for (let i = 0, il = data.locis.length; i < il; ++i) { - const principalAxes = Loci.getPrincipalAxes(data.locis[i]) + const principalAxes = Loci.getPrincipalAxes(data.locis[i]); if (principalAxes) { - state.currentGroup = i - addOrientedBox(state, principalAxes.boxAxes, props.scale, 2, 20) + state.currentGroup = i; + addOrientedBox(state, principalAxes.boxAxes, props.scale, 2, 20); } } - return MeshBuilder.getMesh(state) + return MeshBuilder.getMesh(state); } function getBoxShape(ctx: RuntimeContext, data: OrientationData, props: OrientationProps, shape?: Shape<Mesh>) { const mesh = buildBoxMesh(data, props, shape && shape.geometry); - const name = getOrientationName(data) + const name = getOrientationName(data); const getLabel = function (groupId: number ) { - return orientationLabel(data.locis[groupId]) - } - return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel) + return orientationLabel(data.locis[groupId]); + }; + return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel); } // function buildEllipsoidMesh(data: OrientationData, props: OrientationProps, mesh?: Mesh): Mesh { - const state = MeshBuilder.createState(256, 128, mesh) + const state = MeshBuilder.createState(256, 128, mesh); for (let i = 0, il = data.locis.length; i < il; ++i) { - const principalAxes = Loci.getPrincipalAxes(data.locis[i]) + const principalAxes = Loci.getPrincipalAxes(data.locis[i]); if (principalAxes) { - const axes = principalAxes.boxAxes - const { origin, dirA, dirB } = axes - const size = Axes3D.size(Vec3(), axes) - Vec3.scale(size, size, 0.5) - const radiusScale = Vec3.create(size[2], size[1], size[0]) - - state.currentGroup = i - addEllipsoid(state, origin, dirA, dirB, radiusScale, 2) + const axes = principalAxes.boxAxes; + const { origin, dirA, dirB } = axes; + const size = Axes3D.size(Vec3(), axes); + Vec3.scale(size, size, 0.5); + const radiusScale = Vec3.create(size[2], size[1], size[0]); + + state.currentGroup = i; + addEllipsoid(state, origin, dirA, dirB, radiusScale, 2); } } - return MeshBuilder.getMesh(state) + return MeshBuilder.getMesh(state); } function getEllipsoidShape(ctx: RuntimeContext, data: OrientationData, props: OrientationProps, shape?: Shape<Mesh>) { const mesh = buildEllipsoidMesh(data, props, shape && shape.geometry); - const name = getOrientationName(data) + const name = getOrientationName(data); const getLabel = function (groupId: number ) { - return orientationLabel(data.locis[groupId]) - } - return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel) + return orientationLabel(data.locis[groupId]); + }; + return Shape.create(name, data, mesh, () => props.color, () => 1, getLabel); } // export type OrientationRepresentation = Representation<OrientationData, OrientationParams> export function OrientationRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<OrientationData, OrientationParams>): OrientationRepresentation { - const repr = Representation.createMulti('Orientation', ctx, getParams, Representation.StateBuilder, OrientationVisuals as unknown as Representation.Def<OrientationData, OrientationParams>) - repr.setState({ markerActions: MarkerActions.Highlighting }) - return repr + const repr = Representation.createMulti('Orientation', ctx, getParams, Representation.StateBuilder, OrientationVisuals as unknown as Representation.Def<OrientationData, OrientationParams>); + repr.setState({ markerActions: MarkerActions.Highlighting }); + return repr; } \ No newline at end of file diff --git a/src/mol-repr/shape/model/unitcell.ts b/src/mol-repr/shape/model/unitcell.ts index 47eaa8ec278e79c2188c60a2293395015f131247..a139ae4fc4a4aa5cf3e5290a66b648a5c6317b13 100644 --- a/src/mol-repr/shape/model/unitcell.ts +++ b/src/mol-repr/shape/model/unitcell.ts @@ -18,11 +18,11 @@ import { transformCage, cloneCage } from '../../../mol-geo/primitive/cage'; import { Sphere3D } from '../../../mol-math/geometry'; import { RepresentationParamsGetter, Representation, RepresentationContext } from '../../representation'; -const translate05 = Mat4.fromTranslation(Mat4(), Vec3.create(0.5, 0.5, 0.5)) -const unitCage = transformCage(cloneCage(BoxCage()), translate05) +const translate05 = Mat4.fromTranslation(Mat4(), Vec3.create(0.5, 0.5, 0.5)); +const unitCage = transformCage(cloneCage(BoxCage()), translate05); -const tmpRef = Vec3() -const tmpTranslate = Mat4() +const tmpRef = Vec3(); +const tmpTranslate = Mat4(); interface UnitcellData { symmetry: Symmetry @@ -33,67 +33,67 @@ const CellParams = { ...Mesh.Params, cellColor: PD.Color(ColorNames.orange), cellScale: PD.Numeric(2, { min: 0.1, max: 5, step: 0.1 }) -} +}; type MeshParams = typeof CellParams const UnitcellVisuals = { 'mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<UnitcellData, MeshParams>) => ShapeRepresentation(getUnitcellShape, Mesh.Utils), -} +}; export const UnitcellParams = { ...CellParams -} +}; export type UnitcellParams = typeof UnitcellParams export type UnitcellProps = PD.Values<UnitcellParams> function getUnitcellMesh(data: UnitcellData, props: UnitcellProps, mesh?: Mesh) { - const state = MeshBuilder.createState(256, 128, mesh) - - const { fromFractional } = data.symmetry.spacegroup.cell - - Vec3.floor(tmpRef, data.ref) - Mat4.fromTranslation(tmpTranslate, tmpRef) - const cellCage = transformCage(cloneCage(unitCage), tmpTranslate) - - const radius = (Math.cbrt(data.symmetry.spacegroup.cell.volume) / 300) * props.cellScale - state.currentGroup = 1 - MeshBuilder.addCage(state, fromFractional, cellCage, radius, 2, 20) - - const cpA = Vec3.create(0, 0, 0) - Vec3.transformMat4(cpA, Vec3.add(cpA, cpA, tmpRef), fromFractional) - const cpB = Vec3.create(1, 1, 1) - Vec3.transformMat4(cpB, Vec3.add(cpB, cpB, tmpRef), fromFractional) - const cpC = Vec3.create(1, 0, 0) - Vec3.transformMat4(cpC, Vec3.add(cpC, cpC, tmpRef), fromFractional) - const cpD = Vec3.create(0, 1, 1) - Vec3.transformMat4(cpD, Vec3.add(cpD, cpD, tmpRef), fromFractional) - - const cpE = Vec3.create(0, 0, 1) - Vec3.transformMat4(cpE, Vec3.add(cpE, cpE, tmpRef), fromFractional) - const cpF = Vec3.create(1, 0, 1) - Vec3.transformMat4(cpF, Vec3.add(cpF, cpF, tmpRef), fromFractional) - const cpG = Vec3.create(1, 1, 0) - Vec3.transformMat4(cpG, Vec3.add(cpG, cpG, tmpRef), fromFractional) - const cpH = Vec3.create(0, 1, 0) - Vec3.transformMat4(cpH, Vec3.add(cpH, cpH, tmpRef), fromFractional) - - const center = Vec3() - Vec3.add(center, cpA, cpB) - Vec3.scale(center, center, 0.5) - const d = Math.max(Vec3.distance(cpA, cpB), Vec3.distance(cpC, cpD)) - const sphere = Sphere3D.create(center, d / 2) - Sphere3D.setExtrema(sphere, [cpA, cpB, cpC, cpD, cpE, cpF, cpG, cpH]) - Sphere3D.expand(sphere, sphere, radius) - - const m = MeshBuilder.getMesh(state) - m.setBoundingSphere(sphere) - return m + const state = MeshBuilder.createState(256, 128, mesh); + + const { fromFractional } = data.symmetry.spacegroup.cell; + + Vec3.floor(tmpRef, data.ref); + Mat4.fromTranslation(tmpTranslate, tmpRef); + const cellCage = transformCage(cloneCage(unitCage), tmpTranslate); + + const radius = (Math.cbrt(data.symmetry.spacegroup.cell.volume) / 300) * props.cellScale; + state.currentGroup = 1; + MeshBuilder.addCage(state, fromFractional, cellCage, radius, 2, 20); + + const cpA = Vec3.create(0, 0, 0); + Vec3.transformMat4(cpA, Vec3.add(cpA, cpA, tmpRef), fromFractional); + const cpB = Vec3.create(1, 1, 1); + Vec3.transformMat4(cpB, Vec3.add(cpB, cpB, tmpRef), fromFractional); + const cpC = Vec3.create(1, 0, 0); + Vec3.transformMat4(cpC, Vec3.add(cpC, cpC, tmpRef), fromFractional); + const cpD = Vec3.create(0, 1, 1); + Vec3.transformMat4(cpD, Vec3.add(cpD, cpD, tmpRef), fromFractional); + + const cpE = Vec3.create(0, 0, 1); + Vec3.transformMat4(cpE, Vec3.add(cpE, cpE, tmpRef), fromFractional); + const cpF = Vec3.create(1, 0, 1); + Vec3.transformMat4(cpF, Vec3.add(cpF, cpF, tmpRef), fromFractional); + const cpG = Vec3.create(1, 1, 0); + Vec3.transformMat4(cpG, Vec3.add(cpG, cpG, tmpRef), fromFractional); + const cpH = Vec3.create(0, 1, 0); + Vec3.transformMat4(cpH, Vec3.add(cpH, cpH, tmpRef), fromFractional); + + const center = Vec3(); + Vec3.add(center, cpA, cpB); + Vec3.scale(center, center, 0.5); + const d = Math.max(Vec3.distance(cpA, cpB), Vec3.distance(cpC, cpD)); + const sphere = Sphere3D.create(center, d / 2); + Sphere3D.setExtrema(sphere, [cpA, cpB, cpC, cpD, cpE, cpF, cpG, cpH]); + Sphere3D.expand(sphere, sphere, radius); + + const m = MeshBuilder.getMesh(state); + m.setBoundingSphere(sphere); + return m; } function getUnitcellShape(ctx: RuntimeContext, data: UnitcellData, props: UnitcellProps, shape?: Shape<Mesh>) { const geo = getUnitcellMesh(data, props, shape && shape.geometry); - const label = Symmetry.getUnitcellLabel(data.symmetry) - return Shape.create(label, data, geo, () => props.cellColor, () => 1, () => label) + const label = Symmetry.getUnitcellLabel(data.symmetry); + return Shape.create(label, data, geo, () => props.cellColor, () => 1, () => label); } // @@ -102,10 +102,10 @@ export function getUnitcellData(model: Model, symmetry: Symmetry) { return { symmetry, ref: Vec3.transformMat4(Vec3(), Model.getCenter(model), symmetry.spacegroup.cell.toFractional) - } + }; } export type UnitcellRepresentation = Representation<UnitcellData, UnitcellParams> export function UnitcellRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<UnitcellData, UnitcellParams>): UnitcellRepresentation { - return Representation.createMulti('Unitcell', ctx, getParams, Representation.StateBuilder, UnitcellVisuals as unknown as Representation.Def<UnitcellData, UnitcellParams>) + return Representation.createMulti('Unitcell', ctx, getParams, Representation.StateBuilder, UnitcellVisuals as unknown as Representation.Def<UnitcellData, UnitcellParams>); } \ No newline at end of file diff --git a/src/mol-repr/shape/representation.ts b/src/mol-repr/shape/representation.ts index 0592f107e8ab894aeb0900bf6ee0229a13098028..49020de0b169952013d3342169ce42d09e18043d 100644 --- a/src/mol-repr/shape/representation.ts +++ b/src/mol-repr/shape/representation.ts @@ -36,208 +36,208 @@ export interface ShapeBuilder<G extends Geometry, P extends Geometry.Params<G>> } export function ShapeRepresentation<D, G extends Geometry, P extends Geometry.Params<G>>(getShape: ShapeGetter<D, G, P>, geometryUtils: GeometryUtils<G>, builder: ShapeBuilder<G, P> = {}): ShapeRepresentation<D, G, P> { - let version = 0 - const updated = new Subject<number>() - const _state = Representation.createState() - const materialId = getNextMaterialId() - const renderObjects: GraphicsRenderObject<G['kind']>[] = [] - let _renderObject: GraphicsRenderObject<G['kind']> | undefined - let _shape: Shape<G> - let _theme = Theme.createEmpty() - let currentProps: PD.Values<P> = PD.getDefaultValues(geometryUtils.Params as P) // TODO avoid casting - let currentParams: P - let locationIt: LocationIterator - - if (builder.modifyState) Representation.updateState(_state, builder.modifyState(_state)) - - const updateState = VisualUpdateState.create() + let version = 0; + const updated = new Subject<number>(); + const _state = Representation.createState(); + const materialId = getNextMaterialId(); + const renderObjects: GraphicsRenderObject<G['kind']>[] = []; + let _renderObject: GraphicsRenderObject<G['kind']> | undefined; + let _shape: Shape<G>; + let _theme = Theme.createEmpty(); + let currentProps: PD.Values<P> = PD.getDefaultValues(geometryUtils.Params as P); // TODO avoid casting + let currentParams: P; + let locationIt: LocationIterator; + + if (builder.modifyState) Representation.updateState(_state, builder.modifyState(_state)); + + const updateState = VisualUpdateState.create(); function prepareUpdate(props: Partial<PD.Values<P>> = {}, shape?: Shape<G>) { - VisualUpdateState.reset(updateState) + VisualUpdateState.reset(updateState); if (!shape && !_shape) { // console.error('no shape given') - return + return; } else if (shape && !_shape) { // console.log('first shape') - updateState.createNew = true + updateState.createNew = true; } else if (shape && _shape && shape.id === _shape.id) { // console.log('same shape') // nothing to set } else if (shape && _shape && shape.id !== _shape.id) { // console.log('new shape') - updateState.updateTransform = true - updateState.createGeometry = true + updateState.updateTransform = true; + updateState.createGeometry = true; } else if (!shape) { // console.log('only props') // nothing to set } else { - console.warn('unexpected state') + console.warn('unexpected state'); } if (updateState.updateTransform) { - updateState.updateColor = true - updateState.updateSize = true + updateState.updateColor = true; + updateState.updateSize = true; } if (updateState.createGeometry) { - updateState.updateColor = true - updateState.updateSize = true + updateState.updateColor = true; + updateState.updateSize = true; } } function createOrUpdate(props: Partial<PD.Values<P>> = {}, data?: D) { - if (builder.modifyProps) props = builder.modifyProps(props) + if (builder.modifyProps) props = builder.modifyProps(props); return Task.create('ShapeRepresentation.create', async runtime => { - const newProps = Object.assign(currentProps, props) - const shape = data ? await getShape(runtime, data, newProps, _shape) : undefined + const newProps = Object.assign(currentProps, props); + const shape = data ? await getShape(runtime, data, newProps, _shape) : undefined; - prepareUpdate(props, shape) + prepareUpdate(props, shape); if (shape) { - _shape = shape - Object.assign(_theme, Shape.getTheme(_shape)) + _shape = shape; + Object.assign(_theme, Shape.getTheme(_shape)); } if (updateState.createNew) { - renderObjects.length = 0 // clear list o renderObjects - locationIt = Shape.groupIterator(_shape) - const transform = Shape.createTransform(_shape.transforms) - const values = geometryUtils.createValues(_shape.geometry, transform, locationIt, _theme, newProps) - const state = geometryUtils.createRenderableState(newProps) - if (builder.modifyState) Object.assign(state, builder.modifyState(state)) - Representation.updateState(_state, state) - - _renderObject = createRenderObject(_shape.geometry.kind, values, state, materialId) - if (_renderObject) renderObjects.push(_renderObject) // add new renderObject to list + renderObjects.length = 0; // clear list o renderObjects + locationIt = Shape.groupIterator(_shape); + const transform = Shape.createTransform(_shape.transforms); + const values = geometryUtils.createValues(_shape.geometry, transform, locationIt, _theme, newProps); + const state = geometryUtils.createRenderableState(newProps); + if (builder.modifyState) Object.assign(state, builder.modifyState(state)); + Representation.updateState(_state, state); + + _renderObject = createRenderObject(_shape.geometry.kind, values, state, materialId); + if (_renderObject) renderObjects.push(_renderObject); // add new renderObject to list } else { if (!_renderObject) { - throw new Error('expected renderObject to be available') + throw new Error('expected renderObject to be available'); } if (updateState.updateTransform) { // console.log('update transform') - Shape.createTransform(_shape.transforms, _renderObject.values) - locationIt = Shape.groupIterator(_shape) - const { instanceCount, groupCount } = locationIt - createMarkers(instanceCount * groupCount, _renderObject.values) + Shape.createTransform(_shape.transforms, _renderObject.values); + locationIt = Shape.groupIterator(_shape); + const { instanceCount, groupCount } = locationIt; + createMarkers(instanceCount * groupCount, _renderObject.values); } if (updateState.createGeometry) { // console.log('update geometry') - ValueCell.update(_renderObject.values.drawCount, Geometry.getDrawCount(_shape.geometry)) + ValueCell.update(_renderObject.values.drawCount, Geometry.getDrawCount(_shape.geometry)); } if (updateState.updateTransform || updateState.createGeometry) { // console.log('updateBoundingSphere') - geometryUtils.updateBoundingSphere(_renderObject.values as RenderObjectValues<G['kind']>, _shape.geometry) + geometryUtils.updateBoundingSphere(_renderObject.values as RenderObjectValues<G['kind']>, _shape.geometry); } if (updateState.updateColor) { // console.log('update color') - createColors(locationIt, _theme.color, _renderObject.values) + createColors(locationIt, _theme.color, _renderObject.values); } if (updateState.updateSize) { // not all geometries have size data, so check here if ('uSize' in _renderObject.values) { // console.log('update size') - createSizes(locationIt, _theme.size, _renderObject.values as SizeData) + createSizes(locationIt, _theme.size, _renderObject.values as SizeData); } } - geometryUtils.updateValues(_renderObject.values as RenderObjectValues<G['kind']>, newProps) - geometryUtils.updateRenderableState(_renderObject.state, newProps) + geometryUtils.updateValues(_renderObject.values as RenderObjectValues<G['kind']>, newProps); + geometryUtils.updateRenderableState(_renderObject.state, newProps); } - currentProps = newProps + currentProps = newProps; // increment version - updated.next(version++) + updated.next(version++); }); } function lociApply(loci: Loci, apply: (interval: Interval) => boolean) { if (isEveryLoci(loci) || (Shape.isLoci(loci) && loci.shape === _shape)) { - return apply(Interval.ofBounds(0, _shape.groupCount * _shape.transforms.length)) + return apply(Interval.ofBounds(0, _shape.groupCount * _shape.transforms.length)); } else { - return eachShapeGroup(loci, _shape, apply) + return eachShapeGroup(loci, _shape, apply); } } return { label: 'Shape geometry', - get groupCount () { return locationIt ? locationIt.count : 0 }, - get props () { return currentProps }, - get params () { return currentParams }, - get state() { return _state }, - get theme() { return _theme }, + get groupCount () { return locationIt ? locationIt.count : 0; }, + get props () { return currentProps; }, + get params () { return currentParams; }, + get state() { return _state; }, + get theme() { return _theme; }, renderObjects, updated, createOrUpdate, getLoci(pickingId?: PickingId) { - if (pickingId === undefined) return Shape.Loci(_shape) - const { objectId, groupId, instanceId } = pickingId + if (pickingId === undefined) return Shape.Loci(_shape); + const { objectId, groupId, instanceId } = pickingId; if (_renderObject && _renderObject.id === objectId) { - return ShapeGroup.Loci(_shape, [{ ids: OrderedSet.ofSingleton(groupId), instance: instanceId }]) + return ShapeGroup.Loci(_shape, [{ ids: OrderedSet.ofSingleton(groupId), instance: instanceId }]); } - return EmptyLoci + return EmptyLoci; }, mark(loci: Loci, action: MarkerAction) { - if (!MarkerActions.is(_state.markerActions, action)) return false + if (!MarkerActions.is(_state.markerActions, action)) return false; if (ShapeGroup.isLoci(loci) || Shape.isLoci(loci)) { - if (loci.shape !== _shape) return false + if (loci.shape !== _shape) return false; } else if (!isEveryLoci(loci)) { - return false + return false; } - return Visual.mark(_renderObject, loci, action, lociApply) + return Visual.mark(_renderObject, loci, action, lociApply); }, setState(state: Partial<Representation.State>) { - if (builder.modifyState) state = builder.modifyState(state) + if (builder.modifyState) state = builder.modifyState(state); if (_renderObject) { - if (state.visible !== undefined) Visual.setVisibility(_renderObject, state.visible) - if (state.alphaFactor !== undefined) Visual.setAlphaFactor(_renderObject, state.alphaFactor) - if (state.pickable !== undefined) Visual.setPickable(_renderObject, state.pickable) + if (state.visible !== undefined) Visual.setVisibility(_renderObject, state.visible); + if (state.alphaFactor !== undefined) Visual.setAlphaFactor(_renderObject, state.alphaFactor); + if (state.pickable !== undefined) Visual.setPickable(_renderObject, state.pickable); if (state.overpaint !== undefined) { - Visual.setOverpaint(_renderObject, state.overpaint, lociApply, true) + Visual.setOverpaint(_renderObject, state.overpaint, lociApply, true); } if (state.transparency !== undefined) { - Visual.setTransparency(_renderObject, state.transparency, lociApply, true) + Visual.setTransparency(_renderObject, state.transparency, lociApply, true); } - if (state.transform !== undefined) Visual.setTransform(_renderObject, state.transform) + if (state.transform !== undefined) Visual.setTransform(_renderObject, state.transform); } - Representation.updateState(_state, state) + Representation.updateState(_state, state); }, setTheme(theme: Theme) { - console.warn('The `ShapeRepresentation` theme is fixed to `ShapeGroupColorTheme` and `ShapeGroupSizeTheme`. Colors are taken from `Shape.getColor` and sizes from `Shape.getSize`') + console.warn('The `ShapeRepresentation` theme is fixed to `ShapeGroupColorTheme` and `ShapeGroupSizeTheme`. Colors are taken from `Shape.getColor` and sizes from `Shape.getSize`'); }, destroy() { // TODO - renderObjects.length = 0 - _renderObject = undefined + renderObjects.length = 0; + _renderObject = undefined; } - } + }; } function eachShapeGroup(loci: Loci, shape: Shape, apply: (interval: Interval) => boolean) { - if (!ShapeGroup.isLoci(loci)) return false - if (loci.shape !== shape) return false - let changed = false - const { groupCount } = shape - const { groups } = loci + if (!ShapeGroup.isLoci(loci)) return false; + if (loci.shape !== shape) return false; + let changed = false; + const { groupCount } = shape; + const { groups } = loci; for (const { ids, instance } of groups) { if (Interval.is(ids)) { - const start = instance * groupCount + Interval.start(ids) - const end = instance * groupCount + Interval.end(ids) - if (apply(Interval.ofBounds(start, end))) changed = true + const start = instance * groupCount + Interval.start(ids); + const end = instance * groupCount + Interval.end(ids); + if (apply(Interval.ofBounds(start, end))) changed = true; } else { for (let i = 0, _i = ids.length; i < _i; i++) { const idx = instance * groupCount + ids[i]; - if (apply(Interval.ofSingleton(idx))) changed = true + if (apply(Interval.ofSingleton(idx))) changed = true; } } } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/complex-representation.ts b/src/mol-repr/structure/complex-representation.ts index b6cec476c8e2cc406e0d38014d665ffcc904e68f..359e0d0be8f1886e186c5d68f34081d711e03afc 100644 --- a/src/mol-repr/structure/complex-representation.ts +++ b/src/mol-repr/structure/complex-representation.ts @@ -20,106 +20,106 @@ import { Overpaint } from '../../mol-theme/overpaint'; import { StructureParams } from './params'; export function ComplexRepresentation<P extends StructureParams>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, P>, visualCtor: (materialId: number) => ComplexVisual<P>): StructureRepresentation<P> { - let version = 0 - const updated = new Subject<number>() - const materialId = getNextMaterialId() - const renderObjects: GraphicsRenderObject[] = [] - const _state = StructureRepresentationStateBuilder.create() - let visual: ComplexVisual<P> | undefined + let version = 0; + const updated = new Subject<number>(); + const materialId = getNextMaterialId(); + const renderObjects: GraphicsRenderObject[] = []; + const _state = StructureRepresentationStateBuilder.create(); + let visual: ComplexVisual<P> | undefined; - let _structure: Structure - let _params: P - let _props: PD.Values<P> - let _theme = Theme.createEmpty() + let _structure: Structure; + let _params: P; + let _props: PD.Values<P>; + let _theme = Theme.createEmpty(); function createOrUpdate(props: Partial<PD.Values<P>> = {}, structure?: Structure) { if (structure && structure !== _structure) { - _params = getParams(ctx, structure) - _structure = structure - if (!_props) _props = PD.getDefaultValues(_params) + _params = getParams(ctx, structure); + _structure = structure; + if (!_props) _props = PD.getDefaultValues(_params); } - _props = Object.assign({}, _props, props) + _props = Object.assign({}, _props, props); return Task.create('Creating or updating ComplexRepresentation', async runtime => { - let newVisual = false + let newVisual = false; if (!visual) { - visual = visualCtor(materialId) - newVisual = true + visual = visualCtor(materialId); + newVisual = true; } - const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, structure) - if (promise) await promise + const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, structure); + if (promise) await promise; if (newVisual) { // ensure state is current for new visual - setState(_state) + setState(_state); } // update list of renderObjects - renderObjects.length = 0 - if (visual && visual.renderObject) renderObjects.push(visual.renderObject) + renderObjects.length = 0; + if (visual && visual.renderObject) renderObjects.push(visual.renderObject); // increment version - updated.next(version++) + updated.next(version++); }); } function getLoci(pickingId?: PickingId) { - if (pickingId === undefined) return Structure.Loci(_structure) - return visual ? visual.getLoci(pickingId) : EmptyLoci + if (pickingId === undefined) return Structure.Loci(_structure); + return visual ? visual.getLoci(pickingId) : EmptyLoci; } function mark(loci: Loci, action: MarkerAction) { - if (!_structure) return false - if (!MarkerActions.is(_state.markerActions, action)) return false + if (!_structure) return false; + if (!MarkerActions.is(_state.markerActions, action)) return false; if (Structure.isLoci(loci) || StructureElement.Loci.is(loci) || Bond.isLoci(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, _structure)) return false + if (!Structure.areRootsEquivalent(loci.structure, _structure)) return false; // Remap `loci` from equivalent structure to the current `_structure` - loci = Loci.remap(loci, _structure) + loci = Loci.remap(loci, _structure); } else if (!isEveryLoci(loci) && !isDataLoci(loci)) { - return false + return false; } - if (Loci.isEmpty(loci)) return false - return visual ? visual.mark(loci, action) : false + if (Loci.isEmpty(loci)) return false; + return visual ? visual.mark(loci, action) : false; } function setState(state: Partial<StructureRepresentationState>) { - StructureRepresentationStateBuilder.update(_state, state) + StructureRepresentationStateBuilder.update(_state, state); if (state.visible !== undefined && visual) { // hide visual when _unitTransforms is set and not the identity - visual.setVisibility(state.visible && (_state.unitTransforms === null || _state.unitTransforms.isIdentity)) + visual.setVisibility(state.visible && (_state.unitTransforms === null || _state.unitTransforms.isIdentity)); } - if (state.alphaFactor !== undefined && visual) visual.setAlphaFactor(state.alphaFactor) - if (state.pickable !== undefined && visual) visual.setPickable(state.pickable) + if (state.alphaFactor !== undefined && visual) visual.setAlphaFactor(state.alphaFactor); + if (state.pickable !== undefined && visual) visual.setPickable(state.pickable); if (state.overpaint !== undefined && visual) { // Remap loci from equivalent structure to the current structure - const remappedOverpaint = Overpaint.remap(state.overpaint, _structure) - visual.setOverpaint(remappedOverpaint) + const remappedOverpaint = Overpaint.remap(state.overpaint, _structure); + visual.setOverpaint(remappedOverpaint); } - if (state.transparency !== undefined && visual) visual.setTransparency(state.transparency) - if (state.transform !== undefined && visual) visual.setTransform(state.transform) + if (state.transparency !== undefined && visual) visual.setTransparency(state.transparency); + if (state.transform !== undefined && visual) visual.setTransform(state.transform); if (state.unitTransforms !== undefined && visual) { // Since ComplexVisuals always renders geometries between units, the application // of `unitTransforms` does not make sense. When given here and not the identity, // it is ignored and sets the visual's visibility to `false`. - visual.setVisibility(_state.visible && (state.unitTransforms === null || state.unitTransforms.isIdentity)) + visual.setVisibility(_state.visible && (state.unitTransforms === null || state.unitTransforms.isIdentity)); } } function setTheme(theme: Theme) { - _theme = theme + _theme = theme; } function destroy() { - if (visual) visual.destroy() + if (visual) visual.destroy(); } return { label, get groupCount() { - return visual ? visual.groupCount : 0 + return visual ? visual.groupCount : 0; }, - get props() { return _props }, - get params() { return _params }, - get state() { return _state }, - get theme() { return _theme }, + get props() { return _props; }, + get params() { return _params; }, + get state() { return _state; }, + get theme() { return _theme; }, renderObjects, updated, createOrUpdate, @@ -128,5 +128,5 @@ export function ComplexRepresentation<P extends StructureParams>(label: string, getLoci, mark, destroy - } + }; } \ No newline at end of file diff --git a/src/mol-repr/structure/complex-visual.ts b/src/mol-repr/structure/complex-visual.ts index 18c5a10283ddd0064676f1d49a515f22cc50ee1f..d160adb25b3ea35e81c91e7d38a896a3855413ac 100644 --- a/src/mol-repr/structure/complex-visual.ts +++ b/src/mol-repr/structure/complex-visual.ts @@ -34,11 +34,11 @@ import { StructureParams, StructureMeshParams, StructureTextParams, StructureDir export interface ComplexVisual<P extends StructureParams> extends Visual<Structure, P> { } function createComplexRenderObject<G extends Geometry>(structure: Structure, geometry: G, locationIt: LocationIterator, theme: Theme, props: PD.Values<Geometry.Params<G>>, materialId: number) { - const { createValues, createRenderableState } = Geometry.getUtils(geometry) - const transform = createIdentityTransform() - const values = createValues(geometry, transform, locationIt, theme, props) - const state = createRenderableState(props) - return createRenderObject(geometry.kind, values, state, materialId) + const { createValues, createRenderableState } = Geometry.getUtils(geometry); + const transform = createIdentityTransform(); + const values = createValues(geometry, transform, locationIt, theme, props); + const state = createRenderableState(props); + return createRenderObject(geometry.kind, values, state, materialId); } interface ComplexVisualBuilder<P extends StructureParams, G extends Geometry> { @@ -55,178 +55,178 @@ interface ComplexVisualGeometryBuilder<P extends StructureParams, G extends Geom } export function ComplexVisual<G extends Geometry, P extends StructureParams & Geometry.Params<G>>(builder: ComplexVisualGeometryBuilder<P, G>, materialId: number): ComplexVisual<P> { - const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState } = builder - const { updateValues, updateBoundingSphere, updateRenderableState } = builder.geometryUtils - const updateState = VisualUpdateState.create() + const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState } = builder; + const { updateValues, updateBoundingSphere, updateRenderableState } = builder.geometryUtils; + const updateState = VisualUpdateState.create(); - let renderObject: GraphicsRenderObject<G['kind']> | undefined + let renderObject: GraphicsRenderObject<G['kind']> | undefined; - let newProps: PD.Values<P> - let newTheme: Theme - let newStructure: Structure + let newProps: PD.Values<P>; + let newTheme: Theme; + let newStructure: Structure; - let currentProps: PD.Values<P> = Object.assign({}, defaultProps) - let currentTheme: Theme = Theme.createEmpty() - let currentStructure: Structure + let currentProps: PD.Values<P> = Object.assign({}, defaultProps); + let currentTheme: Theme = Theme.createEmpty(); + let currentStructure: Structure; - let geometry: G - let locationIt: LocationIterator + let geometry: G; + let locationIt: LocationIterator; function prepareUpdate(theme: Theme, props: Partial<PD.Values<P>>, structure: Structure) { if (!structure && !currentStructure) { - throw new Error('missing structure') + throw new Error('missing structure'); } - newProps = Object.assign({}, currentProps, props) - newTheme = theme - newStructure = structure + newProps = Object.assign({}, currentProps, props); + newTheme = theme; + newStructure = structure; - VisualUpdateState.reset(updateState) + VisualUpdateState.reset(updateState); if (!renderObject) { - updateState.createNew = true + updateState.createNew = true; } else if (!currentStructure || !Structure.areEquivalent(newStructure, currentStructure)) { - updateState.createNew = true + updateState.createNew = true; } if (updateState.createNew) { - updateState.createGeometry = true - return + updateState.createGeometry = true; + return; } - setUpdateState(updateState, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure) + setUpdateState(updateState, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure); if (Structure.conformationHash(newStructure) !== Structure.conformationHash(currentStructure)) { updateState.updateTransform = true; - updateState.createGeometry = true + updateState.createGeometry = true; } if (!ColorTheme.areEqual(theme.color, currentTheme.color)) { - updateState.updateColor = true + updateState.updateColor = true; } if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) { - updateState.createGeometry = true + updateState.createGeometry = true; } if (updateState.createGeometry) { - updateState.updateColor = true + updateState.updateColor = true; } } function update(newGeometry?: G) { if (updateState.createNew) { - locationIt = createLocationIterator(newStructure) + locationIt = createLocationIterator(newStructure); if (newGeometry) { - renderObject = createComplexRenderObject(newStructure, newGeometry, locationIt, newTheme, newProps, materialId) + renderObject = createComplexRenderObject(newStructure, newGeometry, locationIt, newTheme, newProps, materialId); } else { - throw new Error('expected geometry to be given') + throw new Error('expected geometry to be given'); } } else { if (!renderObject) { - throw new Error('expected renderObject to be available') + throw new Error('expected renderObject to be available'); } if (updateState.updateTransform) { // console.log('update transform') - locationIt = createLocationIterator(newStructure) - const { instanceCount, groupCount } = locationIt - createMarkers(instanceCount * groupCount, renderObject.values) + locationIt = createLocationIterator(newStructure); + const { instanceCount, groupCount } = locationIt; + createMarkers(instanceCount * groupCount, renderObject.values); } if (updateState.createGeometry) { if (newGeometry) { - ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(newGeometry)) - updateBoundingSphere(renderObject.values as RenderObjectValues<G['kind']>, newGeometry) + ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(newGeometry)); + updateBoundingSphere(renderObject.values as RenderObjectValues<G['kind']>, newGeometry); } else { - throw new Error('expected geometry to be given') + throw new Error('expected geometry to be given'); } } if (updateState.updateSize) { // not all geometries have size data, so check here if ('uSize' in renderObject.values) { - createSizes(locationIt, newTheme.size, renderObject.values as SizeData) + createSizes(locationIt, newTheme.size, renderObject.values as SizeData); } } if (updateState.updateColor) { - createColors(locationIt, newTheme.color, renderObject.values) + createColors(locationIt, newTheme.color, renderObject.values); } - updateValues(renderObject.values as RenderObjectValues<G['kind']>, newProps) - updateRenderableState(renderObject.state, newProps) + updateValues(renderObject.values as RenderObjectValues<G['kind']>, newProps); + updateRenderableState(renderObject.state, newProps); } - currentProps = newProps - currentTheme = newTheme - currentStructure = newStructure - if (newGeometry) geometry = newGeometry + currentProps = newProps; + currentTheme = newTheme; + currentStructure = newStructure; + if (newGeometry) geometry = newGeometry; } function lociIsSuperset(loci: Loci) { - if (isEveryLoci(loci)) return true - if (Structure.isLoci(loci) && Structure.areRootsEquivalent(loci.structure, currentStructure)) return true + if (isEveryLoci(loci)) return true; + if (Structure.isLoci(loci) && Structure.areRootsEquivalent(loci.structure, currentStructure)) return true; if (StructureElement.Loci.is(loci) && Structure.areRootsEquivalent(loci.structure, currentStructure)) { - if (StructureElement.Loci.isWholeStructure(loci)) return true + if (StructureElement.Loci.isWholeStructure(loci)) return true; } - return false + return false; } function lociApply(loci: Loci, apply: (interval: Interval) => boolean) { if (lociIsSuperset(loci)) { - return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount)) + return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount)); } else { - return eachLocation(loci, currentStructure, apply) + return eachLocation(loci, currentStructure, apply); } } return { - get groupCount() { return locationIt ? locationIt.count : 0 }, - get renderObject () { return locationIt && locationIt.count ? renderObject : undefined }, + get groupCount() { return locationIt ? locationIt.count : 0; }, + get renderObject () { return locationIt && locationIt.count ? renderObject : undefined; }, createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}, structure?: Structure) { - prepareUpdate(theme, props, structure || currentStructure) + prepareUpdate(theme, props, structure || currentStructure); if (updateState.createGeometry) { - const newGeometry = createGeometry(ctx, newStructure, newTheme, newProps, geometry) - return newGeometry instanceof Promise ? newGeometry.then(update) : update(newGeometry) + const newGeometry = createGeometry(ctx, newStructure, newTheme, newProps, geometry); + return newGeometry instanceof Promise ? newGeometry.then(update) : update(newGeometry); } else { - update() + update(); } }, getLoci(pickingId: PickingId) { - return renderObject ? getLoci(pickingId, currentStructure, renderObject.id) : EmptyLoci + return renderObject ? getLoci(pickingId, currentStructure, renderObject.id) : EmptyLoci; }, mark(loci: Loci, action: MarkerAction) { - return Visual.mark(renderObject, loci, action, lociApply) + return Visual.mark(renderObject, loci, action, lociApply); }, setVisibility(visible: boolean) { - Visual.setVisibility(renderObject, visible) + Visual.setVisibility(renderObject, visible); }, setAlphaFactor(alphaFactor: number) { - Visual.setAlphaFactor(renderObject, alphaFactor) + Visual.setAlphaFactor(renderObject, alphaFactor); }, setPickable(pickable: boolean) { - Visual.setPickable(renderObject, pickable) + Visual.setPickable(renderObject, pickable); }, setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) { - Visual.setTransform(renderObject, matrix, instanceMatrices) + Visual.setTransform(renderObject, matrix, instanceMatrices); }, setOverpaint(overpaint: Overpaint) { - Visual.setOverpaint(renderObject, overpaint, lociApply, true) + Visual.setOverpaint(renderObject, overpaint, lociApply, true); }, setTransparency(transparency: Transparency) { - Visual.setTransparency(renderObject, transparency, lociApply, true) + Visual.setTransparency(renderObject, transparency, lociApply, true); }, destroy() { // TODO - renderObject = undefined + renderObject = undefined; } - } + }; } // mesh -export const ComplexMeshParams = { ...StructureMeshParams, ...StructureParams } +export const ComplexMeshParams = { ...StructureMeshParams, ...StructureParams }; export type ComplexMeshParams = typeof ComplexMeshParams export interface ComplexMeshVisualBuilder<P extends ComplexMeshParams> extends ComplexVisualBuilder<P, Mesh> { } @@ -235,16 +235,16 @@ export function ComplexMeshVisual<P extends ComplexMeshParams>(builder: ComplexM return ComplexVisual<Mesh, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructure: Structure, currentStructure: Structure) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true; }, geometryUtils: Mesh.Utils - }, materialId) + }, materialId); } // text -export const ComplexTextParams = { ...StructureTextParams, ...StructureParams } +export const ComplexTextParams = { ...StructureTextParams, ...StructureParams }; export type ComplexTextParams = typeof ComplexTextParams export interface ComplexTextVisualBuilder<P extends ComplexTextParams> extends ComplexVisualBuilder<P, Text> { } @@ -253,22 +253,22 @@ export function ComplexTextVisual<P extends ComplexTextParams>(builder: ComplexT return ComplexVisual<Text, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructure: Structure, currentStructure: Structure) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true - if (newProps.background !== currentProps.background) state.createGeometry = true - if (newProps.backgroundMargin !== currentProps.backgroundMargin) state.createGeometry = true - if (newProps.tether !== currentProps.tether) state.createGeometry = true - if (newProps.tetherLength !== currentProps.tetherLength) state.createGeometry = true - if (newProps.tetherBaseWidth !== currentProps.tetherBaseWidth) state.createGeometry = true - if (newProps.attachment !== currentProps.attachment) state.createGeometry = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true; + if (newProps.background !== currentProps.background) state.createGeometry = true; + if (newProps.backgroundMargin !== currentProps.backgroundMargin) state.createGeometry = true; + if (newProps.tether !== currentProps.tether) state.createGeometry = true; + if (newProps.tetherLength !== currentProps.tetherLength) state.createGeometry = true; + if (newProps.tetherBaseWidth !== currentProps.tetherBaseWidth) state.createGeometry = true; + if (newProps.attachment !== currentProps.attachment) state.createGeometry = true; }, geometryUtils: Text.Utils - }, materialId) + }, materialId); } // direct-volume -export const ComplexDirectVolumeParams = { ...StructureDirectVolumeParams, ...StructureParams } +export const ComplexDirectVolumeParams = { ...StructureDirectVolumeParams, ...StructureParams }; export type ComplexDirectVolumeParams = typeof ComplexDirectVolumeParams export interface ComplexDirectVolumeVisualBuilder<P extends ComplexDirectVolumeParams> extends ComplexVisualBuilder<P, DirectVolume> { } @@ -277,9 +277,9 @@ export function ComplexDirectVolumeVisual<P extends ComplexDirectVolumeParams>(b return ComplexVisual<DirectVolume, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructure: Structure, currentStructure: Structure) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructure, currentStructure); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true; }, geometryUtils: DirectVolume.Utils - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/params.ts b/src/mol-repr/structure/params.ts index 5f28b6dc5065b642e1a69602cf583cc2d8820a19..d97ca6c46e7490f85f93dd86615c446d21d22f2b 100644 --- a/src/mol-repr/structure/params.ts +++ b/src/mol-repr/structure/params.ts @@ -16,32 +16,32 @@ import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { UnitKind, UnitKindOptions } from './visual/util/common'; export function getUnitKindsParam(defaultValue: UnitKind[]) { - return PD.MultiSelect<UnitKind>(defaultValue, UnitKindOptions, { description: 'For which kinds of units/chains to show the representation visuals.' }) + return PD.MultiSelect<UnitKind>(defaultValue, UnitKindOptions, { description: 'For which kinds of units/chains to show the representation visuals.' }); } export const StructureParams = { unitKinds: getUnitKindsParam(['atomic', 'spheres']), -} +}; export type StructureParams = typeof StructureParams -export const StructureMeshParams = { ...Mesh.Params } +export const StructureMeshParams = { ...Mesh.Params }; export type StructureMeshParams = typeof StructureMeshParams -export const StructureSpheresParams = { ...Spheres.Params } +export const StructureSpheresParams = { ...Spheres.Params }; export type StructureSpheresParams = typeof StructureSpheresParams -export const StructurePointsParams = { ...Points.Params } +export const StructurePointsParams = { ...Points.Params }; export type StructurePointsParams = typeof StructurePointsParams -export const StructureLinesParams = { ...Lines.Params } +export const StructureLinesParams = { ...Lines.Params }; export type StructureLinesParams = typeof StructureLinesParams -export const StructureTextParams = { ...Text.Params } +export const StructureTextParams = { ...Text.Params }; export type StructureTextParams = typeof StructureTextParams -export const StructureDirectVolumeParams = { ...DirectVolume.Params } +export const StructureDirectVolumeParams = { ...DirectVolume.Params }; export type StructureDirectVolumeParams = typeof StructureDirectVolumeParams -export const StructureTextureMeshParams = { ...TextureMesh.Params } +export const StructureTextureMeshParams = { ...TextureMesh.Params }; export type StructureTextureMeshParams = typeof StructureTextureMeshParams \ No newline at end of file diff --git a/src/mol-repr/structure/registry.ts b/src/mol-repr/structure/registry.ts index e64bc74ae07c781f48ba33a6f6a8659a0cf250d1..161e38d34602bd7bd3ad8749aaa137134f640bab 100644 --- a/src/mol-repr/structure/registry.ts +++ b/src/mol-repr/structure/registry.ts @@ -22,11 +22,11 @@ import { SpacefillRepresentationProvider } from './representation/spacefill'; export class StructureRepresentationRegistry extends RepresentationRegistry<Structure, StructureRepresentationState> { constructor() { - super() + super(); objectForEach(StructureRepresentationRegistry.BuiltIn, (p, k) => { if (p.name !== k) throw new Error(`Fix BuiltInStructureRepresentations to have matching names. ${p.name} ${k}`); - this.add(p as any) - }) + this.add(p as any); + }); } } @@ -44,7 +44,7 @@ export namespace StructureRepresentationRegistry { 'point': PointRepresentationProvider, 'putty': PuttyRepresentationProvider, 'spacefill': SpacefillRepresentationProvider, - } + }; type _BuiltIn = typeof BuiltIn export type BuiltIn = keyof _BuiltIn diff --git a/src/mol-repr/structure/representation.ts b/src/mol-repr/structure/representation.ts index de9c35430415e63e04fbff9ae18c685ba9e7c30e..c75278b729f80f9021faa68f75dcc8064893b57f 100644 --- a/src/mol-repr/structure/representation.ts +++ b/src/mol-repr/structure/representation.ts @@ -20,13 +20,13 @@ export const StructureRepresentationStateBuilder: Representation.StateBuilder<St ...Representation.createState(), unitTransforms: null, unitTransformsVersion: -1 - } + }; }, update: (state: StructureRepresentationState, update: Partial<StructureRepresentationState>) => { - Representation.updateState(state, update) - if (update.unitTransforms !== undefined) state.unitTransforms = update.unitTransforms + Representation.updateState(state, update); + if (update.unitTransforms !== undefined) state.unitTransforms = update.unitTransforms; } -} +}; export interface StructureRepresentation<P extends RepresentationProps = {}> extends Representation<Structure, P, StructureRepresentationState> { } diff --git a/src/mol-repr/structure/representation/ball-and-stick.ts b/src/mol-repr/structure/representation/ball-and-stick.ts index f0f345cbed8aebc7508bd649bf8d51993a253aad..9ddd4290611c8603c00f95c443fe0edcca9d9a53 100644 --- a/src/mol-repr/structure/representation/ball-and-stick.ts +++ b/src/mol-repr/structure/representation/ball-and-stick.ts @@ -20,7 +20,7 @@ const BallAndStickVisuals = { 'element-sphere': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementSphereParams>) => UnitsRepresentation('Element sphere mesh', ctx, getParams, getElementSphereVisual(ctx.webgl)), 'intra-bond': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, IntraUnitBondParams>) => UnitsRepresentation('Intra-unit bond cylinder', ctx, getParams, IntraUnitBondVisual), 'inter-bond': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InterUnitBondParams>) => ComplexRepresentation('Inter-unit bond cylinder', ctx, getParams, InterUnitBondVisual), -} +}; export const BallAndStickParams = { ...ElementSphereParams, @@ -30,15 +30,15 @@ export const BallAndStickParams = { sizeFactor: PD.Numeric(0.15, { min: 0.01, max: 10, step: 0.01 }), sizeAspectRatio: PD.Numeric(2 / 3, { min: 0.01, max: 3, step: 0.01 }), visuals: PD.MultiSelect(['element-sphere', 'intra-bond', 'inter-bond'], PD.objectToOptions(BallAndStickVisuals)) -} +}; export type BallAndStickParams = typeof BallAndStickParams export function getBallAndStickParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(BallAndStickParams) + return PD.clone(BallAndStickParams); } export type BallAndStickRepresentation = StructureRepresentation<BallAndStickParams> export function BallAndStickRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, BallAndStickParams>): BallAndStickRepresentation { - return Representation.createMulti('Ball & Stick', ctx, getParams, StructureRepresentationStateBuilder, BallAndStickVisuals as unknown as Representation.Def<Structure, BallAndStickParams>) + return Representation.createMulti('Ball & Stick', ctx, getParams, StructureRepresentationStateBuilder, BallAndStickVisuals as unknown as Representation.Def<Structure, BallAndStickParams>); } export const BallAndStickRepresentationProvider = StructureRepresentationProvider({ @@ -51,4 +51,4 @@ export const BallAndStickRepresentationProvider = StructureRepresentationProvide defaultColorTheme: { name: 'element-symbol' }, defaultSizeTheme: { name: 'physical' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/carbohydrate.ts b/src/mol-repr/structure/representation/carbohydrate.ts index 589d0e9ca30674c82f35457391487976cce1f19e..cc2031e990d33b94ae8f5b05f4c3c2cd1de4bd93 100644 --- a/src/mol-repr/structure/representation/carbohydrate.ts +++ b/src/mol-repr/structure/representation/carbohydrate.ts @@ -18,22 +18,22 @@ const CarbohydrateVisuals = { 'carbohydrate-symbol': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CarbohydrateSymbolParams>) => ComplexRepresentation('Carbohydrate symbol mesh', ctx, getParams, CarbohydrateSymbolVisual), 'carbohydrate-link': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CarbohydrateLinkParams>) => ComplexRepresentation('Carbohydrate link cylinder', ctx, getParams, CarbohydrateLinkVisual), 'carbohydrate-terminal-link': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CarbohydrateTerminalLinkParams>) => ComplexRepresentation('Carbohydrate terminal link cylinder', ctx, getParams, CarbohydrateTerminalLinkVisual), -} +}; export const CarbohydrateParams = { ...CarbohydrateSymbolParams, ...CarbohydrateLinkParams, ...CarbohydrateTerminalLinkParams, visuals: PD.MultiSelect(['carbohydrate-symbol', 'carbohydrate-link', 'carbohydrate-terminal-link'], PD.objectToOptions(CarbohydrateVisuals)), -} +}; export type CarbohydrateParams = typeof CarbohydrateParams export function getCarbohydrateParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(CarbohydrateParams) + return PD.clone(CarbohydrateParams); } export type CarbohydrateRepresentation = StructureRepresentation<CarbohydrateParams> export function CarbohydrateRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CarbohydrateParams>): CarbohydrateRepresentation { - return Representation.createMulti('Carbohydrate', ctx, getParams, StructureRepresentationStateBuilder, CarbohydrateVisuals as unknown as Representation.Def<Structure, CarbohydrateParams>) + return Representation.createMulti('Carbohydrate', ctx, getParams, StructureRepresentationStateBuilder, CarbohydrateVisuals as unknown as Representation.Def<Structure, CarbohydrateParams>); } export const CarbohydrateRepresentationProvider = StructureRepresentationProvider({ @@ -46,6 +46,6 @@ export const CarbohydrateRepresentationProvider = StructureRepresentationProvide defaultColorTheme: { name: 'carbohydrate-symbol' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => { - return structure.models.reduce((a, v) => a + v.properties.saccharideComponentMap.size, 0) > 0 + return structure.models.reduce((a, v) => a + v.properties.saccharideComponentMap.size, 0) > 0; } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/cartoon.ts b/src/mol-repr/structure/representation/cartoon.ts index b271675047305b4c2a398b9c8620109fe24b54a3..856a38ba3c6eaea15f1b14e518761d4045229291 100644 --- a/src/mol-repr/structure/representation/cartoon.ts +++ b/src/mol-repr/structure/representation/cartoon.ts @@ -24,7 +24,7 @@ const CartoonVisuals = { 'nucleotide-block': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, NucleotideBlockParams>) => UnitsRepresentation('Nucleotide block mesh', ctx, getParams, NucleotideBlockVisual), 'nucleotide-ring': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, NucleotideRingParams>) => UnitsRepresentation('Nucleotide ring mesh', ctx, getParams, NucleotideRingVisual), 'direction-wedge': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, PolymerDirectionParams>) => UnitsRepresentation('Polymer direction wedge', ctx, getParams, PolymerDirectionVisual) -} +}; export const CartoonParams = { ...PolymerTraceParams, @@ -34,26 +34,26 @@ export const CartoonParams = { ...PolymerDirectionParams, sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }), visuals: PD.MultiSelect(['polymer-trace', 'polymer-gap', 'nucleotide-block'], PD.objectToOptions(CartoonVisuals)), -} +}; export type CartoonParams = typeof CartoonParams export function getCartoonParams(ctx: ThemeRegistryContext, structure: Structure) { - const params = PD.clone(CartoonParams) - let hasNucleotides = false - let hasGaps = false + const params = PD.clone(CartoonParams); + let hasNucleotides = false; + let hasGaps = false; structure.units.forEach(u => { - if (!hasNucleotides && Unit.isAtomic(u) && u.nucleotideElements.length) hasNucleotides = true - if (!hasGaps && u.gapElements.length) hasGaps = true - }) - params.visuals.defaultValue = ['polymer-trace'] - if (hasNucleotides) params.visuals.defaultValue.push('nucleotide-block') - if (hasGaps) params.visuals.defaultValue.push('polymer-gap') - return params + if (!hasNucleotides && Unit.isAtomic(u) && u.nucleotideElements.length) hasNucleotides = true; + if (!hasGaps && u.gapElements.length) hasGaps = true; + }); + params.visuals.defaultValue = ['polymer-trace']; + if (hasNucleotides) params.visuals.defaultValue.push('nucleotide-block'); + if (hasGaps) params.visuals.defaultValue.push('polymer-gap'); + return params; } export type CartoonRepresentation = StructureRepresentation<CartoonParams> export function CartoonRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, CartoonParams>): CartoonRepresentation { - return Representation.createMulti('Cartoon', ctx, getParams, StructureRepresentationStateBuilder, CartoonVisuals as unknown as Representation.Def<Structure, CartoonParams>) + return Representation.createMulti('Cartoon', ctx, getParams, StructureRepresentationStateBuilder, CartoonVisuals as unknown as Representation.Def<Structure, CartoonParams>); } export const CartoonRepresentationProvider = StructureRepresentationProvider({ @@ -70,4 +70,4 @@ export const CartoonRepresentationProvider = StructureRepresentationProvider({ attach: (ctx: CustomProperty.Context, structure: Structure) => SecondaryStructureProvider.attach(ctx, structure, void 0, true), detach: (data) => SecondaryStructureProvider.ref(data, false) } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/ellipsoid.ts b/src/mol-repr/structure/representation/ellipsoid.ts index 90af41838d2ef6d1be2f46e6bb7a33074bdc16d1..ce346292b729eb9745411eed14fa05bf62d7fb64 100644 --- a/src/mol-repr/structure/representation/ellipsoid.ts +++ b/src/mol-repr/structure/representation/ellipsoid.ts @@ -19,7 +19,7 @@ const EllipsoidVisuals = { 'ellipsoid-mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, EllipsoidMeshParams>) => UnitsRepresentation('Ellipsoid Mesh', ctx, getParams, EllipsoidMeshVisual), 'intra-bond': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, IntraUnitBondParams>) => UnitsRepresentation('Intra-unit bond cylinder', ctx, getParams, IntraUnitBondVisual), 'inter-bond': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, InterUnitBondParams>) => ComplexRepresentation('Inter-unit bond cylinder', ctx, getParams, InterUnitBondVisual), -} +}; export const EllipsoidParams = { ...EllipsoidMeshParams, @@ -30,15 +30,15 @@ export const EllipsoidParams = { sizeAspectRatio: PD.Numeric(0.1, { min: 0.01, max: 3, step: 0.01 }), linkCap: PD.Boolean(true), visuals: PD.MultiSelect(['ellipsoid-mesh', 'intra-bond', 'inter-bond'], PD.objectToOptions(EllipsoidVisuals)), -} +}; export type EllipsoidParams = typeof EllipsoidParams export function getEllipsoidParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(EllipsoidParams) + return PD.clone(EllipsoidParams); } export type EllipsoidRepresentation = StructureRepresentation<EllipsoidParams> export function EllipsoidRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, EllipsoidParams>): EllipsoidRepresentation { - return Representation.createMulti('Ellipsoid', ctx, getParams, StructureRepresentationStateBuilder, EllipsoidVisuals as unknown as Representation.Def<Structure, EllipsoidParams>) + return Representation.createMulti('Ellipsoid', ctx, getParams, StructureRepresentationStateBuilder, EllipsoidVisuals as unknown as Representation.Def<Structure, EllipsoidParams>); } export const EllipsoidRepresentationProvider = StructureRepresentationProvider({ @@ -51,4 +51,4 @@ export const EllipsoidRepresentationProvider = StructureRepresentationProvider({ defaultColorTheme: { name: 'element-symbol' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => structure.elementCount > 0 && structure.models.some(m => AtomSiteAnisotrop.Provider.isApplicable(m)) -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/gaussian-surface.ts b/src/mol-repr/structure/representation/gaussian-surface.ts index b72cb0c4323f6914fd0908c4142d0d01f90f21ea..832eada9db839a522cb5cda812eca4ab8faddb18 100644 --- a/src/mol-repr/structure/representation/gaussian-surface.ts +++ b/src/mol-repr/structure/representation/gaussian-surface.ts @@ -18,21 +18,21 @@ const GaussianSurfaceVisuals = { 'structure-gaussian-surface-mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, StructureGaussianSurfaceMeshParams>) => ComplexRepresentation('Structure-Gaussian surface mesh', ctx, getParams, StructureGaussianSurfaceMeshVisual), 'gaussian-surface-texture-mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, GaussianSurfaceMeshParams>) => UnitsRepresentation('Gaussian surface texture-mesh', ctx, getParams, GaussianSurfaceTextureMeshVisual), 'gaussian-surface-wireframe': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, GaussianWireframeParams>) => UnitsRepresentation('Gaussian surface wireframe', ctx, getParams, GaussianWireframeVisual), -} +}; export const GaussianSurfaceParams = { ...GaussianSurfaceMeshParams, ...GaussianWireframeParams, visuals: PD.MultiSelect(['gaussian-surface-mesh'], PD.objectToOptions(GaussianSurfaceVisuals)), -} +}; export type GaussianSurfaceParams = typeof GaussianSurfaceParams export function getGaussianSurfaceParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(GaussianSurfaceParams) + return PD.clone(GaussianSurfaceParams); } export type GaussianSurfaceRepresentation = StructureRepresentation<GaussianSurfaceParams> export function GaussianSurfaceRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, GaussianSurfaceParams>): GaussianSurfaceRepresentation { - return Representation.createMulti('Gaussian Surface', ctx, getParams, StructureRepresentationStateBuilder, GaussianSurfaceVisuals as unknown as Representation.Def<Structure, GaussianSurfaceParams>) + return Representation.createMulti('Gaussian Surface', ctx, getParams, StructureRepresentationStateBuilder, GaussianSurfaceVisuals as unknown as Representation.Def<Structure, GaussianSurfaceParams>); } export const GaussianSurfaceRepresentationProvider = StructureRepresentationProvider({ @@ -45,4 +45,4 @@ export const GaussianSurfaceRepresentationProvider = StructureRepresentationProv defaultColorTheme: { name: 'polymer-id' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/gaussian-volume.ts b/src/mol-repr/structure/representation/gaussian-volume.ts index 4f66376c01f4e27eeae1e88fcbfe49056c8770e7..dd4d57f3e5ba0a69bf2babce71b0aa33c1bf5f7a 100644 --- a/src/mol-repr/structure/representation/gaussian-volume.ts +++ b/src/mol-repr/structure/representation/gaussian-volume.ts @@ -13,19 +13,19 @@ import { Structure } from '../../../mol-model/structure'; const GaussianVolumeVisuals = { 'gaussian-volume': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, GaussianDensityVolumeParams>) => ComplexRepresentation('Gaussian volume', ctx, getParams, GaussianDensityVolumeVisual) -} +}; export const GaussianVolumeParams = { ...GaussianDensityVolumeParams, -} +}; export type GaussianVolumeParams = typeof GaussianVolumeParams export function getGaussianVolumeParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(GaussianVolumeParams) + return PD.clone(GaussianVolumeParams); } export type GaussianVolumeRepresentation = StructureRepresentation<GaussianVolumeParams> export function GaussianVolumeRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, GaussianVolumeParams>): GaussianVolumeRepresentation { - return Representation.createMulti('Gaussian Volume', ctx, getParams, StructureRepresentationStateBuilder, GaussianVolumeVisuals as unknown as Representation.Def<Structure, GaussianVolumeParams>) + return Representation.createMulti('Gaussian Volume', ctx, getParams, StructureRepresentationStateBuilder, GaussianVolumeVisuals as unknown as Representation.Def<Structure, GaussianVolumeParams>); } export const GaussianVolumeRepresentationProvider = StructureRepresentationProvider({ @@ -38,4 +38,4 @@ export const GaussianVolumeRepresentationProvider = StructureRepresentationProvi defaultColorTheme: { name: 'polymer-id' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/label.ts b/src/mol-repr/structure/representation/label.ts index 68f97b02b0ff747dc903dff01fb0e22b87d078a2..d29d5a32a96a5118e87a1d2299a0f7600b6a83e7 100644 --- a/src/mol-repr/structure/representation/label.ts +++ b/src/mol-repr/structure/representation/label.ts @@ -14,22 +14,22 @@ import { MarkerAction } from '../../../mol-util/marker-action'; const LabelVisuals = { 'label-text': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, LabelTextParams>) => ComplexRepresentation('Label text', ctx, getParams, LabelTextVisual), -} +}; export const LabelParams = { ...LabelTextParams, visuals: PD.MultiSelect(['label-text'], PD.objectToOptions(LabelVisuals)), -} +}; export type LabelParams = typeof LabelParams export function getLabelParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(LabelParams) + return PD.clone(LabelParams); } export type LabelRepresentation = StructureRepresentation<LabelParams> export function LabelRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, LabelParams>): LabelRepresentation { - const repr = Representation.createMulti('Label', ctx, getParams, StructureRepresentationStateBuilder, LabelVisuals as unknown as Representation.Def<Structure, LabelParams>) - repr.setState({ pickable: false, markerActions: MarkerAction.None }) - return repr + const repr = Representation.createMulti('Label', ctx, getParams, StructureRepresentationStateBuilder, LabelVisuals as unknown as Representation.Def<Structure, LabelParams>); + repr.setState({ pickable: false, markerActions: MarkerAction.None }); + return repr; } export const LabelRepresentationProvider = StructureRepresentationProvider({ @@ -42,4 +42,4 @@ export const LabelRepresentationProvider = StructureRepresentationProvider({ defaultColorTheme: { name: 'uniform' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/molecular-surface.ts b/src/mol-repr/structure/representation/molecular-surface.ts index 81e46fd20a69b499b24fe0c60fe7ea2dd3a17298..548006fcfc28b7f321c23ec9be3c747192c593f1 100644 --- a/src/mol-repr/structure/representation/molecular-surface.ts +++ b/src/mol-repr/structure/representation/molecular-surface.ts @@ -16,21 +16,21 @@ import { MolecularSurfaceWireframeParams, MolecularSurfaceWireframeVisual } from const MolecularSurfaceVisuals = { 'molecular-surface-mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, MolecularSurfaceMeshParams>) => UnitsRepresentation('Molecular surface mesh', ctx, getParams, MolecularSurfaceMeshVisual), 'molecular-surface-wireframe': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, MolecularSurfaceWireframeParams>) => UnitsRepresentation('Molecular surface wireframe', ctx, getParams, MolecularSurfaceWireframeVisual), -} +}; export const MolecularSurfaceParams = { ...MolecularSurfaceMeshParams, ...MolecularSurfaceWireframeParams, visuals: PD.MultiSelect(['molecular-surface-mesh'], PD.objectToOptions(MolecularSurfaceVisuals)), -} +}; export type MolecularSurfaceParams = typeof MolecularSurfaceParams export function getMolecularSurfaceParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(MolecularSurfaceParams) + return PD.clone(MolecularSurfaceParams); } export type MolecularSurfaceRepresentation = StructureRepresentation<MolecularSurfaceParams> export function MolecularSurfaceRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, MolecularSurfaceParams>): MolecularSurfaceRepresentation { - return Representation.createMulti('Molecular Surface', ctx, getParams, StructureRepresentationStateBuilder, MolecularSurfaceVisuals as unknown as Representation.Def<Structure, MolecularSurfaceParams>) + return Representation.createMulti('Molecular Surface', ctx, getParams, StructureRepresentationStateBuilder, MolecularSurfaceVisuals as unknown as Representation.Def<Structure, MolecularSurfaceParams>); } export const MolecularSurfaceRepresentationProvider = StructureRepresentationProvider({ @@ -43,4 +43,4 @@ export const MolecularSurfaceRepresentationProvider = StructureRepresentationPro defaultColorTheme: { name: 'polymer-id' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/orientation.ts b/src/mol-repr/structure/representation/orientation.ts index f37d17b653ed0ffbfc27126131dac7023e67ee01..c58b69cf0f1467134d81d9cef713d075dc6b99df 100644 --- a/src/mol-repr/structure/representation/orientation.ts +++ b/src/mol-repr/structure/representation/orientation.ts @@ -14,20 +14,20 @@ import { OrientationEllipsoidMeshParams, OrientationEllipsoidMeshVisual } from ' const OrientationVisuals = { 'orientation-ellipsoid-mesh': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, OrientationEllipsoidMeshParams>) => UnitsRepresentation('Orientation ellipsoid mesh', ctx, getParams, OrientationEllipsoidMeshVisual), -} +}; export const OrientationParams = { ...OrientationEllipsoidMeshParams, visuals: PD.MultiSelect(['orientation-ellipsoid-mesh'], PD.objectToOptions(OrientationVisuals)), -} +}; export type OrientationParams = typeof OrientationParams export function getOrientationParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(OrientationParams) + return PD.clone(OrientationParams); } export type OrientationRepresentation = StructureRepresentation<OrientationParams> export function OrientationRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, OrientationParams>): OrientationRepresentation { - return Representation.createMulti('Orientation', ctx, getParams, StructureRepresentationStateBuilder, OrientationVisuals as unknown as Representation.Def<Structure, OrientationParams>) + return Representation.createMulti('Orientation', ctx, getParams, StructureRepresentationStateBuilder, OrientationVisuals as unknown as Representation.Def<Structure, OrientationParams>); } export const OrientationRepresentationProvider = StructureRepresentationProvider({ @@ -40,4 +40,4 @@ export const OrientationRepresentationProvider = StructureRepresentationProvider defaultColorTheme: { name: 'polymer-id' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/point.ts b/src/mol-repr/structure/representation/point.ts index 5306e287789c4598b471955bd87ef0f96d7d05b3..019d61ca955a7ca1934dc58bebd06cfa797621bd 100644 --- a/src/mol-repr/structure/representation/point.ts +++ b/src/mol-repr/structure/representation/point.ts @@ -14,19 +14,19 @@ import { Structure } from '../../../mol-model/structure'; const PointVisuals = { 'element-point': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementPointParams>) => UnitsRepresentation('Points', ctx, getParams, ElementPointVisual), -} +}; export const PointParams = { ...ElementPointParams, -} +}; export type PointParams = typeof PointParams export function getPointParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(PointParams) + return PD.clone(PointParams); } export type PointRepresentation = StructureRepresentation<PointParams> export function PointRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, PointParams>): PointRepresentation { - return Representation.createMulti('Point', ctx, getParams, StructureRepresentationStateBuilder, PointVisuals as unknown as Representation.Def<Structure, PointParams>) + return Representation.createMulti('Point', ctx, getParams, StructureRepresentationStateBuilder, PointVisuals as unknown as Representation.Def<Structure, PointParams>); } export const PointRepresentationProvider = StructureRepresentationProvider({ @@ -39,4 +39,4 @@ export const PointRepresentationProvider = StructureRepresentationProvider({ defaultColorTheme: { name: 'element-symbol' }, defaultSizeTheme: { name: 'physical' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/putty.ts b/src/mol-repr/structure/representation/putty.ts index 29504744dae1fafab864c0210ebb0281a24de2ad..085afdad5abd10f429132a508cb3570c178bb5bc 100644 --- a/src/mol-repr/structure/representation/putty.ts +++ b/src/mol-repr/structure/representation/putty.ts @@ -16,31 +16,31 @@ import { ThemeRegistryContext } from '../../../mol-theme/theme'; const PuttyVisuals = { 'polymer-tube': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, PolymerTubeParams>) => UnitsRepresentation('Polymer tube mesh', ctx, getParams, PolymerTubeVisual), 'polymer-gap': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, PolymerGapParams>) => UnitsRepresentation('Polymer gap cylinder', ctx, getParams, PolymerGapVisual), -} +}; export const PuttyParams = { ...PolymerTubeParams, ...PolymerGapParams, sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }), visuals: PD.MultiSelect(['polymer-tube', 'polymer-gap'], PD.objectToOptions(PuttyVisuals)), -} +}; export type PuttyParams = typeof PuttyParams export function getPuttyParams(ctx: ThemeRegistryContext, structure: Structure) { - const params = PD.clone(PuttyParams) - let hasNucleotides = false - let hasGaps = false + const params = PD.clone(PuttyParams); + let hasNucleotides = false; + let hasGaps = false; structure.units.forEach(u => { - if (!hasNucleotides && Unit.isAtomic(u) && u.nucleotideElements.length) hasNucleotides = true - if (!hasGaps && u.gapElements.length) hasGaps = true - }) - params.visuals.defaultValue = ['polymer-tube'] - if (hasGaps) params.visuals.defaultValue.push('polymer-gap') - return params + if (!hasNucleotides && Unit.isAtomic(u) && u.nucleotideElements.length) hasNucleotides = true; + if (!hasGaps && u.gapElements.length) hasGaps = true; + }); + params.visuals.defaultValue = ['polymer-tube']; + if (hasGaps) params.visuals.defaultValue.push('polymer-gap'); + return params; } export type PuttyRepresentation = StructureRepresentation<PuttyParams> export function PuttyRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, PuttyParams>): PuttyRepresentation { - return Representation.createMulti('Putty', ctx, getParams, StructureRepresentationStateBuilder, PuttyVisuals as unknown as Representation.Def<Structure, PuttyParams>) + return Representation.createMulti('Putty', ctx, getParams, StructureRepresentationStateBuilder, PuttyVisuals as unknown as Representation.Def<Structure, PuttyParams>); } export const PuttyRepresentationProvider = StructureRepresentationProvider({ @@ -53,4 +53,4 @@ export const PuttyRepresentationProvider = StructureRepresentationProvider({ defaultColorTheme: { name: 'polymer-id' }, defaultSizeTheme: { name: 'uncertainty' }, isApplicable: (structure: Structure) => structure.polymerResidueCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/representation/spacefill.ts b/src/mol-repr/structure/representation/spacefill.ts index 6034e7039a0b8846f65bdb84686733d255170983..0bff452c283b707417c8ea2581e301e4f4b71e54 100644 --- a/src/mol-repr/structure/representation/spacefill.ts +++ b/src/mol-repr/structure/representation/spacefill.ts @@ -14,19 +14,19 @@ import { Structure } from '../../../mol-model/structure'; const SpacefillVisuals = { 'element-sphere': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, ElementSphereParams>) => UnitsRepresentation('Sphere mesh', ctx, getParams, getElementSphereVisual(ctx.webgl)), -} +}; export const SpacefillParams = { ...ElementSphereParams, -} +}; export type SpacefillParams = typeof SpacefillParams export function getSpacefillParams(ctx: ThemeRegistryContext, structure: Structure) { - return PD.clone(SpacefillParams) + return PD.clone(SpacefillParams); } export type SpacefillRepresentation = StructureRepresentation<SpacefillParams> export function SpacefillRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, SpacefillParams>): SpacefillRepresentation { - return Representation.createMulti('Spacefill', ctx, getParams, StructureRepresentationStateBuilder, SpacefillVisuals as unknown as Representation.Def<Structure, SpacefillParams>) + return Representation.createMulti('Spacefill', ctx, getParams, StructureRepresentationStateBuilder, SpacefillVisuals as unknown as Representation.Def<Structure, SpacefillParams>); } export const SpacefillRepresentationProvider = StructureRepresentationProvider({ @@ -39,4 +39,4 @@ export const SpacefillRepresentationProvider = StructureRepresentationProvider({ defaultColorTheme: { name: 'element-symbol' }, defaultSizeTheme: { name: 'physical' }, isApplicable: (structure: Structure) => structure.elementCount > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/structure/units-representation.ts b/src/mol-repr/structure/units-representation.ts index ce5c31d12b68b28d9b3970c1ef567036675892f7..a75b7304739f47c71262124014dda70b82a3bba5 100644 --- a/src/mol-repr/structure/units-representation.ts +++ b/src/mol-repr/structure/units-representation.ts @@ -27,62 +27,62 @@ import { StructureParams } from './params'; export interface UnitsVisual<P extends StructureParams> extends Visual<StructureGroup, P> { } export function UnitsRepresentation<P extends StructureParams>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<Structure, P>, visualCtor: (materialId: number) => UnitsVisual<P>): StructureRepresentation<P> { - let version = 0 - const updated = new Subject<number>() - const materialId = getNextMaterialId() - const renderObjects: GraphicsRenderObject[] = [] - const _state = StructureRepresentationStateBuilder.create() - let visuals = new Map<number, { group: Unit.SymmetryGroup, visual: UnitsVisual<P> }>() + let version = 0; + const updated = new Subject<number>(); + const materialId = getNextMaterialId(); + const renderObjects: GraphicsRenderObject[] = []; + const _state = StructureRepresentationStateBuilder.create(); + let visuals = new Map<number, { group: Unit.SymmetryGroup, visual: UnitsVisual<P> }>(); - let _structure: Structure - let _groups: ReadonlyArray<Unit.SymmetryGroup> - let _params: P - let _props: PD.Values<P> - let _theme = Theme.createEmpty() + let _structure: Structure; + let _groups: ReadonlyArray<Unit.SymmetryGroup>; + let _params: P; + let _props: PD.Values<P>; + let _theme = Theme.createEmpty(); function createOrUpdate(props: Partial<PD.Values<P>> = {}, structure?: Structure) { if (structure && structure !== _structure) { - _params = getParams(ctx, structure) - if (!_props) _props = PD.getDefaultValues(_params) + _params = getParams(ctx, structure); + if (!_props) _props = PD.getDefaultValues(_params); } - _props = Object.assign({}, _props, props) + _props = Object.assign({}, _props, props); return Task.create('Creating or updating UnitsRepresentation', async runtime => { if (!_structure && !structure) { - throw new Error('missing structure') + throw new Error('missing structure'); } else if (structure && !_structure) { // console.log(label, 'initial structure') // First call with a structure, create visuals for each group. _groups = structure.unitSymmetryGroups; for (let i = 0; i < _groups.length; i++) { const group = _groups[i]; - const visual = visualCtor(materialId) - const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }) - if (promise) await promise + const visual = visualCtor(materialId); + const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }); + if (promise) await promise; // ensure state is current for new visual - setVisualState(visual, group, _state) - visuals.set(group.hashCode, { visual, group }) - if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length }) + setVisualState(visual, group, _state); + visuals.set(group.hashCode, { visual, group }); + if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length }); } } else if (structure && !Structure.areEquivalent(structure, _structure)) { // Tries to re-use existing visuals for the groups of the new structure. // Creates additional visuals if needed, destroys left-over visuals. _groups = structure.unitSymmetryGroups; // const newGroups: Unit.SymmetryGroup[] = [] - const oldVisuals = visuals - visuals = new Map() + const oldVisuals = visuals; + visuals = new Map(); for (let i = 0; i < _groups.length; i++) { const group = _groups[i]; - const visualGroup = oldVisuals.get(group.hashCode) + const visualGroup = oldVisuals.get(group.hashCode); if (visualGroup) { // console.log(label, 'found visualGroup to reuse') // console.log('old', visualGroup.group) // console.log('new', group) - const { visual } = visualGroup - const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }) - if (promise) await promise - visuals.set(group.hashCode, { visual, group }) - oldVisuals.delete(group.hashCode) + const { visual } = visualGroup; + const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }); + if (promise) await promise; + visuals.set(group.hashCode, { visual, group }); + oldVisuals.delete(group.hashCode); // Remove highlight // TODO: remove selection too?? @@ -93,19 +93,19 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct } else { // console.log(label, 'did not find visualGroup to reuse, creating new') // newGroups.push(group) - const visual = visualCtor(materialId) - const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }) - if (promise) await promise + const visual = visualCtor(materialId); + const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }); + if (promise) await promise; // ensure state is current for new visual - setVisualState(visual, group, _state) - visuals.set(group.hashCode, { visual, group }) + setVisualState(visual, group, _state); + visuals.set(group.hashCode, { visual, group }); } - if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length }) + if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length }); } oldVisuals.forEach(({ visual }) => { // console.log(label, 'removed unused visual') - visual.destroy() - }) + visual.destroy(); + }); // TODO review logic // For new groups, re-use left-over visuals @@ -127,141 +127,141 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct // console.log('old', _structure.unitSymmetryGroups) for (let i = 0; i < _groups.length; i++) { const group = _groups[i]; - const visualGroup = visuals.get(group.hashCode) + const visualGroup = visuals.get(group.hashCode); if (visualGroup) { - const promise = visualGroup.visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }) - if (promise) await promise - visualGroup.group = group + const promise = visualGroup.visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, { group, structure }); + if (promise) await promise; + visualGroup.group = group; } else { - throw new Error(`expected to find visual for hashCode ${group.hashCode}`) + throw new Error(`expected to find visual for hashCode ${group.hashCode}`); } - if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length }) + if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: _groups.length }); } } else { // console.log(label, 'no new structure') // No new structure given, just update all visuals with new props. - const visualsList: [ UnitsVisual<P>, Unit.SymmetryGroup ][] = [] // TODO avoid allocation - visuals.forEach(({ visual, group }) => visualsList.push([ visual, group ])) + const visualsList: [ UnitsVisual<P>, Unit.SymmetryGroup ][] = []; // TODO avoid allocation + visuals.forEach(({ visual, group }) => visualsList.push([ visual, group ])); for (let i = 0, il = visualsList.length; i < il; ++i) { - const [ visual ] = visualsList[i] - const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props) - if (promise) await promise - if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: il }) + const [ visual ] = visualsList[i]; + const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props); + if (promise) await promise; + if (runtime.shouldUpdate) await runtime.update({ message: 'Creating or updating UnitsVisual', current: i, max: il }); } } // update list of renderObjects - renderObjects.length = 0 + renderObjects.length = 0; visuals.forEach(({ visual }) => { - if (visual.renderObject) renderObjects.push(visual.renderObject) - }) + if (visual.renderObject) renderObjects.push(visual.renderObject); + }); // set new structure - if (structure) _structure = structure + if (structure) _structure = structure; // increment version - updated.next(version++) + updated.next(version++); }); } function getLoci(pickingId?: PickingId) { - if (pickingId === undefined) return Structure.Loci(_structure) - let loci: Loci = EmptyLoci + if (pickingId === undefined) return Structure.Loci(_structure); + let loci: Loci = EmptyLoci; visuals.forEach(({ visual }) => { - const _loci = visual.getLoci(pickingId) - if (!isEmptyLoci(_loci)) loci = _loci - }) - return loci + const _loci = visual.getLoci(pickingId); + if (!isEmptyLoci(_loci)) loci = _loci; + }); + return loci; } function mark(loci: Loci, action: MarkerAction) { - if (!_structure) return false - if (!MarkerActions.is(_state.markerActions, action)) return false + if (!_structure) return false; + if (!MarkerActions.is(_state.markerActions, action)) return false; if (Structure.isLoci(loci) || StructureElement.Loci.is(loci) || Bond.isLoci(loci)) { - if (!Structure.areRootsEquivalent(loci.structure, _structure)) return false + if (!Structure.areRootsEquivalent(loci.structure, _structure)) return false; // Remap `loci` from equivalent structure to the current `_structure` - loci = Loci.remap(loci, _structure) + loci = Loci.remap(loci, _structure); } else if (!isEveryLoci(loci) && !isDataLoci(loci)) { - return false + return false; } - if (Loci.isEmpty(loci)) return false + if (Loci.isEmpty(loci)) return false; - let changed = false + let changed = false; visuals.forEach(({ visual }) => { - changed = visual.mark(loci, action) || changed - }) - return changed + changed = visual.mark(loci, action) || changed; + }); + return changed; } function setVisualState(visual: UnitsVisual<P>, group: Unit.SymmetryGroup, state: Partial<StructureRepresentationState>) { - const { visible, alphaFactor, pickable, overpaint, transparency, transform, unitTransforms } = state + const { visible, alphaFactor, pickable, overpaint, transparency, transform, unitTransforms } = state; - if (visible !== undefined) visual.setVisibility(visible) - if (alphaFactor !== undefined) visual.setAlphaFactor(alphaFactor) - if (pickable !== undefined) visual.setPickable(pickable) - if (overpaint !== undefined) visual.setOverpaint(overpaint) - if (transparency !== undefined) visual.setTransparency(transparency) - if (transform !== undefined) visual.setTransform(transform) + if (visible !== undefined) visual.setVisibility(visible); + if (alphaFactor !== undefined) visual.setAlphaFactor(alphaFactor); + if (pickable !== undefined) visual.setPickable(pickable); + if (overpaint !== undefined) visual.setOverpaint(overpaint); + if (transparency !== undefined) visual.setTransparency(transparency); + if (transform !== undefined) visual.setTransform(transform); if (unitTransforms !== undefined) { if (unitTransforms) { // console.log(group.hashCode, unitTransforms.getSymmetryGroupTransforms(group)) - visual.setTransform(undefined, unitTransforms.getSymmetryGroupTransforms(group)) + visual.setTransform(undefined, unitTransforms.getSymmetryGroupTransforms(group)); } else { - visual.setTransform(undefined, null) + visual.setTransform(undefined, null); } } } function setState(state: Partial<StructureRepresentationState>) { - const { visible, alphaFactor, pickable, overpaint, transparency, transform, unitTransforms, syncManually, markerActions } = state - const newState: Partial<StructureRepresentationState> = {} + const { visible, alphaFactor, pickable, overpaint, transparency, transform, unitTransforms, syncManually, markerActions } = state; + const newState: Partial<StructureRepresentationState> = {}; - if (visible !== _state.visible) newState.visible = visible - if (alphaFactor !== _state.alphaFactor) newState.alphaFactor = alphaFactor - if (pickable !== _state.pickable) newState.pickable = pickable + if (visible !== _state.visible) newState.visible = visible; + if (alphaFactor !== _state.alphaFactor) newState.alphaFactor = alphaFactor; + if (pickable !== _state.pickable) newState.pickable = pickable; if (overpaint !== undefined && !Overpaint.areEqual(overpaint, _state.overpaint)) { if (_structure) { - newState.overpaint = Overpaint.remap(overpaint, _structure) + newState.overpaint = Overpaint.remap(overpaint, _structure); } } if (transparency !== undefined && !Transparency.areEqual(transparency, _state.transparency)) { - newState.transparency = transparency + newState.transparency = transparency; } if (transform !== undefined && !Mat4.areEqual(transform, _state.transform, EPSILON)) { - newState.transform = transform + newState.transform = transform; } if (unitTransforms !== _state.unitTransforms || unitTransforms?.version !== state.unitTransformsVersion) { - newState.unitTransforms = unitTransforms - _state.unitTransformsVersion = unitTransforms ? unitTransforms?.version : -1 + newState.unitTransforms = unitTransforms; + _state.unitTransformsVersion = unitTransforms ? unitTransforms?.version : -1; } - if (syncManually !== _state.syncManually) newState.syncManually = syncManually - if (markerActions !== _state.markerActions) newState.markerActions = markerActions + if (syncManually !== _state.syncManually) newState.syncManually = syncManually; + if (markerActions !== _state.markerActions) newState.markerActions = markerActions; - visuals.forEach(({ visual, group }) => setVisualState(visual, group, newState)) + visuals.forEach(({ visual, group }) => setVisualState(visual, group, newState)); - StructureRepresentationStateBuilder.update(_state, newState) + StructureRepresentationStateBuilder.update(_state, newState); } function setTheme(theme: Theme) { - _theme = theme + _theme = theme; } function destroy() { - visuals.forEach(({ visual }) => visual.destroy()) - visuals.clear() + visuals.forEach(({ visual }) => visual.destroy()); + visuals.clear(); } return { label, get groupCount() { - let groupCount = 0 + let groupCount = 0; visuals.forEach(({ visual }) => { - if (visual.renderObject) groupCount += visual.groupCount - }) - return groupCount + if (visual.renderObject) groupCount += visual.groupCount; + }); + return groupCount; }, - get props() { return _props }, - get params() { return _params }, - get state() { return _state }, - get theme() { return _theme }, + get props() { return _props; }, + get params() { return _params; }, + get state() { return _state; }, + get theme() { return _theme; }, renderObjects, updated, createOrUpdate, @@ -270,5 +270,5 @@ export function UnitsRepresentation<P extends StructureParams>(label: string, ct getLoci, mark, destroy - } + }; } \ No newline at end of file diff --git a/src/mol-repr/structure/units-visual.ts b/src/mol-repr/structure/units-visual.ts index 61ea73795335d4c1fbcb2525caa54039ddf9e211..1b24edab18a79c6c70050d455d460b069f803eea 100644 --- a/src/mol-repr/structure/units-visual.ts +++ b/src/mol-repr/structure/units-visual.ts @@ -42,11 +42,11 @@ export type StructureGroup = { structure: Structure, group: Unit.SymmetryGroup } export interface UnitsVisual<P extends RepresentationProps = {}> extends Visual<StructureGroup, P> { } function createUnitsRenderObject<G extends Geometry>(group: Unit.SymmetryGroup, geometry: G, locationIt: LocationIterator, theme: Theme, props: PD.Values<Geometry.Params<G>>, materialId: number) { - const { createValues, createRenderableState } = Geometry.getUtils(geometry) - const transform = createUnitsTransform(group) - const values = createValues(geometry, transform, locationIt, theme, props) - const state = createRenderableState(props) - return createRenderObject(geometry.kind, values, state, materialId) + const { createValues, createRenderableState } = Geometry.getUtils(geometry); + const transform = createUnitsTransform(group); + const values = createValues(geometry, transform, locationIt, theme, props); + const state = createRenderableState(props); + return createRenderObject(geometry.kind, values, state, materialId); } interface UnitsVisualBuilder<P extends StructureParams, G extends Geometry> { @@ -63,221 +63,221 @@ interface UnitsVisualGeometryBuilder<P extends StructureParams, G extends Geomet } export function UnitsVisual<G extends Geometry, P extends StructureParams & Geometry.Params<G>>(builder: UnitsVisualGeometryBuilder<P, G>, materialId: number): UnitsVisual<P> { - const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState } = builder - const { createEmpty: createEmptyGeometry, updateValues, updateBoundingSphere, updateRenderableState } = builder.geometryUtils - const updateState = VisualUpdateState.create() + const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState } = builder; + const { createEmpty: createEmptyGeometry, updateValues, updateBoundingSphere, updateRenderableState } = builder.geometryUtils; + const updateState = VisualUpdateState.create(); - let renderObject: GraphicsRenderObject<G['kind']> | undefined + let renderObject: GraphicsRenderObject<G['kind']> | undefined; - let newProps: PD.Values<P> = Object.assign({}, defaultProps) - let newTheme: Theme = Theme.createEmpty() - let newStructureGroup: StructureGroup + let newProps: PD.Values<P> = Object.assign({}, defaultProps); + let newTheme: Theme = Theme.createEmpty(); + let newStructureGroup: StructureGroup; - let currentProps: PD.Values<P> - let currentTheme: Theme - let currentStructureGroup: StructureGroup + let currentProps: PD.Values<P>; + let currentTheme: Theme; + let currentStructureGroup: StructureGroup; - let geometry: G - let locationIt: LocationIterator + let geometry: G; + let locationIt: LocationIterator; function prepareUpdate(theme: Theme, props: Partial<PD.Values<P>> = {}, structureGroup: StructureGroup) { if (!structureGroup && !currentStructureGroup) { - throw new Error('missing structureGroup') + throw new Error('missing structureGroup'); } - newProps = Object.assign({}, currentProps, props) - newTheme = theme - newStructureGroup = structureGroup + newProps = Object.assign({}, currentProps, props); + newTheme = theme; + newStructureGroup = structureGroup; - VisualUpdateState.reset(updateState) + VisualUpdateState.reset(updateState); if (!renderObject) { - updateState.createNew = true + updateState.createNew = true; } else if (!currentStructureGroup || !Unit.SymmetryGroup.areInvariantElementsEqual(newStructureGroup.group, currentStructureGroup.group)) { - updateState.createNew = true + updateState.createNew = true; } if (updateState.createNew) { - updateState.createGeometry = true - return + updateState.createGeometry = true; + return; } - setUpdateState(updateState, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) + setUpdateState(updateState, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); if (!ColorTheme.areEqual(newTheme.color, currentTheme.color)) { // console.log('new colorTheme') - updateState.updateColor = true + updateState.updateColor = true; } if (!deepEqual(newProps.unitKinds, currentProps.unitKinds)) { // console.log('new unitKinds') - updateState.createGeometry = true + updateState.createGeometry = true; } if (newStructureGroup.group.transformHash !== currentStructureGroup.group.transformHash) { // console.log('new transformHash') if (newStructureGroup.group.units.length !== currentStructureGroup.group.units.length || updateState.updateColor) { - updateState.updateTransform = true + updateState.updateTransform = true; } else { - updateState.updateMatrix = true + updateState.updateMatrix = true; } } // check if the conformation of unit.model has changed - const newUnit = newStructureGroup.group.units[0] - const currentUnit = currentStructureGroup.group.units[0] + const newUnit = newStructureGroup.group.units[0]; + const currentUnit = currentStructureGroup.group.units[0]; // if (Unit.conformationId(newUnit) !== Unit.conformationId(currentUnit)) { if (Unit.conformationId(newUnit) !== Unit.conformationId(currentUnit) // TODO: this needs more attention || newUnit.conformation !== currentUnit.conformation) { // console.log('new conformation') updateState.updateTransform = true; - updateState.createGeometry = true + updateState.createGeometry = true; } if (updateState.updateTransform) { - updateState.updateColor = true - updateState.updateSize = true - updateState.updateMatrix = true + updateState.updateColor = true; + updateState.updateSize = true; + updateState.updateMatrix = true; } if (updateState.createGeometry) { - updateState.updateColor = true - updateState.updateSize = true + updateState.updateColor = true; + updateState.updateSize = true; } } function update(newGeometry?: G) { if (updateState.createNew) { - locationIt = createLocationIterator(newStructureGroup) + locationIt = createLocationIterator(newStructureGroup); if (newGeometry) { - renderObject = createUnitsRenderObject(newStructureGroup.group, newGeometry, locationIt, newTheme, newProps, materialId) + renderObject = createUnitsRenderObject(newStructureGroup.group, newGeometry, locationIt, newTheme, newProps, materialId); } else { - throw new Error('expected geometry to be given') + throw new Error('expected geometry to be given'); } } else { if (!renderObject) { - throw new Error('expected renderObject to be available') + throw new Error('expected renderObject to be available'); } if (updateState.updateTransform) { // console.log('update transform') - locationIt = createLocationIterator(newStructureGroup) - const { instanceCount, groupCount } = locationIt - createMarkers(instanceCount * groupCount, renderObject.values) + locationIt = createLocationIterator(newStructureGroup); + const { instanceCount, groupCount } = locationIt; + createMarkers(instanceCount * groupCount, renderObject.values); } if (updateState.updateMatrix) { // console.log('update matrix') - createUnitsTransform(newStructureGroup.group, renderObject.values) + createUnitsTransform(newStructureGroup.group, renderObject.values); } if (updateState.createGeometry) { // console.log('update geometry') if (newGeometry) { - ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(newGeometry)) + ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(newGeometry)); } else { - throw new Error('expected geometry to be given') + throw new Error('expected geometry to be given'); } } if (updateState.updateTransform || updateState.createGeometry) { // console.log('UnitsVisual.updateBoundingSphere') - updateBoundingSphere(renderObject.values as RenderObjectValues<G['kind']>, newGeometry || geometry) + updateBoundingSphere(renderObject.values as RenderObjectValues<G['kind']>, newGeometry || geometry); } if (updateState.updateSize) { // not all geometries have size data, so check here if ('uSize' in renderObject.values) { // console.log('update size') - createSizes(locationIt, newTheme.size, renderObject.values as SizeValues) + createSizes(locationIt, newTheme.size, renderObject.values as SizeValues); } } if (updateState.updateColor) { // console.log('update color') - createColors(locationIt, newTheme.color, renderObject.values) + createColors(locationIt, newTheme.color, renderObject.values); } - updateValues(renderObject.values as RenderObjectValues<G['kind']>, newProps) - updateRenderableState(renderObject.state, newProps) + updateValues(renderObject.values as RenderObjectValues<G['kind']>, newProps); + updateRenderableState(renderObject.state, newProps); } - currentProps = newProps - currentTheme = newTheme - currentStructureGroup = newStructureGroup - if (newGeometry) geometry = newGeometry + currentProps = newProps; + currentTheme = newTheme; + currentStructureGroup = newStructureGroup; + if (newGeometry) geometry = newGeometry; } function _createGeometry(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<P>, geometry?: G) { return includesUnitKind(props.unitKinds, unit) ? createGeometry(ctx, unit, structure, theme, props, geometry) - : createEmptyGeometry(geometry) + : createEmptyGeometry(geometry); } function lociIsSuperset(loci: Loci) { - if (isEveryLoci(loci)) return true - if (Structure.isLoci(loci) && Structure.areRootsEquivalent(loci.structure, currentStructureGroup.structure)) return true + if (isEveryLoci(loci)) return true; + if (Structure.isLoci(loci) && Structure.areRootsEquivalent(loci.structure, currentStructureGroup.structure)) return true; if (StructureElement.Loci.is(loci) && Structure.areRootsEquivalent(loci.structure, currentStructureGroup.structure)) { - if (StructureElement.Loci.isWholeStructure(loci)) return true + if (StructureElement.Loci.isWholeStructure(loci)) return true; } - return false + return false; } function lociApply(loci: Loci, apply: (interval: Interval) => boolean) { if (lociIsSuperset(loci)) { - return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount)) + return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount)); } else { - return eachLocation(loci, currentStructureGroup, apply) + return eachLocation(loci, currentStructureGroup, apply); } } return { - get groupCount() { return locationIt ? locationIt.count : 0 }, - get renderObject () { return locationIt && locationIt.count ? renderObject : undefined }, + get groupCount() { return locationIt ? locationIt.count : 0; }, + get renderObject () { return locationIt && locationIt.count ? renderObject : undefined; }, createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}, structureGroup?: StructureGroup) { - prepareUpdate(theme, props, structureGroup || currentStructureGroup) + prepareUpdate(theme, props, structureGroup || currentStructureGroup); if (updateState.createGeometry) { - const newGeometry = _createGeometry(ctx, newStructureGroup.group.units[0], newStructureGroup.structure, newTheme, newProps, geometry) - return newGeometry instanceof Promise ? newGeometry.then(update) : update(newGeometry as G) + const newGeometry = _createGeometry(ctx, newStructureGroup.group.units[0], newStructureGroup.structure, newTheme, newProps, geometry); + return newGeometry instanceof Promise ? newGeometry.then(update) : update(newGeometry as G); } else { - update() + update(); } }, getLoci(pickingId: PickingId) { - return renderObject ? getLoci(pickingId, currentStructureGroup, renderObject.id) : EmptyLoci + return renderObject ? getLoci(pickingId, currentStructureGroup, renderObject.id) : EmptyLoci; }, mark(loci: Loci, action: MarkerAction) { - return Visual.mark(renderObject, loci, action, lociApply) + return Visual.mark(renderObject, loci, action, lociApply); }, setVisibility(visible: boolean) { - Visual.setVisibility(renderObject, visible) + Visual.setVisibility(renderObject, visible); }, setAlphaFactor(alphaFactor: number) { - Visual.setAlphaFactor(renderObject, alphaFactor) + Visual.setAlphaFactor(renderObject, alphaFactor); }, setPickable(pickable: boolean) { - Visual.setPickable(renderObject, pickable) + Visual.setPickable(renderObject, pickable); }, setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) { - Visual.setTransform(renderObject, matrix, instanceMatrices) + Visual.setTransform(renderObject, matrix, instanceMatrices); }, setOverpaint(overpaint: Overpaint) { - Visual.setOverpaint(renderObject, overpaint, lociApply, true) + Visual.setOverpaint(renderObject, overpaint, lociApply, true); }, setTransparency(transparency: Transparency) { - Visual.setTransparency(renderObject, transparency, lociApply, true) + Visual.setTransparency(renderObject, transparency, lociApply, true); }, destroy() { // TODO - renderObject = undefined + renderObject = undefined; } - } + }; } // mesh -export const UnitsMeshParams = { ...StructureMeshParams, ...StructureParams } +export const UnitsMeshParams = { ...StructureMeshParams, ...StructureParams }; export type UnitsMeshParams = typeof UnitsMeshParams export interface UnitsMeshVisualBuilder<P extends UnitsMeshParams> extends UnitsVisualBuilder<P, Mesh> { } @@ -285,16 +285,16 @@ export function UnitsMeshVisual<P extends UnitsMeshParams>(builder: UnitsMeshVis return UnitsVisual<Mesh, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true; }, geometryUtils: Mesh.Utils - }, materialId) + }, materialId); } // spheres -export const UnitsSpheresParams = { ...StructureSpheresParams, ...StructureParams } +export const UnitsSpheresParams = { ...StructureSpheresParams, ...StructureParams }; export type UnitsSpheresParams = typeof UnitsSpheresParams export interface UnitsSpheresVisualBuilder<P extends UnitsSpheresParams> extends UnitsVisualBuilder<P, Spheres> { } @@ -302,16 +302,16 @@ export function UnitsSpheresVisual<P extends UnitsSpheresParams>(builder: UnitsS return UnitsVisual<Spheres, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true; }, geometryUtils: Spheres.Utils - }, materialId) + }, materialId); } // points -export const UnitsPointsParams = { ...StructurePointsParams, ...StructureParams } +export const UnitsPointsParams = { ...StructurePointsParams, ...StructureParams }; export type UnitsPointsParams = typeof UnitsPointsParams export interface UnitsPointVisualBuilder<P extends UnitsPointsParams> extends UnitsVisualBuilder<P, Points> { } @@ -319,16 +319,16 @@ export function UnitsPointsVisual<P extends UnitsPointsParams>(builder: UnitsPoi return UnitsVisual<Points, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true; }, geometryUtils: Points.Utils - }, materialId) + }, materialId); } // lines -export const UnitsLinesParams = { ...StructureLinesParams, ...StructureParams } +export const UnitsLinesParams = { ...StructureLinesParams, ...StructureParams }; export type UnitsLinesParams = typeof UnitsLinesParams export interface UnitsLinesVisualBuilder<P extends UnitsLinesParams> extends UnitsVisualBuilder<P, Lines> { } @@ -336,16 +336,16 @@ export function UnitsLinesVisual<P extends UnitsLinesParams>(builder: UnitsLines return UnitsVisual<Lines, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true; }, geometryUtils: Lines.Utils - }, materialId) + }, materialId); } // text -export const UnitsTextParams = { ...StructureTextParams, ...StructureParams } +export const UnitsTextParams = { ...StructureTextParams, ...StructureParams }; export type UnitsTextParams = typeof UnitsTextParams export interface UnitsTextVisualBuilder<P extends UnitsTextParams> extends UnitsVisualBuilder<P, Text> { } @@ -353,22 +353,22 @@ export function UnitsTextVisual<P extends UnitsTextParams>(builder: UnitsTextVis return UnitsVisual<Text, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true - if (newProps.background !== currentProps.background) state.createGeometry = true - if (newProps.backgroundMargin !== currentProps.backgroundMargin) state.createGeometry = true - if (newProps.tether !== currentProps.tether) state.createGeometry = true - if (newProps.tetherLength !== currentProps.tetherLength) state.createGeometry = true - if (newProps.tetherBaseWidth !== currentProps.tetherBaseWidth) state.createGeometry = true - if (newProps.attachment !== currentProps.attachment) state.createGeometry = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.updateSize = true; + if (newProps.background !== currentProps.background) state.createGeometry = true; + if (newProps.backgroundMargin !== currentProps.backgroundMargin) state.createGeometry = true; + if (newProps.tether !== currentProps.tether) state.createGeometry = true; + if (newProps.tetherLength !== currentProps.tetherLength) state.createGeometry = true; + if (newProps.tetherBaseWidth !== currentProps.tetherBaseWidth) state.createGeometry = true; + if (newProps.attachment !== currentProps.attachment) state.createGeometry = true; }, geometryUtils: Text.Utils - }, materialId) + }, materialId); } // direct-volume -export const UnitsDirectVolumeParams = { ...StructureDirectVolumeParams, ...StructureParams } +export const UnitsDirectVolumeParams = { ...StructureDirectVolumeParams, ...StructureParams }; export type UnitsDirectVolumeParams = typeof UnitsDirectVolumeParams export interface UnitsDirectVolumeVisualBuilder<P extends UnitsDirectVolumeParams> extends UnitsVisualBuilder<P, DirectVolume> { } @@ -376,16 +376,16 @@ export function UnitsDirectVolumeVisual<P extends UnitsDirectVolumeParams>(build return UnitsVisual<DirectVolume, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true; }, geometryUtils: DirectVolume.Utils - }, materialId) + }, materialId); } // texture-mesh -export const UnitsTextureMeshParams = { ...StructureTextureMeshParams, ...StructureParams } +export const UnitsTextureMeshParams = { ...StructureTextureMeshParams, ...StructureParams }; export type UnitsTextureMeshParams = typeof UnitsTextureMeshParams export interface UnitsTextureMeshVisualBuilder<P extends UnitsTextureMeshParams> extends UnitsVisualBuilder<P, TextureMesh> { } @@ -393,9 +393,9 @@ export function UnitsTextureMeshVisual<P extends UnitsTextureMeshParams>(builder return UnitsVisual<TextureMesh, P>({ ...builder, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<P>, currentProps: PD.Values<P>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => { - builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup) - if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true + builder.setUpdateState(state, newProps, currentProps, newTheme, currentTheme, newStructureGroup, currentStructureGroup); + if (!SizeTheme.areEqual(newTheme.size, currentTheme.size)) state.createGeometry = true; }, geometryUtils: TextureMesh.Utils - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts b/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts index 32897cb6c1fa82d19ece83099f6cc24a0702bd00..99ef4d842b032601f44fa557d7bb57cc446c16ad 100644 --- a/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts +++ b/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts @@ -21,88 +21,88 @@ import { isHydrogen } from './util/common'; import { BondType } from '../../../mol-model/structure/model/types'; import { ignoreBondType, BondCylinderParams, BondIterator } from './util/bond'; -const tmpRefPosBondIt = new Bond.ElementBondIterator() +const tmpRefPosBondIt = new Bond.ElementBondIterator(); function setRefPosition(pos: Vec3, structure: Structure, unit: Unit.Atomic, index: StructureElement.UnitIndex) { - tmpRefPosBondIt.setElement(structure, unit, index) + tmpRefPosBondIt.setElement(structure, unit, index); while (tmpRefPosBondIt.hasNext) { - const bA = tmpRefPosBondIt.move() - bA.otherUnit.conformation.position(bA.otherUnit.elements[bA.otherIndex], pos) - return pos + const bA = tmpRefPosBondIt.move(); + bA.otherUnit.conformation.position(bA.otherUnit.elements[bA.otherIndex], pos); + return pos; } - return null + return null; } -const tmpRef = Vec3() -const tmpLoc = StructureElement.Location.create(void 0) +const tmpRef = Vec3(); +const tmpLoc = StructureElement.Location.create(void 0); function createInterUnitBondCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<InterUnitBondParams>, mesh?: Mesh) { - const bonds = structure.interUnitBonds - const { edgeCount, edges } = bonds - const { sizeFactor, sizeAspectRatio, ignoreHydrogens, includeTypes, excludeTypes } = props + const bonds = structure.interUnitBonds; + const { edgeCount, edges } = bonds; + const { sizeFactor, sizeAspectRatio, ignoreHydrogens, includeTypes, excludeTypes } = props; - const include = BondType.fromNames(includeTypes) - const exclude = BondType.fromNames(excludeTypes) + const include = BondType.fromNames(includeTypes); + const exclude = BondType.fromNames(excludeTypes); const ignoreHydrogen = ignoreHydrogens ? (edgeIndex: number) => { - const b = edges[edgeIndex] - const uA = b.unitA, uB = b.unitB - return isHydrogen(uA, uA.elements[b.indexA]) || isHydrogen(uB, uB.elements[b.indexB]) - } : () => false + const b = edges[edgeIndex]; + const uA = b.unitA, uB = b.unitB; + return isHydrogen(uA, uA.elements[b.indexA]) || isHydrogen(uB, uB.elements[b.indexB]); + } : () => false; - if (!edgeCount) return Mesh.createEmpty(mesh) + if (!edgeCount) return Mesh.createEmpty(mesh); const builderProps = { linkCount: edgeCount, referencePosition: (edgeIndex: number) => { - const b = edges[edgeIndex] - let unitA: Unit, unitB: Unit - let indexA: StructureElement.UnitIndex, indexB: StructureElement.UnitIndex + const b = edges[edgeIndex]; + let unitA: Unit, unitB: Unit; + let indexA: StructureElement.UnitIndex, indexB: StructureElement.UnitIndex; if (b.unitA.id < b.unitB.id) { - unitA = b.unitA, unitB = b.unitB - indexA = b.indexA, indexB = b.indexB + unitA = b.unitA, unitB = b.unitB; + indexA = b.indexA, indexB = b.indexB; } else if (b.unitA.id > b.unitB.id) { - unitA = b.unitB, unitB = b.unitA - indexA = b.indexB, indexB = b.indexA + unitA = b.unitB, unitB = b.unitA; + indexA = b.indexB, indexB = b.indexA; } else { - throw new Error('same units in createInterUnitBondCylinderMesh') + throw new Error('same units in createInterUnitBondCylinderMesh'); } - return setRefPosition(tmpRef, structure, unitA, indexA) || setRefPosition(tmpRef, structure, unitB, indexB) + return setRefPosition(tmpRef, structure, unitA, indexA) || setRefPosition(tmpRef, structure, unitB, indexB); }, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - const b = edges[edgeIndex] - const uA = b.unitA, uB = b.unitB - uA.conformation.position(uA.elements[b.indexA], posA) - uB.conformation.position(uB.elements[b.indexB], posB) + const b = edges[edgeIndex]; + const uA = b.unitA, uB = b.unitB; + uA.conformation.position(uA.elements[b.indexA], posA); + uB.conformation.position(uB.elements[b.indexB], posB); }, style: (edgeIndex: number) => { - const o = edges[edgeIndex].props.order - const f = BitFlags.create(edges[edgeIndex].props.flag) + const o = edges[edgeIndex].props.order; + const f = BitFlags.create(edges[edgeIndex].props.flag); if (BondType.is(f, BondType.Flag.MetallicCoordination) || BondType.is(f, BondType.Flag.HydrogenBond)) { // show metall coordinations and hydrogen bonds with dashed cylinders - return LinkCylinderStyle.Dashed + return LinkCylinderStyle.Dashed; } else if (o === 2) { - return LinkCylinderStyle.Double + return LinkCylinderStyle.Double; } else if (o === 3) { - return LinkCylinderStyle.Triple + return LinkCylinderStyle.Triple; } else { - return LinkCylinderStyle.Solid + return LinkCylinderStyle.Solid; } }, radius: (edgeIndex: number) => { - const b = edges[edgeIndex] - tmpLoc.structure = structure - tmpLoc.unit = b.unitA - tmpLoc.element = b.unitA.elements[b.indexA] - const sizeA = theme.size.size(tmpLoc) - tmpLoc.unit = b.unitB - tmpLoc.element = b.unitB.elements[b.indexB] - const sizeB = theme.size.size(tmpLoc) - return Math.min(sizeA, sizeB) * sizeFactor * sizeAspectRatio + const b = edges[edgeIndex]; + tmpLoc.structure = structure; + tmpLoc.unit = b.unitA; + tmpLoc.element = b.unitA.elements[b.indexA]; + const sizeA = theme.size.size(tmpLoc); + tmpLoc.unit = b.unitB; + tmpLoc.element = b.unitB.elements[b.indexB]; + const sizeB = theme.size.size(tmpLoc); + return Math.min(sizeA, sizeB) * sizeFactor * sizeAspectRatio; }, ignore: (edgeIndex: number) => ignoreHydrogen(edgeIndex) || ignoreBondType(include, exclude, edges[edgeIndex].props.flag) - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const InterUnitBondParams = { @@ -111,7 +111,7 @@ export const InterUnitBondParams = { sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }), sizeAspectRatio: PD.Numeric(2 / 3, { min: 0, max: 3, step: 0.01 }), ignoreHydrogens: PD.Boolean(false), -} +}; export type InterUnitBondParams = typeof InterUnitBondParams export function InterUnitBondVisual(materialId: number): ComplexVisual<InterUnitBondParams> { @@ -132,15 +132,15 @@ export function InterUnitBondVisual(materialId: number): ComplexVisual<InterUnit newProps.linkCap !== currentProps.linkCap || !arrayEqual(newProps.includeTypes, currentProps.includeTypes) || !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes) - ) + ); } - }, materialId) + }, materialId); } function getBondLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const bond = structure.interUnitBonds.edges[groupId] + const bond = structure.interUnitBonds.edges[groupId]; return Bond.Loci(structure, [ Bond.Location( structure, bond.unitA, bond.indexA as StructureElement.UnitIndex, @@ -150,46 +150,46 @@ function getBondLoci(pickingId: PickingId, structure: Structure, id: number) { structure, bond.unitB, bond.indexB as StructureElement.UnitIndex, structure, bond.unitA, bond.indexA as StructureElement.UnitIndex ) - ]) + ]); } - return EmptyLoci + return EmptyLoci; } function eachBond(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; if (Bond.isLoci(loci)) { - if (!Structure.areEquivalent(loci.structure, structure)) return false + if (!Structure.areEquivalent(loci.structure, structure)) return false; for (const b of loci.bonds) { - const idx = structure.interUnitBonds.getBondIndexFromLocation(b) + const idx = structure.interUnitBonds.getBondIndexFromLocation(b); if (idx !== -1) { - if (apply(Interval.ofSingleton(idx))) changed = true + if (apply(Interval.ofSingleton(idx))) changed = true; } } } else if (StructureElement.Loci.is(loci)) { - if (!Structure.areEquivalent(loci.structure, structure)) return false - if (loci.elements.length === 1) return false // only a single unit + if (!Structure.areEquivalent(loci.structure, structure)) return false; + if (loci.elements.length === 1) return false; // only a single unit - const map = new Map<number, OrderedSet<StructureElement.UnitIndex>>() - for (const e of loci.elements) map.set(e.unit.id, e.indices) + const map = new Map<number, OrderedSet<StructureElement.UnitIndex>>(); + for (const e of loci.elements) map.set(e.unit.id, e.indices); for (const e of loci.elements) { - const { unit } = e - if (!Unit.isAtomic(unit)) continue + const { unit } = e; + if (!Unit.isAtomic(unit)) continue; structure.interUnitBonds.getConnectedUnits(unit).forEach(b => { - const otherLociIndices = map.get(b.unitB.id) + const otherLociIndices = map.get(b.unitB.id); if (otherLociIndices) { OrderedSet.forEach(e.indices, v => { - if (!b.connectedIndices.includes(v)) return + if (!b.connectedIndices.includes(v)) return; b.getEdges(v).forEach(bi => { if (OrderedSet.has(otherLociIndices, bi.indexB)) { - const idx = structure.interUnitBonds.getEdgeIndex(v, unit, bi.indexB, b.unitB) - if (apply(Interval.ofSingleton(idx))) changed = true + const idx = structure.interUnitBonds.getEdgeIndex(v, unit, bi.indexB, b.unitB); + if (apply(Interval.ofSingleton(idx))) changed = true; } - }) - }) + }); + }); } - }) + }); } } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts b/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts index 5cb4f5a7ddada573b109eeb71faf74d485600e66..f67dbe0130f762070a30d7634a9e82a2872434b4 100644 --- a/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts +++ b/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts @@ -24,81 +24,81 @@ import { ignoreBondType, BondCylinderParams, BondIterator } from './util/bond'; import { Sphere3D } from '../../../mol-math/geometry'; function createIntraUnitBondCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitBondParams>, mesh?: Mesh) { - if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) + if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh); - const location = StructureElement.Location.create(structure, unit) + const location = StructureElement.Location.create(structure, unit); const elements = unit.elements; - const bonds = unit.bonds - const { edgeCount, a, b, edgeProps, offset } = bonds - const { order: _order, flags: _flags } = edgeProps - const { sizeFactor, sizeAspectRatio, ignoreHydrogens, includeTypes, excludeTypes } = props + const bonds = unit.bonds; + const { edgeCount, a, b, edgeProps, offset } = bonds; + const { order: _order, flags: _flags } = edgeProps; + const { sizeFactor, sizeAspectRatio, ignoreHydrogens, includeTypes, excludeTypes } = props; - const include = BondType.fromNames(includeTypes) - const exclude = BondType.fromNames(excludeTypes) + const include = BondType.fromNames(includeTypes); + const exclude = BondType.fromNames(excludeTypes); const ignoreHydrogen = ignoreHydrogens ? (edgeIndex: number) => { - return isHydrogen(unit, elements[a[edgeIndex]]) || isHydrogen(unit, elements[b[edgeIndex]]) - } : () => false + return isHydrogen(unit, elements[a[edgeIndex]]) || isHydrogen(unit, elements[b[edgeIndex]]); + } : () => false; - if (!edgeCount) return Mesh.createEmpty(mesh) + if (!edgeCount) return Mesh.createEmpty(mesh); - const vRef = Vec3.zero() - const pos = unit.conformation.invariantPosition + const vRef = Vec3.zero(); + const pos = unit.conformation.invariantPosition; const builderProps = { linkCount: edgeCount * 2, referencePosition: (edgeIndex: number) => { let aI = a[edgeIndex], bI = b[edgeIndex]; - if (aI > bI) [aI, bI] = [bI, aI] - if (offset[aI + 1] - offset[aI] === 1) [aI, bI] = [bI, aI] + if (aI > bI) [aI, bI] = [bI, aI]; + if (offset[aI + 1] - offset[aI] === 1) [aI, bI] = [bI, aI]; // TODO prefer reference atoms in rings for (let i = offset[aI], il = offset[aI + 1]; i < il; ++i) { - const _bI = b[i] - if (_bI !== bI && _bI !== aI) return pos(elements[_bI], vRef) + const _bI = b[i]; + if (_bI !== bI && _bI !== aI) return pos(elements[_bI], vRef); } for (let i = offset[bI], il = offset[bI + 1]; i < il; ++i) { - const _aI = a[i] - if (_aI !== aI && _aI !== bI) return pos(elements[_aI], vRef) + const _aI = a[i]; + if (_aI !== aI && _aI !== bI) return pos(elements[_aI], vRef); } - return null + return null; }, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - pos(elements[a[edgeIndex]], posA) - pos(elements[b[edgeIndex]], posB) + pos(elements[a[edgeIndex]], posA); + pos(elements[b[edgeIndex]], posB); }, style: (edgeIndex: number) => { - const o = _order[edgeIndex] - const f = BitFlags.create(_flags[edgeIndex]) + const o = _order[edgeIndex]; + const f = BitFlags.create(_flags[edgeIndex]); if (BondType.is(f, BondType.Flag.MetallicCoordination) || BondType.is(f, BondType.Flag.HydrogenBond)) { // show metall coordinations and hydrogen bonds with dashed cylinders - return LinkCylinderStyle.Dashed + return LinkCylinderStyle.Dashed; } else if (o === 2) { - return LinkCylinderStyle.Double + return LinkCylinderStyle.Double; } else if (o === 3) { - return LinkCylinderStyle.Triple + return LinkCylinderStyle.Triple; } else { - return LinkCylinderStyle.Solid + return LinkCylinderStyle.Solid; } }, radius: (edgeIndex: number) => { - location.element = elements[a[edgeIndex]] - const sizeA = theme.size.size(location) - location.element = elements[b[edgeIndex]] - const sizeB = theme.size.size(location) - return Math.min(sizeA, sizeB) * sizeFactor * sizeAspectRatio + location.element = elements[a[edgeIndex]]; + const sizeA = theme.size.size(location); + location.element = elements[b[edgeIndex]]; + const sizeB = theme.size.size(location); + return Math.min(sizeA, sizeB) * sizeFactor * sizeAspectRatio; }, ignore: (edgeIndex: number) => ignoreHydrogen(edgeIndex) || ignoreBondType(include, exclude, _flags[edgeIndex]) - } + }; - const m = createLinkCylinderMesh(ctx, builderProps, props, mesh) + const m = createLinkCylinderMesh(ctx, builderProps, props, mesh); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const IntraUnitBondParams = { @@ -107,7 +107,7 @@ export const IntraUnitBondParams = { sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }), sizeAspectRatio: PD.Numeric(2 / 3, { min: 0, max: 3, step: 0.01 }), ignoreHydrogens: PD.Boolean(false), -} +}; export type IntraUnitBondParams = typeof IntraUnitBondParams export function IntraUnitBondVisual(materialId: number): UnitsVisual<IntraUnitBondParams> { @@ -128,16 +128,16 @@ export function IntraUnitBondVisual(materialId: number): UnitsVisual<IntraUnitBo newProps.linkCap !== currentProps.linkCap || !arrayEqual(newProps.includeTypes, currentProps.includeTypes) || !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes) - ) + ); } - }, materialId) + }, materialId); } function getBondLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; if (Unit.isAtomic(unit)) { return Bond.Loci(structure, [ Bond.Location( @@ -148,48 +148,48 @@ function getBondLoci(pickingId: PickingId, structureGroup: StructureGroup, id: n structure, unit, unit.bonds.b[groupId] as StructureElement.UnitIndex, structure, unit, unit.bonds.a[groupId] as StructureElement.UnitIndex ) - ]) + ]); } } - return EmptyLoci + return EmptyLoci; } function eachBond(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; if (Bond.isLoci(loci)) { - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.structure, structure)) return false - const unit = group.units[0] - if (!Unit.isAtomic(unit)) return false - const groupCount = unit.bonds.edgeCount * 2 + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const unit = group.units[0]; + if (!Unit.isAtomic(unit)) return false; + const groupCount = unit.bonds.edgeCount * 2; for (const b of loci.bonds) { - const unitIdx = group.unitIndexMap.get(b.aUnit.id) + const unitIdx = group.unitIndexMap.get(b.aUnit.id); if (unitIdx !== undefined) { - const idx = unit.bonds.getDirectedEdgeIndex(b.aIndex, b.bIndex) + const idx = unit.bonds.getDirectedEdgeIndex(b.aIndex, b.bIndex); if (idx !== -1) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true + if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true; } } } } else if (StructureElement.Loci.is(loci)) { - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.structure, structure)) return false - const unit = group.units[0] - if (!Unit.isAtomic(unit)) return false - const groupCount = unit.bonds.edgeCount * 2 + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const unit = group.units[0]; + if (!Unit.isAtomic(unit)) return false; + const groupCount = unit.bonds.edgeCount * 2; for (const e of loci.elements) { - const unitIdx = group.unitIndexMap.get(e.unit.id) + const unitIdx = group.unitIndexMap.get(e.unit.id); if (unitIdx !== undefined) { - const { offset, b } = unit.bonds + const { offset, b } = unit.bonds; OrderedSet.forEach(e.indices, v => { for (let t = offset[v], _t = offset[v + 1]; t < _t; t++) { if (OrderedSet.has(e.indices, b[t])) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + t))) changed = true + if (apply(Interval.ofSingleton(unitIdx * groupCount + t))) changed = true; } } - }) + }); } } } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts index 0379023e9fdd0dcab6580e3d723dda028ad17fea..5d29d4073b98395564ddf69c58198325ba564aae 100644 --- a/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts +++ b/src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts @@ -21,36 +21,36 @@ import { Theme } from '../../../mol-theme/theme'; import { getAltResidueLociFromId } from './util/common'; function createCarbohydrateLinkCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CarbohydrateLinkParams>, mesh?: Mesh) { - const { links, elements } = structure.carbohydrates - const { linkSizeFactor } = props + const { links, elements } = structure.carbohydrates; + const { linkSizeFactor } = props; - const location = StructureElement.Location.create(structure) + const location = StructureElement.Location.create(structure); const builderProps = { linkCount: links.length, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - const l = links[edgeIndex] - Vec3.copy(posA, elements[l.carbohydrateIndexA].geometry.center) - Vec3.copy(posB, elements[l.carbohydrateIndexB].geometry.center) + const l = links[edgeIndex]; + Vec3.copy(posA, elements[l.carbohydrateIndexA].geometry.center); + Vec3.copy(posB, elements[l.carbohydrateIndexB].geometry.center); }, radius: (edgeIndex: number) => { - const l = links[edgeIndex] - const carbA = elements[l.carbohydrateIndexA] - const ringA = carbA.unit.rings.all[carbA.ringIndex] - location.unit = carbA.unit - location.element = carbA.unit.elements[ringA[0]] - return theme.size.size(location) * linkSizeFactor + const l = links[edgeIndex]; + const carbA = elements[l.carbohydrateIndexA]; + const ringA = carbA.unit.rings.all[carbA.ringIndex]; + location.unit = carbA.unit; + location.element = carbA.unit.elements[ringA[0]]; + return theme.size.size(location) * linkSizeFactor; }, - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const CarbohydrateLinkParams = { ...UnitsMeshParams, ...LinkCylinderParams, linkSizeFactor: PD.Numeric(0.3, { min: 0, max: 3, step: 0.01 }), -} +}; export type CarbohydrateLinkParams = typeof CarbohydrateLinkParams export function CarbohydrateLinkVisual(materialId: number): ComplexVisual<CarbohydrateLinkParams> { @@ -65,58 +65,58 @@ export function CarbohydrateLinkVisual(materialId: number): ComplexVisual<Carboh newProps.linkSizeFactor !== currentProps.linkSizeFactor || newProps.radialSegments !== currentProps.radialSegments || newProps.linkCap !== currentProps.linkCap - ) + ); } - }, materialId) + }, materialId); } function CarbohydrateLinkIterator(structure: Structure): LocationIterator { - const { elements, links } = structure.carbohydrates - const groupCount = links.length - const instanceCount = 1 - const location = StructureElement.Location.create(structure) + const { elements, links } = structure.carbohydrates; + const groupCount = links.length; + const instanceCount = 1; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number) => { - const link = links[groupIndex] - const carbA = elements[link.carbohydrateIndexA] - const ringA = carbA.unit.rings.all[carbA.ringIndex] - location.unit = carbA.unit - location.element = carbA.unit.elements[ringA[0]] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + const link = links[groupIndex]; + const carbA = elements[link.carbohydrateIndexA]; + const ringA = carbA.unit.rings.all[carbA.ringIndex]; + location.unit = carbA.unit; + location.element = carbA.unit.elements[ringA[0]]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const { links, elements } = structure.carbohydrates - const l = links[groupId] - const carbA = elements[l.carbohydrateIndexA] - const carbB = elements[l.carbohydrateIndexB] + const { links, elements } = structure.carbohydrates; + const l = links[groupId]; + const carbA = elements[l.carbohydrateIndexA]; + const carbB = elements[l.carbohydrateIndexB]; return StructureElement.Loci.union( getAltResidueLociFromId(structure, carbA.unit, carbA.residueIndex, carbA.altId), getAltResidueLociFromId(structure, carbB.unit, carbB.residueIndex, carbB.altId) - ) + ); } - return EmptyLoci + return EmptyLoci; } function eachCarbohydrateLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - if (!Structure.areEquivalent(loci.structure, structure)) return false + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + if (!Structure.areEquivalent(loci.structure, structure)) return false; - const { getLinkIndices } = structure.carbohydrates + const { getLinkIndices } = structure.carbohydrates; for (const { unit, indices } of loci.elements) { - if (!Unit.isAtomic(unit)) continue + if (!Unit.isAtomic(unit)) continue; OrderedSet.forEach(indices, v => { // TODO avoid duplicate calls to apply - const linkIndices = getLinkIndices(unit, unit.elements[v]) + const linkIndices = getLinkIndices(unit, unit.elements[v]); for (let i = 0, il = linkIndices.length; i < il; ++i) { - if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true + if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true; } - }) + }); } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts index 8236030f2eec840c745e82e8d82147dd1e7f134a..5ee62cd1168853b1a8af65c6bf2838ea83186955 100644 --- a/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts +++ b/src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts @@ -27,144 +27,144 @@ import { VisualContext } from '../../../mol-repr/visual'; import { Theme } from '../../../mol-theme/theme'; import { getAltResidueLociFromId } from './util/common'; -const t = Mat4.identity() -const sVec = Vec3.zero() -const pd = Vec3.zero() +const t = Mat4.identity(); +const sVec = Vec3.zero(); +const pd = Vec3.zero(); const SideFactor = 2 * 0.806; // 0.806 == Math.cos(Math.PI / 4) -const box = Box() -const perforatedBox = PerforatedBox() -const octagonalPyramid = OctagonalPyramid() -const perforatedOctagonalPyramid = PerforatedOctagonalPyramid() -const star = Star({ outerRadius: 1, innerRadius: 0.5, thickness: 0.5, pointCount: 5 }) -const octahedron = Octahedron() -const perforatedOctahedron = PerforatedOctahedron() -const diamondPrism = DiamondPrism() -const pentagonalPrism = PentagonalPrism() -const hexagonalPrism = HexagonalPrism() -const shiftedHexagonalPrism = ShiftedHexagonalPrism() -const heptagonalPrism = HeptagonalPrism() +const box = Box(); +const perforatedBox = PerforatedBox(); +const octagonalPyramid = OctagonalPyramid(); +const perforatedOctagonalPyramid = PerforatedOctagonalPyramid(); +const star = Star({ outerRadius: 1, innerRadius: 0.5, thickness: 0.5, pointCount: 5 }); +const octahedron = Octahedron(); +const perforatedOctahedron = PerforatedOctahedron(); +const diamondPrism = DiamondPrism(); +const pentagonalPrism = PentagonalPrism(); +const hexagonalPrism = HexagonalPrism(); +const shiftedHexagonalPrism = ShiftedHexagonalPrism(); +const heptagonalPrism = HeptagonalPrism(); function createCarbohydrateSymbolMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CarbohydrateSymbolParams>, mesh?: Mesh) { - const builderState = MeshBuilder.createState(256, 128, mesh) + const builderState = MeshBuilder.createState(256, 128, mesh); - const { detail, sizeFactor } = props + const { detail, sizeFactor } = props; - const carbohydrates = structure.carbohydrates - const n = carbohydrates.elements.length - const l = StructureElement.Location.create(structure) + const carbohydrates = structure.carbohydrates; + const n = carbohydrates.elements.length; + const l = StructureElement.Location.create(structure); for (let i = 0; i < n; ++i) { const c = carbohydrates.elements[i]; - const ring = c.unit.rings.all[c.ringIndex] - const shapeType = getSaccharideShape(c.component.type, ring.length) + const ring = c.unit.rings.all[c.ringIndex]; + const shapeType = getSaccharideShape(c.component.type, ring.length); - l.unit = c.unit - l.element = c.unit.elements[ring[0]] - const size = theme.size.size(l) - const radius = size * sizeFactor - const side = size * sizeFactor * SideFactor + l.unit = c.unit; + l.element = c.unit.elements[ring[0]]; + const size = theme.size.size(l); + const radius = size * sizeFactor; + const side = size * sizeFactor * SideFactor; - const { center, normal, direction } = c.geometry - Vec3.add(pd, center, direction) - Mat4.targetTo(t, center, pd, normal) - Mat4.setTranslation(t, center) + const { center, normal, direction } = c.geometry; + Vec3.add(pd, center, direction); + Mat4.targetTo(t, center, pd, normal); + Mat4.setTranslation(t, center); - builderState.currentGroup = i * 2 + builderState.currentGroup = i * 2; switch (shapeType) { case SaccharideShape.FilledSphere: - addSphere(builderState, center, radius, detail) + addSphere(builderState, center, radius, detail); break; case SaccharideShape.FilledCube: - Mat4.scaleUniformly(t, t, side) - MeshBuilder.addPrimitive(builderState, t, box) + Mat4.scaleUniformly(t, t, side); + MeshBuilder.addPrimitive(builderState, t, box); break; case SaccharideShape.CrossedCube: - Mat4.scaleUniformly(t, t, side) - MeshBuilder.addPrimitive(builderState, t, perforatedBox) - Mat4.mul(t, t, Mat4.rotZ90X180) - builderState.currentGroup += 1 - MeshBuilder.addPrimitive(builderState, t, perforatedBox) + Mat4.scaleUniformly(t, t, side); + MeshBuilder.addPrimitive(builderState, t, perforatedBox); + Mat4.mul(t, t, Mat4.rotZ90X180); + builderState.currentGroup += 1; + MeshBuilder.addPrimitive(builderState, t, perforatedBox); break; case SaccharideShape.FilledCone: - Mat4.scaleUniformly(t, t, side * 1.2) - MeshBuilder.addPrimitive(builderState, t, octagonalPyramid) - break + Mat4.scaleUniformly(t, t, side * 1.2); + MeshBuilder.addPrimitive(builderState, t, octagonalPyramid); + break; case SaccharideShape.DevidedCone: - Mat4.scaleUniformly(t, t, side * 1.2) - MeshBuilder.addPrimitive(builderState, t, perforatedOctagonalPyramid) - Mat4.mul(t, t, Mat4.rotZ90) - builderState.currentGroup += 1 - MeshBuilder.addPrimitive(builderState, t, perforatedOctagonalPyramid) - break + Mat4.scaleUniformly(t, t, side * 1.2); + MeshBuilder.addPrimitive(builderState, t, perforatedOctagonalPyramid); + Mat4.mul(t, t, Mat4.rotZ90); + builderState.currentGroup += 1; + MeshBuilder.addPrimitive(builderState, t, perforatedOctagonalPyramid); + break; case SaccharideShape.FlatBox: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)) - MeshBuilder.addPrimitive(builderState, t, box) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)); + MeshBuilder.addPrimitive(builderState, t, box); + break; case SaccharideShape.FilledStar: - Mat4.scaleUniformly(t, t, side) - Mat4.mul(t, t, Mat4.rotZY90) - MeshBuilder.addPrimitive(builderState, t, star) - break + Mat4.scaleUniformly(t, t, side); + Mat4.mul(t, t, Mat4.rotZY90); + MeshBuilder.addPrimitive(builderState, t, star); + break; case SaccharideShape.FilledDiamond: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4)) - MeshBuilder.addPrimitive(builderState, t, octahedron) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4)); + MeshBuilder.addPrimitive(builderState, t, octahedron); + break; case SaccharideShape.DividedDiamond: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4)) - MeshBuilder.addPrimitive(builderState, t, perforatedOctahedron) - Mat4.mul(t, t, Mat4.rotY90) - builderState.currentGroup += 1 - MeshBuilder.addPrimitive(builderState, t, perforatedOctahedron) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side * 1.4, side * 1.4, side * 1.4)); + MeshBuilder.addPrimitive(builderState, t, perforatedOctahedron); + Mat4.mul(t, t, Mat4.rotY90); + builderState.currentGroup += 1; + MeshBuilder.addPrimitive(builderState, t, perforatedOctahedron); + break; case SaccharideShape.FlatDiamond: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side, side / 2, side / 2)) - MeshBuilder.addPrimitive(builderState, t, diamondPrism) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side, side / 2, side / 2)); + MeshBuilder.addPrimitive(builderState, t, diamondPrism); + break; case SaccharideShape.DiamondPrism: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)) - MeshBuilder.addPrimitive(builderState, t, diamondPrism) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)); + MeshBuilder.addPrimitive(builderState, t, diamondPrism); + break; case SaccharideShape.PentagonalPrism: case SaccharideShape.Pentagon: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)) - MeshBuilder.addPrimitive(builderState, t, pentagonalPrism) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)); + MeshBuilder.addPrimitive(builderState, t, pentagonalPrism); + break; case SaccharideShape.HexagonalPrism: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)) - MeshBuilder.addPrimitive(builderState, t, hexagonalPrism) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)); + MeshBuilder.addPrimitive(builderState, t, hexagonalPrism); + break; case SaccharideShape.HeptagonalPrism: - Mat4.mul(t, t, Mat4.rotZY90) - Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)) - MeshBuilder.addPrimitive(builderState, t, heptagonalPrism) - break + Mat4.mul(t, t, Mat4.rotZY90); + Mat4.scale(t, t, Vec3.set(sVec, side, side, side / 2)); + MeshBuilder.addPrimitive(builderState, t, heptagonalPrism); + break; case SaccharideShape.FlatHexagon: default: - Mat4.mul(t, t, Mat4.rotZYZ90) - Mat4.scale(t, t, Vec3.set(sVec, side / 1.5, side, side / 2)) - MeshBuilder.addPrimitive(builderState, t, shiftedHexagonalPrism) - break + Mat4.mul(t, t, Mat4.rotZYZ90); + Mat4.scale(t, t, Vec3.set(sVec, side / 1.5, side, side / 2)); + MeshBuilder.addPrimitive(builderState, t, shiftedHexagonalPrism); + break; } } - return MeshBuilder.getMesh(builderState) + return MeshBuilder.getMesh(builderState); } export const CarbohydrateSymbolParams = { ...ComplexMeshParams, detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }), sizeFactor: PD.Numeric(1.75, { min: 0, max: 10, step: 0.01 }), -} +}; export type CarbohydrateSymbolParams = typeof CarbohydrateSymbolParams export function CarbohydrateSymbolVisual(materialId: number): ComplexVisual<CarbohydrateSymbolParams> { @@ -178,56 +178,56 @@ export function CarbohydrateSymbolVisual(materialId: number): ComplexVisual<Carb state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.detail !== currentProps.detail - ) + ); } - }, materialId) + }, materialId); } function CarbohydrateElementIterator(structure: Structure): LocationIterator { - const carbElements = structure.carbohydrates.elements - const groupCount = carbElements.length * 2 - const instanceCount = 1 - const location = StructureElement.Location.create(structure) + const carbElements = structure.carbohydrates.elements; + const groupCount = carbElements.length * 2; + const instanceCount = 1; + const location = StructureElement.Location.create(structure); function getLocation (groupIndex: number, instanceIndex: number) { - const carb = carbElements[Math.floor(groupIndex / 2)] - const ring = carb.unit.rings.all[carb.ringIndex] - location.unit = carb.unit - location.element = carb.unit.elements[ring[0]] - return location + const carb = carbElements[Math.floor(groupIndex / 2)]; + const ring = carb.unit.rings.all[carb.ringIndex]; + location.unit = carb.unit; + location.element = carb.unit.elements[ring[0]]; + return location; } function isSecondary (elementIndex: number, instanceIndex: number) { - return (elementIndex % 2) === 1 + return (elementIndex % 2) === 1; } - return LocationIterator(groupCount, instanceCount, getLocation, true, isSecondary) + return LocationIterator(groupCount, instanceCount, getLocation, true, isSecondary); } /** Return a Loci for the elements of the whole residue of a carbohydrate. */ function getCarbohydrateLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const carb = structure.carbohydrates.elements[Math.floor(groupId / 2)] - return getAltResidueLociFromId(structure, carb.unit, carb.residueIndex, carb.altId) + const carb = structure.carbohydrates.elements[Math.floor(groupId / 2)]; + return getAltResidueLociFromId(structure, carb.unit, carb.residueIndex, carb.altId); } - return EmptyLoci + return EmptyLoci; } /** For each carbohydrate (usually a monosaccharide) when all its residue's elements are in a loci. */ function eachCarbohydrate(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - const { getElementIndices } = structure.carbohydrates - let changed = false - if (!StructureElement.Loci.is(loci)) return false - if (!Structure.areEquivalent(loci.structure, structure)) return false + const { getElementIndices } = structure.carbohydrates; + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + if (!Structure.areEquivalent(loci.structure, structure)) return false; for (const { unit, indices } of loci.elements) { - if (!Unit.isAtomic(unit)) continue + if (!Unit.isAtomic(unit)) continue; OrderedSet.forEach(indices, v => { // TODO avoid duplicate calls to apply - const elementIndices = getElementIndices(unit, unit.elements[v]) + const elementIndices = getElementIndices(unit, unit.elements[v]); for (let i = 0, il = elementIndices.length; i < il; ++i) { - if (apply(Interval.ofSingleton(elementIndices[i] * 2))) changed = true + if (apply(Interval.ofSingleton(elementIndices[i] * 2))) changed = true; } - }) + }); } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/carbohydrate-terminal-link-cylinder.ts b/src/mol-repr/structure/visual/carbohydrate-terminal-link-cylinder.ts index 1b176e4b3065c257d7b6760ada6e503fd2707837..0fd32a926c33ca9de4c5f236f1ade0257209b657 100644 --- a/src/mol-repr/structure/visual/carbohydrate-terminal-link-cylinder.ts +++ b/src/mol-repr/structure/visual/carbohydrate-terminal-link-cylinder.ts @@ -22,52 +22,52 @@ import { getElementIdx, MetalsSet } from '../../../mol-model/structure/structure import { getAltResidueLociFromId, getAltResidueLoci } from './util/common'; function createCarbohydrateTerminalLinkCylinderMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: PD.Values<CarbohydrateTerminalLinkParams>, mesh?: Mesh) { - const { terminalLinks, elements } = structure.carbohydrates - const { terminalLinkSizeFactor } = props + const { terminalLinks, elements } = structure.carbohydrates; + const { terminalLinkSizeFactor } = props; - const location = StructureElement.Location.create(structure) + const location = StructureElement.Location.create(structure); const builderProps = { linkCount: terminalLinks.length, position: (posA: Vec3, posB: Vec3, edgeIndex: number) => { - const l = terminalLinks[edgeIndex] + const l = terminalLinks[edgeIndex]; if (l.fromCarbohydrate) { - Vec3.copy(posA, elements[l.carbohydrateIndex].geometry.center) - l.elementUnit.conformation.position(l.elementUnit.elements[l.elementIndex], posB) + Vec3.copy(posA, elements[l.carbohydrateIndex].geometry.center); + l.elementUnit.conformation.position(l.elementUnit.elements[l.elementIndex], posB); } else { - l.elementUnit.conformation.position(l.elementUnit.elements[l.elementIndex], posA) - Vec3.copy(posB, elements[l.carbohydrateIndex].geometry.center) + l.elementUnit.conformation.position(l.elementUnit.elements[l.elementIndex], posA); + Vec3.copy(posB, elements[l.carbohydrateIndex].geometry.center); } }, radius: (edgeIndex: number) => { - const l = terminalLinks[edgeIndex] + const l = terminalLinks[edgeIndex]; if (l.fromCarbohydrate) { - const carb = elements[l.carbohydrateIndex] - const ring = carb.unit.rings.all[carb.ringIndex] - location.unit = carb.unit - location.element = carb.unit.elements[ring[0]] + const carb = elements[l.carbohydrateIndex]; + const ring = carb.unit.rings.all[carb.ringIndex]; + location.unit = carb.unit; + location.element = carb.unit.elements[ring[0]]; } else { - location.unit = l.elementUnit - location.element = l.elementUnit.elements[l.elementIndex] + location.unit = l.elementUnit; + location.element = l.elementUnit.elements[l.elementIndex]; } - return theme.size.size(location) * terminalLinkSizeFactor + return theme.size.size(location) * terminalLinkSizeFactor; }, style: (edgeIndex: number) => { - const l = terminalLinks[edgeIndex] - const eI = l.elementUnit.elements[l.elementIndex] + const l = terminalLinks[edgeIndex]; + const eI = l.elementUnit.elements[l.elementIndex]; const beI = getElementIdx(l.elementUnit.model.atomicHierarchy.atoms.type_symbol.value(eI)); - return MetalsSet.has(beI) ? LinkCylinderStyle.Dashed : LinkCylinderStyle.Solid + return MetalsSet.has(beI) ? LinkCylinderStyle.Dashed : LinkCylinderStyle.Solid; } - } + }; - return createLinkCylinderMesh(ctx, builderProps, props, mesh) + return createLinkCylinderMesh(ctx, builderProps, props, mesh); } export const CarbohydrateTerminalLinkParams = { ...UnitsMeshParams, ...LinkCylinderParams, terminalLinkSizeFactor: PD.Numeric(0.2, { min: 0, max: 3, step: 0.01 }), -} +}; export type CarbohydrateTerminalLinkParams = typeof CarbohydrateTerminalLinkParams export function CarbohydrateTerminalLinkVisual(materialId: number): ComplexVisual<CarbohydrateTerminalLinkParams> { @@ -82,63 +82,63 @@ export function CarbohydrateTerminalLinkVisual(materialId: number): ComplexVisua newProps.terminalLinkSizeFactor !== currentProps.terminalLinkSizeFactor || newProps.radialSegments !== currentProps.radialSegments || newProps.linkCap !== currentProps.linkCap - ) + ); } - }, materialId) + }, materialId); } function CarbohydrateTerminalLinkIterator(structure: Structure): LocationIterator { - const { elements, terminalLinks } = structure.carbohydrates - const groupCount = terminalLinks.length - const instanceCount = 1 - const location = StructureElement.Location.create(structure) + const { elements, terminalLinks } = structure.carbohydrates; + const groupCount = terminalLinks.length; + const instanceCount = 1; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number) => { - const terminalLink = terminalLinks[groupIndex] + const terminalLink = terminalLinks[groupIndex]; if (terminalLink.fromCarbohydrate) { - const carb = elements[terminalLink.carbohydrateIndex] - const ring = carb.unit.rings.all[carb.ringIndex] - location.unit = carb.unit - location.element = carb.unit.elements[ring[0]] + const carb = elements[terminalLink.carbohydrateIndex]; + const ring = carb.unit.rings.all[carb.ringIndex]; + location.unit = carb.unit; + location.element = carb.unit.elements[ring[0]]; } else { - location.unit = terminalLink.elementUnit - location.element = terminalLink.elementUnit.elements[terminalLink.elementIndex] + location.unit = terminalLink.elementUnit; + location.element = terminalLink.elementUnit.elements[terminalLink.elementIndex]; } - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } function getTerminalLinkLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const { terminalLinks, elements } = structure.carbohydrates - const l = terminalLinks[groupId] - const carb = elements[l.carbohydrateIndex] + const { terminalLinks, elements } = structure.carbohydrates; + const l = terminalLinks[groupId]; + const carb = elements[l.carbohydrateIndex]; return StructureElement.Loci.union( getAltResidueLociFromId(structure, carb.unit, carb.residueIndex, carb.altId), getAltResidueLoci(structure, l.elementUnit, l.elementUnit.elements[l.elementIndex]) - ) + ); } - return EmptyLoci + return EmptyLoci; } function eachTerminalLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - if (!Structure.areEquivalent(loci.structure, structure)) return false + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + if (!Structure.areEquivalent(loci.structure, structure)) return false; - const { getTerminalLinkIndices } = structure.carbohydrates + const { getTerminalLinkIndices } = structure.carbohydrates; for (const { unit, indices } of loci.elements) { - if (!Unit.isAtomic(unit)) continue + if (!Unit.isAtomic(unit)) continue; OrderedSet.forEach(indices, v => { // TODO avoid duplicate calls to apply - const linkIndices = getTerminalLinkIndices(unit, unit.elements[v]) + const linkIndices = getTerminalLinkIndices(unit, unit.elements[v]); for (let i = 0, il = linkIndices.length; i < il; ++i) { - if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true + if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true; } - }) + }); } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/element-point.ts b/src/mol-repr/structure/visual/element-point.ts index 6d861682220e77526258435c1231c6f9aa717a16..118ae2a0d1b759992f8da18225bc31092a4a060f 100644 --- a/src/mol-repr/structure/visual/element-point.ts +++ b/src/mol-repr/structure/visual/element-point.ts @@ -21,7 +21,7 @@ export const ElementPointParams = { // sizeFactor: PD.Numeric(1.0, { min: 0, max: 10, step: 0.01 }), pointSizeAttenuation: PD.Boolean(false), showHydrogens: PD.Boolean(true), -} +}; export type ElementPointParams = typeof ElementPointParams // TODO size @@ -29,24 +29,24 @@ export type ElementPointParams = typeof ElementPointParams export function createElementPoint(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<ElementPointParams>, points: Points) { // const { sizeFactor } = props - const elements = unit.elements - const n = elements.length - const builder = PointsBuilder.create(n, n / 10, points) + const elements = unit.elements; + const n = elements.length; + const builder = PointsBuilder.create(n, n / 10, points); - const pos = unit.conformation.invariantPosition - const p = Vec3.zero() + const pos = unit.conformation.invariantPosition; + const p = Vec3.zero(); for (let i = 0; i < n; ++i) { - pos(elements[i], p) - builder.add(p[0], p[1], p[2], i) + pos(elements[i], p); + builder.add(p[0], p[1], p[2], i); } - const pt = builder.getPoints() + const pt = builder.getPoints(); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - pt.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + pt.setBoundingSphere(sphere); - return pt + return pt; } export function ElementPointVisual(materialId: number): UnitsVisual<ElementPointParams> { @@ -59,5 +59,5 @@ export function ElementPointVisual(materialId: number): UnitsVisual<ElementPoint setUpdateState: (state: VisualUpdateState, newProps: PD.Values<ElementPointParams>, currentProps: PD.Values<ElementPointParams>) => { } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/element-sphere.ts b/src/mol-repr/structure/visual/element-sphere.ts index 0c0f2536ddc76ad26b5584f126be293c4bf784c1..a15159f7c37023c47d7fc331fdb3d87adbfefcc0 100644 --- a/src/mol-repr/structure/visual/element-sphere.ts +++ b/src/mol-repr/structure/visual/element-sphere.ts @@ -18,11 +18,11 @@ export const ElementSphereParams = { detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }), ignoreHydrogens: PD.Boolean(false), traceOnly: PD.Boolean(false), -} +}; export type ElementSphereParams = typeof ElementSphereParams export function getElementSphereVisual(webgl?: WebGLContext) { - return webgl && webgl.extensions.fragDepth ? ElementSphereImpostorVisual : ElementSphereMeshVisual + return webgl && webgl.extensions.fragDepth ? ElementSphereImpostorVisual : ElementSphereMeshVisual; } export function ElementSphereImpostorVisual(materialId: number): UnitsVisual<ElementSphereParams> { @@ -36,9 +36,9 @@ export function ElementSphereImpostorVisual(materialId: number): UnitsVisual<Ele state.createGeometry = ( newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || newProps.traceOnly !== currentProps.traceOnly - ) + ); } - }, materialId) + }, materialId); } export function ElementSphereMeshVisual(materialId: number): UnitsVisual<ElementSphereParams> { @@ -54,7 +54,7 @@ export function ElementSphereMeshVisual(materialId: number): UnitsVisual<Element newProps.detail !== currentProps.detail || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || newProps.traceOnly !== currentProps.traceOnly - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/ellipsoid-mesh.ts b/src/mol-repr/structure/visual/ellipsoid-mesh.ts index d8ddd5ad220de5e83ea8ce723ae1490411c2c186..18098c9c45ecec3d9dc2ce567243a6d9f4782f1c 100644 --- a/src/mol-repr/structure/visual/ellipsoid-mesh.ts +++ b/src/mol-repr/structure/visual/ellipsoid-mesh.ts @@ -17,7 +17,7 @@ import { MeshBuilder } from '../../../mol-geo/geometry/mesh/mesh-builder'; import { Vec3, Mat3, Tensor, EPSILON } from '../../../mol-math/linear-algebra'; import { isHydrogen } from '../../../mol-repr/structure/visual/util/common'; import { addEllipsoid } from '../../../mol-geo/geometry/mesh/builder/ellipsoid'; -import { AtomSiteAnisotrop } from '../../../mol-model-formats/structure/property/anisotropic' +import { AtomSiteAnisotrop } from '../../../mol-model-formats/structure/property/anisotropic'; import { equalEps } from '../../../mol-math/linear-algebra/3d/common'; import { addSphere } from '../../../mol-geo/geometry/mesh/builder/sphere'; import { Sphere3D } from '../../../mol-math/geometry'; @@ -27,7 +27,7 @@ export const EllipsoidMeshParams = { sizeFactor: PD.Numeric(1, { min: 0, max: 10, step: 0.1 }), detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }), ignoreHydrogens: PD.Boolean(false), -} +}; export type EllipsoidMeshParams = typeof EllipsoidMeshParams export function EllipsoidMeshVisual(materialId: number): UnitsVisual<EllipsoidMeshParams> { @@ -42,9 +42,9 @@ export function EllipsoidMeshVisual(materialId: number): UnitsVisual<EllipsoidMe newProps.sizeFactor !== currentProps.sizeFactor || newProps.detail !== currentProps.detail || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens - ) + ); } - }, materialId) + }, materialId); } // @@ -56,61 +56,61 @@ export interface EllipsoidMeshProps { } export function createEllipsoidMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: EllipsoidMeshProps, mesh?: Mesh): Mesh { - const { detail, sizeFactor } = props + const { detail, sizeFactor } = props; const { elements, model } = unit; const elementCount = elements.length; - const vertexCount = elementCount * sphereVertexCount(detail) - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh) - - const atomSiteAnisotrop = AtomSiteAnisotrop.Provider.get(model) - if (!atomSiteAnisotrop) return Mesh.createEmpty(mesh) - - const v = Vec3() - const mat = Mat3() - const eigvals = Vec3() - const eigvec1 = Vec3() - const eigvec2 = Vec3() - const { elementToAnsiotrop, data } = atomSiteAnisotrop - const { U } = data - const space = data._schema.U.space - const pos = unit.conformation.invariantPosition - const l = StructureElement.Location.create(structure) - l.unit = unit + const vertexCount = elementCount * sphereVertexCount(detail); + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh); + + const atomSiteAnisotrop = AtomSiteAnisotrop.Provider.get(model); + if (!atomSiteAnisotrop) return Mesh.createEmpty(mesh); + + const v = Vec3(); + const mat = Mat3(); + const eigvals = Vec3(); + const eigvec1 = Vec3(); + const eigvec2 = Vec3(); + const { elementToAnsiotrop, data } = atomSiteAnisotrop; + const { U } = data; + const space = data._schema.U.space; + const pos = unit.conformation.invariantPosition; + const l = StructureElement.Location.create(structure); + l.unit = unit; for (let i = 0; i < elementCount; i++) { - const ei = elements[i] - const ai = elementToAnsiotrop[ei] - if (ai === -1) continue - if (props.ignoreHydrogens && isHydrogen(unit, ei)) continue - - l.element = ei - pos(ei, v) - - builderState.currentGroup = i - Tensor.toMat3(mat, space, U.value(ai)) - Mat3.symmtricFromLower(mat, mat) - Mat3.symmetricEigenvalues(eigvals, mat) - Mat3.eigenvector(eigvec1, mat, eigvals[1]) - Mat3.eigenvector(eigvec2, mat, eigvals[2]) + const ei = elements[i]; + const ai = elementToAnsiotrop[ei]; + if (ai === -1) continue; + if (props.ignoreHydrogens && isHydrogen(unit, ei)) continue; + + l.element = ei; + pos(ei, v); + + builderState.currentGroup = i; + Tensor.toMat3(mat, space, U.value(ai)); + Mat3.symmtricFromLower(mat, mat); + Mat3.symmetricEigenvalues(eigvals, mat); + Mat3.eigenvector(eigvec1, mat, eigvals[1]); + Mat3.eigenvector(eigvec2, mat, eigvals[2]); for (let j = 0; j < 3; ++j) { // show 50% probability surface, needs sqrt as U matrix is in angstrom-squared // take abs of eigenvalue to avoid reflection // multiply by given size-factor - eigvals[j] = sizeFactor * 1.5958 * Math.sqrt(Math.abs(eigvals[j])) + eigvals[j] = sizeFactor * 1.5958 * Math.sqrt(Math.abs(eigvals[j])); } if (equalEps(eigvals[0], eigvals[1], EPSILON) && equalEps(eigvals[1], eigvals[2], EPSILON)) { - addSphere(builderState, v, eigvals[0], detail) + addSphere(builderState, v, eigvals[0], detail); } else { - addEllipsoid(builderState, v, eigvec2, eigvec1, eigvals, detail) + addEllipsoid(builderState, v, eigvec2, eigvec1, eigvals, detail); } } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/gaussian-density-volume.ts b/src/mol-repr/structure/visual/gaussian-density-volume.ts index d20f23f94fc4f2f1fe669e8fbeb20f4234ee503c..55074288f22d39065c3c871ddbddc91d692ca47e 100644 --- a/src/mol-repr/structure/visual/gaussian-density-volume.ts +++ b/src/mol-repr/structure/visual/gaussian-density-volume.ts @@ -17,22 +17,22 @@ import { EmptyLoci } from '../../../mol-model/loci'; import { VisualUpdateState } from '../../util'; async function createGaussianDensityVolume(ctx: VisualContext, structure: Structure, theme: Theme, props: GaussianDensityTextureProps, directVolume?: DirectVolume): Promise<DirectVolume> { - const { runtime, webgl } = ctx - if (webgl === undefined) throw new Error('createGaussianDensityVolume requires `webgl` object in VisualContext') + const { runtime, webgl } = ctx; + if (webgl === undefined) throw new Error('createGaussianDensityVolume requires `webgl` object in VisualContext'); - const p = { ...props, useGpu: true } - const oldTexture = directVolume ? directVolume.gridTexture.ref.value : undefined - const densityTextureData = await computeStructureGaussianDensityTexture(structure, p, webgl, oldTexture).runInContext(runtime) - const { transform, texture, bbox, gridDim } = densityTextureData + const p = { ...props, useGpu: true }; + const oldTexture = directVolume ? directVolume.gridTexture.ref.value : undefined; + const densityTextureData = await computeStructureGaussianDensityTexture(structure, p, webgl, oldTexture).runInContext(runtime); + const { transform, texture, bbox, gridDim } = densityTextureData; - return DirectVolume.create(bbox, gridDim, transform, texture, directVolume) + return DirectVolume.create(bbox, gridDim, transform, texture, directVolume); } export const GaussianDensityVolumeParams = { ...ComplexDirectVolumeParams, ...GaussianDensityTextureParams, ignoreHydrogens: PD.Boolean(false), -} +}; export type GaussianDensityVolumeParams = typeof GaussianDensityVolumeParams export function GaussianDensityVolumeVisual(materialId: number): ComplexVisual<GaussianDensityVolumeParams> { @@ -43,14 +43,14 @@ export function GaussianDensityVolumeVisual(materialId: number): ComplexVisual<G getLoci: () => EmptyLoci, // TODO eachLocation: () => false, // TODO setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianDensityVolumeParams>, currentProps: PD.Values<GaussianDensityVolumeParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true; if (newProps.smoothness !== currentProps.smoothness) { - state.createGeometry = true - newProps.isoValueNorm = Math.exp(-newProps.smoothness) + state.createGeometry = true; + newProps.isoValueNorm = Math.exp(-newProps.smoothness); } - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true; } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts index 77888f2415119e4e3ae3f5a740adae82f9d0c130..6f1e5fa242296837d6f77ed04d25509fbdd919cb 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-mesh.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-mesh.ts @@ -26,33 +26,33 @@ export const GaussianSurfaceMeshParams = { ...UnitsMeshParams, ...UnitsTextureMeshParams, ...GaussianDensityParams, -} +}; export type GaussianSurfaceMeshParams = typeof GaussianSurfaceMeshParams export function getGaussianSurfaceVisual(webgl?: WebGLContext) { - return webgl && webgl.extensions.drawBuffers ? GaussianSurfaceTextureMeshVisual : GaussianSurfaceMeshVisual + return webgl && webgl.extensions.drawBuffers ? GaussianSurfaceTextureMeshVisual : GaussianSurfaceMeshVisual; } // async function createGaussianSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> { - const { smoothness } = props - const { transform, field, idField } = await computeUnitGaussianDensity(structure, unit, props, ctx.webgl).runInContext(ctx.runtime) + const { smoothness } = props; + const { transform, field, idField } = await computeUnitGaussianDensity(structure, unit, props, ctx.webgl).runInContext(ctx.runtime); const params = { isoLevel: Math.exp(-smoothness), scalarField: field, idField - } - const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime) + }; + const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime); - Mesh.transform(surface, transform) - if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface) + Mesh.transform(surface, transform); + if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset) - surface.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset); + surface.setBoundingSphere(sphere); - return surface + return surface; } export function GaussianSurfaceMeshVisual(materialId: number): UnitsVisual<GaussianSurfaceMeshParams> { @@ -63,15 +63,15 @@ export function GaussianSurfaceMeshVisual(materialId: number): UnitsVisual<Gauss getLoci: getElementLoci, eachLocation: eachElement, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianSurfaceMeshParams>, currentProps: PD.Values<GaussianSurfaceMeshParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true - if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true - if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true - if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true; + if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true; + if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true; + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true; + if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true; } - }, materialId) + }, materialId); } // @@ -80,27 +80,27 @@ export const StructureGaussianSurfaceMeshParams = { ...ComplexMeshParams, ...GaussianDensityParams, ignoreHydrogens: PD.Boolean(false), -} +}; export type StructureGaussianSurfaceMeshParams = typeof StructureGaussianSurfaceMeshParams async function createStructureGaussianSurfaceMesh(ctx: VisualContext, structure: Structure, theme: Theme, props: GaussianDensityProps, mesh?: Mesh): Promise<Mesh> { - const { smoothness } = props - const { transform, field, idField } = await computeStructureGaussianDensity(structure, props, ctx.webgl).runInContext(ctx.runtime) + const { smoothness } = props; + const { transform, field, idField } = await computeStructureGaussianDensity(structure, props, ctx.webgl).runInContext(ctx.runtime); const params = { isoLevel: Math.exp(-smoothness), scalarField: field, idField - } - const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime) + }; + const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime); - Mesh.transform(surface, transform) - if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface) + Mesh.transform(surface, transform); + if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface); - const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset) - surface.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), structure.boundary.sphere, props.radiusOffset); + surface.setBoundingSphere(sphere); - return surface + return surface; } export function StructureGaussianSurfaceMeshVisual(materialId: number): ComplexVisual<StructureGaussianSurfaceMeshParams> { @@ -111,43 +111,43 @@ export function StructureGaussianSurfaceMeshVisual(materialId: number): ComplexV getLoci: getSerialElementLoci, eachLocation: eachSerialElement, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianSurfaceMeshParams>, currentProps: PD.Values<GaussianSurfaceMeshParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true - if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true - if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true; + if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true; + if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true; + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true; } - }, materialId) + }, materialId); } // async function createGaussianSurfaceTextureMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityTextureProps, textureMesh?: TextureMesh): Promise<TextureMesh> { - if (!ctx.webgl) throw new Error('webgl context required to create gaussian surface texture-mesh') - const isoLevel = Math.exp(-props.smoothness) + if (!ctx.webgl) throw new Error('webgl context required to create gaussian surface texture-mesh'); + const isoLevel = Math.exp(-props.smoothness); - const densityTextureData = await computeUnitGaussianDensityTexture2d(structure, unit, props, ctx.webgl).runInContext(ctx.runtime) + const densityTextureData = await computeUnitGaussianDensityTexture2d(structure, unit, props, ctx.webgl).runInContext(ctx.runtime); // console.log(densityTextureData) // console.log('vertexGroupTexture', readTexture(ctx.webgl, densityTextureData.texture)) // ctx.webgl.waitForGpuCommandsCompleteSync() - const activeVoxelsTex = calcActiveVoxels(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, isoLevel, densityTextureData.gridTexScale) + const activeVoxelsTex = calcActiveVoxels(ctx.webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, isoLevel, densityTextureData.gridTexScale); // ctx.webgl.waitForGpuCommandsCompleteSync() - const compacted = createHistogramPyramid(ctx.webgl, activeVoxelsTex, densityTextureData.gridTexScale) + const compacted = createHistogramPyramid(ctx.webgl, activeVoxelsTex, densityTextureData.gridTexScale); // ctx.webgl.waitForGpuCommandsCompleteSync() - const gv = createIsosurfaceBuffers(ctx.webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoLevel, textureMesh ? textureMesh.vertexGroupTexture.ref.value : undefined, textureMesh ? textureMesh.normalTexture.ref.value : undefined) + const gv = createIsosurfaceBuffers(ctx.webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoLevel, textureMesh ? textureMesh.vertexGroupTexture.ref.value : undefined, textureMesh ? textureMesh.normalTexture.ref.value : undefined); // ctx.webgl.waitForGpuCommandsCompleteSync() // const boundingSphere = Sphere3D.zero() // Sphere3D.addVec3(boundingSphere, boundingSphere, densityTextureData.gridDimension) - const boundingSphere = Sphere3D.fromBox3D(Sphere3D(), densityTextureData.bbox) - const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexGroupTexture, gv.normalTexture, boundingSphere, textureMesh) + const boundingSphere = Sphere3D.fromBox3D(Sphere3D(), densityTextureData.bbox); + const surface = TextureMesh.create(gv.vertexCount, 1, gv.vertexGroupTexture, gv.normalTexture, boundingSphere, textureMesh); // ctx.webgl.waitForGpuCommandsCompleteSync() - return surface + return surface; } export function GaussianSurfaceTextureMeshVisual(materialId: number): UnitsVisual<GaussianSurfaceMeshParams> { @@ -158,12 +158,12 @@ export function GaussianSurfaceTextureMeshVisual(materialId: number): UnitsVisua getLoci: getElementLoci, eachLocation: eachElement, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianSurfaceMeshParams>, currentProps: PD.Values<GaussianSurfaceMeshParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true - if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true - if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true; + if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true; + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true; + if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true; } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts index 41f2bb2627fc246950c8a90dbb62756e2bb8d841..cc31cc930144e93d52662532d859abd71e708edc 100644 --- a/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts +++ b/src/mol-repr/structure/visual/gaussian-surface-wireframe.ts @@ -17,22 +17,22 @@ import { VisualUpdateState } from '../../util'; import { Sphere3D } from '../../../mol-math/geometry'; async function createGaussianWireframe(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: GaussianDensityProps, lines?: Lines): Promise<Lines> { - const { smoothness } = props - const { transform, field, idField } = await computeUnitGaussianDensity(structure, unit, props, ctx.webgl).runInContext(ctx.runtime) + const { smoothness } = props; + const { transform, field, idField } = await computeUnitGaussianDensity(structure, unit, props, ctx.webgl).runInContext(ctx.runtime); const params = { isoLevel: Math.exp(-smoothness), scalarField: field, idField - } - const wireframe = await computeMarchingCubesLines(params, lines).runAsChild(ctx.runtime) + }; + const wireframe = await computeMarchingCubesLines(params, lines).runAsChild(ctx.runtime); - Lines.transform(wireframe, transform) + Lines.transform(wireframe, transform); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset) - wireframe.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.radiusOffset); + wireframe.setBoundingSphere(sphere); - return wireframe + return wireframe; } export const GaussianWireframeParams = { @@ -41,7 +41,7 @@ export const GaussianWireframeParams = { sizeFactor: PD.Numeric(1.5, { min: 0, max: 10, step: 0.1 }), lineSizeAttenuation: PD.Boolean(false), ignoreHydrogens: PD.Boolean(false), -} +}; export type GaussianWireframeParams = typeof GaussianWireframeParams export function GaussianWireframeVisual(materialId: number): UnitsVisual<GaussianWireframeParams> { @@ -52,13 +52,13 @@ export function GaussianWireframeVisual(materialId: number): UnitsVisual<Gaussia getLoci: getElementLoci, eachLocation: eachElement, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<GaussianWireframeParams>, currentProps: PD.Values<GaussianWireframeParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true - if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true - if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true - if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.radiusOffset !== currentProps.radiusOffset) state.createGeometry = true; + if (newProps.smoothness !== currentProps.smoothness) state.createGeometry = true; + if (newProps.useGpu !== currentProps.useGpu) state.createGeometry = true; + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.traceOnly !== currentProps.traceOnly) state.createGeometry = true; + if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true; } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/label-text.ts b/src/mol-repr/structure/visual/label-text.ts index 780107264eca7baebfc63ac4f5b0d1c70fe481a8..95b6bb29a5cf40088f3206592e784138e6c551c0 100644 --- a/src/mol-repr/structure/visual/label-text.ts +++ b/src/mol-repr/structure/visual/label-text.ts @@ -29,7 +29,7 @@ export const LabelTextParams = { chainScale: PD.Numeric(10, { min: 0, max: 20, step: 0.1 }), residueScale: PD.Numeric(1, { min: 0, max: 20, step: 0.1 }), elementScale: PD.Numeric(0.5, { min: 0, max: 20, step: 0.1 }), -} +}; export type LabelTextParams = typeof LabelTextParams export type LabelTextProps = PD.Values<LabelTextParams> export type LabelLevels = LabelTextProps['level'] @@ -47,17 +47,17 @@ export function LabelTextVisual(materialId: number): ComplexVisual<LabelTextPara (newProps.level === 'chain' && newProps.chainScale !== currentProps.chainScale) || (newProps.level === 'residue' && newProps.residueScale !== currentProps.residueScale) || (newProps.level === 'element' && newProps.elementScale !== currentProps.elementScale) - ) + ); } - }, materialId) + }, materialId); } function createLabelText(ctx: VisualContext, structure: Structure, theme: Theme, props: LabelTextProps, text?: Text): Text { switch (props.level) { - case 'chain': return createChainText(ctx, structure, theme, props, text) - case 'residue': return createResidueText(ctx, structure, theme, props, text) - case 'element': return createElementText(ctx, structure, theme, props, text) + case 'chain': return createChainText(ctx, structure, theme, props, text); + case 'residue': return createResidueText(ctx, structure, theme, props, text); + case 'element': return createElementText(ctx, structure, theme, props, text); } } @@ -70,46 +70,46 @@ function createChainText(ctx: VisualContext, structure: Structure, theme: Theme, const l = StructureElement.Location.create(structure); const { units, serialMapping } = structure; const { auth_asym_id, label_asym_id } = StructureProperties.chain; - const { cumulativeUnitElementCount } = serialMapping + const { cumulativeUnitElementCount } = serialMapping; - const count = units.length - const { chainScale } = props - const builder = TextBuilder.create(props, count, count / 2, text) + const count = units.length; + const { chainScale } = props; + const builder = TextBuilder.create(props, count, count / 2, text); for (let i = 0, il = units.length; i < il; ++i) { - const unit = units[i] - l.unit = unit - l.element = unit.elements[0] - const { center, radius } = unit.lookup3d.boundary.sphere - Vec3.transformMat4(tmpVec, center, unit.conformation.operator.matrix) - const authId = auth_asym_id(l) - const labelId = label_asym_id(l) - const text = authId === labelId ? labelId : `${labelId} [${authId}]` - builder.add(text, tmpVec[0], tmpVec[1], tmpVec[2], radius, chainScale, cumulativeUnitElementCount[i]) + const unit = units[i]; + l.unit = unit; + l.element = unit.elements[0]; + const { center, radius } = unit.lookup3d.boundary.sphere; + Vec3.transformMat4(tmpVec, center, unit.conformation.operator.matrix); + const authId = auth_asym_id(l); + const labelId = label_asym_id(l); + const text = authId === labelId ? labelId : `${labelId} [${authId}]`; + builder.add(text, tmpVec[0], tmpVec[1], tmpVec[2], radius, chainScale, cumulativeUnitElementCount[i]); } - return builder.getText() + return builder.getText(); } function createResidueText(ctx: VisualContext, structure: Structure, theme: Theme, props: LabelTextProps, text?: Text): Text { const l = StructureElement.Location.create(structure); const { units, serialMapping } = structure; const { auth_seq_id, label_comp_id } = StructureProperties.residue; - const { cumulativeUnitElementCount } = serialMapping + const { cumulativeUnitElementCount } = serialMapping; - const count = structure.polymerResidueCount * 2 - const { residueScale } = props - const builder = TextBuilder.create(props, count, count / 2, text) + const count = structure.polymerResidueCount * 2; + const { residueScale } = props; + const builder = TextBuilder.create(props, count, count / 2, text); for (let i = 0, il = units.length; i < il; ++i) { - const unit = units[i] + const unit = units[i]; const pos = unit.conformation.position; - const { elements } = unit - l.unit = unit - l.element = unit.elements[0] + const { elements } = unit; + l.unit = unit; + l.element = unit.elements[0]; const residueIndex = unit.model.atomicHierarchy.residueAtomSegments.index; - const groupOffset = cumulativeUnitElementCount[i] + const groupOffset = cumulativeUnitElementCount[i]; let j = 0, jl = elements.length; while (j < jl) { @@ -130,47 +130,47 @@ function createResidueText(ctx: VisualContext, structure: Structure, theme: Them l.element = elements[start]; - const { center, radius } = boundaryHelper.getSphere() - const authSeqId = auth_seq_id(l) - const compId = label_comp_id(l) + const { center, radius } = boundaryHelper.getSphere(); + const authSeqId = auth_seq_id(l); + const compId = label_comp_id(l); - const text = `${compId} ${authSeqId}` - builder.add(text, center[0], center[1], center[2], radius, residueScale, groupOffset + start) + const text = `${compId} ${authSeqId}`; + builder.add(text, center[0], center[1], center[2], radius, residueScale, groupOffset + start); } } - return builder.getText() + return builder.getText(); } function createElementText(ctx: VisualContext, structure: Structure, theme: Theme, props: LabelTextProps, text?: Text): Text { const l = StructureElement.Location.create(structure); const { units, serialMapping } = structure; const { label_atom_id, label_alt_id } = StructureProperties.atom; - const { cumulativeUnitElementCount } = serialMapping + const { cumulativeUnitElementCount } = serialMapping; - const sizeTheme = PhysicalSizeTheme({}, {}) + const sizeTheme = PhysicalSizeTheme({}, {}); - const count = structure.elementCount - const { elementScale } = props - const builder = TextBuilder.create(props, count, count / 2, text) + const count = structure.elementCount; + const { elementScale } = props; + const builder = TextBuilder.create(props, count, count / 2, text); for (let i = 0, il = units.length; i < il; ++i) { - const unit = units[i] + const unit = units[i]; const pos = unit.conformation.position; - const { elements } = unit - l.unit = unit + const { elements } = unit; + l.unit = unit; - const groupOffset = cumulativeUnitElementCount[i] + const groupOffset = cumulativeUnitElementCount[i]; for (let j = 0, _j = elements.length; j < _j; j++) { l.element = elements[j]; pos(l.element, tmpVec); - const atomId = label_atom_id(l) - const altId = label_alt_id(l) - const text = altId ? `${atomId}%${altId}` : atomId - builder.add(text, tmpVec[0], tmpVec[1], tmpVec[2], sizeTheme.size(l), elementScale, groupOffset + j) + const atomId = label_atom_id(l); + const altId = label_alt_id(l); + const text = altId ? `${atomId}%${altId}` : atomId; + builder.add(text, tmpVec[0], tmpVec[1], tmpVec[2], sizeTheme.size(l), elementScale, groupOffset + j); } } - return builder.getText() + return builder.getText(); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/molecular-surface-mesh.ts b/src/mol-repr/structure/visual/molecular-surface-mesh.ts index 5935d40ac544bf2bad9b7245c0003c53f15af2f7..1e8ea5aed80c871af8c324ccea4edb178df5a595 100644 --- a/src/mol-repr/structure/visual/molecular-surface-mesh.ts +++ b/src/mol-repr/structure/visual/molecular-surface-mesh.ts @@ -22,27 +22,27 @@ export const MolecularSurfaceMeshParams = { ...UnitsMeshParams, ...MolecularSurfaceCalculationParams, ...CommonSurfaceParams -} +}; export type MolecularSurfaceMeshParams = typeof MolecularSurfaceMeshParams // async function createMolecularSurfaceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: MolecularSurfaceProps, mesh?: Mesh): Promise<Mesh> { - const { transform, field, idField } = await computeUnitMolecularSurface(structure, unit, props).runInContext(ctx.runtime) + const { transform, field, idField } = await computeUnitMolecularSurface(structure, unit, props).runInContext(ctx.runtime); const params = { isoLevel: props.probeRadius, scalarField: field, idField - } - const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime) + }; + const surface = await computeMarchingCubesMesh(params, mesh).runAsChild(ctx.runtime); - Mesh.transform(surface, transform) - if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface) + Mesh.transform(surface, transform); + if (ctx.webgl && !ctx.webgl.isWebGL2) Mesh.uniformTriangleGroup(surface); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.probeRadius) - surface.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.probeRadius); + surface.setBoundingSphere(sphere); - return surface + return surface; } export function MolecularSurfaceMeshVisual(materialId: number): UnitsVisual<MolecularSurfaceMeshParams> { @@ -53,11 +53,11 @@ export function MolecularSurfaceMeshVisual(materialId: number): UnitsVisual<Mole getLoci: getElementLoci, eachLocation: eachElement, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<MolecularSurfaceMeshParams>, currentProps: PD.Values<MolecularSurfaceMeshParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true - if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true; + if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true; + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true; } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/molecular-surface-wireframe.ts b/src/mol-repr/structure/visual/molecular-surface-wireframe.ts index e27ab0cbd33af9bdff15bcb01b05a099c95d14ee..e3e6482f3bc7b110e80c4fbb9298abcc00934573 100644 --- a/src/mol-repr/structure/visual/molecular-surface-wireframe.ts +++ b/src/mol-repr/structure/visual/molecular-surface-wireframe.ts @@ -23,26 +23,26 @@ export const MolecularSurfaceWireframeParams = { ...MolecularSurfaceCalculationParams, ...CommonSurfaceParams, sizeFactor: PD.Numeric(1.5, { min: 0, max: 10, step: 0.1 }), -} +}; export type MolecularSurfaceWireframeParams = typeof MolecularSurfaceWireframeParams // async function createMolecularSurfaceWireframe(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: MolecularSurfaceProps, lines?: Lines): Promise<Lines> { - const { transform, field, idField } = await computeUnitMolecularSurface(structure, unit, props).runInContext(ctx.runtime) + const { transform, field, idField } = await computeUnitMolecularSurface(structure, unit, props).runInContext(ctx.runtime); const params = { isoLevel: props.probeRadius, scalarField: field, idField - } - const wireframe = await computeMarchingCubesLines(params, lines).runAsChild(ctx.runtime) + }; + const wireframe = await computeMarchingCubesLines(params, lines).runAsChild(ctx.runtime); - Lines.transform(wireframe, transform) + Lines.transform(wireframe, transform); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.probeRadius) - wireframe.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, props.probeRadius); + wireframe.setBoundingSphere(sphere); - return wireframe + return wireframe; } export function MolecularSurfaceWireframeVisual(materialId: number): UnitsVisual<MolecularSurfaceWireframeParams> { @@ -53,11 +53,11 @@ export function MolecularSurfaceWireframeVisual(materialId: number): UnitsVisual getLoci: getElementLoci, eachLocation: eachElement, setUpdateState: (state: VisualUpdateState, newProps: PD.Values<MolecularSurfaceWireframeParams>, currentProps: PD.Values<MolecularSurfaceWireframeParams>) => { - if (newProps.resolution !== currentProps.resolution) state.createGeometry = true - if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true - if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true - if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true - if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true + if (newProps.resolution !== currentProps.resolution) state.createGeometry = true; + if (newProps.probeRadius !== currentProps.probeRadius) state.createGeometry = true; + if (newProps.probePositions !== currentProps.probePositions) state.createGeometry = true; + if (newProps.ignoreHydrogens !== currentProps.ignoreHydrogens) state.createGeometry = true; + if (newProps.includeParent !== currentProps.includeParent) state.createGeometry = true; } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/nucleotide-block-mesh.ts b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts index 5ad7e8c14f480c76bd421ca6a7465b5ea2e95728..a5f195e23c5daa2587e7083442bc69a1d697987b 100644 --- a/src/mol-repr/structure/visual/nucleotide-block-mesh.ts +++ b/src/mol-repr/structure/visual/nucleotide-block-mesh.ts @@ -22,50 +22,50 @@ import { VisualUpdateState } from '../../util'; import { BaseGeometry } from '../../../mol-geo/geometry/base'; import { Sphere3D } from '../../../mol-math/geometry'; -const p1 = Vec3.zero() -const p2 = Vec3.zero() -const p3 = Vec3.zero() -const p4 = Vec3.zero() -const p5 = Vec3.zero() -const p6 = Vec3.zero() -const v12 = Vec3.zero() -const v34 = Vec3.zero() -const vC = Vec3.zero() -const center = Vec3.zero() -const t = Mat4.identity() -const sVec = Vec3.zero() -const box = Box() +const p1 = Vec3.zero(); +const p2 = Vec3.zero(); +const p3 = Vec3.zero(); +const p4 = Vec3.zero(); +const p5 = Vec3.zero(); +const p6 = Vec3.zero(); +const v12 = Vec3.zero(); +const v34 = Vec3.zero(); +const vC = Vec3.zero(); +const center = Vec3.zero(); +const t = Mat4.identity(); +const sVec = Vec3.zero(); +const box = Box(); export const NucleotideBlockMeshParams = { sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo), -} -export const DefaultNucleotideBlockMeshProps = PD.getDefaultValues(NucleotideBlockMeshParams) +}; +export const DefaultNucleotideBlockMeshProps = PD.getDefaultValues(NucleotideBlockMeshParams); export type NucleotideBlockMeshProps = typeof DefaultNucleotideBlockMeshProps function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: NucleotideBlockMeshProps, mesh?: Mesh) { - if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) + if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh); - const nucleotideElementCount = unit.nucleotideElements.length - if (!nucleotideElementCount) return Mesh.createEmpty(mesh) + const nucleotideElementCount = unit.nucleotideElements.length; + if (!nucleotideElementCount) return Mesh.createEmpty(mesh); - const { sizeFactor, radialSegments } = props + const { sizeFactor, radialSegments } = props; - const vertexCount = nucleotideElementCount * (box.vertices.length / 3 + radialSegments * 2) - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 4, mesh) + const vertexCount = nucleotideElementCount * (box.vertices.length / 3 + radialSegments * 2); + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 4, mesh); - const { elements, model } = unit - const { chainAtomSegments, residueAtomSegments, residues, index: atomicIndex } = model.atomicHierarchy - const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue - const { label_comp_id } = residues - const pos = unit.conformation.invariantPosition + const { elements, model } = unit; + const { chainAtomSegments, residueAtomSegments, residues, index: atomicIndex } = model.atomicHierarchy; + const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue; + const { label_comp_id } = residues; + const pos = unit.conformation.invariantPosition; - const chainIt = Segmentation.transientSegments(chainAtomSegments, elements) - const residueIt = Segmentation.transientSegments(residueAtomSegments, elements) + const chainIt = Segmentation.transientSegments(chainAtomSegments, elements); + const residueIt = Segmentation.transientSegments(residueAtomSegments, elements); - const cylinderProps: CylinderProps = { radiusTop: 1 * sizeFactor, radiusBottom: 1 * sizeFactor, radialSegments, bottomCap: true } + const cylinderProps: CylinderProps = { radiusTop: 1 * sizeFactor, radiusBottom: 1 * sizeFactor, radialSegments, bottomCap: true }; - let i = 0 + let i = 0; while (chainIt.hasNext) { residueIt.setSegment(chainIt.move()); @@ -73,80 +73,80 @@ function createNucleotideBlockMesh(ctx: VisualContext, unit: Unit, structure: St const { index: residueIndex } = residueIt.move(); if (isNucleic(moleculeType[residueIndex])) { - const compId = label_comp_id.value(residueIndex) - let idx1: ElementIndex | -1 = -1, idx2: ElementIndex | -1 = -1, idx3: ElementIndex | -1 = -1, idx4: ElementIndex | -1 = -1, idx5: ElementIndex | -1 = -1, idx6: ElementIndex | -1 = -1 - let width = 4.5, height = 4.5, depth = 2.5 * sizeFactor + const compId = label_comp_id.value(residueIndex); + let idx1: ElementIndex | -1 = -1, idx2: ElementIndex | -1 = -1, idx3: ElementIndex | -1 = -1, idx4: ElementIndex | -1 = -1, idx5: ElementIndex | -1 = -1, idx6: ElementIndex | -1 = -1; + let width = 4.5, height = 4.5, depth = 2.5 * sizeFactor; - let isPurine = isPurineBase(compId) - let isPyrimidine = isPyrimidineBase(compId) + let isPurine = isPurineBase(compId); + let isPyrimidine = isPyrimidineBase(compId); if (!isPurine && !isPyrimidine) { // detect Purine or Pyrimidin based on geometry - const idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') - const idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9') + const idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4'); + const idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9'); if (idxC4 !== -1 && idxN9 !== -1 && Vec3.distance(pos(idxC4, p1), pos(idxN9, p2)) < 1.6) { - isPurine = true + isPurine = true; } else { - isPyrimidine = true + isPyrimidine = true; } } if (isPurine) { - height = 4.5 - idx1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') - idx2 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') - idx3 = atomicIndex.findAtomOnResidue(residueIndex, 'C6') - idx4 = atomicIndex.findAtomOnResidue(residueIndex, 'C2') - idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'N9') - idx6 = traceElementIndex[residueIndex] + height = 4.5; + idx1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1'); + idx2 = atomicIndex.findAtomOnResidue(residueIndex, 'C4'); + idx3 = atomicIndex.findAtomOnResidue(residueIndex, 'C6'); + idx4 = atomicIndex.findAtomOnResidue(residueIndex, 'C2'); + idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'N9'); + idx6 = traceElementIndex[residueIndex]; } else if (isPyrimidine) { - height = 3.0 - idx1 = atomicIndex.findAtomOnResidue(residueIndex, 'N3') - idx2 = atomicIndex.findAtomOnResidue(residueIndex, 'C6') - idx3 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') - idx4 = atomicIndex.findAtomOnResidue(residueIndex, 'C2') - idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') + height = 3.0; + idx1 = atomicIndex.findAtomOnResidue(residueIndex, 'N3'); + idx2 = atomicIndex.findAtomOnResidue(residueIndex, 'C6'); + idx3 = atomicIndex.findAtomOnResidue(residueIndex, 'C4'); + idx4 = atomicIndex.findAtomOnResidue(residueIndex, 'C2'); + idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'N1'); if (idx5 === -1) { // modified ring, e.g. DZ - idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'C1') + idx5 = atomicIndex.findAtomOnResidue(residueIndex, 'C1'); } - idx6 = traceElementIndex[residueIndex] + idx6 = traceElementIndex[residueIndex]; } if (idx5 !== -1 && idx6 !== -1) { - pos(idx5, p5); pos(idx6, p6) - builderState.currentGroup = i - addCylinder(builderState, p5, p6, 1, cylinderProps) + pos(idx5, p5); pos(idx6, p6); + builderState.currentGroup = i; + addCylinder(builderState, p5, p6, 1, cylinderProps); if (idx1 !== -1 && idx2 !== -1 && idx3 !== -1 && idx4 !== -1) { pos(idx1, p1); pos(idx2, p2); pos(idx3, p3); pos(idx4, p4); - Vec3.normalize(v12, Vec3.sub(v12, p2, p1)) - Vec3.normalize(v34, Vec3.sub(v34, p4, p3)) - Vec3.normalize(vC, Vec3.cross(vC, v12, v34)) - Mat4.targetTo(t, p1, p2, vC) - Vec3.scaleAndAdd(center, p1, v12, height / 2 - 0.2) - Mat4.scale(t, t, Vec3.set(sVec, width, depth, height)) - Mat4.setTranslation(t, center) - MeshBuilder.addPrimitive(builderState, t, box) + Vec3.normalize(v12, Vec3.sub(v12, p2, p1)); + Vec3.normalize(v34, Vec3.sub(v34, p4, p3)); + Vec3.normalize(vC, Vec3.cross(vC, v12, v34)); + Mat4.targetTo(t, p1, p2, vC); + Vec3.scaleAndAdd(center, p1, v12, height / 2 - 0.2); + Mat4.scale(t, t, Vec3.set(sVec, width, depth, height)); + Mat4.setTranslation(t, center); + MeshBuilder.addPrimitive(builderState, t, box); } } - ++i + ++i; } } } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const NucleotideBlockParams = { ...UnitsMeshParams, ...NucleotideBlockMeshParams -} +}; export type NucleotideBlockParams = typeof NucleotideBlockParams export function NucleotideBlockVisual(materialId: number): UnitsVisual<NucleotideBlockParams> { @@ -160,7 +160,7 @@ export function NucleotideBlockVisual(materialId: number): UnitsVisual<Nucleotid state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts b/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts index e72aa3f07ae12a2c07587020d94a2c6f79f12954..dedc5a1eb9232e298d591fc0cd2531dd48e3a27d 100644 --- a/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts +++ b/src/mol-repr/structure/visual/nucleotide-ring-mesh.ts @@ -23,70 +23,70 @@ import { VisualUpdateState } from '../../util'; import { BaseGeometry } from '../../../mol-geo/geometry/base'; import { Sphere3D } from '../../../mol-math/geometry'; -const pTrace = Vec3.zero() -const pN1 = Vec3.zero() -const pC2 = Vec3.zero() -const pN3 = Vec3.zero() -const pC4 = Vec3.zero() -const pC5 = Vec3.zero() -const pC6 = Vec3.zero() -const pN7 = Vec3.zero() -const pC8 = Vec3.zero() -const pN9 = Vec3.zero() -const normal = Vec3.zero() +const pTrace = Vec3.zero(); +const pN1 = Vec3.zero(); +const pC2 = Vec3.zero(); +const pN3 = Vec3.zero(); +const pC4 = Vec3.zero(); +const pC5 = Vec3.zero(); +const pC6 = Vec3.zero(); +const pN7 = Vec3.zero(); +const pC8 = Vec3.zero(); +const pN9 = Vec3.zero(); +const normal = Vec3.zero(); export const NucleotideRingMeshParams = { sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo), detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }, BaseGeometry.CustomQualityParamInfo), -} -export const DefaultNucleotideRingMeshProps = PD.getDefaultValues(NucleotideRingMeshParams) +}; +export const DefaultNucleotideRingMeshProps = PD.getDefaultValues(NucleotideRingMeshParams); export type NucleotideRingProps = typeof DefaultNucleotideRingMeshProps -const positionsRing5_6 = new Float32Array(2 * 9 * 3) -const stripIndicesRing5_6 = new Uint32Array([0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 14, 15, 12, 13, 8, 9, 10, 11, 0, 1]) -const fanIndicesTopRing5_6 = new Uint32Array([8, 12, 14, 16, 6, 4, 2, 0, 10]) -const fanIndicesBottomRing5_6 = new Uint32Array([9, 11, 1, 3, 5, 7, 17, 15, 13]) +const positionsRing5_6 = new Float32Array(2 * 9 * 3); +const stripIndicesRing5_6 = new Uint32Array([0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 14, 15, 12, 13, 8, 9, 10, 11, 0, 1]); +const fanIndicesTopRing5_6 = new Uint32Array([8, 12, 14, 16, 6, 4, 2, 0, 10]); +const fanIndicesBottomRing5_6 = new Uint32Array([9, 11, 1, 3, 5, 7, 17, 15, 13]); -const positionsRing6 = new Float32Array(2 * 6 * 3) -const stripIndicesRing6 = new Uint32Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1]) -const fanIndicesTopRing6 = new Uint32Array([0, 10, 8, 6, 4, 2]) -const fanIndicesBottomRing6 = new Uint32Array([1, 3, 5, 7, 9, 11]) +const positionsRing6 = new Float32Array(2 * 6 * 3); +const stripIndicesRing6 = new Uint32Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1]); +const fanIndicesTopRing6 = new Uint32Array([0, 10, 8, 6, 4, 2]); +const fanIndicesBottomRing6 = new Uint32Array([1, 3, 5, 7, 9, 11]); -const tmpShiftV = Vec3.zero() +const tmpShiftV = Vec3.zero(); function shiftPositions(out: NumberArray, dir: Vec3, ...positions: Vec3[]) { for (let i = 0, il = positions.length; i < il; ++i) { - const v = positions[i] - Vec3.toArray(Vec3.add(tmpShiftV, v, dir), out, (i * 2) * 3) - Vec3.toArray(Vec3.sub(tmpShiftV, v, dir), out, (i * 2 + 1) * 3) + const v = positions[i]; + Vec3.toArray(Vec3.add(tmpShiftV, v, dir), out, (i * 2) * 3); + Vec3.toArray(Vec3.sub(tmpShiftV, v, dir), out, (i * 2 + 1) * 3); } } function createNucleotideRingMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: NucleotideRingProps, mesh?: Mesh) { - if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh) + if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh); - const nucleotideElementCount = unit.nucleotideElements.length - if (!nucleotideElementCount) return Mesh.createEmpty(mesh) + const nucleotideElementCount = unit.nucleotideElements.length; + if (!nucleotideElementCount) return Mesh.createEmpty(mesh); - const { sizeFactor, radialSegments, detail } = props + const { sizeFactor, radialSegments, detail } = props; - const vertexCount = nucleotideElementCount * (26 + radialSegments * 2) - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 4, mesh) + const vertexCount = nucleotideElementCount * (26 + radialSegments * 2); + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 4, mesh); - const { elements, model } = unit - const { chainAtomSegments, residueAtomSegments, residues, index: atomicIndex } = model.atomicHierarchy - const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue - const { label_comp_id } = residues - const pos = unit.conformation.invariantPosition + const { elements, model } = unit; + const { chainAtomSegments, residueAtomSegments, residues, index: atomicIndex } = model.atomicHierarchy; + const { moleculeType, traceElementIndex } = model.atomicHierarchy.derived.residue; + const { label_comp_id } = residues; + const pos = unit.conformation.invariantPosition; - const chainIt = Segmentation.transientSegments(chainAtomSegments, elements) - const residueIt = Segmentation.transientSegments(residueAtomSegments, elements) + const chainIt = Segmentation.transientSegments(chainAtomSegments, elements); + const residueIt = Segmentation.transientSegments(residueAtomSegments, elements); - const radius = 1 * sizeFactor - const halfThickness = 1.25 * sizeFactor - const cylinderProps: CylinderProps = { radiusTop: 1 * sizeFactor, radiusBottom: 1 * sizeFactor, radialSegments } + const radius = 1 * sizeFactor; + const halfThickness = 1.25 * sizeFactor; + const cylinderProps: CylinderProps = { radiusTop: 1 * sizeFactor, radiusBottom: 1 * sizeFactor, radialSegments }; - let i = 0 + let i = 0; while (chainIt.hasNext) { residueIt.setSegment(chainIt.move()); @@ -94,114 +94,114 @@ function createNucleotideRingMesh(ctx: VisualContext, unit: Unit, structure: Str const { index: residueIndex } = residueIt.move(); if (isNucleic(moleculeType[residueIndex])) { - const compId = label_comp_id.value(residueIndex) + const compId = label_comp_id.value(residueIndex); - let idxTrace: ElementIndex | -1 = -1, idxN1: ElementIndex | -1 = -1, idxC2: ElementIndex | -1 = -1, idxN3: ElementIndex | -1 = -1, idxC4: ElementIndex | -1 = -1, idxC5: ElementIndex | -1 = -1, idxC6: ElementIndex | -1 = -1, idxN7: ElementIndex | -1 = -1, idxC8: ElementIndex | -1 = -1, idxN9: ElementIndex | -1 = -1 + let idxTrace: ElementIndex | -1 = -1, idxN1: ElementIndex | -1 = -1, idxC2: ElementIndex | -1 = -1, idxN3: ElementIndex | -1 = -1, idxC4: ElementIndex | -1 = -1, idxC5: ElementIndex | -1 = -1, idxC6: ElementIndex | -1 = -1, idxN7: ElementIndex | -1 = -1, idxC8: ElementIndex | -1 = -1, idxN9: ElementIndex | -1 = -1; - builderState.currentGroup = i + builderState.currentGroup = i; - let isPurine = isPurineBase(compId) - let isPyrimidine = isPyrimidineBase(compId) + let isPurine = isPurineBase(compId); + let isPyrimidine = isPyrimidineBase(compId); if (!isPurine && !isPyrimidine) { // detect Purine or Pyrimidin based on geometry - const idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') - const idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9') + const idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4'); + const idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9'); if (idxC4 !== -1 && idxN9 !== -1 && Vec3.distance(pos(idxC4, pC4), pos(idxN9, pN9)) < 1.6) { - isPurine = true + isPurine = true; } else { - isPyrimidine = true + isPyrimidine = true; } } if (isPurine) { - idxTrace = traceElementIndex[residueIndex] - idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') - idxC2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2') - idxN3 = atomicIndex.findAtomOnResidue(residueIndex, 'N3') - idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') - idxC5 = atomicIndex.findAtomOnResidue(residueIndex, 'C5') + idxTrace = traceElementIndex[residueIndex]; + idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1'); + idxC2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2'); + idxN3 = atomicIndex.findAtomOnResidue(residueIndex, 'N3'); + idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4'); + idxC5 = atomicIndex.findAtomOnResidue(residueIndex, 'C5'); if (idxC5 === -1) { // modified ring, e.g. DP - idxC5 = atomicIndex.findAtomOnResidue(residueIndex, 'N5') + idxC5 = atomicIndex.findAtomOnResidue(residueIndex, 'N5'); } - idxC6 = atomicIndex.findAtomOnResidue(residueIndex, 'C6') - idxN7 = atomicIndex.findAtomOnResidue(residueIndex, 'N7') + idxC6 = atomicIndex.findAtomOnResidue(residueIndex, 'C6'); + idxN7 = atomicIndex.findAtomOnResidue(residueIndex, 'N7'); if (idxN7 === -1) { // modified ring, e.g. DP - idxN7 = atomicIndex.findAtomOnResidue(residueIndex, 'C7') + idxN7 = atomicIndex.findAtomOnResidue(residueIndex, 'C7'); } - idxC8 = atomicIndex.findAtomOnResidue(residueIndex, 'C8') - idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9') + idxC8 = atomicIndex.findAtomOnResidue(residueIndex, 'C8'); + idxN9 = atomicIndex.findAtomOnResidue(residueIndex, 'N9'); if (idxN9 !== -1 && idxTrace !== -1) { - pos(idxN9, pN9); pos(idxTrace, pTrace) - builderState.currentGroup = i - addCylinder(builderState, pN9, pTrace, 1, cylinderProps) - addSphere(builderState, pN9, radius, detail) + pos(idxN9, pN9); pos(idxTrace, pTrace); + builderState.currentGroup = i; + addCylinder(builderState, pN9, pTrace, 1, cylinderProps); + addSphere(builderState, pN9, radius, detail); } if (idxN1 !== -1 && idxC2 !== -1 && idxN3 !== -1 && idxC4 !== -1 && idxC5 !== -1 && idxC6 !== -1 && idxN7 !== -1 && idxC8 !== -1 && idxN9 !== -1 ) { - pos(idxN1, pN1); pos(idxC2, pC2); pos(idxN3, pN3); pos(idxC4, pC4); pos(idxC5, pC5); pos(idxC6, pC6); pos(idxN7, pN7); pos(idxC8, pC8) + pos(idxN1, pN1); pos(idxC2, pC2); pos(idxN3, pN3); pos(idxC4, pC4); pos(idxC5, pC5); pos(idxC6, pC6); pos(idxN7, pN7); pos(idxC8, pC8); - Vec3.triangleNormal(normal, pN1, pC4, pC5) - Vec3.scale(normal, normal, halfThickness) - shiftPositions(positionsRing5_6, normal, pN1, pC2, pN3, pC4, pC5, pC6, pN7, pC8, pN9) + Vec3.triangleNormal(normal, pN1, pC4, pC5); + Vec3.scale(normal, normal, halfThickness); + shiftPositions(positionsRing5_6, normal, pN1, pC2, pN3, pC4, pC5, pC6, pN7, pC8, pN9); - MeshBuilder.addTriangleStrip(builderState, positionsRing5_6, stripIndicesRing5_6) - MeshBuilder.addTriangleFan(builderState, positionsRing5_6, fanIndicesTopRing5_6) - MeshBuilder.addTriangleFan(builderState, positionsRing5_6, fanIndicesBottomRing5_6) + MeshBuilder.addTriangleStrip(builderState, positionsRing5_6, stripIndicesRing5_6); + MeshBuilder.addTriangleFan(builderState, positionsRing5_6, fanIndicesTopRing5_6); + MeshBuilder.addTriangleFan(builderState, positionsRing5_6, fanIndicesBottomRing5_6); } } else if (isPyrimidine) { - idxTrace = traceElementIndex[residueIndex] - idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1') + idxTrace = traceElementIndex[residueIndex]; + idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'N1'); if (idxN1 === -1) { // modified ring, e.g. DZ - idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'C1') + idxN1 = atomicIndex.findAtomOnResidue(residueIndex, 'C1'); } - idxC2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2') - idxN3 = atomicIndex.findAtomOnResidue(residueIndex, 'N3') - idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4') - idxC5 = atomicIndex.findAtomOnResidue(residueIndex, 'C5') - idxC6 = atomicIndex.findAtomOnResidue(residueIndex, 'C6') + idxC2 = atomicIndex.findAtomOnResidue(residueIndex, 'C2'); + idxN3 = atomicIndex.findAtomOnResidue(residueIndex, 'N3'); + idxC4 = atomicIndex.findAtomOnResidue(residueIndex, 'C4'); + idxC5 = atomicIndex.findAtomOnResidue(residueIndex, 'C5'); + idxC6 = atomicIndex.findAtomOnResidue(residueIndex, 'C6'); if (idxN1 !== -1 && idxTrace !== -1) { - pos(idxN1, pN1); pos(idxTrace, pTrace) - builderState.currentGroup = i - addCylinder(builderState, pN1, pTrace, 1, cylinderProps) - addSphere(builderState, pN1, radius, detail) + pos(idxN1, pN1); pos(idxTrace, pTrace); + builderState.currentGroup = i; + addCylinder(builderState, pN1, pTrace, 1, cylinderProps); + addSphere(builderState, pN1, radius, detail); } if (idxN1 !== -1 && idxC2 !== -1 && idxN3 !== -1 && idxC4 !== -1 && idxC5 !== -1 && idxC6 !== -1) { pos(idxC2, pC2); pos(idxN3, pN3); pos(idxC4, pC4); pos(idxC5, pC5); pos(idxC6, pC6); - Vec3.triangleNormal(normal, pN1, pC4, pC5) - Vec3.scale(normal, normal, halfThickness) - shiftPositions(positionsRing6, normal, pN1, pC2, pN3, pC4, pC5, pC6) + Vec3.triangleNormal(normal, pN1, pC4, pC5); + Vec3.scale(normal, normal, halfThickness); + shiftPositions(positionsRing6, normal, pN1, pC2, pN3, pC4, pC5, pC6); - MeshBuilder.addTriangleStrip(builderState, positionsRing6, stripIndicesRing6) - MeshBuilder.addTriangleFan(builderState, positionsRing6, fanIndicesTopRing6) - MeshBuilder.addTriangleFan(builderState, positionsRing6, fanIndicesBottomRing6) + MeshBuilder.addTriangleStrip(builderState, positionsRing6, stripIndicesRing6); + MeshBuilder.addTriangleFan(builderState, positionsRing6, fanIndicesTopRing6); + MeshBuilder.addTriangleFan(builderState, positionsRing6, fanIndicesBottomRing6); } } - ++i + ++i; } } } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const NucleotideRingParams = { ...UnitsMeshParams, ...NucleotideRingMeshParams -} +}; export type NucleotideRingParams = typeof NucleotideRingParams export function NucleotideRingVisual(materialId: number): UnitsVisual<NucleotideRingParams> { @@ -215,7 +215,7 @@ export function NucleotideRingVisual(materialId: number): UnitsVisual<Nucleotide state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/orientation-ellipsoid-mesh.ts b/src/mol-repr/structure/visual/orientation-ellipsoid-mesh.ts index 5d2ea8a211685fb778d09d48d9406dc928c7d586..75acf89dd808f678445b0ebb3388b32606bab18f 100644 --- a/src/mol-repr/structure/visual/orientation-ellipsoid-mesh.ts +++ b/src/mol-repr/structure/visual/orientation-ellipsoid-mesh.ts @@ -26,7 +26,7 @@ export const OrientationEllipsoidMeshParams = { ...UnitsMeshParams, sizeFactor: PD.Numeric(1, { min: 0, max: 2, step: 0.1 }), detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }), -} +}; export type OrientationEllipsoidMeshParams = typeof OrientationEllipsoidMeshParams export function OrientationEllipsoidMeshVisual(materialId: number): UnitsVisual<OrientationEllipsoidMeshParams> { @@ -40,9 +40,9 @@ export function OrientationEllipsoidMeshVisual(materialId: number): UnitsVisual< state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.detail !== currentProps.detail - ) + ); } - }, materialId) + }, materialId); } // @@ -53,83 +53,83 @@ export interface OrientationEllipsoidMeshProps { } function isUnitApplicable(unit: Unit) { - if (Unit.Traits.is(unit.traits, Unit.Trait.MultiChain)) return false - if (Unit.Traits.is(unit.traits, Unit.Trait.Partitioned)) return false - if (Unit.isCoarse(unit)) return true - if (unit.elements.length === 0) return false - unit.model.atomicHierarchy.derived.residue.moleculeType - const rI = unit.residueIndex[unit.elements[0]] - const mt = unit.model.atomicHierarchy.derived.residue.moleculeType[rI] - if (mt === MoleculeType.Ion) return false - if (mt === MoleculeType.Water) return false - return true + if (Unit.Traits.is(unit.traits, Unit.Trait.MultiChain)) return false; + if (Unit.Traits.is(unit.traits, Unit.Trait.Partitioned)) return false; + if (Unit.isCoarse(unit)) return true; + if (unit.elements.length === 0) return false; + unit.model.atomicHierarchy.derived.residue.moleculeType; + const rI = unit.residueIndex[unit.elements[0]]; + const mt = unit.model.atomicHierarchy.derived.residue.moleculeType[rI]; + if (mt === MoleculeType.Ion) return false; + if (mt === MoleculeType.Water) return false; + return true; } export function createOrientationEllipsoidMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: OrientationEllipsoidMeshProps, mesh?: Mesh): Mesh { - if (!isUnitApplicable(unit)) return Mesh.createEmpty(mesh) + if (!isUnitApplicable(unit)) return Mesh.createEmpty(mesh); - const { detail, sizeFactor } = props + const { detail, sizeFactor } = props; - const vertexCount = 256 - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh) - const axes = unit.principalAxes.boxAxes - const { origin, dirA, dirB } = axes + const vertexCount = 256; + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh); + const axes = unit.principalAxes.boxAxes; + const { origin, dirA, dirB } = axes; - const size = Axes3D.size(Vec3(), axes) - Vec3.scale(size, size, sizeFactor / 2) - const radiusScale = Vec3.create(size[2], size[1], size[0]) + const size = Axes3D.size(Vec3(), axes); + Vec3.scale(size, size, sizeFactor / 2); + const radiusScale = Vec3.create(size[2], size[1], size[0]); - builderState.currentGroup = 0 - addEllipsoid(builderState, origin, dirA, dirB, radiusScale, detail) + builderState.currentGroup = 0; + addEllipsoid(builderState, origin, dirA, dirB, radiusScale, detail); - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } // function UnitIterator(structureGroup: StructureGroup): LocationIterator { - const { group, structure } = structureGroup - const groupCount = 1 - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { group, structure } = structureGroup; + const groupCount = 1; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = unit.elements[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = unit.elements[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } function getUnitLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId } = pickingId + const { objectId, instanceId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] - const indices = OrderedSet.ofBounds(0, unit.elements.length) as OrderedSet<UnitIndex> - return StructureElement.Loci(structure, [{ unit, indices }]) + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; + const indices = OrderedSet.ofBounds(0, unit.elements.length) as OrderedSet<UnitIndex>; + return StructureElement.Loci(structure, [{ unit, indices }]); } - return EmptyLoci + return EmptyLoci; } function eachUnit(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.structure, structure)) return false - const elementCount = group.elements.length + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const elementCount = group.elements.length; for (const e of loci.elements) { - const unitIdx = group.unitIndexMap.get(e.unit.id) + const unitIdx = group.unitIndexMap.get(e.unit.id); if (unitIdx !== undefined) { if (OrderedSet.size(e.indices) === elementCount) { - if (apply(Interval.ofSingleton(unitIdx))) changed = true + if (apply(Interval.ofSingleton(unitIdx))) changed = true; } } } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts index d2bacb845c8cb1c68ba314608e1f28c5a2716873..3eb18b64cc01be71adbbe9dca39de6cc27bfd7a4 100644 --- a/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts +++ b/src/mol-repr/structure/visual/polymer-backbone-cylinder.ts @@ -24,53 +24,53 @@ import { Sphere3D } from '../../../mol-math/geometry'; export const PolymerBackboneCylinderParams = { sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo), -} -export const DefaultPolymerBackboneCylinderProps = PD.getDefaultValues(PolymerBackboneCylinderParams) +}; +export const DefaultPolymerBackboneCylinderProps = PD.getDefaultValues(PolymerBackboneCylinderParams); export type PolymerBackboneCylinderProps = typeof DefaultPolymerBackboneCylinderProps // TODO do group id based on polymer index not element index function createPolymerBackboneCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerBackboneCylinderProps, mesh?: Mesh) { - const polymerElementCount = unit.polymerElements.length - if (!polymerElementCount) return Mesh.createEmpty(mesh) + const polymerElementCount = unit.polymerElements.length; + if (!polymerElementCount) return Mesh.createEmpty(mesh); - const { radialSegments, sizeFactor } = props + const { radialSegments, sizeFactor } = props; - const vertexCountEstimate = radialSegments * 2 * polymerElementCount * 2 - const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 10, mesh) + const vertexCountEstimate = radialSegments * 2 * polymerElementCount * 2; + const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 10, mesh); - const { elements } = unit - const pos = unit.conformation.invariantPosition - const pA = Vec3.zero() - const pB = Vec3.zero() - const cylinderProps: CylinderProps = { radiusTop: 1, radiusBottom: 1, radialSegments } + const { elements } = unit; + const pos = unit.conformation.invariantPosition; + const pA = Vec3.zero(); + const pB = Vec3.zero(); + const cylinderProps: CylinderProps = { radiusTop: 1, radiusBottom: 1, radialSegments }; - const polymerBackboneIt = PolymerBackboneIterator(structure, unit) + const polymerBackboneIt = PolymerBackboneIterator(structure, unit); while (polymerBackboneIt.hasNext) { - const { centerA, centerB } = polymerBackboneIt.move() - pos(centerA.element, pA) - pos(centerB.element, pB) + const { centerA, centerB } = polymerBackboneIt.move(); + pos(centerA.element, pA); + pos(centerB.element, pB); - cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerA) * sizeFactor - builderState.currentGroup = OrderedSet.indexOf(elements, centerA.element) - addCylinder(builderState, pA, pB, 0.5, cylinderProps) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerA) * sizeFactor; + builderState.currentGroup = OrderedSet.indexOf(elements, centerA.element); + addCylinder(builderState, pA, pB, 0.5, cylinderProps); - cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerB) * sizeFactor - builderState.currentGroup = OrderedSet.indexOf(elements, centerB.element) - addCylinder(builderState, pB, pA, 0.5, cylinderProps) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerB) * sizeFactor; + builderState.currentGroup = OrderedSet.indexOf(elements, centerB.element); + addCylinder(builderState, pB, pA, 0.5, cylinderProps); } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const PolymerBackboneParams = { ...UnitsMeshParams, ...PolymerBackboneCylinderParams, -} +}; export type PolymerBackboneParams = typeof PolymerBackboneParams export function PolymerBackboneVisual(materialId: number): UnitsVisual<PolymerBackboneParams> { @@ -85,7 +85,7 @@ export function PolymerBackboneVisual(materialId: number): UnitsVisual<PolymerBa state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/polymer-direction-wedge.ts b/src/mol-repr/structure/visual/polymer-direction-wedge.ts index 6cd1606892100a387579d808715324c0e74cf352..36afb138999e500f84e6067ead207c60693d2d60 100644 --- a/src/mol-repr/structure/visual/polymer-direction-wedge.ts +++ b/src/mol-repr/structure/visual/polymer-direction-wedge.ts @@ -18,83 +18,83 @@ import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual } from '../units-visual'; import { VisualUpdateState } from '../../util'; import { Sphere3D } from '../../../mol-math/geometry'; -const t = Mat4.identity() -const sVec = Vec3.zero() -const n0 = Vec3.zero() -const n1 = Vec3.zero() -const upVec = Vec3.zero() +const t = Mat4.identity(); +const sVec = Vec3.zero(); +const n0 = Vec3.zero(); +const n1 = Vec3.zero(); +const upVec = Vec3.zero(); -const depthFactor = 4 -const widthFactor = 4 -const heightFactor = 6 +const depthFactor = 4; +const widthFactor = 4; +const heightFactor = 6; -const wedge = Wedge() +const wedge = Wedge(); export const PolymerDirectionWedgeParams = { sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }), -} -export const DefaultPolymerDirectionWedgeProps = PD.getDefaultValues(PolymerDirectionWedgeParams) +}; +export const DefaultPolymerDirectionWedgeProps = PD.getDefaultValues(PolymerDirectionWedgeParams); export type PolymerDirectionWedgeProps = typeof DefaultPolymerDirectionWedgeProps function createPolymerDirectionWedgeMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerDirectionWedgeProps, mesh?: Mesh) { - const polymerElementCount = unit.polymerElements.length + const polymerElementCount = unit.polymerElements.length; - if (!polymerElementCount) return Mesh.createEmpty(mesh) - const { sizeFactor } = props + if (!polymerElementCount) return Mesh.createEmpty(mesh); + const { sizeFactor } = props; - const vertexCount = polymerElementCount * 24 - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 10, mesh) - const linearSegments = 1 + const vertexCount = polymerElementCount * 24; + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 10, mesh); + const linearSegments = 1; - const state = createCurveSegmentState(linearSegments) - const { normalVectors, binormalVectors } = state + const state = createCurveSegmentState(linearSegments); + const { normalVectors, binormalVectors } = state; - let i = 0 - const polymerTraceIt = PolymerTraceIterator(unit, structure) + let i = 0; + const polymerTraceIt = PolymerTraceIterator(unit, structure); while (polymerTraceIt.hasNext) { - const v = polymerTraceIt.move() - builderState.currentGroup = i + const v = polymerTraceIt.move(); + builderState.currentGroup = i; - const isNucleicType = isNucleic(v.moleculeType) - const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta) - const tension = (isNucleicType || isSheet) ? 0.5 : 0.9 - const shift = isNucleicType ? 0.3 : 0.5 + const isNucleicType = isNucleic(v.moleculeType); + const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta); + const tension = (isNucleicType || isSheet) ? 0.5 : 0.9; + const shift = isNucleicType ? 0.3 : 0.5; - interpolateCurveSegment(state, v, tension, shift) + interpolateCurveSegment(state, v, tension, shift); if ((isSheet && !v.secStrucLast) || !isSheet) { - const size = theme.size.size(v.center) * sizeFactor - const depth = depthFactor * size - const width = widthFactor * size - const height = heightFactor * size - - const vectors = isNucleicType ? binormalVectors : normalVectors - Vec3.fromArray(n0, vectors, 0) - Vec3.fromArray(n1, vectors, 3) - Vec3.normalize(upVec, Vec3.add(upVec, n0, n1)) - - Mat4.targetTo(t, v.p3, v.p1, upVec) - Mat4.mul(t, t, Mat4.rotY90Z180) - Mat4.scale(t, t, Vec3.set(sVec, height, width, depth)) - Mat4.setTranslation(t, v.p2) - MeshBuilder.addPrimitive(builderState, t, wedge) + const size = theme.size.size(v.center) * sizeFactor; + const depth = depthFactor * size; + const width = widthFactor * size; + const height = heightFactor * size; + + const vectors = isNucleicType ? binormalVectors : normalVectors; + Vec3.fromArray(n0, vectors, 0); + Vec3.fromArray(n1, vectors, 3); + Vec3.normalize(upVec, Vec3.add(upVec, n0, n1)); + + Mat4.targetTo(t, v.p3, v.p1, upVec); + Mat4.mul(t, t, Mat4.rotY90Z180); + Mat4.scale(t, t, Vec3.set(sVec, height, width, depth)); + Mat4.setTranslation(t, v.p2); + MeshBuilder.addPrimitive(builderState, t, wedge); } - ++i + ++i; } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const PolymerDirectionParams = { ...UnitsMeshParams, ...PolymerDirectionWedgeParams -} +}; export type PolymerDirectionParams = typeof PolymerDirectionParams export function PolymerDirectionVisual(materialId: number): UnitsVisual<PolymerDirectionParams> { @@ -107,7 +107,7 @@ export function PolymerDirectionVisual(materialId: number): UnitsVisual<PolymerD setUpdateState: (state: VisualUpdateState, newProps: PD.Values<PolymerDirectionParams>, currentProps: PD.Values<PolymerDirectionParams>) => { state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/polymer-gap-cylinder.ts b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts index 35813e1c3db8f25a0bb0458a4adcf37b94085d17..5dcfbe56647cf0ee0bedbc86093457944182be68 100644 --- a/src/mol-repr/structure/visual/polymer-gap-cylinder.ts +++ b/src/mol-repr/structure/visual/polymer-gap-cylinder.ts @@ -20,13 +20,13 @@ import { BaseGeometry } from '../../../mol-geo/geometry/base'; import { Sphere3D } from '../../../mol-math/geometry'; // import { TriangularPyramid } from '../../../mol-geo/primitive/pyramid'; -const segmentCount = 10 +const segmentCount = 10; export const PolymerGapCylinderParams = { sizeFactor: PD.Numeric(0.2, { min: 0, max: 10, step: 0.01 }), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo), -} -export const DefaultPolymerGapCylinderProps = PD.getDefaultValues(PolymerGapCylinderParams) +}; +export const DefaultPolymerGapCylinderProps = PD.getDefaultValues(PolymerGapCylinderParams); export type PolymerGapCylinderProps = typeof DefaultPolymerGapCylinderProps // const triangularPyramid = TriangularPyramid() @@ -34,25 +34,25 @@ export type PolymerGapCylinderProps = typeof DefaultPolymerGapCylinderProps // const pd = Vec3.zero() function createPolymerGapCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerGapCylinderProps, mesh?: Mesh) { - const polymerGapCount = unit.gapElements.length - if (!polymerGapCount) return Mesh.createEmpty(mesh) + const polymerGapCount = unit.gapElements.length; + if (!polymerGapCount) return Mesh.createEmpty(mesh); - const { sizeFactor, radialSegments } = props + const { sizeFactor, radialSegments } = props; - const vertexCountEstimate = segmentCount * radialSegments * 2 * polymerGapCount * 2 - const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 10, mesh) + const vertexCountEstimate = segmentCount * radialSegments * 2 * polymerGapCount * 2; + const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 10, mesh); - const pos = unit.conformation.invariantPosition - const pA = Vec3.zero() - const pB = Vec3.zero() + const pos = unit.conformation.invariantPosition; + const pA = Vec3.zero(); + const pB = Vec3.zero(); const cylinderProps: CylinderProps = { radiusTop: 1, radiusBottom: 1, topCap: true, bottomCap: true, radialSegments - } + }; - let i = 0 - const polymerGapIt = PolymerGapIterator(structure, unit) + let i = 0; + const polymerGapIt = PolymerGapIterator(structure, unit); while (polymerGapIt.hasNext) { - const { centerA, centerB } = polymerGapIt.move() + const { centerA, centerB } = polymerGapIt.move(); if (centerA.element === centerB.element) { // TODO // builderState.currentGroup = i @@ -63,33 +63,33 @@ function createPolymerGapCylinderMesh(ctx: VisualContext, unit: Unit, structure: // Mat4.scale(t, t, Vec3.create(0.7, 0.7, 2.5)) // MeshBuilder.addPrimitive(builderState, t, triangularPyramid) } else { - pos(centerA.element, pA) - pos(centerB.element, pB) + pos(centerA.element, pA); + pos(centerB.element, pB); - cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerA) * sizeFactor - builderState.currentGroup = i - addFixedCountDashedCylinder(builderState, pA, pB, 0.5, segmentCount, cylinderProps) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerA) * sizeFactor; + builderState.currentGroup = i; + addFixedCountDashedCylinder(builderState, pA, pB, 0.5, segmentCount, cylinderProps); - cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerB) * sizeFactor - builderState.currentGroup = i + 1 - addFixedCountDashedCylinder(builderState, pB, pA, 0.5, segmentCount, cylinderProps) + cylinderProps.radiusTop = cylinderProps.radiusBottom = theme.size.size(centerB) * sizeFactor; + builderState.currentGroup = i + 1; + addFixedCountDashedCylinder(builderState, pB, pA, 0.5, segmentCount, cylinderProps); } - i += 2 + i += 2; } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const PolymerGapParams = { ...UnitsMeshParams, ...PolymerGapCylinderParams -} +}; export type PolymerGapParams = typeof PolymerGapParams export function PolymerGapVisual(materialId: number): UnitsVisual<PolymerGapParams> { @@ -103,7 +103,7 @@ export function PolymerGapVisual(materialId: number): UnitsVisual<PolymerGapPara state.createGeometry = ( newProps.sizeFactor !== currentProps.sizeFactor || newProps.radialSegments !== currentProps.radialSegments - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/polymer-trace-mesh.ts b/src/mol-repr/structure/visual/polymer-trace-mesh.ts index f8ec43bc88486231c33269853a234cbe9d42acb6..6a2fb15eebb6af2ff000a06bb47edc73a61ec2bf 100644 --- a/src/mol-repr/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-repr/structure/visual/polymer-trace-mesh.ts @@ -30,91 +30,91 @@ export const PolymerTraceMeshParams = { detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }, BaseGeometry.CustomQualityParamInfo), linearSegments: PD.Numeric(8, { min: 1, max: 48, step: 1 }, BaseGeometry.CustomQualityParamInfo), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo) -} -export const DefaultPolymerTraceMeshProps = PD.getDefaultValues(PolymerTraceMeshParams) +}; +export const DefaultPolymerTraceMeshProps = PD.getDefaultValues(PolymerTraceMeshParams); export type PolymerTraceMeshProps = typeof DefaultPolymerTraceMeshProps -const tmpV1 = Vec3() +const tmpV1 = Vec3(); function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerTraceMeshProps, mesh?: Mesh) { - const polymerElementCount = unit.polymerElements.length + const polymerElementCount = unit.polymerElements.length; - if (!polymerElementCount) return Mesh.createEmpty(mesh) - const { sizeFactor, detail, linearSegments, radialSegments, aspectRatio, arrowFactor } = props + if (!polymerElementCount) return Mesh.createEmpty(mesh); + const { sizeFactor, detail, linearSegments, radialSegments, aspectRatio, arrowFactor } = props; - const vertexCount = linearSegments * radialSegments * polymerElementCount + (radialSegments + 1) * polymerElementCount * 2 - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 10, mesh) + const vertexCount = linearSegments * radialSegments * polymerElementCount + (radialSegments + 1) * polymerElementCount * 2; + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 10, mesh); - const isCoarse = Unit.isCoarse(unit) - const state = createCurveSegmentState(linearSegments) - const { curvePoints, normalVectors, binormalVectors, widthValues, heightValues } = state + const isCoarse = Unit.isCoarse(unit); + const state = createCurveSegmentState(linearSegments); + const { curvePoints, normalVectors, binormalVectors, widthValues, heightValues } = state; - let i = 0 - const polymerTraceIt = PolymerTraceIterator(unit, structure) + let i = 0; + const polymerTraceIt = PolymerTraceIterator(unit, structure); while (polymerTraceIt.hasNext) { - const v = polymerTraceIt.move() - builderState.currentGroup = i + const v = polymerTraceIt.move(); + builderState.currentGroup = i; - const isNucleicType = isNucleic(v.moleculeType) - const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta) - const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix) - const tension = isHelix ? HelixTension : StandardTension - const shift = isNucleicType ? NucleicShift : StandardShift + const isNucleicType = isNucleic(v.moleculeType); + const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta); + const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix); + const tension = isHelix ? HelixTension : StandardTension; + const shift = isNucleicType ? NucleicShift : StandardShift; - interpolateCurveSegment(state, v, tension, shift) + interpolateCurveSegment(state, v, tension, shift); - let w0 = theme.size.size(v.centerPrev) * sizeFactor - let w1 = theme.size.size(v.center) * sizeFactor - let w2 = theme.size.size(v.centerNext) * sizeFactor + let w0 = theme.size.size(v.centerPrev) * sizeFactor; + let w1 = theme.size.size(v.center) * sizeFactor; + let w2 = theme.size.size(v.centerNext) * sizeFactor; if (isCoarse) { - w0 *= aspectRatio / 2 - w1 *= aspectRatio / 2 - w2 *= aspectRatio / 2 + w0 *= aspectRatio / 2; + w1 *= aspectRatio / 2; + w2 *= aspectRatio / 2; } - const startCap = v.secStrucFirst || v.coarseBackboneFirst || v.first - const endCap = v.secStrucLast || v.coarseBackboneLast || v.last + const startCap = v.secStrucFirst || v.coarseBackboneFirst || v.first; + const endCap = v.secStrucLast || v.coarseBackboneLast || v.last; - let segmentCount = linearSegments + let segmentCount = linearSegments; if (v.initial) { - segmentCount = Math.max(Math.round(linearSegments * shift), 1) - const offset = linearSegments - segmentCount - curvePoints.copyWithin(0, offset * 3) - binormalVectors.copyWithin(0, offset * 3) - normalVectors.copyWithin(0, offset * 3) - Vec3.fromArray(tmpV1, curvePoints, 3) - Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)) - Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, w1 * OverhangFactor) - Vec3.toArray(tmpV1, curvePoints, 0) + segmentCount = Math.max(Math.round(linearSegments * shift), 1); + const offset = linearSegments - segmentCount; + curvePoints.copyWithin(0, offset * 3); + binormalVectors.copyWithin(0, offset * 3); + normalVectors.copyWithin(0, offset * 3); + Vec3.fromArray(tmpV1, curvePoints, 3); + Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)); + Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, w1 * OverhangFactor); + Vec3.toArray(tmpV1, curvePoints, 0); } else if (v.final) { - segmentCount = Math.max(Math.round(linearSegments * (1 - shift)), 1) - Vec3.fromArray(tmpV1, curvePoints, segmentCount * 3 - 3) - Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)) - Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, w1 * OverhangFactor) - Vec3.toArray(tmpV1, curvePoints, segmentCount * 3) + segmentCount = Math.max(Math.round(linearSegments * (1 - shift)), 1); + Vec3.fromArray(tmpV1, curvePoints, segmentCount * 3 - 3); + Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)); + Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, w1 * OverhangFactor); + Vec3.toArray(tmpV1, curvePoints, segmentCount * 3); } if (v.initial === true && v.final === true) { - addSphere(builderState, v.p2, w1 * 2, detail) + addSphere(builderState, v.p2, w1 * 2, detail); } else if (isSheet) { - const h0 = w0 * aspectRatio - const h1 = w1 * aspectRatio - const h2 = w2 * aspectRatio - const arrowHeight = v.secStrucLast ? h1 * arrowFactor : 0 + const h0 = w0 * aspectRatio; + const h1 = w1 * aspectRatio; + const h2 = w2 * aspectRatio; + const arrowHeight = v.secStrucLast ? h1 * arrowFactor : 0; - interpolateSizes(state, w0, w1, w2, h0, h1, h2, shift) + interpolateSizes(state, w0, w1, w2, h0, h1, h2, shift); if (radialSegments === 2) { - addRibbon(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, arrowHeight) + addRibbon(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, arrowHeight); } else { - addSheet(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, arrowHeight, startCap, endCap) + addSheet(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, arrowHeight, startCap, endCap); } } else { - let h0: number, h1: number, h2: number + let h0: number, h1: number, h2: number; if (isHelix && !v.isCoarseBackbone) { - h0 = w0 * aspectRatio - h1 = w1 * aspectRatio - h2 = w2 * aspectRatio + h0 = w0 * aspectRatio; + h1 = w1 * aspectRatio; + h2 = w2 * aspectRatio; } else if (isNucleicType && !v.isCoarseBackbone) { h0 = w0 * aspectRatio; h1 = w1 * aspectRatio; @@ -123,43 +123,43 @@ function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Struc [w1, h1] = [h1, w1]; [w2, h2] = [h2, w2]; } else { - h0 = w0 - h1 = w1 - h2 = w2 + h0 = w0; + h1 = w1; + h2 = w2; } - interpolateSizes(state, w0, w1, w2, h0, h1, h2, shift) + interpolateSizes(state, w0, w1, w2, h0, h1, h2, shift); if (radialSegments === 2) { if (isNucleicType && !v.isCoarseBackbone) { // TODO find a cleaner way to swap normal and binormal for nucleic types - for (let i = 0, il = binormalVectors.length; i < il; i++) binormalVectors[i] *= -1 - addRibbon(builderState, curvePoints, binormalVectors, normalVectors, segmentCount, heightValues, widthValues, 0) + for (let i = 0, il = binormalVectors.length; i < il; i++) binormalVectors[i] *= -1; + addRibbon(builderState, curvePoints, binormalVectors, normalVectors, segmentCount, heightValues, widthValues, 0); } else { - addRibbon(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0) + addRibbon(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0); } } else if (radialSegments === 4) { - addSheet(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0, startCap, endCap) + addSheet(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0, startCap, endCap); } else { - addTube(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, radialSegments, widthValues, heightValues, 1, startCap, endCap) + addTube(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, radialSegments, widthValues, heightValues, 1, startCap, endCap); } } - ++i + ++i; } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const PolymerTraceParams = { ...UnitsMeshParams, ...PolymerTraceMeshParams -} +}; export type PolymerTraceParams = typeof PolymerTraceParams export function PolymerTraceVisual(materialId: number): UnitsVisual<PolymerTraceParams> { @@ -177,13 +177,13 @@ export function PolymerTraceVisual(materialId: number): UnitsVisual<PolymerTrace newProps.radialSegments !== currentProps.radialSegments || newProps.aspectRatio !== currentProps.aspectRatio || newProps.arrowFactor !== currentProps.arrowFactor - ) + ); - const secondaryStructureHash = SecondaryStructureProvider.get(newStructureGroup.structure).version + const secondaryStructureHash = SecondaryStructureProvider.get(newStructureGroup.structure).version; if ((state.info.secondaryStructureHash as number) !== secondaryStructureHash) { state.createGeometry = true; - state.info.secondaryStructureHash = secondaryStructureHash + state.info.secondaryStructureHash = secondaryStructureHash; } } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/polymer-tube-mesh.ts b/src/mol-repr/structure/visual/polymer-tube-mesh.ts index 3318e85fcc22d553c4eea3076cb5a280b7252456..d6ba7b90c6a66c3cc0e39847fce5ecf563bc534a 100644 --- a/src/mol-repr/structure/visual/polymer-tube-mesh.ts +++ b/src/mol-repr/structure/visual/polymer-tube-mesh.ts @@ -27,92 +27,92 @@ export const PolymerTubeMeshParams = { detail: PD.Numeric(0, { min: 0, max: 3, step: 1 }, BaseGeometry.CustomQualityParamInfo), linearSegments: PD.Numeric(8, { min: 1, max: 48, step: 1 }, BaseGeometry.CustomQualityParamInfo), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo), -} -export const DefaultPolymerTubeMeshProps = PD.getDefaultValues(PolymerTubeMeshParams) +}; +export const DefaultPolymerTubeMeshProps = PD.getDefaultValues(PolymerTubeMeshParams); export type PolymerTubeMeshProps = typeof DefaultPolymerTubeMeshProps -const tmpV1 = Vec3() +const tmpV1 = Vec3(); function createPolymerTubeMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PolymerTubeMeshProps, mesh?: Mesh) { - const polymerElementCount = unit.polymerElements.length + const polymerElementCount = unit.polymerElements.length; - if (!polymerElementCount) return Mesh.createEmpty(mesh) - const { sizeFactor, detail, linearSegments, radialSegments } = props + if (!polymerElementCount) return Mesh.createEmpty(mesh); + const { sizeFactor, detail, linearSegments, radialSegments } = props; - const vertexCount = linearSegments * radialSegments * polymerElementCount + (radialSegments + 1) * polymerElementCount * 2 - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 10, mesh) + const vertexCount = linearSegments * radialSegments * polymerElementCount + (radialSegments + 1) * polymerElementCount * 2; + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 10, mesh); - const state = createCurveSegmentState(linearSegments) - const { curvePoints, normalVectors, binormalVectors, widthValues, heightValues } = state + const state = createCurveSegmentState(linearSegments); + const { curvePoints, normalVectors, binormalVectors, widthValues, heightValues } = state; - let i = 0 - const polymerTraceIt = PolymerTraceIterator(unit, structure) + let i = 0; + const polymerTraceIt = PolymerTraceIterator(unit, structure); while (polymerTraceIt.hasNext) { - const v = polymerTraceIt.move() - builderState.currentGroup = i + const v = polymerTraceIt.move(); + builderState.currentGroup = i; - const isNucleicType = isNucleic(v.moleculeType) - const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix) - const tension = isHelix ? HelixTension : StandardTension - const shift = isNucleicType ? NucleicShift : StandardShift + const isNucleicType = isNucleic(v.moleculeType); + const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix); + const tension = isHelix ? HelixTension : StandardTension; + const shift = isNucleicType ? NucleicShift : StandardShift; - interpolateCurveSegment(state, v, tension, shift) + interpolateCurveSegment(state, v, tension, shift); - const startCap = v.secStrucFirst || v.coarseBackboneFirst || v.first - const endCap = v.secStrucLast || v.coarseBackboneLast || v.last + const startCap = v.secStrucFirst || v.coarseBackboneFirst || v.first; + const endCap = v.secStrucLast || v.coarseBackboneLast || v.last; - let s0 = theme.size.size(v.centerPrev) * sizeFactor - let s1 = theme.size.size(v.center) * sizeFactor - let s2 = theme.size.size(v.centerNext) * sizeFactor + let s0 = theme.size.size(v.centerPrev) * sizeFactor; + let s1 = theme.size.size(v.center) * sizeFactor; + let s2 = theme.size.size(v.centerNext) * sizeFactor; - interpolateSizes(state, s0, s1, s2, s0, s1, s2, shift) + interpolateSizes(state, s0, s1, s2, s0, s1, s2, shift); - let segmentCount = linearSegments + let segmentCount = linearSegments; if (v.initial) { - segmentCount = Math.max(Math.round(linearSegments * shift), 1) - const offset = linearSegments - segmentCount - curvePoints.copyWithin(0, offset * 3) - binormalVectors.copyWithin(0, offset * 3) - normalVectors.copyWithin(0, offset * 3) - widthValues.copyWithin(0, offset * 3) - heightValues.copyWithin(0, offset * 3) - Vec3.fromArray(tmpV1, curvePoints, 3) - Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)) - Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, s1 * OverhangFactor) - Vec3.toArray(tmpV1, curvePoints, 0) + segmentCount = Math.max(Math.round(linearSegments * shift), 1); + const offset = linearSegments - segmentCount; + curvePoints.copyWithin(0, offset * 3); + binormalVectors.copyWithin(0, offset * 3); + normalVectors.copyWithin(0, offset * 3); + widthValues.copyWithin(0, offset * 3); + heightValues.copyWithin(0, offset * 3); + Vec3.fromArray(tmpV1, curvePoints, 3); + Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)); + Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, s1 * OverhangFactor); + Vec3.toArray(tmpV1, curvePoints, 0); } else if (v.final) { - segmentCount = Math.max(Math.round(linearSegments * (1 - shift)), 1) - Vec3.fromArray(tmpV1, curvePoints, segmentCount * 3 - 3) - Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)) - Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, s1 * OverhangFactor) - Vec3.toArray(tmpV1, curvePoints, segmentCount * 3) + segmentCount = Math.max(Math.round(linearSegments * (1 - shift)), 1); + Vec3.fromArray(tmpV1, curvePoints, segmentCount * 3 - 3); + Vec3.normalize(tmpV1, Vec3.sub(tmpV1, v.p2, tmpV1)); + Vec3.scaleAndAdd(tmpV1, v.p2, tmpV1, s1 * OverhangFactor); + Vec3.toArray(tmpV1, curvePoints, segmentCount * 3); } if (v.initial === true && v.final === true) { - addSphere(builderState, v.p2, s1 * 2, detail) + addSphere(builderState, v.p2, s1 * 2, detail); } else if (radialSegments === 2) { - addRibbon(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0) + addRibbon(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0); } else if (radialSegments === 4) { - addSheet(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0, startCap, endCap) + addSheet(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, widthValues, heightValues, 0, startCap, endCap); } else { - addTube(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, radialSegments, widthValues, heightValues, 1, startCap, endCap) + addTube(builderState, curvePoints, normalVectors, binormalVectors, segmentCount, radialSegments, widthValues, heightValues, 1, startCap, endCap); } - ++i + ++i; } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * props.sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export const PolymerTubeParams = { ...UnitsMeshParams, ...PolymerTubeMeshParams -} +}; export type PolymerTubeParams = typeof PolymerTubeParams export function PolymerTubeVisual(materialId: number): UnitsVisual<PolymerTubeParams> { @@ -128,7 +128,7 @@ export function PolymerTubeVisual(materialId: number): UnitsVisual<PolymerTubePa newProps.detail !== currentProps.detail || newProps.linearSegments !== currentProps.linearSegments || newProps.radialSegments !== currentProps.radialSegments - ) + ); } - }, materialId) + }, materialId); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/bond.ts b/src/mol-repr/structure/visual/util/bond.ts index 1b05d5e840b9fcd865fd146157d940e909e29828..2feb4bbf55ab006e70237db959845d6a8636a0c7 100644 --- a/src/mol-repr/structure/visual/util/bond.ts +++ b/src/mol-repr/structure/visual/util/bond.ts @@ -15,40 +15,40 @@ export const BondCylinderParams = { ...LinkCylinderParams, includeTypes: PD.MultiSelect(Object.keys(BondType.Names) as BondType.Names[], PD.objectToOptions(BondType.Names)), excludeTypes: PD.MultiSelect([] as BondType.Names[], PD.objectToOptions(BondType.Names)), -} -export const DefaultBondCylinderProps = PD.getDefaultValues(BondCylinderParams) +}; +export const DefaultBondCylinderProps = PD.getDefaultValues(BondCylinderParams); export type BondCylinderProps = typeof DefaultBondCylinderProps export function ignoreBondType(include: BondType.Flag, exclude: BondType.Flag, f: BondType.Flag) { - return !BondType.is(include, f) || BondType.is(exclude, f) + return !BondType.is(include, f) || BondType.is(exclude, f); } export namespace BondIterator { export function fromGroup(structureGroup: StructureGroup): LocationIterator { - const { group, structure } = structureGroup - const unit = group.units[0] - const groupCount = Unit.isAtomic(unit) ? unit.bonds.edgeCount * 2 : 0 - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { group, structure } = structureGroup; + const unit = group.units[0]; + const groupCount = Unit.isAtomic(unit) ? unit.bonds.edgeCount * 2 : 0; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = unit.elements[(unit as Unit.Atomic).bonds.a[groupIndex]] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = unit.elements[(unit as Unit.Atomic).bonds.a[groupIndex]]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } export function fromStructure(structure: Structure): LocationIterator { - const groupCount = structure.interUnitBonds.edgeCount - const instanceCount = 1 - const location = StructureElement.Location.create(structure) + const groupCount = structure.interUnitBonds.edgeCount; + const instanceCount = 1; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number) => { - const bond = structure.interUnitBonds.edges[groupIndex] - location.unit = bond.unitA - location.element = bond.unitA.elements[bond.indexA] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + const bond = structure.interUnitBonds.edges[groupIndex]; + location.unit = bond.unitA; + location.element = bond.unitA.elements[bond.indexA]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/common.ts b/src/mol-repr/structure/visual/util/common.ts index bd3e4fdbafa03d367c7fda87600a75c569befc1c..ebc5eb17e179c5dc76dde85fa1676f8467e4e6aa 100644 --- a/src/mol-repr/structure/visual/util/common.ts +++ b/src/mol-repr/structure/visual/util/common.ts @@ -18,19 +18,19 @@ import { getBoundary } from '../../../../mol-math/geometry/boundary'; /** Return a Loci for the elements of a whole residue the elementIndex belongs to. */ export function getResidueLoci(structure: Structure, unit: Unit.Atomic, elementIndex: ElementIndex): Loci { - const { elements, model } = unit + const { elements, model } = unit; if (OrderedSet.indexOf(elements, elementIndex) !== -1) { - const { index, offsets } = model.atomicHierarchy.residueAtomSegments - const rI = index[elementIndex] - const _indices: number[] = [] + const { index, offsets } = model.atomicHierarchy.residueAtomSegments; + const rI = index[elementIndex]; + const _indices: number[] = []; for (let i = offsets[rI], il = offsets[rI + 1]; i < il; ++i) { - const unitIndex = OrderedSet.indexOf(elements, i) - if (unitIndex !== -1) _indices.push(unitIndex) + const unitIndex = OrderedSet.indexOf(elements, i); + if (unitIndex !== -1) _indices.push(unitIndex); } - const indices = OrderedSet.ofSortedArray<StructureElement.UnitIndex>(SortedArray.ofSortedArray(_indices)) - return StructureElement.Loci(structure, [{ unit, indices }]) + const indices = OrderedSet.ofSortedArray<StructureElement.UnitIndex>(SortedArray.ofSortedArray(_indices)); + return StructureElement.Loci(structure, [{ unit, indices }]); } - return EmptyLoci + return EmptyLoci; } /** @@ -38,72 +38,72 @@ export function getResidueLoci(structure: Structure, unit: Unit.Atomic, elementI * restrict to elements that have the same label_alt_id or none */ export function getAltResidueLoci(structure: Structure, unit: Unit.Atomic, elementIndex: ElementIndex) { - const { elements, model } = unit - const { label_alt_id } = model.atomicHierarchy.atoms - const elementAltId = label_alt_id.value(elementIndex) + const { elements, model } = unit; + const { label_alt_id } = model.atomicHierarchy.atoms; + const elementAltId = label_alt_id.value(elementIndex); if (OrderedSet.indexOf(elements, elementIndex) !== -1) { - const { index } = model.atomicHierarchy.residueAtomSegments - const rI = index[elementIndex] - return getAltResidueLociFromId(structure, unit, rI, elementAltId) + const { index } = model.atomicHierarchy.residueAtomSegments; + const rI = index[elementIndex]; + return getAltResidueLociFromId(structure, unit, rI, elementAltId); } - return StructureElement.Loci(structure, []) + return StructureElement.Loci(structure, []); } export function getAltResidueLociFromId(structure: Structure, unit: Unit.Atomic, residueIndex: ResidueIndex, elementAltId: string) { - const { elements, model } = unit - const { label_alt_id } = model.atomicHierarchy.atoms - const { offsets } = model.atomicHierarchy.residueAtomSegments + const { elements, model } = unit; + const { label_alt_id } = model.atomicHierarchy.atoms; + const { offsets } = model.atomicHierarchy.residueAtomSegments; - const _indices: number[] = [] + const _indices: number[] = []; for (let i = offsets[residueIndex], il = offsets[residueIndex + 1]; i < il; ++i) { - const unitIndex = OrderedSet.indexOf(elements, i) + const unitIndex = OrderedSet.indexOf(elements, i); if (unitIndex !== -1) { - const altId = label_alt_id.value(i) + const altId = label_alt_id.value(i); if (elementAltId === altId || altId === '') { - _indices.push(unitIndex) + _indices.push(unitIndex); } } } - const indices = OrderedSet.ofSortedArray<StructureElement.UnitIndex>(SortedArray.ofSortedArray(_indices)) - return StructureElement.Loci(structure, [{ unit, indices }]) + const indices = OrderedSet.ofSortedArray<StructureElement.UnitIndex>(SortedArray.ofSortedArray(_indices)); + return StructureElement.Loci(structure, [{ unit, indices }]); } // export function createUnitsTransform({ units }: Unit.SymmetryGroup, transformData?: TransformData) { - const unitCount = units.length - const n = unitCount * 16 - const array = transformData && transformData.aTransform.ref.value.length >= n ? transformData.aTransform.ref.value : new Float32Array(n) + const unitCount = units.length; + const n = unitCount * 16; + const array = transformData && transformData.aTransform.ref.value.length >= n ? transformData.aTransform.ref.value : new Float32Array(n); for (let i = 0; i < unitCount; i++) { - Mat4.toArray(units[i].conformation.operator.matrix, array, i * 16) + Mat4.toArray(units[i].conformation.operator.matrix, array, i * 16); } - return createTransform(array, unitCount, transformData) + return createTransform(array, unitCount, transformData); } export const UnitKindInfo = { 'atomic': {}, 'spheres': {}, 'gaussians': {}, -} +}; export type UnitKind = keyof typeof UnitKindInfo -export const UnitKindOptions = PD.objectToOptions(UnitKindInfo) +export const UnitKindOptions = PD.objectToOptions(UnitKindInfo); export function includesUnitKind(unitKinds: UnitKind[], unit: Unit) { for (let i = 0, il = unitKinds.length; i < il; ++i) { - if (Unit.isAtomic(unit) && unitKinds[i] === 'atomic') return true - if (Unit.isSpheres(unit) && unitKinds[i] === 'spheres') return true - if (Unit.isGaussians(unit) && unitKinds[i] === 'gaussians') return true + if (Unit.isAtomic(unit) && unitKinds[i] === 'atomic') return true; + if (Unit.isSpheres(unit) && unitKinds[i] === 'spheres') return true; + if (Unit.isGaussians(unit) && unitKinds[i] === 'gaussians') return true; } - return false + return false; } // export function getConformation(unit: Unit) { switch (unit.kind) { - case Unit.Kind.Atomic: return unit.model.atomicConformation - case Unit.Kind.Spheres: return unit.model.coarseConformation.spheres - case Unit.Kind.Gaussians: return unit.model.coarseConformation.gaussians + case Unit.Kind.Atomic: return unit.model.atomicConformation; + case Unit.Kind.Spheres: return unit.model.coarseConformation.spheres; + case Unit.Kind.Gaussians: return unit.model.coarseConformation.gaussians; } } @@ -111,160 +111,160 @@ export const CommonSurfaceParams = { ignoreHydrogens: PD.Boolean(false, { description: 'Whether or not to include hydrogen atoms in the surface calculation.' }), traceOnly: PD.Boolean(false, { description: 'Whether or not to only use trace atoms in the surface calculation.' }), includeParent: PD.Boolean(false, { description: 'Include elements of the parent structure in surface calculation to get a surface patch of the current structure.' }), -} -export const DefaultCommonSurfaceProps = PD.getDefaultValues(CommonSurfaceParams) +}; +export const DefaultCommonSurfaceProps = PD.getDefaultValues(CommonSurfaceParams); export type CommonSurfaceProps = typeof DefaultCommonSurfaceProps -const v = Vec3() +const v = Vec3(); function squaredDistance(x: number, y: number, z: number, center: Vec3) { - return Vec3.squaredDistance(Vec3.set(v, x, y, z), center) + return Vec3.squaredDistance(Vec3.set(v, x, y, z), center); } /** marks `indices` for filtering/ignoring in `id` when not in `elements` */ function filterId(id: AssignableArrayLike<number>, elements: SortedArray, indices: SortedArray) { - let start = 0 - const end = elements.length + let start = 0; + const end = elements.length; for (let i = 0, il = indices.length; i < il; ++i) { - const idx = SortedArray.indexOfInRange(elements, indices[i], start, end) + const idx = SortedArray.indexOfInRange(elements, indices[i], start, end); if (idx === -1) { - id[i] = -2 + id[i] = -2; } else { - id[i] = idx - start = idx + id[i] = idx; + start = idx; } } } export function getUnitConformationAndRadius(structure: Structure, unit: Unit, props: CommonSurfaceProps) { - const { ignoreHydrogens, traceOnly, includeParent } = props - const rootUnit = includeParent ? structure.root.unitMap.get(unit.id) : unit + const { ignoreHydrogens, traceOnly, includeParent } = props; + const rootUnit = includeParent ? structure.root.unitMap.get(unit.id) : unit; - const { x, y, z } = getConformation(rootUnit) - const { elements } = rootUnit - const { center, radius: sphereRadius } = unit.boundary.sphere - const extraRadius = (2 + 1.5) * 2 // TODO should be twice (the max vdW/sphere radius plus the probe radius) - const radiusSq = (sphereRadius + extraRadius) * (sphereRadius + extraRadius) + const { x, y, z } = getConformation(rootUnit); + const { elements } = rootUnit; + const { center, radius: sphereRadius } = unit.boundary.sphere; + const extraRadius = (2 + 1.5) * 2; // TODO should be twice (the max vdW/sphere radius plus the probe radius) + const radiusSq = (sphereRadius + extraRadius) * (sphereRadius + extraRadius); - let indices: SortedArray<ElementIndex> - let id: AssignableArrayLike<number> + let indices: SortedArray<ElementIndex>; + let id: AssignableArrayLike<number>; if (ignoreHydrogens || (includeParent && rootUnit !== unit)) { - const _indices = [] - const _id = [] + const _indices = []; + const _id = []; for (let i = 0, il = elements.length; i < il; ++i) { - const eI = elements[i] - if (ignoreHydrogens && isHydrogen(rootUnit, eI)) continue - if (traceOnly && !isTrace(rootUnit, eI)) continue - if (includeParent && squaredDistance(x[eI], y[eI], z[eI], center) > radiusSq) continue + const eI = elements[i]; + if (ignoreHydrogens && isHydrogen(rootUnit, eI)) continue; + if (traceOnly && !isTrace(rootUnit, eI)) continue; + if (includeParent && squaredDistance(x[eI], y[eI], z[eI], center) > radiusSq) continue; - _indices.push(eI) - _id.push(i) + _indices.push(eI); + _id.push(i); } - indices = SortedArray.ofSortedArray(_indices) - id = _id + indices = SortedArray.ofSortedArray(_indices); + id = _id; } else { - indices = elements - id = fillSerial(new Int32Array(indices.length)) + indices = elements; + id = fillSerial(new Int32Array(indices.length)); } if (includeParent && rootUnit !== unit) { - filterId(id, unit.elements, indices) + filterId(id, unit.elements, indices); } - const position = { indices, x, y, z, id } - const boundary = unit === rootUnit ? unit.boundary : getBoundary(position) + const position = { indices, x, y, z, id }; + const boundary = unit === rootUnit ? unit.boundary : getBoundary(position); - const l = StructureElement.Location.create(structure, rootUnit) - const sizeTheme = PhysicalSizeTheme({}, {}) + const l = StructureElement.Location.create(structure, rootUnit); + const sizeTheme = PhysicalSizeTheme({}, {}); const radius = (index: number) => { - l.element = index as ElementIndex - return sizeTheme.size(l) - } + l.element = index as ElementIndex; + return sizeTheme.size(l); + }; - return { position, boundary, radius } + return { position, boundary, radius }; } export function getStructureConformationAndRadius(structure: Structure, ignoreHydrogens: boolean, traceOnly: boolean) { - const l = StructureElement.Location.create(structure) - const sizeTheme = PhysicalSizeTheme({}, {}) + const l = StructureElement.Location.create(structure); + const sizeTheme = PhysicalSizeTheme({}, {}); - let xs: ArrayLike<number> - let ys: ArrayLike<number> - let zs: ArrayLike<number> - let rs: ArrayLike<number> - let id: ArrayLike<number> + let xs: ArrayLike<number>; + let ys: ArrayLike<number>; + let zs: ArrayLike<number>; + let rs: ArrayLike<number>; + let id: ArrayLike<number>; if (ignoreHydrogens || traceOnly) { - const _xs: number[] = [] - const _ys: number[] = [] - const _zs: number[] = [] - const _rs: number[] = [] - const _id: number[] = [] + const _xs: number[] = []; + const _ys: number[] = []; + const _zs: number[] = []; + const _rs: number[] = []; + const _id: number[] = []; for (let i = 0, m = 0, il = structure.units.length; i < il; ++i) { - const unit = structure.units[i] - const { elements } = unit - const { x, y, z } = unit.conformation + const unit = structure.units[i]; + const { elements } = unit; + const { x, y, z } = unit.conformation; - l.unit = unit + l.unit = unit; for (let j = 0, jl = elements.length; j < jl; ++j) { - const eI = elements[j] - if (ignoreHydrogens && isHydrogen(unit, eI)) continue - if (traceOnly && !isTrace(unit, eI)) continue - - _xs.push(x(eI)) - _ys.push(y(eI)) - _zs.push(z(eI)) - l.element = eI - _rs.push(sizeTheme.size(l)) - _id.push(m + j) + const eI = elements[j]; + if (ignoreHydrogens && isHydrogen(unit, eI)) continue; + if (traceOnly && !isTrace(unit, eI)) continue; + + _xs.push(x(eI)); + _ys.push(y(eI)); + _zs.push(z(eI)); + l.element = eI; + _rs.push(sizeTheme.size(l)); + _id.push(m + j); } - m += elements.length + m += elements.length; } - xs = _xs, ys = _ys, zs = _zs, rs = _rs - id = _id + xs = _xs, ys = _ys, zs = _zs, rs = _rs; + id = _id; } else { - const { elementCount } = structure - const _xs = new Float32Array(elementCount) - const _ys = new Float32Array(elementCount) - const _zs = new Float32Array(elementCount) - const _rs = new Float32Array(elementCount) + const { elementCount } = structure; + const _xs = new Float32Array(elementCount); + const _ys = new Float32Array(elementCount); + const _zs = new Float32Array(elementCount); + const _rs = new Float32Array(elementCount); for (let i = 0, m = 0, il = structure.units.length; i < il; ++i) { - const unit = structure.units[i] - const { elements } = unit - const { x, y, z } = unit.conformation - l.unit = unit + const unit = structure.units[i]; + const { elements } = unit; + const { x, y, z } = unit.conformation; + l.unit = unit; for (let j = 0, jl = elements.length; j < jl; ++j) { - const eI = elements[j] - - const mj = m + j - _xs[mj] = x(eI) - _ys[mj] = y(eI) - _zs[mj] = z(eI) - l.element = eI - _rs[mj] = sizeTheme.size(l) + const eI = elements[j]; + + const mj = m + j; + _xs[mj] = x(eI); + _ys[mj] = y(eI); + _zs[mj] = z(eI); + l.element = eI; + _rs[mj] = sizeTheme.size(l); } - m += elements.length + m += elements.length; } - xs = _xs, ys = _ys, zs = _zs, rs = _rs - id = fillSerial(new Uint32Array(elementCount)) + xs = _xs, ys = _ys, zs = _zs, rs = _rs; + id = fillSerial(new Uint32Array(elementCount)); } - const position = { indices: OrderedSet.ofRange(0, id.length), x: xs, y: ys, z: zs, id } - const radius = (index: number) => rs[index] + const position = { indices: OrderedSet.ofRange(0, id.length), x: xs, y: ys, z: zs, id }; + const radius = (index: number) => rs[index]; - return { position, radius } + return { position, radius }; } -const _H = AtomicNumbers['H'] +const _H = AtomicNumbers['H']; export function isHydrogen(unit: Unit, element: ElementIndex) { - if (Unit.isCoarse(unit)) return false - if (AtomNumber(unit.model.atomicHierarchy.atoms.type_symbol.value(element)) === _H) return true - return false + if (Unit.isCoarse(unit)) return false; + if (AtomNumber(unit.model.atomicHierarchy.atoms.type_symbol.value(element)) === _H) return true; + return false; } export function isTrace(unit: Unit, element: ElementIndex) { - if (Unit.isCoarse(unit)) return true - const atomId = unit.model.atomicHierarchy.atoms.label_atom_id.value(element) - if (atomId === 'CA' || atomId === 'P') return true - return false + if (Unit.isCoarse(unit)) return true; + const atomId = unit.model.atomicHierarchy.atoms.label_atom_id.value(element); + if (atomId === 'CA' || atomId === 'P') return true; + return false; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/element.ts b/src/mol-repr/structure/visual/util/element.ts index 3f93d7538d71e4332e8f47a4a333236b4244c4ed..4a48adecff2c0b28e27307aed21a2767b5497051 100644 --- a/src/mol-repr/structure/visual/util/element.ts +++ b/src/mol-repr/structure/visual/util/element.ts @@ -31,35 +31,35 @@ export interface ElementSphereMeshProps { } export function createElementSphereMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementSphereMeshProps, mesh?: Mesh): Mesh { - const { detail, sizeFactor, ignoreHydrogens, traceOnly } = props + const { detail, sizeFactor, ignoreHydrogens, traceOnly } = props; const { elements } = unit; const elementCount = elements.length; - const vertexCount = elementCount * sphereVertexCount(detail) - const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh) + const vertexCount = elementCount * sphereVertexCount(detail); + const builderState = MeshBuilder.createState(vertexCount, vertexCount / 2, mesh); - const v = Vec3.zero() - const pos = unit.conformation.invariantPosition - const l = StructureElement.Location.create(structure) - l.unit = unit + const v = Vec3.zero(); + const pos = unit.conformation.invariantPosition; + const l = StructureElement.Location.create(structure); + l.unit = unit; for (let i = 0; i < elementCount; i++) { - if (ignoreHydrogens && isHydrogen(unit, elements[i])) continue - if (traceOnly && !isTrace(unit, elements[i])) continue + if (ignoreHydrogens && isHydrogen(unit, elements[i])) continue; + if (traceOnly && !isTrace(unit, elements[i])) continue; - l.element = elements[i] - pos(elements[i], v) + l.element = elements[i]; + pos(elements[i], v); - builderState.currentGroup = i - addSphere(builderState, v, theme.size.size(l) * sizeFactor, detail) + builderState.currentGroup = i; + addSphere(builderState, v, theme.size.size(l) * sizeFactor, detail); } - const m = MeshBuilder.getMesh(builderState) + const m = MeshBuilder.getMesh(builderState); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * sizeFactor) - m.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1 * sizeFactor); + m.setBoundingSphere(sphere); - return m + return m; } export interface ElementSphereImpostorProps { @@ -68,45 +68,45 @@ export interface ElementSphereImpostorProps { } export function createElementSphereImpostor(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: ElementSphereImpostorProps, spheres?: Spheres): Spheres { - const { ignoreHydrogens, traceOnly } = props + const { ignoreHydrogens, traceOnly } = props; const { elements } = unit; const elementCount = elements.length; - const builder = SpheresBuilder.create(elementCount, elementCount / 2, spheres) + const builder = SpheresBuilder.create(elementCount, elementCount / 2, spheres); - const v = Vec3.zero() - const pos = unit.conformation.invariantPosition + const v = Vec3.zero(); + const pos = unit.conformation.invariantPosition; for (let i = 0; i < elementCount; i++) { - if (ignoreHydrogens && isHydrogen(unit, elements[i])) continue - if (traceOnly && !isTrace(unit, elements[i])) continue + if (ignoreHydrogens && isHydrogen(unit, elements[i])) continue; + if (traceOnly && !isTrace(unit, elements[i])) continue; - pos(elements[i], v) - builder.add(v[0], v[1], v[2], i) + pos(elements[i], v); + builder.add(v[0], v[1], v[2], i); } - const s = builder.getSpheres() + const s = builder.getSpheres(); - const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1) - s.setBoundingSphere(sphere) + const sphere = Sphere3D.expand(Sphere3D(), unit.boundary.sphere, 1); + s.setBoundingSphere(sphere); - return s + return s; } export function eachElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.structure, structure)) return false - const elementCount = group.elements.length + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const elementCount = group.elements.length; for (const e of loci.elements) { - const unitIdx = group.unitIndexMap.get(e.unit.id) + const unitIdx = group.unitIndexMap.get(e.unit.id); if (unitIdx !== undefined) { - const offset = unitIdx * elementCount // to target unit instance + const offset = unitIdx * elementCount; // to target unit instance if (Interval.is(e.indices)) { - const start = offset + Interval.start(e.indices) - const end = offset + Interval.end(e.indices) - if (apply(Interval.ofBounds(start, end))) changed = true + const start = offset + Interval.start(e.indices); + const end = offset + Interval.end(e.indices); + if (apply(Interval.ofBounds(start, end))) changed = true; } else { for (let i = 0, _i = e.indices.length; i < _i; i++) { const start = e.indices[i]; @@ -119,86 +119,86 @@ export function eachElement(loci: Loci, structureGroup: StructureGroup, apply: ( } } } - return changed + return changed; } export function getElementLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] - const indices = OrderedSet.ofSingleton(groupId as StructureElement.UnitIndex) - return StructureElement.Loci(structure, [{ unit, indices }]) + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; + const indices = OrderedSet.ofSingleton(groupId as StructureElement.UnitIndex); + return StructureElement.Loci(structure, [{ unit, indices }]); } - return EmptyLoci + return EmptyLoci; } // export function eachSerialElement(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - if (!Structure.areEquivalent(loci.structure, structure)) return false - const { cumulativeUnitElementCount } = structure.serialMapping + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const { cumulativeUnitElementCount } = structure.serialMapping; for (const e of loci.elements) { - const unitIdx = structure.unitIndexMap.get(e.unit.id) + const unitIdx = structure.unitIndexMap.get(e.unit.id); if (unitIdx !== undefined) { if (Interval.is(e.indices)) { - const start = cumulativeUnitElementCount[unitIdx] + Interval.start(e.indices) - const end = cumulativeUnitElementCount[unitIdx] + Interval.end(e.indices) - if (apply(Interval.ofBounds(start, end))) changed = true + const start = cumulativeUnitElementCount[unitIdx] + Interval.start(e.indices); + const end = cumulativeUnitElementCount[unitIdx] + Interval.end(e.indices); + if (apply(Interval.ofBounds(start, end))) changed = true; } else { for (let i = 0, _i = e.indices.length; i < _i; i++) { - const idx = cumulativeUnitElementCount[unitIdx] + e.indices[i] - if (apply(Interval.ofSingleton(idx))) changed = true + const idx = cumulativeUnitElementCount[unitIdx] + e.indices[i]; + if (apply(Interval.ofSingleton(idx))) changed = true; } } } } - return changed + return changed; } export function getSerialElementLoci(pickingId: PickingId, structure: Structure, id: number) { - const { objectId, groupId } = pickingId + const { objectId, groupId } = pickingId; if (id === objectId) { - const { unitIndices, cumulativeUnitElementCount } = structure.serialMapping - const unitIdx = unitIndices[groupId] - const unit = structure.units[unitIdx] - const idx = groupId - cumulativeUnitElementCount[unitIdx] - const indices = OrderedSet.ofSingleton(idx as StructureElement.UnitIndex) - return StructureElement.Loci(structure, [{ unit, indices }]) + const { unitIndices, cumulativeUnitElementCount } = structure.serialMapping; + const unitIdx = unitIndices[groupId]; + const unit = structure.units[unitIdx]; + const idx = groupId - cumulativeUnitElementCount[unitIdx]; + const indices = OrderedSet.ofSingleton(idx as StructureElement.UnitIndex); + return StructureElement.Loci(structure, [{ unit, indices }]); } - return EmptyLoci + return EmptyLoci; } // export namespace ElementIterator { export function fromGroup(structureGroup: StructureGroup): LocationIterator { - const { group, structure } = structureGroup - const groupCount = group.elements.length - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { group, structure } = structureGroup; + const groupCount = group.elements.length; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = unit.elements[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = unit.elements[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } export function fromStructure(structure: Structure): LocationIterator { - const { units, elementCount } = structure - const groupCount = elementCount - const instanceCount = 1 - const { unitIndices, elementIndices } = structure.serialMapping - const location = StructureElement.Location.create(structure) + const { units, elementCount } = structure; + const groupCount = elementCount; + const instanceCount = 1; + const { unitIndices, elementIndices } = structure.serialMapping; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number) => { - location.unit = units[unitIndices[groupIndex]] - location.element = elementIndices[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation, true) + location.unit = units[unitIndices[groupIndex]]; + location.element = elementIndices[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation, true); } } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/gaussian.ts b/src/mol-repr/structure/visual/util/gaussian.ts index 717ccd02ad5ae057526f3ebb77a34a2abbcfc88d..bce2ac9bb441268d79c79b33e167d8e9f0a79b77 100644 --- a/src/mol-repr/structure/visual/util/gaussian.ts +++ b/src/mol-repr/structure/visual/util/gaussian.ts @@ -19,39 +19,39 @@ const SharedGaussianDensityParams = { radiusOffset: PD.Numeric(0, { min: 0, max: 10, step: 0.1 }, { description: 'Extra/offset radius added to the atoms/coarse elements for gaussian calculation. Useful to create coarse, low resolution surfaces.' }), smoothness: PD.Numeric(1.5, { min: 0.5, max: 2.5, step: 0.1 }, { description: 'Smoothness of the gausian surface, lower is smoother.' }), ...CommonSurfaceParams -} +}; export const GaussianDensityParams = { ...SharedGaussianDensityParams, useGpu: PD.Boolean(false), -} -export const DefaultGaussianDensityProps = PD.getDefaultValues(GaussianDensityParams) +}; +export const DefaultGaussianDensityProps = PD.getDefaultValues(GaussianDensityParams); export type GaussianDensityProps = typeof DefaultGaussianDensityProps export const GaussianDensityTextureParams = { ...SharedGaussianDensityParams -} -export const DefaultGaussianDensityTextureProps = PD.getDefaultValues(GaussianDensityTextureParams) +}; +export const DefaultGaussianDensityTextureProps = PD.getDefaultValues(GaussianDensityTextureParams); export type GaussianDensityTextureProps = typeof DefaultGaussianDensityTextureProps // export function computeUnitGaussianDensity(structure: Structure, unit: Unit, props: GaussianDensityProps, webgl?: WebGLContext) { - const { position, radius } = getUnitConformationAndRadius(structure, unit, props) + const { position, radius } = getUnitConformationAndRadius(structure, unit, props); return Task.create('Gaussian Density', async ctx => { return await GaussianDensity(ctx, position, unit.lookup3d.boundary.box, radius, props, webgl); }); } export function computeUnitGaussianDensityTexture(structure: Structure, unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { - const { position, radius } = getUnitConformationAndRadius(structure, unit, props) + const { position, radius } = getUnitConformationAndRadius(structure, unit, props); return Task.create('Gaussian Density', async ctx => { return GaussianDensityTexture(webgl, position, unit.lookup3d.boundary.box, radius, props, texture); }); } export function computeUnitGaussianDensityTexture2d(structure: Structure, unit: Unit, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { - const { position, radius } = getUnitConformationAndRadius(structure, unit, props) + const { position, radius } = getUnitConformationAndRadius(structure, unit, props); return Task.create('Gaussian Density', async ctx => { return GaussianDensityTexture2d(webgl, position, unit.lookup3d.boundary.box, radius, props, texture); }); @@ -60,14 +60,14 @@ export function computeUnitGaussianDensityTexture2d(structure: Structure, unit: // export function computeStructureGaussianDensity(structure: Structure, props: GaussianDensityProps, webgl?: WebGLContext) { - const { position, radius } = getStructureConformationAndRadius(structure, props.ignoreHydrogens, props.traceOnly) + const { position, radius } = getStructureConformationAndRadius(structure, props.ignoreHydrogens, props.traceOnly); return Task.create('Gaussian Density', async ctx => { return await GaussianDensity(ctx, position, structure.lookup3d.boundary.box, radius, props, webgl); }); } export function computeStructureGaussianDensityTexture(structure: Structure, props: GaussianDensityTextureProps, webgl: WebGLContext, texture?: Texture) { - const { position, radius } = getStructureConformationAndRadius(structure, props.ignoreHydrogens, props.traceOnly) + const { position, radius } = getStructureConformationAndRadius(structure, props.ignoreHydrogens, props.traceOnly); return Task.create('Gaussian Density', async ctx => { return GaussianDensityTexture(webgl, position, structure.lookup3d.boundary.box, radius, props, texture); }); diff --git a/src/mol-repr/structure/visual/util/link.ts b/src/mol-repr/structure/visual/util/link.ts index 1435b1ac030b09c3900eb050b21a7788a6d581c3..a0e599830743abbcee03c3a71decdb98149300e5 100644 --- a/src/mol-repr/structure/visual/util/link.ts +++ b/src/mol-repr/structure/visual/util/link.ts @@ -18,39 +18,39 @@ export const LinkCylinderParams = { linkSpacing: PD.Numeric(1, { min: 0, max: 2, step: 0.01 }), linkCap: PD.Boolean(false), radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo), -} -export const DefaultLinkCylinderProps = PD.getDefaultValues(LinkCylinderParams) +}; +export const DefaultLinkCylinderProps = PD.getDefaultValues(LinkCylinderParams); export type LinkCylinderProps = typeof DefaultLinkCylinderProps -const tmpV12 = Vec3() -const tmpShiftV12 = Vec3() -const tmpShiftV13 = Vec3() -const up = Vec3.create(0, 1, 0) +const tmpV12 = Vec3(); +const tmpShiftV12 = Vec3(); +const tmpShiftV13 = Vec3(); +const up = Vec3.create(0, 1, 0); /** Calculate 'shift' direction that is perpendiculat to v1 - v2 and goes through v3 */ export function calculateShiftDir (out: Vec3, v1: Vec3, v2: Vec3, v3: Vec3 | null) { - Vec3.normalize(tmpShiftV12, Vec3.sub(tmpShiftV12, v1, v2)) + Vec3.normalize(tmpShiftV12, Vec3.sub(tmpShiftV12, v1, v2)); if (v3 !== null) { - Vec3.sub(tmpShiftV13, v1, v3) + Vec3.sub(tmpShiftV13, v1, v3); } else { - Vec3.copy(tmpShiftV13, v1) // no reference point, use v1 + Vec3.copy(tmpShiftV13, v1); // no reference point, use v1 } - Vec3.normalize(tmpShiftV13, tmpShiftV13) + Vec3.normalize(tmpShiftV13, tmpShiftV13); // ensure v13 and v12 are not colinear - let dp = Vec3.dot(tmpShiftV12, tmpShiftV13) + let dp = Vec3.dot(tmpShiftV12, tmpShiftV13); if (1 - Math.abs(dp) < 1e-5) { - Vec3.set(tmpShiftV13, 1, 0, 0) - dp = Vec3.dot(tmpShiftV12, tmpShiftV13) + Vec3.set(tmpShiftV13, 1, 0, 0); + dp = Vec3.dot(tmpShiftV12, tmpShiftV13); if (1 - Math.abs(dp) < 1e-5) { - Vec3.set(tmpShiftV13, 0, 1, 0) - dp = Vec3.dot(tmpShiftV12, tmpShiftV13) + Vec3.set(tmpShiftV13, 0, 1, 0); + dp = Vec3.dot(tmpShiftV12, tmpShiftV13); } } - Vec3.setMagnitude(tmpShiftV12, tmpShiftV12, dp) - Vec3.sub(tmpShiftV13, tmpShiftV13, tmpShiftV12) - return Vec3.normalize(out, tmpShiftV13) + Vec3.setMagnitude(tmpShiftV12, tmpShiftV12, dp); + Vec3.sub(tmpShiftV13, tmpShiftV13, tmpShiftV12); + return Vec3.normalize(out, tmpShiftV13); } export interface LinkCylinderMeshBuilderProps { @@ -75,75 +75,75 @@ export enum LinkCylinderStyle { * the half closer to the first vertex, i.e. vertex a. */ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkCylinderMeshBuilderProps, props: LinkCylinderProps, mesh?: Mesh) { - const { linkCount, referencePosition, position, style, radius, ignore } = linkBuilder + const { linkCount, referencePosition, position, style, radius, ignore } = linkBuilder; - if (!linkCount) return Mesh.createEmpty(mesh) + if (!linkCount) return Mesh.createEmpty(mesh); - const { linkScale, linkSpacing, radialSegments, linkCap } = props + const { linkScale, linkSpacing, radialSegments, linkCap } = props; - const vertexCountEstimate = radialSegments * 2 * linkCount * 2 - const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 4, mesh) + const vertexCountEstimate = radialSegments * 2 * linkCount * 2; + const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 4, mesh); - const va = Vec3.zero() - const vb = Vec3.zero() - const vShift = Vec3.zero() + const va = Vec3.zero(); + const vb = Vec3.zero(); + const vShift = Vec3.zero(); const cylinderProps: CylinderProps = { radiusTop: 1, radiusBottom: 1, radialSegments, topCap: linkCap, bottomCap: linkCap - } + }; for (let edgeIndex = 0, _eI = linkCount; edgeIndex < _eI; ++edgeIndex) { - if (ignore && ignore(edgeIndex)) continue + if (ignore && ignore(edgeIndex)) continue; - position(va, vb, edgeIndex) + position(va, vb, edgeIndex); - const linkRadius = radius(edgeIndex) - const linkStyle = style ? style(edgeIndex) : LinkCylinderStyle.Solid - builderState.currentGroup = edgeIndex + const linkRadius = radius(edgeIndex); + const linkStyle = style ? style(edgeIndex) : LinkCylinderStyle.Solid; + builderState.currentGroup = edgeIndex; if (linkStyle === LinkCylinderStyle.Dashed) { - cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius / 3 - cylinderProps.topCap = cylinderProps.bottomCap = true + cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius / 3; + cylinderProps.topCap = cylinderProps.bottomCap = true; - addFixedCountDashedCylinder(builderState, va, vb, 0.5, 7, cylinderProps) + addFixedCountDashedCylinder(builderState, va, vb, 0.5, 7, cylinderProps); } else if (linkStyle === LinkCylinderStyle.Double || linkStyle === LinkCylinderStyle.Triple) { - const order = LinkCylinderStyle.Double ? 2 : 3 - const multiRadius = linkRadius * (linkScale / (0.5 * order)) - const absOffset = (linkRadius - multiRadius) * linkSpacing + const order = LinkCylinderStyle.Double ? 2 : 3; + const multiRadius = linkRadius * (linkScale / (0.5 * order)); + const absOffset = (linkRadius - multiRadius) * linkSpacing; - calculateShiftDir(vShift, va, vb, referencePosition ? referencePosition(edgeIndex) : null) - Vec3.setMagnitude(vShift, vShift, absOffset) + calculateShiftDir(vShift, va, vb, referencePosition ? referencePosition(edgeIndex) : null); + Vec3.setMagnitude(vShift, vShift, absOffset); - cylinderProps.radiusTop = cylinderProps.radiusBottom = multiRadius - cylinderProps.topCap = cylinderProps.bottomCap = linkCap + cylinderProps.radiusTop = cylinderProps.radiusBottom = multiRadius; + cylinderProps.topCap = cylinderProps.bottomCap = linkCap; - if (order === 3) addCylinder(builderState, va, vb, 0.5, cylinderProps) - addDoubleCylinder(builderState, va, vb, 0.5, vShift, cylinderProps) + if (order === 3) addCylinder(builderState, va, vb, 0.5, cylinderProps); + addDoubleCylinder(builderState, va, vb, 0.5, vShift, cylinderProps); } else if (linkStyle === LinkCylinderStyle.Disk) { - Vec3.scale(tmpV12, Vec3.sub(tmpV12, vb, va), 0.475) - Vec3.add(va, va, tmpV12) - Vec3.sub(vb, vb, tmpV12) + Vec3.scale(tmpV12, Vec3.sub(tmpV12, vb, va), 0.475); + Vec3.add(va, va, tmpV12); + Vec3.sub(vb, vb, tmpV12); - cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius + cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius; if (Vec3.dot(tmpV12, up) > 0) { - cylinderProps.topCap = false - cylinderProps.bottomCap = linkCap + cylinderProps.topCap = false; + cylinderProps.bottomCap = linkCap; } else { - cylinderProps.topCap = linkCap - cylinderProps.bottomCap = false + cylinderProps.topCap = linkCap; + cylinderProps.bottomCap = false; } - addCylinder(builderState, va, vb, 0.5, cylinderProps) + addCylinder(builderState, va, vb, 0.5, cylinderProps); } else { - cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius - cylinderProps.topCap = cylinderProps.bottomCap = linkCap + cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius; + cylinderProps.topCap = cylinderProps.bottomCap = linkCap; - addCylinder(builderState, va, vb, 0.5, cylinderProps) + addCylinder(builderState, va, vb, 0.5, cylinderProps); } } - return MeshBuilder.getMesh(builderState) + return MeshBuilder.getMesh(builderState); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/molecular-surface.ts b/src/mol-repr/structure/visual/util/molecular-surface.ts index a3a23106f1cc7ea017078f98de15e1a1990233d2..d375c424a3ecaa67957d64eaa21fece8a407ea0c 100644 --- a/src/mol-repr/structure/visual/util/molecular-surface.ts +++ b/src/mol-repr/structure/visual/util/molecular-surface.ts @@ -15,26 +15,26 @@ import { Boundary } from '../../../../mol-math/geometry/boundary'; export type MolecularSurfaceProps = MolecularSurfaceCalculationProps & CommonSurfaceProps function getPositionDataAndMaxRadius(structure: Structure, unit: Unit, props: MolecularSurfaceProps) { - const { probeRadius } = props - const { position, boundary, radius } = getUnitConformationAndRadius(structure, unit, props) - const { indices } = position - const n = OrderedSet.size(indices) - const radii = new Float32Array(OrderedSet.end(indices)) + const { probeRadius } = props; + const { position, boundary, radius } = getUnitConformationAndRadius(structure, unit, props); + const { indices } = position; + const n = OrderedSet.size(indices); + const radii = new Float32Array(OrderedSet.end(indices)); - let maxRadius = 0 + let maxRadius = 0; for (let i = 0; i < n; ++i) { - const j = OrderedSet.getAt(indices, i) - const r = radius(j) - if (maxRadius < r) maxRadius = r - radii[j] = r + probeRadius + const j = OrderedSet.getAt(indices, i); + const r = radius(j); + if (maxRadius < r) maxRadius = r; + radii[j] = r + probeRadius; } - return { position: { ...position, radius: radii }, boundary, maxRadius } + return { position: { ...position, radius: radii }, boundary, maxRadius }; } export function computeUnitMolecularSurface(structure: Structure, unit: Unit, props: MolecularSurfaceProps) { - const { box } = unit.lookup3d.boundary - const { position, boundary, maxRadius } = getPositionDataAndMaxRadius(structure, unit, props) + const { box } = unit.lookup3d.boundary; + const { position, boundary, maxRadius } = getPositionDataAndMaxRadius(structure, unit, props); return Task.create('Molecular Surface', async ctx => { return await MolecularSurface(ctx, position, boundary, maxRadius, box, props); }); @@ -43,5 +43,5 @@ export function computeUnitMolecularSurface(structure: Structure, unit: Unit, pr // async function MolecularSurface(ctx: RuntimeContext, position: Required<PositionData>, boundary: Boundary, maxRadius: number, box: Box3D | null, props: MolecularSurfaceCalculationProps): Promise<DensityData> { - return calcMolecularSurface(ctx, position, boundary, maxRadius, box, props) + return calcMolecularSurface(ctx, position, boundary, maxRadius, box, props); } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/nucleotide.ts b/src/mol-repr/structure/visual/util/nucleotide.ts index 6b54f3bb1648f8ea6a004502689eed80ec00a373..06673baa3e2baa9d29608c014f9e0aac04cec779 100644 --- a/src/mol-repr/structure/visual/util/nucleotide.ts +++ b/src/mol-repr/structure/visual/util/nucleotide.ts @@ -15,32 +15,32 @@ import { eachAtomicUnitTracedElement } from './polymer'; export namespace NucleotideLocationIterator { export function fromGroup(structureGroup: StructureGroup): LocationIterator { - const { group, structure } = structureGroup - const u = group.units[0] - const nucleotideElementIndices = Unit.isAtomic(u) ? u.nucleotideElements : [] - const groupCount = nucleotideElementIndices.length - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { group, structure } = structureGroup; + const u = group.units[0]; + const nucleotideElementIndices = Unit.isAtomic(u) ? u.nucleotideElements : []; + const groupCount = nucleotideElementIndices.length; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = nucleotideElementIndices[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = nucleotideElementIndices[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } } export function getNucleotideElementLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; if (Unit.isAtomic(unit)) { - return getResidueLoci(structure, unit, unit.nucleotideElements[groupId]) + return getResidueLoci(structure, unit, unit.nucleotideElements[groupId]); } } - return EmptyLoci + return EmptyLoci; } function selectNuclotideElements(u: Unit.Atomic) { return u.nucleotideElements; } @@ -50,14 +50,14 @@ function selectNuclotideElements(u: Unit.Atomic) { return u.nucleotideElements; * - mark only when all its residue's elements are in a loci */ export function eachNucleotideElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.structure, structure)) return false - const unit = group.units[0] - if (!Unit.isAtomic(unit)) return false - const { nucleotideElements } = unit - const groupCount = nucleotideElements.length + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const unit = group.units[0]; + if (!Unit.isAtomic(unit)) return false; + const { nucleotideElements } = unit; + const groupCount = nucleotideElements.length; for (const e of loci.elements) { if (!Unit.isAtomic(e.unit)) continue; if (!group.unitIndexMap.has(e.unit.id)) continue; @@ -68,5 +68,5 @@ export function eachNucleotideElement(loci: Loci, structureGroup: StructureGroup changed = eachAtomicUnitTracedElement(intervalOffset, groupCount, selectNuclotideElements, apply, e) || changed; } } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/polymer.ts b/src/mol-repr/structure/visual/util/polymer.ts index dc868b4587a62883b04b11d9c4c54e8b1c02da2d..9afedbfe7ccb8d84c5244ab6d81c361d6428df5d 100644 --- a/src/mol-repr/structure/visual/util/polymer.ts +++ b/src/mol-repr/structure/visual/util/polymer.ts @@ -14,86 +14,86 @@ import { PickingId } from '../../../../mol-geo/geometry/picking'; import { StructureGroup } from '../../../structure/units-visual'; import { getResidueLoci } from './common'; -export * from './polymer/backbone-iterator' -export * from './polymer/gap-iterator' -export * from './polymer/trace-iterator' -export * from './polymer/curve-segment' +export * from './polymer/backbone-iterator'; +export * from './polymer/gap-iterator'; +export * from './polymer/trace-iterator'; +export * from './polymer/curve-segment'; -export const StandardTension = 0.5 -export const HelixTension = 0.9 -export const StandardShift = 0.5 -export const NucleicShift = 0.3 -export const OverhangFactor = 2 +export const StandardTension = 0.5; +export const HelixTension = 0.9; +export const StandardShift = 0.5; +export const NucleicShift = 0.3; +export const OverhangFactor = 2; export function getPolymerRanges(unit: Unit): SortedRanges<ElementIndex> { switch (unit.kind) { - case Unit.Kind.Atomic: return unit.model.atomicRanges.polymerRanges - case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.polymerRanges - case Unit.Kind.Gaussians: return unit.model.coarseHierarchy.gaussians.polymerRanges + case Unit.Kind.Atomic: return unit.model.atomicRanges.polymerRanges; + case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.polymerRanges; + case Unit.Kind.Gaussians: return unit.model.coarseHierarchy.gaussians.polymerRanges; } } export function getGapRanges(unit: Unit): SortedRanges<ElementIndex> { switch (unit.kind) { - case Unit.Kind.Atomic: return unit.model.atomicRanges.gapRanges - case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.gapRanges - case Unit.Kind.Gaussians: return unit.model.coarseHierarchy.gaussians.gapRanges + case Unit.Kind.Atomic: return unit.model.atomicRanges.gapRanges; + case Unit.Kind.Spheres: return unit.model.coarseHierarchy.spheres.gapRanges; + case Unit.Kind.Gaussians: return unit.model.coarseHierarchy.gaussians.gapRanges; } } export namespace PolymerLocationIterator { export function fromGroup(structureGroup: StructureGroup): LocationIterator { - const { group, structure } = structureGroup - const polymerElements = group.units[0].polymerElements - const groupCount = polymerElements.length - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { group, structure } = structureGroup; + const polymerElements = group.units[0].polymerElements; + const groupCount = polymerElements.length; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = polymerElements[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = polymerElements[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } } export namespace PolymerGapLocationIterator { export function fromGroup(structureGroup: StructureGroup): LocationIterator { - const { group, structure } = structureGroup - const gapElements = group.units[0].gapElements - const groupCount = gapElements.length - const instanceCount = group.units.length - const location = StructureElement.Location.create(structure) + const { group, structure } = structureGroup; + const gapElements = group.units[0].gapElements; + const groupCount = gapElements.length; + const instanceCount = group.units.length; + const location = StructureElement.Location.create(structure); const getLocation = (groupIndex: number, instanceIndex: number) => { - const unit = group.units[instanceIndex] - location.unit = unit - location.element = gapElements[groupIndex] - return location - } - return LocationIterator(groupCount, instanceCount, getLocation) + const unit = group.units[instanceIndex]; + location.unit = unit; + location.element = gapElements[groupIndex]; + return location; + }; + return LocationIterator(groupCount, instanceCount, getLocation); } } /** Return a Loci for the elements of the whole residue of a polymer element. */ export function getPolymerElementLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; if (Unit.isAtomic(unit)) { - return getResidueLoci(structure, unit, unit.polymerElements[groupId]) + return getResidueLoci(structure, unit, unit.polymerElements[groupId]); } else { - const { elements } = unit - const elementIndex = unit.polymerElements[groupId] - const unitIndex = OrderedSet.indexOf(elements, elementIndex) as StructureElement.UnitIndex | -1 + const { elements } = unit; + const elementIndex = unit.polymerElements[groupId]; + const unitIndex = OrderedSet.indexOf(elements, elementIndex) as StructureElement.UnitIndex | -1; if (unitIndex !== -1) { - const indices = OrderedSet.ofSingleton(unitIndex) - return StructureElement.Loci(structure, [{ unit, indices }]) + const indices = OrderedSet.ofSingleton(unitIndex); + return StructureElement.Loci(structure, [{ unit, indices }]); } } } - return EmptyLoci + return EmptyLoci; } @@ -172,11 +172,11 @@ function selectPolymerElements(u: Unit) { return u.polymerElements; } /** Mark a polymer element (e.g. part of a cartoon trace) */ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false - if (!StructureElement.Loci.is(loci)) return false - const { structure, group } = structureGroup - if (!Structure.areEquivalent(loci.structure, structure)) return false - const groupCount = group.units[0].polymerElements.length + let changed = false; + if (!StructureElement.Loci.is(loci)) return false; + const { structure, group } = structureGroup; + if (!Structure.areEquivalent(loci.structure, structure)) return false; + const groupCount = group.units[0].polymerElements.length; for (const e of loci.elements) { if (!group.unitIndexMap.has(e.unit.id)) continue; @@ -201,60 +201,60 @@ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, a } } } - return changed + return changed; } /** Return a Loci for both directions of the polymer gap element. */ export function getPolymerGapElementLoci(pickingId: PickingId, structureGroup: StructureGroup, id: number) { - const { objectId, instanceId, groupId } = pickingId + const { objectId, instanceId, groupId } = pickingId; if (id === objectId) { - const { structure, group } = structureGroup - const unit = group.units[instanceId] - const unitIndexA = OrderedSet.indexOf(unit.elements, unit.gapElements[groupId]) as StructureElement.UnitIndex - const unitIndexB = OrderedSet.indexOf(unit.elements, unit.gapElements[groupId % 2 ? groupId - 1 : groupId + 1]) as StructureElement.UnitIndex + const { structure, group } = structureGroup; + const unit = group.units[instanceId]; + const unitIndexA = OrderedSet.indexOf(unit.elements, unit.gapElements[groupId]) as StructureElement.UnitIndex; + const unitIndexB = OrderedSet.indexOf(unit.elements, unit.gapElements[groupId % 2 ? groupId - 1 : groupId + 1]) as StructureElement.UnitIndex; if (unitIndexA !== -1 && unitIndexB !== -1) { return Bond.Loci(structure, [ Bond.Location(structure, unit, unitIndexA, structure, unit, unitIndexB), Bond.Location(structure, unit, unitIndexB, structure, unit, unitIndexA) - ]) + ]); } } - return EmptyLoci + return EmptyLoci; } export function eachPolymerGapElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { - let changed = false + let changed = false; if (Bond.isLoci(loci)) { - const { structure, group } = structureGroup - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - loci = Bond.remapLoci(loci, structure) - const groupCount = group.units[0].gapElements.length + const { structure, group } = structureGroup; + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + loci = Bond.remapLoci(loci, structure); + const groupCount = group.units[0].gapElements.length; for (const b of loci.bonds) { - const unitIdx = group.unitIndexMap.get(b.aUnit.id) + const unitIdx = group.unitIndexMap.get(b.aUnit.id); if (unitIdx !== undefined) { - const idxA = OrderedSet.indexOf(b.aUnit.gapElements, b.aUnit.elements[b.aIndex]) - const idxB = OrderedSet.indexOf(b.bUnit.gapElements, b.bUnit.elements[b.bIndex]) + const idxA = OrderedSet.indexOf(b.aUnit.gapElements, b.aUnit.elements[b.aIndex]); + const idxB = OrderedSet.indexOf(b.bUnit.gapElements, b.bUnit.elements[b.bIndex]); if (idxA !== -1 && idxB !== -1) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + idxA))) changed = true + if (apply(Interval.ofSingleton(unitIdx * groupCount + idxA))) changed = true; } } } } else if (StructureElement.Loci.is(loci)) { - const { structure, group } = structureGroup - if (!Structure.areRootsEquivalent(loci.structure, structure)) return false - loci = StructureElement.Loci.remap(loci, structure) - const groupCount = group.units[0].gapElements.length + const { structure, group } = structureGroup; + if (!Structure.areRootsEquivalent(loci.structure, structure)) return false; + loci = StructureElement.Loci.remap(loci, structure); + const groupCount = group.units[0].gapElements.length; for (const e of loci.elements) { - const unitIdx = group.unitIndexMap.get(e.unit.id) + const unitIdx = group.unitIndexMap.get(e.unit.id); if (unitIdx !== undefined) { OrderedSet.forEach(e.indices, v => { - const idx = OrderedSet.indexOf(e.unit.gapElements, e.unit.elements[v]) + const idx = OrderedSet.indexOf(e.unit.gapElements, e.unit.elements[v]); if (idx !== -1) { - if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true + if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true; } - }) + }); } } } - return changed + return changed; } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/polymer/backbone-iterator.ts b/src/mol-repr/structure/visual/util/polymer/backbone-iterator.ts index c8bb7f68173506b6879a8a197e076833e08c88d4..bc621b0b91d06c66270a38ed06c7d01757fd9549 100644 --- a/src/mol-repr/structure/visual/util/polymer/backbone-iterator.ts +++ b/src/mol-repr/structure/visual/util/polymer/backbone-iterator.ts @@ -13,10 +13,10 @@ import { getPolymerRanges } from '../polymer'; /** Iterates over consecutive pairs of residues/coarse elements in polymers */ export function PolymerBackboneIterator(structure: Structure, unit: Unit): Iterator<PolymerBackbonePair> { switch (unit.kind) { - case Unit.Kind.Atomic: return new AtomicPolymerBackboneIterator(structure, unit) + case Unit.Kind.Atomic: return new AtomicPolymerBackboneIterator(structure, unit); case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return new CoarsePolymerBackboneIterator(structure, unit) + return new CoarsePolymerBackboneIterator(structure, unit); } } @@ -29,7 +29,7 @@ function createPolymerBackbonePair (structure: Structure, unit: Unit) { return { centerA: StructureElement.Location.create(structure, unit), centerB: StructureElement.Location.create(structure, unit), - } + }; } const enum AtomicPolymerBackboneIteratorState { nextPolymer, firstResidue, nextResidue, cycle } @@ -48,44 +48,44 @@ export class AtomicPolymerBackboneIterator implements Iterator<PolymerBackbonePa while (this.polymerIt.hasNext) { this.residueIt.setSegment(this.polymerIt.move()); if (this.residueIt.hasNext) { - this.residueSegment = this.residueIt.move() - this.value.centerB.element = this.traceElementIndex[this.residueSegment.index] - this.state = AtomicPolymerBackboneIteratorState.nextResidue - break + this.residueSegment = this.residueIt.move(); + this.value.centerB.element = this.traceElementIndex[this.residueSegment.index]; + this.state = AtomicPolymerBackboneIteratorState.nextResidue; + break; } } } if (this.state === AtomicPolymerBackboneIteratorState.nextResidue) { - this.residueSegment = this.residueIt.move() - this.value.centerA.element = this.value.centerB.element - this.value.centerB.element = this.traceElementIndex[this.residueSegment.index] + this.residueSegment = this.residueIt.move(); + this.value.centerA.element = this.value.centerB.element; + this.value.centerB.element = this.traceElementIndex[this.residueSegment.index]; if (!this.residueIt.hasNext) { if (this.unit.model.atomicRanges.cyclicPolymerMap.has(this.residueSegment.index)) { - this.state = AtomicPolymerBackboneIteratorState.cycle + this.state = AtomicPolymerBackboneIteratorState.cycle; } else { // TODO need to advance to a polymer that has two or more residues (can't assume it has) - this.state = AtomicPolymerBackboneIteratorState.nextPolymer + this.state = AtomicPolymerBackboneIteratorState.nextPolymer; } } } else if (this.state === AtomicPolymerBackboneIteratorState.cycle) { - const { cyclicPolymerMap } = this.unit.model.atomicRanges - this.value.centerA.element = this.value.centerB.element - this.value.centerB.element = this.traceElementIndex[cyclicPolymerMap.get(this.residueSegment.index)!] + const { cyclicPolymerMap } = this.unit.model.atomicRanges; + this.value.centerA.element = this.value.centerB.element; + this.value.centerB.element = this.traceElementIndex[cyclicPolymerMap.get(this.residueSegment.index)!]; // TODO need to advance to a polymer that has two or more residues (can't assume it has) - this.state = AtomicPolymerBackboneIteratorState.nextPolymer + this.state = AtomicPolymerBackboneIteratorState.nextPolymer; } - this.hasNext = this.residueIt.hasNext || this.polymerIt.hasNext || this.state === AtomicPolymerBackboneIteratorState.cycle + this.hasNext = this.residueIt.hasNext || this.polymerIt.hasNext || this.state === AtomicPolymerBackboneIteratorState.cycle; return this.value; } constructor(structure: Structure, private unit: Unit.Atomic) { - this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex> // can assume it won't be -1 for polymer residues - this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements) - this.residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, unit.elements) - this.value = createPolymerBackbonePair(structure, unit) - this.hasNext = this.residueIt.hasNext && this.polymerIt.hasNext + this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex>; // can assume it won't be -1 for polymer residues + this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements); + this.residueIt = Segmentation.transientSegments(unit.model.atomicHierarchy.residueAtomSegments, unit.elements); + this.value = createPolymerBackbonePair(structure, unit); + this.hasNext = this.residueIt.hasNext && this.polymerIt.hasNext; } } @@ -103,32 +103,32 @@ export class CoarsePolymerBackboneIterator implements Iterator<PolymerBackbonePa if (this.state === CoarsePolymerBackboneIteratorState.nextPolymer) { if (this.polymerIt.hasNext) { this.polymerSegment = this.polymerIt.move(); - this.elementIndex = this.polymerSegment.start + this.elementIndex = this.polymerSegment.start; if (this.elementIndex + 1 < this.polymerSegment.end) { - this.value.centerB.element = this.unit.elements[this.elementIndex] - this.state = CoarsePolymerBackboneIteratorState.nextElement + this.value.centerB.element = this.unit.elements[this.elementIndex]; + this.state = CoarsePolymerBackboneIteratorState.nextElement; } else { - this.state = CoarsePolymerBackboneIteratorState.nextPolymer + this.state = CoarsePolymerBackboneIteratorState.nextPolymer; } } } if (this.state === CoarsePolymerBackboneIteratorState.nextElement) { - this.elementIndex += 1 - this.value.centerA.element = this.value.centerB.element - this.value.centerB.element = this.unit.elements[this.elementIndex] + this.elementIndex += 1; + this.value.centerA.element = this.value.centerB.element; + this.value.centerB.element = this.unit.elements[this.elementIndex]; if (this.elementIndex + 1 >= this.polymerSegment.end) { - this.state = CoarsePolymerBackboneIteratorState.nextPolymer + this.state = CoarsePolymerBackboneIteratorState.nextPolymer; } } - this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || this.polymerIt.hasNext + this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || this.polymerIt.hasNext; return this.value; } constructor(structure: Structure, private unit: Unit.Spheres | Unit.Gaussians) { this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements); - this.value = createPolymerBackbonePair(structure, unit) - this.hasNext = this.polymerIt.hasNext + this.value = createPolymerBackbonePair(structure, unit); + this.hasNext = this.polymerIt.hasNext; } } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/polymer/curve-segment.ts b/src/mol-repr/structure/visual/util/polymer/curve-segment.ts index 33512cd75f5f73195c2be2357f3c08f9fa578311..952c05a2f270961adfdd811bb5d0d06c75d1f4e7 100644 --- a/src/mol-repr/structure/visual/util/polymer/curve-segment.ts +++ b/src/mol-repr/structure/visual/util/polymer/curve-segment.ts @@ -25,8 +25,8 @@ export interface CurveSegmentControls { } export function createCurveSegmentState(linearSegments: number): CurveSegmentState { - const n = linearSegments + 1 - const pn = n * 3 + const n = linearSegments + 1; + const pn = n * 3; return { curvePoints: new Float32Array(pn), tangentVectors: new Float32Array(pn), @@ -35,103 +35,103 @@ export function createCurveSegmentState(linearSegments: number): CurveSegmentSta widthValues: new Float32Array(n), heightValues: new Float32Array(n), linearSegments - } + }; } export function interpolateCurveSegment(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) { - interpolatePointsAndTangents(state, controls, tension, shift) - interpolateNormals(state, controls) + interpolatePointsAndTangents(state, controls, tension, shift); + interpolateNormals(state, controls); } -const tanA = Vec3.zero() -const tanB = Vec3.zero() -const curvePoint = Vec3.zero() +const tanA = Vec3.zero(); +const tanB = Vec3.zero(); +const curvePoint = Vec3.zero(); export function interpolatePointsAndTangents(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) { - const { curvePoints, tangentVectors, linearSegments } = state - const { p0, p1, p2, p3, p4, secStrucFirst, secStrucLast } = controls + const { curvePoints, tangentVectors, linearSegments } = state; + const { p0, p1, p2, p3, p4, secStrucFirst, secStrucLast } = controls; - const shift1 = 1 - shift + const shift1 = 1 - shift; - const tensionBeg = secStrucFirst ? 0.5 : tension - const tensionEnd = secStrucLast ? 0.5 : tension + const tensionBeg = secStrucFirst ? 0.5 : tension; + const tensionEnd = secStrucLast ? 0.5 : tension; for (let j = 0; j <= linearSegments; ++j) { const t = j * 1.0 / linearSegments; if (t < shift1) { - const te = lerp(tensionBeg, tension, t) - Vec3.spline(curvePoint, p0, p1, p2, p3, t + shift, te) - Vec3.spline(tanA, p0, p1, p2, p3, t + shift + 0.01, tensionBeg) - Vec3.spline(tanB, p0, p1, p2, p3, t + shift - 0.01, tensionBeg) + const te = lerp(tensionBeg, tension, t); + Vec3.spline(curvePoint, p0, p1, p2, p3, t + shift, te); + Vec3.spline(tanA, p0, p1, p2, p3, t + shift + 0.01, tensionBeg); + Vec3.spline(tanB, p0, p1, p2, p3, t + shift - 0.01, tensionBeg); } else { - const te = lerp(tension, tensionEnd, t) - Vec3.spline(curvePoint, p1, p2, p3, p4, t - shift1, te) - Vec3.spline(tanA, p1, p2, p3, p4, t - shift1 + 0.01, te) - Vec3.spline(tanB, p1, p2, p3, p4, t - shift1 - 0.01, te) + const te = lerp(tension, tensionEnd, t); + Vec3.spline(curvePoint, p1, p2, p3, p4, t - shift1, te); + Vec3.spline(tanA, p1, p2, p3, p4, t - shift1 + 0.01, te); + Vec3.spline(tanB, p1, p2, p3, p4, t - shift1 - 0.01, te); } - Vec3.toArray(curvePoint, curvePoints, j * 3) - Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tanA, tanB)) - Vec3.toArray(tangentVec, tangentVectors, j * 3) + Vec3.toArray(curvePoint, curvePoints, j * 3); + Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tanA, tanB)); + Vec3.toArray(tangentVec, tangentVectors, j * 3); } } -const tmpNormal = Vec3() -const tangentVec = Vec3() -const normalVec = Vec3() -const binormalVec = Vec3() -const prevNormal = Vec3() -const firstTangentVec = Vec3() -const lastTangentVec = Vec3() -const firstNormalVec = Vec3() -const lastNormalVec = Vec3() +const tmpNormal = Vec3(); +const tangentVec = Vec3(); +const normalVec = Vec3(); +const binormalVec = Vec3(); +const prevNormal = Vec3(); +const firstTangentVec = Vec3(); +const lastTangentVec = Vec3(); +const firstNormalVec = Vec3(); +const lastNormalVec = Vec3(); /** * Populate normalVectors by interpolating from firstDirection to lastDirection with * resulting vector perpendicular to tangentVectors and binormalVectors */ export function interpolateNormals(state: CurveSegmentState, controls: CurveSegmentControls) { - const { curvePoints, tangentVectors, normalVectors, binormalVectors } = state - const { d12: firstDirection, d23: lastDirection } = controls + const { curvePoints, tangentVectors, normalVectors, binormalVectors } = state; + const { d12: firstDirection, d23: lastDirection } = controls; - const n = curvePoints.length / 3 + const n = curvePoints.length / 3; - Vec3.fromArray(firstTangentVec, tangentVectors, 0) - Vec3.fromArray(lastTangentVec, tangentVectors, (n - 1) * 3) + Vec3.fromArray(firstTangentVec, tangentVectors, 0); + Vec3.fromArray(lastTangentVec, tangentVectors, (n - 1) * 3); - Vec3.orthogonalize(firstNormalVec, firstTangentVec, firstDirection) - Vec3.orthogonalize(lastNormalVec, lastTangentVec, lastDirection) - Vec3.matchDirection(lastNormalVec, lastNormalVec, firstNormalVec) + Vec3.orthogonalize(firstNormalVec, firstTangentVec, firstDirection); + Vec3.orthogonalize(lastNormalVec, lastTangentVec, lastDirection); + Vec3.matchDirection(lastNormalVec, lastNormalVec, firstNormalVec); - Vec3.copy(prevNormal, firstNormalVec) + Vec3.copy(prevNormal, firstNormalVec); for (let i = 0; i < n; ++i) { - const t = i === 0 ? 0 : 1 / (n - i) + const t = i === 0 ? 0 : 1 / (n - i); - Vec3.fromArray(tangentVec, tangentVectors, i * 3) + Vec3.fromArray(tangentVec, tangentVectors, i * 3); - Vec3.orthogonalize(normalVec, tangentVec, Vec3.slerp(tmpNormal, prevNormal, lastNormalVec, t)) - Vec3.toArray(normalVec, normalVectors, i * 3) + Vec3.orthogonalize(normalVec, tangentVec, Vec3.slerp(tmpNormal, prevNormal, lastNormalVec, t)); + Vec3.toArray(normalVec, normalVectors, i * 3); - Vec3.copy(prevNormal, normalVec) + Vec3.copy(prevNormal, normalVec); - Vec3.normalize(binormalVec, Vec3.cross(binormalVec, tangentVec, normalVec)) - Vec3.toArray(binormalVec, binormalVectors, i * 3) + Vec3.normalize(binormalVec, Vec3.cross(binormalVec, tangentVec, normalVec)); + Vec3.toArray(binormalVec, binormalVectors, i * 3); } } export function interpolateSizes(state: CurveSegmentState, w0: number, w1: number, w2: number, h0: number, h1: number, h2: number, shift: number) { - const { widthValues, heightValues, linearSegments } = state + const { widthValues, heightValues, linearSegments } = state; - const shift1 = 1 - shift + const shift1 = 1 - shift; for (let i = 0; i <= linearSegments; ++i) { const t = i * 1.0 / linearSegments; if (t < shift1) { - widthValues[i] = lerp(w0, w1, t + shift) - heightValues[i] = lerp(h0, h1, t + shift) + widthValues[i] = lerp(w0, w1, t + shift); + heightValues[i] = lerp(h0, h1, t + shift); } else { - widthValues[i] = lerp(w1, w2, t - shift1) - heightValues[i] = lerp(h1, h2, t - shift1) + widthValues[i] = lerp(w1, w2, t - shift1); + heightValues[i] = lerp(h1, h2, t - shift1); } } } \ No newline at end of file diff --git a/src/mol-repr/structure/visual/util/polymer/gap-iterator.ts b/src/mol-repr/structure/visual/util/polymer/gap-iterator.ts index 0da71df3904149025a867a7a0421dc3ffb2f7152..ead22ab1a17fc0538d6d5c171e697bdb061f306f 100644 --- a/src/mol-repr/structure/visual/util/polymer/gap-iterator.ts +++ b/src/mol-repr/structure/visual/util/polymer/gap-iterator.ts @@ -12,10 +12,10 @@ import { getGapRanges } from '../polymer'; /** Iterates over gaps, i.e. the stem residues/coarse elements adjacent to gaps */ export function PolymerGapIterator(structure: Structure, unit: Unit): Iterator<PolymerGapPair> { switch (unit.kind) { - case Unit.Kind.Atomic: return new AtomicPolymerGapIterator(structure, unit) + case Unit.Kind.Atomic: return new AtomicPolymerGapIterator(structure, unit); case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return new CoarsePolymerGapIterator(structure, unit) + return new CoarsePolymerGapIterator(structure, unit); } } @@ -28,7 +28,7 @@ function createPolymerGapPair (structure: Structure, unit: Unit) { return { centerA: StructureElement.Location.create(structure, unit), centerB: StructureElement.Location.create(structure, unit), - } + }; } export class AtomicPolymerGapIterator implements Iterator<PolymerGapPair> { @@ -38,19 +38,19 @@ export class AtomicPolymerGapIterator implements Iterator<PolymerGapPair> { hasNext: boolean = false; move() { - const { elements, residueIndex } = this.unit + const { elements, residueIndex } = this.unit; const gapSegment = this.gapIt.move(); - this.value.centerA.element = this.traceElementIndex[residueIndex[elements[gapSegment.start]]] - this.value.centerB.element = this.traceElementIndex[residueIndex[elements[gapSegment.end - 1]]] - this.hasNext = this.gapIt.hasNext + this.value.centerA.element = this.traceElementIndex[residueIndex[elements[gapSegment.start]]]; + this.value.centerB.element = this.traceElementIndex[residueIndex[elements[gapSegment.end - 1]]]; + this.hasNext = this.gapIt.hasNext; return this.value; } constructor(structure: Structure, private unit: Unit.Atomic) { - this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex> // can assume it won't be -1 for polymer residues + this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex>; // can assume it won't be -1 for polymer residues this.gapIt = SortedRanges.transientSegments(getGapRanges(unit), unit.elements); - this.value = createPolymerGapPair(structure, unit) - this.hasNext = this.gapIt.hasNext + this.value = createPolymerGapPair(structure, unit); + this.hasNext = this.gapIt.hasNext; } } @@ -61,15 +61,15 @@ export class CoarsePolymerGapIterator implements Iterator<PolymerGapPair> { move() { const gapSegment = this.gapIt.move(); - this.value.centerA.element = this.unit.elements[gapSegment.start] - this.value.centerB.element = this.unit.elements[gapSegment.end - 1] - this.hasNext = this.gapIt.hasNext + this.value.centerA.element = this.unit.elements[gapSegment.start]; + this.value.centerB.element = this.unit.elements[gapSegment.end - 1]; + this.hasNext = this.gapIt.hasNext; return this.value; } constructor(structure: Structure, private unit: Unit.Spheres | Unit.Gaussians) { this.gapIt = SortedRanges.transientSegments(getGapRanges(unit), unit.elements); - this.value = createPolymerGapPair(structure, unit) - this.hasNext = this.gapIt.hasNext + this.value = createPolymerGapPair(structure, unit); + this.hasNext = this.gapIt.hasNext; } } diff --git a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts index c8f8cb4bf27da90eb8154f579c3654fa4eeeb4bc..a8b529b743428ff76a16a3d29cf584ace27adbb8 100644 --- a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts +++ b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts @@ -22,10 +22,10 @@ import { SecondaryStructure } from '../../../../../mol-model/structure/model/pro */ export function PolymerTraceIterator(unit: Unit, structure: Structure): Iterator<PolymerTraceElement> { switch (unit.kind) { - case Unit.Kind.Atomic: return new AtomicPolymerTraceIterator(unit, structure) + case Unit.Kind.Atomic: return new AtomicPolymerTraceIterator(unit, structure); case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return new CoarsePolymerTraceIterator(unit, structure) + return new CoarsePolymerTraceIterator(unit, structure); } } @@ -45,7 +45,7 @@ interface PolymerTraceElement { d12: Vec3, d23: Vec3 } -const SecStrucTypeNA = SecondaryStructureType.create(SecondaryStructureType.Flag.NA) +const SecStrucTypeNA = SecondaryStructureType.create(SecondaryStructureType.Flag.NA); function createPolymerTraceElement (structure: Structure, unit: Unit): PolymerTraceElement { return { @@ -61,14 +61,14 @@ function createPolymerTraceElement (structure: Structure, unit: Unit): PolymerTr isCoarseBackbone: false, p0: Vec3(), p1: Vec3(), p2: Vec3(), p3: Vec3(), p4: Vec3(), d12: Vec3(), d23: Vec3() - } + }; } const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue } -const tmpDir = Vec3() -const tmpVecA = Vec3() -const tmpVecB = Vec3() +const tmpDir = Vec3(); +const tmpVecA = Vec3(); +const tmpVecB = Vec3(); export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> { private value: PolymerTraceElement @@ -114,201 +114,201 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> private pos(target: Vec3, index: number) { if (index !== -1) { - target[0] = this.atomicConformation.x[index] - target[1] = this.atomicConformation.y[index] - target[2] = this.atomicConformation.z[index] + target[0] = this.atomicConformation.x[index]; + target[1] = this.atomicConformation.y[index]; + target[2] = this.atomicConformation.z[index]; } } private updateResidueSegmentRange(polymerSegment: Segmentation.Segment<number>) { - const { index } = this.residueAtomSegments - this.residueSegmentBeg = index[this.unit.elements[polymerSegment.start]] - this.residueSegmentEnd = index[this.unit.elements[polymerSegment.end - 1]] - this.residueSegmentMin = index[this.polymerRanges[polymerSegment.index * 2]] - this.residueSegmentMax = index[this.polymerRanges[polymerSegment.index * 2 + 1] - 1] + const { index } = this.residueAtomSegments; + this.residueSegmentBeg = index[this.unit.elements[polymerSegment.start]]; + this.residueSegmentEnd = index[this.unit.elements[polymerSegment.end - 1]]; + this.residueSegmentMin = index[this.polymerRanges[polymerSegment.index * 2]]; + this.residueSegmentMax = index[this.polymerRanges[polymerSegment.index * 2 + 1] - 1]; } private getResidueIndex(residueIndex: number) { if (residueIndex < this.residueSegmentMin) { - const cyclicIndex = this.cyclicPolymerMap.get(this.residueSegmentMin) + const cyclicIndex = this.cyclicPolymerMap.get(this.residueSegmentMin); if (cyclicIndex !== undefined) { - residueIndex = cyclicIndex - (this.residueSegmentMin - residueIndex - 1) + residueIndex = cyclicIndex - (this.residueSegmentMin - residueIndex - 1); } else { - residueIndex = this.residueSegmentMin + residueIndex = this.residueSegmentMin; } } else if (residueIndex > this.residueSegmentMax) { - const cyclicIndex = this.cyclicPolymerMap.get(this.residueSegmentMax) + const cyclicIndex = this.cyclicPolymerMap.get(this.residueSegmentMax); if (cyclicIndex !== undefined) { - residueIndex = cyclicIndex + (residueIndex - this.residueSegmentMax - 1) + residueIndex = cyclicIndex + (residueIndex - this.residueSegmentMax - 1); } else { - residueIndex = this.residueSegmentMax + residueIndex = this.residueSegmentMax; } } - return residueIndex as ResidueIndex + return residueIndex as ResidueIndex; } private getSecStruc(residueIndex: number) { - return this.secondaryStructureType[this.secondaryStructureGetIndex(residueIndex as ResidueIndex)] + return this.secondaryStructureType[this.secondaryStructureGetIndex(residueIndex as ResidueIndex)]; } private setControlPoint(out: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, residueIndex: ResidueIndex) { - const ss = this.getSecStruc(residueIndex) + const ss = this.getSecStruc(residueIndex); if (SecondaryStructureType.is(ss, SecondaryStructureType.Flag.Beta)) { - Vec3.scale(out, Vec3.add(out, p1, Vec3.add(out, p3, Vec3.add(out, p2, p2))), 1 / 4) + Vec3.scale(out, Vec3.add(out, p1, Vec3.add(out, p3, Vec3.add(out, p2, p2))), 1 / 4); } else { - Vec3.copy(out, p2) + Vec3.copy(out, p2); } } private setFromToVector(out: Vec3, residueIndex: ResidueIndex) { if (this.value.isCoarseBackbone) { - Vec3.set(out, 1, 0, 0) + Vec3.set(out, 1, 0, 0); } else { - this.pos(tmpVecA, this.directionFromElementIndex[residueIndex]) - this.pos(tmpVecB, this.directionToElementIndex[residueIndex]) - Vec3.sub(out, tmpVecB, tmpVecA) + this.pos(tmpVecA, this.directionFromElementIndex[residueIndex]); + this.pos(tmpVecB, this.directionToElementIndex[residueIndex]); + Vec3.sub(out, tmpVecB, tmpVecA); } } private setDirection(out: Vec3, v1: Vec3, v2: Vec3, v3: Vec3) { - Vec3.matchDirection(tmpVecA, v1, v2) - Vec3.matchDirection(tmpVecB, v3, v2) - Vec3.scale(out, Vec3.add(out, tmpVecA, Vec3.add(out, tmpVecB, Vec3.add(out, v2, v2))), 1 / 4) + Vec3.matchDirection(tmpVecA, v1, v2); + Vec3.matchDirection(tmpVecB, v3, v2); + Vec3.scale(out, Vec3.add(out, tmpVecA, Vec3.add(out, tmpVecB, Vec3.add(out, v2, v2))), 1 / 4); } move() { - const { residueIt, polymerIt, value } = this + const { residueIt, polymerIt, value } = this; if (this.state === AtomicPolymerTraceIteratorState.nextPolymer) { while (polymerIt.hasNext) { this.polymerSegment = polymerIt.move(); residueIt.setSegment(this.polymerSegment); - this.updateResidueSegmentRange(this.polymerSegment) + this.updateResidueSegmentRange(this.polymerSegment); if (residueIt.hasNext) { - this.state = AtomicPolymerTraceIteratorState.nextResidue - this.currSecStrucType = SecStrucTypeNA - this.nextSecStrucType = this.getSecStruc(this.residueSegmentBeg) - this.currCoarseBackbone = false - this.nextCoarseBackbone = this.directionFromElementIndex[this.residueSegmentBeg] === -1 || this.directionToElementIndex[this.residueSegmentBeg] === -1 - break + this.state = AtomicPolymerTraceIteratorState.nextResidue; + this.currSecStrucType = SecStrucTypeNA; + this.nextSecStrucType = this.getSecStruc(this.residueSegmentBeg); + this.currCoarseBackbone = false; + this.nextCoarseBackbone = this.directionFromElementIndex[this.residueSegmentBeg] === -1 || this.directionToElementIndex[this.residueSegmentBeg] === -1; + break; } } } if (this.state === AtomicPolymerTraceIteratorState.nextResidue) { const { index: residueIndex } = residueIt.move(); - this.prevSecStrucType = this.currSecStrucType - this.currSecStrucType = this.nextSecStrucType - this.nextSecStrucType = residueIt.hasNext ? this.getSecStruc(residueIndex + 1) : SecStrucTypeNA - - this.prevCoarseBackbone = this.currCoarseBackbone - this.currCoarseBackbone = this.nextCoarseBackbone - this.nextCoarseBackbone = residueIt.hasNext ? (this.directionFromElementIndex[residueIndex + 1] === -1 || this.directionToElementIndex[residueIndex + 1] === -1) : false - - value.secStrucType = this.currSecStrucType - value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType - value.secStrucLast = this.currSecStrucType !== this.nextSecStrucType - value.isCoarseBackbone = this.currCoarseBackbone - value.coarseBackboneFirst = this.prevCoarseBackbone !== this.currCoarseBackbone - value.coarseBackboneLast = this.currCoarseBackbone !== this.nextCoarseBackbone - value.first = residueIndex === this.residueSegmentBeg - value.last = residueIndex === this.residueSegmentEnd - value.moleculeType = this.moleculeType[residueIndex] - value.isCoarseBackbone = this.directionFromElementIndex[residueIndex] === -1 || this.directionToElementIndex[residueIndex] === -1 - - const residueIndexPrev3 = this.getResidueIndex(residueIndex - 3) - const residueIndexPrev2 = this.getResidueIndex(residueIndex - 2) - const residueIndexPrev1 = this.getResidueIndex(residueIndex - 1) - const residueIndexNext1 = this.getResidueIndex(residueIndex + 1) - const residueIndexNext2 = this.getResidueIndex(residueIndex + 2) - const residueIndexNext3 = this.getResidueIndex(residueIndex + 3) - - value.initial = residueIndex === residueIndexPrev1 - value.final = residueIndex === residueIndexNext1 - - value.centerPrev.element = this.traceElementIndex[residueIndexPrev1] - value.center.element = this.traceElementIndex[residueIndex] - value.centerNext.element = this.traceElementIndex[residueIndexNext1] - - this.pos(this.p0, this.traceElementIndex[residueIndexPrev3]) - this.pos(this.p1, this.traceElementIndex[residueIndexPrev2]) - this.pos(this.p2, this.traceElementIndex[residueIndexPrev1]) - this.pos(this.p3, this.traceElementIndex[residueIndex]) - this.pos(this.p4, this.traceElementIndex[residueIndexNext1]) - this.pos(this.p5, this.traceElementIndex[residueIndexNext2]) - this.pos(this.p6, this.traceElementIndex[residueIndexNext3]) - - this.setFromToVector(this.d01, residueIndexPrev1) - this.setFromToVector(this.d12, residueIndex) - this.setFromToVector(this.d23, residueIndexNext1) - this.setFromToVector(this.d34, residueIndexNext2) + this.prevSecStrucType = this.currSecStrucType; + this.currSecStrucType = this.nextSecStrucType; + this.nextSecStrucType = residueIt.hasNext ? this.getSecStruc(residueIndex + 1) : SecStrucTypeNA; + + this.prevCoarseBackbone = this.currCoarseBackbone; + this.currCoarseBackbone = this.nextCoarseBackbone; + this.nextCoarseBackbone = residueIt.hasNext ? (this.directionFromElementIndex[residueIndex + 1] === -1 || this.directionToElementIndex[residueIndex + 1] === -1) : false; + + value.secStrucType = this.currSecStrucType; + value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType; + value.secStrucLast = this.currSecStrucType !== this.nextSecStrucType; + value.isCoarseBackbone = this.currCoarseBackbone; + value.coarseBackboneFirst = this.prevCoarseBackbone !== this.currCoarseBackbone; + value.coarseBackboneLast = this.currCoarseBackbone !== this.nextCoarseBackbone; + value.first = residueIndex === this.residueSegmentBeg; + value.last = residueIndex === this.residueSegmentEnd; + value.moleculeType = this.moleculeType[residueIndex]; + value.isCoarseBackbone = this.directionFromElementIndex[residueIndex] === -1 || this.directionToElementIndex[residueIndex] === -1; + + const residueIndexPrev3 = this.getResidueIndex(residueIndex - 3); + const residueIndexPrev2 = this.getResidueIndex(residueIndex - 2); + const residueIndexPrev1 = this.getResidueIndex(residueIndex - 1); + const residueIndexNext1 = this.getResidueIndex(residueIndex + 1); + const residueIndexNext2 = this.getResidueIndex(residueIndex + 2); + const residueIndexNext3 = this.getResidueIndex(residueIndex + 3); + + value.initial = residueIndex === residueIndexPrev1; + value.final = residueIndex === residueIndexNext1; + + value.centerPrev.element = this.traceElementIndex[residueIndexPrev1]; + value.center.element = this.traceElementIndex[residueIndex]; + value.centerNext.element = this.traceElementIndex[residueIndexNext1]; + + this.pos(this.p0, this.traceElementIndex[residueIndexPrev3]); + this.pos(this.p1, this.traceElementIndex[residueIndexPrev2]); + this.pos(this.p2, this.traceElementIndex[residueIndexPrev1]); + this.pos(this.p3, this.traceElementIndex[residueIndex]); + this.pos(this.p4, this.traceElementIndex[residueIndexNext1]); + this.pos(this.p5, this.traceElementIndex[residueIndexNext2]); + this.pos(this.p6, this.traceElementIndex[residueIndexNext3]); + + this.setFromToVector(this.d01, residueIndexPrev1); + this.setFromToVector(this.d12, residueIndex); + this.setFromToVector(this.d23, residueIndexNext1); + this.setFromToVector(this.d34, residueIndexNext2); // extend termini - const f = 0.5 + const f = 0.5; if (residueIndex === residueIndexPrev1) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p3, this.p4), f) - Vec3.add(this.p2, this.p3, tmpDir) - Vec3.add(this.p1, this.p2, tmpDir) - Vec3.add(this.p0, this.p1, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p3, this.p4), f); + Vec3.add(this.p2, this.p3, tmpDir); + Vec3.add(this.p1, this.p2, tmpDir); + Vec3.add(this.p0, this.p1, tmpDir); } else if (residueIndexPrev1 === residueIndexPrev2) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p2, this.p3), f) - Vec3.add(this.p1, this.p2, tmpDir) - Vec3.add(this.p0, this.p1, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p2, this.p3), f); + Vec3.add(this.p1, this.p2, tmpDir); + Vec3.add(this.p0, this.p1, tmpDir); } else if (residueIndexPrev2 === residueIndexPrev3) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p1, this.p2), f) - Vec3.add(this.p0, this.p1, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p1, this.p2), f); + Vec3.add(this.p0, this.p1, tmpDir); } if (residueIndex === residueIndexNext1) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p3, this.p2), f) - Vec3.add(this.p4, this.p3, tmpDir) - Vec3.add(this.p5, this.p4, tmpDir) - Vec3.add(this.p6, this.p5, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p3, this.p2), f); + Vec3.add(this.p4, this.p3, tmpDir); + Vec3.add(this.p5, this.p4, tmpDir); + Vec3.add(this.p6, this.p5, tmpDir); } else if (residueIndexNext1 === residueIndexNext2) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p4, this.p3), f) - Vec3.add(this.p5, this.p4, tmpDir) - Vec3.add(this.p6, this.p5, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p4, this.p3), f); + Vec3.add(this.p5, this.p4, tmpDir); + Vec3.add(this.p6, this.p5, tmpDir); } else if (residueIndexNext2 === residueIndexNext3) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p5, this.p4), f) - Vec3.add(this.p6, this.p5, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p5, this.p4), f); + Vec3.add(this.p6, this.p5, tmpDir); } - this.setControlPoint(value.p0, this.p0, this.p1, this.p2, residueIndexPrev2) - this.setControlPoint(value.p1, this.p1, this.p2, this.p3, residueIndexPrev1) - this.setControlPoint(value.p2, this.p2, this.p3, this.p4, residueIndex) - this.setControlPoint(value.p3, this.p3, this.p4, this.p5, residueIndexNext1) - this.setControlPoint(value.p4, this.p4, this.p5, this.p6, residueIndexNext2) + this.setControlPoint(value.p0, this.p0, this.p1, this.p2, residueIndexPrev2); + this.setControlPoint(value.p1, this.p1, this.p2, this.p3, residueIndexPrev1); + this.setControlPoint(value.p2, this.p2, this.p3, this.p4, residueIndex); + this.setControlPoint(value.p3, this.p3, this.p4, this.p5, residueIndexNext1); + this.setControlPoint(value.p4, this.p4, this.p5, this.p6, residueIndexNext2); - this.setDirection(value.d12, this.d01, this.d12, this.d23) - this.setDirection(value.d23, this.d12, this.d23, this.d34) + this.setDirection(value.d12, this.d01, this.d12, this.d23); + this.setDirection(value.d23, this.d12, this.d23, this.d34); if (!residueIt.hasNext) { - this.state = AtomicPolymerTraceIteratorState.nextPolymer + this.state = AtomicPolymerTraceIteratorState.nextPolymer; } } - this.hasNext = residueIt.hasNext || polymerIt.hasNext + this.hasNext = residueIt.hasNext || polymerIt.hasNext; return this.value; } constructor(private unit: Unit.Atomic, structure: Structure) { - this.atomicConformation = unit.model.atomicConformation - this.residueAtomSegments = unit.model.atomicHierarchy.residueAtomSegments - this.polymerRanges = unit.model.atomicRanges.polymerRanges - this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex> // can assume it won't be -1 for polymer residues - this.directionFromElementIndex = unit.model.atomicHierarchy.derived.residue.directionFromElementIndex - this.directionToElementIndex = unit.model.atomicHierarchy.derived.residue.directionToElementIndex - this.moleculeType = unit.model.atomicHierarchy.derived.residue.moleculeType - this.cyclicPolymerMap = unit.model.atomicRanges.cyclicPolymerMap - this.polymerIt = SortedRanges.transientSegments(this.polymerRanges, unit.elements) + this.atomicConformation = unit.model.atomicConformation; + this.residueAtomSegments = unit.model.atomicHierarchy.residueAtomSegments; + this.polymerRanges = unit.model.atomicRanges.polymerRanges; + this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex>; // can assume it won't be -1 for polymer residues + this.directionFromElementIndex = unit.model.atomicHierarchy.derived.residue.directionFromElementIndex; + this.directionToElementIndex = unit.model.atomicHierarchy.derived.residue.directionToElementIndex; + this.moleculeType = unit.model.atomicHierarchy.derived.residue.moleculeType; + this.cyclicPolymerMap = unit.model.atomicRanges.cyclicPolymerMap; + this.polymerIt = SortedRanges.transientSegments(this.polymerRanges, unit.elements); this.residueIt = Segmentation.transientSegments(this.residueAtomSegments, unit.elements); - this.value = createPolymerTraceElement(structure, unit) - this.hasNext = this.residueIt.hasNext && this.polymerIt.hasNext + this.value = createPolymerTraceElement(structure, unit); + this.hasNext = this.residueIt.hasNext && this.polymerIt.hasNext; - const secondaryStructure = SecondaryStructureProvider.get(structure).value?.get(unit.invariantId) - if (!secondaryStructure) throw new Error('missing secondary structure') - this.secondaryStructureType = secondaryStructure.type - this.secondaryStructureGetIndex = secondaryStructure.getIndex + const secondaryStructure = SecondaryStructureProvider.get(structure).value?.get(unit.invariantId); + if (!secondaryStructure) throw new Error('missing secondary structure'); + this.secondaryStructureType = secondaryStructure.type; + this.secondaryStructureGetIndex = secondaryStructure.getIndex; } } @@ -324,86 +324,86 @@ export class CoarsePolymerTraceIterator implements Iterator<PolymerTraceElement> hasNext: boolean = false; private getElementIndex(elementIndex: number) { - return Math.min(Math.max(this.polymerSegment.start, elementIndex), this.polymerSegment.end - 1) as ElementIndex + return Math.min(Math.max(this.polymerSegment.start, elementIndex), this.polymerSegment.end - 1) as ElementIndex; } private pos(target: Vec3, elementIndex: number) { - const index = this.unit.elements[elementIndex] - target[0] = this.conformation.x[index] - target[1] = this.conformation.y[index] - target[2] = this.conformation.z[index] + const index = this.unit.elements[elementIndex]; + target[0] = this.conformation.x[index]; + target[1] = this.conformation.y[index]; + target[2] = this.conformation.z[index]; } move() { if (this.state === CoarsePolymerTraceIteratorState.nextPolymer) { while (this.polymerIt.hasNext) { this.polymerSegment = this.polymerIt.move(); - this.elementIndex = this.polymerSegment.start + this.elementIndex = this.polymerSegment.start; if (this.elementIndex < this.polymerSegment.end) { - this.state = CoarsePolymerTraceIteratorState.nextElement - break + this.state = CoarsePolymerTraceIteratorState.nextElement; + break; } } } if (this.state === CoarsePolymerTraceIteratorState.nextElement) { - const elementIndexPrev2 = this.getElementIndex(this.elementIndex - 2) - const elementIndexPrev1 = this.getElementIndex(this.elementIndex - 1) - const elementIndexNext1 = this.getElementIndex(this.elementIndex + 1) - const elementIndexNext2 = this.getElementIndex(this.elementIndex + 2) + const elementIndexPrev2 = this.getElementIndex(this.elementIndex - 2); + const elementIndexPrev1 = this.getElementIndex(this.elementIndex - 1); + const elementIndexNext1 = this.getElementIndex(this.elementIndex + 1); + const elementIndexNext2 = this.getElementIndex(this.elementIndex + 2); - this.value.centerPrev.element = this.value.center.unit.elements[elementIndexPrev1] - this.value.center.element = this.value.center.unit.elements[this.elementIndex] - this.value.centerNext.element = this.value.center.unit.elements[elementIndexNext1] + this.value.centerPrev.element = this.value.center.unit.elements[elementIndexPrev1]; + this.value.center.element = this.value.center.unit.elements[this.elementIndex]; + this.value.centerNext.element = this.value.center.unit.elements[elementIndexNext1]; - this.pos(this.value.p0, elementIndexPrev2) - this.pos(this.value.p1, elementIndexPrev1) - this.pos(this.value.p2, this.elementIndex) - this.pos(this.value.p3, elementIndexNext1) - this.pos(this.value.p4, elementIndexNext2) + this.pos(this.value.p0, elementIndexPrev2); + this.pos(this.value.p1, elementIndexPrev1); + this.pos(this.value.p2, this.elementIndex); + this.pos(this.value.p3, elementIndexNext1); + this.pos(this.value.p4, elementIndexNext2); // extend termini - const f = 0.5 + const f = 0.5; if (this.elementIndex === elementIndexPrev1) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p2, this.value.p3), f) - Vec3.add(this.value.p1, this.value.p2, tmpDir) - Vec3.add(this.value.p0, this.value.p1, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p2, this.value.p3), f); + Vec3.add(this.value.p1, this.value.p2, tmpDir); + Vec3.add(this.value.p0, this.value.p1, tmpDir); } else if (elementIndexPrev1 === elementIndexPrev2) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p1, this.value.p2), f) - Vec3.add(this.value.p0, this.value.p1, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p1, this.value.p2), f); + Vec3.add(this.value.p0, this.value.p1, tmpDir); } if (this.elementIndex === elementIndexNext1) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p2, this.value.p1), f) - Vec3.add(this.value.p3, this.value.p2, tmpDir) - Vec3.add(this.value.p4, this.value.p3, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p2, this.value.p1), f); + Vec3.add(this.value.p3, this.value.p2, tmpDir); + Vec3.add(this.value.p4, this.value.p3, tmpDir); } else if (elementIndexNext1 === elementIndexNext2) { - Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p3, this.value.p2), f) - Vec3.add(this.value.p4, this.value.p3, tmpDir) + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p3, this.value.p2), f); + Vec3.add(this.value.p4, this.value.p3, tmpDir); } - this.value.first = this.elementIndex === this.polymerSegment.start - this.value.last = this.elementIndex === this.polymerSegment.end - 1 + this.value.first = this.elementIndex === this.polymerSegment.start; + this.value.last = this.elementIndex === this.polymerSegment.end - 1; if (this.elementIndex + 1 >= this.polymerSegment.end) { - this.state = CoarsePolymerTraceIteratorState.nextPolymer + this.state = CoarsePolymerTraceIteratorState.nextPolymer; } } - this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || this.polymerIt.hasNext - this.elementIndex += 1 + this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || this.polymerIt.hasNext; + this.elementIndex += 1; return this.value; } constructor(private unit: Unit.Spheres | Unit.Gaussians, structure: Structure) { this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements); - this.value = createPolymerTraceElement(structure, unit) - Vec3.set(this.value.d12, 1, 0, 0) - Vec3.set(this.value.d23, 1, 0, 0) + this.value = createPolymerTraceElement(structure, unit); + Vec3.set(this.value.d12, 1, 0, 0); + Vec3.set(this.value.d23, 1, 0, 0); switch (unit.kind) { - case Unit.Kind.Spheres: this.conformation = unit.model.coarseConformation.spheres; break - case Unit.Kind.Gaussians: this.conformation = unit.model.coarseConformation.gaussians; break + case Unit.Kind.Spheres: this.conformation = unit.model.coarseConformation.spheres; break; + case Unit.Kind.Gaussians: this.conformation = unit.model.coarseConformation.gaussians; break; } - this.hasNext = this.polymerIt.hasNext + this.hasNext = this.polymerIt.hasNext; } } \ No newline at end of file diff --git a/src/mol-repr/util.ts b/src/mol-repr/util.ts index e6f6439165f3eeafbcbff7a51e48e889450ab1f0..31c545d351403b11833d9e9fdb67bc2d60128477 100644 --- a/src/mol-repr/util.ts +++ b/src/mol-repr/util.ts @@ -30,15 +30,15 @@ export namespace VisualUpdateState { createNew: false, info: {} - } + }; } export function reset(state: VisualUpdateState) { - state.updateTransform = false - state.updateMatrix = false - state.updateColor = false - state.updateSize = false - state.createGeometry = false - state.createNew = false + state.updateTransform = false; + state.updateMatrix = false; + state.updateColor = false; + state.updateSize = false; + state.createGeometry = false; + state.createNew = false; } } @@ -62,93 +62,93 @@ export const DefaultQualityThresholds = { coarseGrainedFactor: 10, elementCountFactor: 1 -} +}; export type QualityThresholds = typeof DefaultQualityThresholds export function getStructureQuality(structure: Structure, tresholds: Partial<QualityThresholds> = {}): VisualQuality { - const t = { ...DefaultQualityThresholds, ...tresholds } - let score = structure.elementCount * t.elementCountFactor - if (structure.isCoarseGrained) score *= t.coarseGrainedFactor + const t = { ...DefaultQualityThresholds, ...tresholds }; + let score = structure.elementCount * t.elementCountFactor; + if (structure.isCoarseGrained) score *= t.coarseGrainedFactor; if (score > t.lowestElementCount) { - return 'lowest' + return 'lowest'; } else if (score > t.lowerElementCount) { - return 'lower' + return 'lower'; } else if (score > t.lowElementCount) { - return 'low' + return 'low'; } else if (score > t.mediumElementCount) { - return 'medium' + return 'medium'; } else if (score > t.highElementCount) { - return 'high' + return 'high'; } else { - return 'higher' + return 'higher'; } } export function getQualityProps(props: Partial<QualityProps>, data?: any) { - let quality = defaults(props.quality, 'auto' as VisualQuality) - let detail = defaults(props.detail, 1) - let radialSegments = defaults(props.radialSegments, 12) - let linearSegments = defaults(props.linearSegments, 8) - let resolution = defaults(props.resolution, 2) - let doubleSided = defaults(props.doubleSided, true) + let quality = defaults(props.quality, 'auto' as VisualQuality); + let detail = defaults(props.detail, 1); + let radialSegments = defaults(props.radialSegments, 12); + let linearSegments = defaults(props.linearSegments, 8); + let resolution = defaults(props.resolution, 2); + let doubleSided = defaults(props.doubleSided, true); if (quality === 'auto' && data instanceof Structure) { - quality = getStructureQuality(data.root) + quality = getStructureQuality(data.root); } switch (quality) { case 'highest': - detail = 3 - radialSegments = 36 - linearSegments = 18 - resolution = 0.1 - doubleSided = true - break + detail = 3; + radialSegments = 36; + linearSegments = 18; + resolution = 0.1; + doubleSided = true; + break; case 'higher': - detail = 3 - radialSegments = 28 - linearSegments = 14 - resolution = 0.3 - doubleSided = true - break + detail = 3; + radialSegments = 28; + linearSegments = 14; + resolution = 0.3; + doubleSided = true; + break; case 'high': - detail = 2 - radialSegments = 20 - linearSegments = 10 - resolution = 0.5 - doubleSided = true - break + detail = 2; + radialSegments = 20; + linearSegments = 10; + resolution = 0.5; + doubleSided = true; + break; case 'medium': - detail = 1 - radialSegments = 12 - linearSegments = 8 - resolution = 1 - doubleSided = true - break + detail = 1; + radialSegments = 12; + linearSegments = 8; + resolution = 1; + doubleSided = true; + break; case 'low': - detail = 0 - radialSegments = 8 - linearSegments = 3 - resolution = 2 - doubleSided = false - break + detail = 0; + radialSegments = 8; + linearSegments = 3; + resolution = 2; + doubleSided = false; + break; case 'lower': - detail = 0 - radialSegments = 4 - linearSegments = 2 - resolution = 4 - doubleSided = false - break + detail = 0; + radialSegments = 4; + linearSegments = 2; + resolution = 4; + doubleSided = false; + break; case 'lowest': - detail = 0 - radialSegments = 2 - linearSegments = 1 - resolution = 8 - doubleSided = false - break + detail = 0; + radialSegments = 2; + linearSegments = 1; + resolution = 8; + doubleSided = false; + break; case 'custom': // use defaults or given props as set above - break + break; } return { @@ -157,5 +157,5 @@ export function getQualityProps(props: Partial<QualityProps>, data?: any) { linearSegments, resolution, doubleSided - } + }; } \ No newline at end of file diff --git a/src/mol-repr/visual.ts b/src/mol-repr/visual.ts index 0935e499ca63ee4852391bbcc0078e4e9d11603a..a748344379065f0aefb778d8d60319209a88aaf7 100644 --- a/src/mol-repr/visual.ts +++ b/src/mol-repr/visual.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { RuntimeContext } from '../mol-task' -import { GraphicsRenderObject } from '../mol-gl/render-object' +import { RuntimeContext } from '../mol-task'; +import { GraphicsRenderObject } from '../mol-gl/render-object'; import { PickingId } from '../mol-geo/geometry/picking'; import { Loci, isEmptyLoci, isEveryLoci } from '../mol-model/loci'; import { MarkerAction, applyMarkerAction } from '../mol-util/marker-action'; @@ -28,7 +28,7 @@ export interface VisualContext { } // export type VisualFactory<D, P extends PD.Params> = (ctx: VisualContext) => Visual<D, P> -export { Visual } +export { Visual }; interface Visual<D, P extends PD.Params> { /** Number of addressable groups in all instances of the visual */ readonly groupCount: number @@ -48,103 +48,103 @@ namespace Visual { export type LociApply = (loci: Loci, apply: (interval: Interval) => boolean) => boolean export function setVisibility(renderObject: GraphicsRenderObject | undefined, visible: boolean) { - if (renderObject) renderObject.state.visible = visible + if (renderObject) renderObject.state.visible = visible; } export function setAlphaFactor(renderObject: GraphicsRenderObject | undefined, alphaFactor: number) { - if (renderObject) renderObject.state.alphaFactor = alphaFactor + if (renderObject) renderObject.state.alphaFactor = alphaFactor; } export function setPickable(renderObject: GraphicsRenderObject | undefined, pickable: boolean) { - if (renderObject) renderObject.state.pickable = pickable + if (renderObject) renderObject.state.pickable = pickable; } export function mark(renderObject: GraphicsRenderObject | undefined, loci: Loci, action: MarkerAction, lociApply: LociApply) { - if (!renderObject) return false + if (!renderObject) return false; - const { tMarker, uGroupCount, instanceCount } = renderObject.values - const count = uGroupCount.ref.value * instanceCount.ref.value - const { array } = tMarker.ref.value + const { tMarker, uGroupCount, instanceCount } = renderObject.values; + const count = uGroupCount.ref.value * instanceCount.ref.value; + const { array } = tMarker.ref.value; - let changed = false + let changed = false; if (isEveryLoci(loci)) { - changed = applyMarkerAction(array, Interval.ofLength(count), action) + changed = applyMarkerAction(array, Interval.ofLength(count), action); } else if (!isEmptyLoci(loci)) { - changed = lociApply(loci, interval => applyMarkerAction(array, interval, action)) + changed = lociApply(loci, interval => applyMarkerAction(array, interval, action)); } - if (changed) ValueCell.update(tMarker, tMarker.ref.value) - return changed + if (changed) ValueCell.update(tMarker, tMarker.ref.value); + return changed; } export function setOverpaint(renderObject: GraphicsRenderObject | undefined, overpaint: Overpaint, lociApply: LociApply, clear: boolean) { - if (!renderObject) return + if (!renderObject) return; - const { tOverpaint, uGroupCount, instanceCount } = renderObject.values - const count = uGroupCount.ref.value * instanceCount.ref.value + const { tOverpaint, uGroupCount, instanceCount } = renderObject.values; + const count = uGroupCount.ref.value * instanceCount.ref.value; // ensure texture has right size - createOverpaint(overpaint.layers.length ? count : 0, renderObject.values) - const { array } = tOverpaint.ref.value + createOverpaint(overpaint.layers.length ? count : 0, renderObject.values); + const { array } = tOverpaint.ref.value; // clear all if requested - if (clear) clearOverpaint(array, 0, count) + if (clear) clearOverpaint(array, 0, count); for (let i = 0, il = overpaint.layers.length; i < il; ++i) { - const { loci, color, clear } = overpaint.layers[i] + const { loci, color, clear } = overpaint.layers[i]; const apply = (interval: Interval) => { - const start = Interval.start(interval) - const end = Interval.end(interval) + const start = Interval.start(interval); + const end = Interval.end(interval); return clear ? clearOverpaint(array, start, end) - : applyOverpaintColor(array, start, end, color, overpaint.alpha) - } - lociApply(loci, apply) + : applyOverpaintColor(array, start, end, color, overpaint.alpha); + }; + lociApply(loci, apply); } - ValueCell.update(tOverpaint, tOverpaint.ref.value) + ValueCell.update(tOverpaint, tOverpaint.ref.value); } export function setTransparency(renderObject: GraphicsRenderObject | undefined, transparency: Transparency, lociApply: LociApply, clear: boolean) { - if (!renderObject) return + if (!renderObject) return; - const { tTransparency, uGroupCount, instanceCount } = renderObject.values - const count = uGroupCount.ref.value * instanceCount.ref.value + const { tTransparency, uGroupCount, instanceCount } = renderObject.values; + const count = uGroupCount.ref.value * instanceCount.ref.value; - const { loci, value, variant } = transparency + const { loci, value, variant } = transparency; // ensure texture has right size and variant - createTransparency(value && !isEmptyLoci(loci) ? count : 0, variant, renderObject.values) - const { array } = tTransparency.ref.value + createTransparency(value && !isEmptyLoci(loci) ? count : 0, variant, renderObject.values); + const { array } = tTransparency.ref.value; // clear if requested - if (clear) clearTransparency(array, 0, count) + if (clear) clearTransparency(array, 0, count); const apply = (interval: Interval) => { - const start = Interval.start(interval) - const end = Interval.end(interval) - return applyTransparencyValue(array, start, end, value) - } - lociApply(loci, apply) + const start = Interval.start(interval); + const end = Interval.end(interval); + return applyTransparencyValue(array, start, end, value); + }; + lociApply(loci, apply); - ValueCell.update(tTransparency, tTransparency.ref.value) + ValueCell.update(tTransparency, tTransparency.ref.value); } export function setTransform(renderObject: GraphicsRenderObject | undefined, transform?: Mat4, instanceTransforms?: Float32Array | null) { - if (!renderObject || (!transform && !instanceTransforms)) return + if (!renderObject || (!transform && !instanceTransforms)) return; - const { values } = renderObject + const { values } = renderObject; if (transform) { - Mat4.copy(values.matrix.ref.value, transform) - ValueCell.update(values.matrix, values.matrix.ref.value) + Mat4.copy(values.matrix.ref.value, transform); + ValueCell.update(values.matrix, values.matrix.ref.value); } if (instanceTransforms) { - values.extraTransform.ref.value.set(instanceTransforms) - ValueCell.update(values.extraTransform, values.extraTransform.ref.value) + values.extraTransform.ref.value.set(instanceTransforms); + ValueCell.update(values.extraTransform, values.extraTransform.ref.value); } else if (instanceTransforms === null) { - fillIdentityTransform(values.extraTransform.ref.value, values.instanceCount.ref.value) - ValueCell.update(values.extraTransform, values.extraTransform.ref.value) + fillIdentityTransform(values.extraTransform.ref.value, values.instanceCount.ref.value); + ValueCell.update(values.extraTransform, values.extraTransform.ref.value); } - updateTransformData(values) - const boundingSphere = calculateTransformBoundingSphere(values.invariantBoundingSphere.ref.value, values.aTransform.ref.value, values.instanceCount.ref.value) - ValueCell.update(values.boundingSphere, boundingSphere) + updateTransformData(values); + const boundingSphere = calculateTransformBoundingSphere(values.invariantBoundingSphere.ref.value, values.aTransform.ref.value, values.instanceCount.ref.value); + ValueCell.update(values.boundingSphere, boundingSphere); } } \ No newline at end of file diff --git a/src/mol-repr/volume/direct-volume.ts b/src/mol-repr/volume/direct-volume.ts index 840b57a9d1c075b47eeb9d24ffcfccbc30d16967..0c603a19d1d8f199e04d7e6ba03b17692ad8d47b 100644 --- a/src/mol-repr/volume/direct-volume.ts +++ b/src/mol-repr/volume/direct-volume.ts @@ -22,133 +22,133 @@ import { VisualUpdateState } from '../util'; import { RepresentationContext, RepresentationParamsGetter } from '../representation'; function getBoundingBox(gridDimension: Vec3, transform: Mat4) { - const bbox = Box3D.empty() - Box3D.add(bbox, gridDimension) - Box3D.transform(bbox, bbox, transform) - return bbox + const bbox = Box3D.empty(); + Box3D.add(bbox, gridDimension); + Box3D.transform(bbox, bbox, transform); + return bbox; } // 2d volume texture function getVolumeTexture2dLayout(dim: Vec3, maxTextureSize: number) { - let width = 0 - let height = dim[1] - let rows = 1 - let columns = dim[0] + let width = 0; + let height = dim[1]; + let rows = 1; + let columns = dim[0]; if (maxTextureSize < dim[0] * dim[2]) { - columns = Math.floor(maxTextureSize / dim[0]) - rows = Math.ceil(dim[2] / columns) - width = columns * dim[0] - height *= rows + columns = Math.floor(maxTextureSize / dim[0]); + rows = Math.ceil(dim[2] / columns); + width = columns * dim[0]; + height *= rows; } else { - width = dim[0] * dim[2] + width = dim[0] * dim[2]; } - width += columns // horizontal padding - height += rows // vertical padding - return { width, height, columns, rows } + width += columns; // horizontal padding + height += rows; // vertical padding + return { width, height, columns, rows }; } function createVolumeTexture2d(volume: VolumeData, maxTextureSize: number) { - const { data: tensor, dataStats: stats } = volume - const { space, data } = tensor - const dim = space.dimensions as Vec3 - const { get } = space - const { width, height, columns, rows } = getVolumeTexture2dLayout(dim, maxTextureSize) + const { data: tensor, dataStats: stats } = volume; + const { space, data } = tensor; + const dim = space.dimensions as Vec3; + const { get } = space; + const { width, height, columns, rows } = getVolumeTexture2dLayout(dim, maxTextureSize); - const array = new Uint8Array(width * height * 4) - const textureImage = { array, width, height } + const array = new Uint8Array(width * height * 4); + const textureImage = { array, width, height }; - const [ xl, yl, zl ] = dim - const xlp = xl + 1 // horizontal padding - const ylp = yl + 1 // vertical padding + const [ xl, yl, zl ] = dim; + const xlp = xl + 1; // horizontal padding + const ylp = yl + 1; // vertical padding function setTex(value: number, x: number, y: number, z: number) { - const column = Math.floor(((z * xlp) % width) / xlp) - const row = Math.floor((z * xlp) / width) - const px = column * xlp + x - const index = 4 * ((row * ylp * width) + (y * width) + px) - array[index + 3] = ((value - stats.min) / (stats.max - stats.min)) * 255 + const column = Math.floor(((z * xlp) % width) / xlp); + const row = Math.floor((z * xlp) / width); + const px = column * xlp + x; + const index = 4 * ((row * ylp * width) + (y * width) + px); + array[index + 3] = ((value - stats.min) / (stats.max - stats.min)) * 255; } - console.log('dim', dim) - console.log('layout', { width, height, columns, rows }) + console.log('dim', dim); + console.log('layout', { width, height, columns, rows }); for (let z = 0; z < zl; ++z) { for (let y = 0; y < yl; ++y) { for (let x = 0; x < xl; ++x) { - setTex(get(data, x, y, z), x, y, z) + setTex(get(data, x, y, z), x, y, z); } } } - return textureImage + return textureImage; } export function createDirectVolume2d(ctx: RuntimeContext, webgl: WebGLContext, volume: VolumeData, directVolume?: DirectVolume) { - const gridDimension = volume.data.space.dimensions as Vec3 - const textureImage = createVolumeTexture2d(volume, webgl.maxTextureSize) + const gridDimension = volume.data.space.dimensions as Vec3; + const textureImage = createVolumeTexture2d(volume, webgl.maxTextureSize); // debugTexture(createImageData(textureImage.array, textureImage.width, textureImage.height), 1/3) - const transform = VolumeData.getGridToCartesianTransform(volume) - const bbox = getBoundingBox(gridDimension, transform) - const dim = Vec3.create(gridDimension[0], gridDimension[1], gridDimension[2]) - dim[0] += 1 // horizontal padding - dim[0] += 1 // vertical padding + const transform = VolumeData.getGridToCartesianTransform(volume); + const bbox = getBoundingBox(gridDimension, transform); + const dim = Vec3.create(gridDimension[0], gridDimension[1], gridDimension[2]); + dim[0] += 1; // horizontal padding + dim[0] += 1; // vertical padding - const texture = directVolume ? directVolume.gridTexture.ref.value : webgl.resources.texture('volume-uint8', 'rgba', 'ubyte', 'linear') - texture.load(textureImage) + const texture = directVolume ? directVolume.gridTexture.ref.value : webgl.resources.texture('volume-uint8', 'rgba', 'ubyte', 'linear'); + texture.load(textureImage); - return DirectVolume.create(bbox, dim, transform, texture, directVolume) + return DirectVolume.create(bbox, dim, transform, texture, directVolume); } // 3d volume texture function createVolumeTexture3d(volume: VolumeData) { - const { data: tensor, dataStats: stats } = volume - const { space, data } = tensor - const [ width, height, depth ] = space.dimensions as Vec3 - const { get } = space + const { data: tensor, dataStats: stats } = volume; + const { space, data } = tensor; + const [ width, height, depth ] = space.dimensions as Vec3; + const { get } = space; - const array = new Uint8Array(width * height * depth * 4) - const textureVolume = { array, width, height, depth } + const array = new Uint8Array(width * height * depth * 4); + const textureVolume = { array, width, height, depth }; - let i = 0 + let i = 0; for (let z = 0; z < depth; ++z) { for (let y = 0; y < height; ++y) { for (let x = 0; x < width; ++x) { if (i < 100) { - console.log(get(data, x, y, z), ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255) + console.log(get(data, x, y, z), ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255); } - array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255 - i += 4 + array[i + 3] = ((get(data, x, y, z) - stats.min) / (stats.max - stats.min)) * 255; + i += 4; } } } - return textureVolume + return textureVolume; } export function createDirectVolume3d(ctx: RuntimeContext, webgl: WebGLContext, volume: VolumeData, directVolume?: DirectVolume) { - const gridDimension = volume.data.space.dimensions as Vec3 - const textureVolume = createVolumeTexture3d(volume) - const transform = VolumeData.getGridToCartesianTransform(volume) + const gridDimension = volume.data.space.dimensions as Vec3; + const textureVolume = createVolumeTexture3d(volume); + const transform = VolumeData.getGridToCartesianTransform(volume); // Mat4.invert(transform, transform) - const bbox = getBoundingBox(gridDimension, transform) + const bbox = getBoundingBox(gridDimension, transform); - const texture = directVolume ? directVolume.gridTexture.ref.value : webgl.resources.texture('volume-uint8', 'rgba', 'ubyte', 'linear') - texture.load(textureVolume) + const texture = directVolume ? directVolume.gridTexture.ref.value : webgl.resources.texture('volume-uint8', 'rgba', 'ubyte', 'linear'); + texture.load(textureVolume); - return DirectVolume.create(bbox, gridDimension, transform, texture, directVolume) + return DirectVolume.create(bbox, gridDimension, transform, texture, directVolume); } // export async function createDirectVolume(ctx: VisualContext, volume: VolumeData, theme: Theme, props: PD.Values<DirectVolumeParams>, directVolume?: DirectVolume) { - const { runtime, webgl } = ctx - if (webgl === undefined) throw new Error('DirectVolumeVisual requires `webgl` in props') + const { runtime, webgl } = ctx; + if (webgl === undefined) throw new Error('DirectVolumeVisual requires `webgl` in props'); return webgl.isWebGL2 ? await createDirectVolume3d(runtime, webgl, volume, directVolume) : - await createDirectVolume2d(runtime, webgl, volume, directVolume) + await createDirectVolume2d(runtime, webgl, volume, directVolume); } // @@ -156,10 +156,10 @@ export async function createDirectVolume(ctx: VisualContext, volume: VolumeData, export const DirectVolumeParams = { ...BaseGeometry.Params, ...DirectVolume.Params -} +}; export type DirectVolumeParams = typeof DirectVolumeParams export function getDirectVolumeParams(ctx: ThemeRegistryContext, volume: VolumeData) { - return PD.clone(DirectVolumeParams) + return PD.clone(DirectVolumeParams); } export function DirectVolumeVisual(materialId: number): VolumeVisual<DirectVolumeParams> { @@ -172,11 +172,11 @@ export function DirectVolumeVisual(materialId: number): VolumeVisual<DirectVolum setUpdateState: (state: VisualUpdateState, volume: VolumeData, newProps: PD.Values<DirectVolumeParams>, currentProps: PD.Values<DirectVolumeParams>) => { }, geometryUtils: DirectVolume.Utils - }, materialId) + }, materialId); } export function DirectVolumeRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<VolumeData, DirectVolumeParams>): VolumeRepresentation<DirectVolumeParams> { - return VolumeRepresentation('Direct Volume', ctx, getParams, DirectVolumeVisual) + return VolumeRepresentation('Direct Volume', ctx, getParams, DirectVolumeVisual); } export const DirectVolumeRepresentationProvider = VolumeRepresentationProvider({ @@ -189,4 +189,4 @@ export const DirectVolumeRepresentationProvider = VolumeRepresentationProvider({ defaultColorTheme: { name: 'uniform' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (volume: VolumeData) => volume.data.data.length > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/volume/isosurface.ts b/src/mol-repr/volume/isosurface.ts index 0898911f7ed73787172a19b52f3ba3610f9f18d7..431fbbf4af3053d51d599e51419a053d911bc199 100644 --- a/src/mol-repr/volume/isosurface.ts +++ b/src/mol-repr/volume/isosurface.ts @@ -63,7 +63,7 @@ type IsoValueParam = typeof IsoValueParam export const VolumeIsosurfaceParams = { isoValue: IsoValueParam -} +}; export type VolumeIsosurfaceParams = typeof VolumeIsosurfaceParams export type VolumeIsosurfaceProps = PD.Values<VolumeIsosurfaceParams> @@ -87,7 +87,7 @@ export async function createVolumeIsosurfaceMesh(ctx: VisualContext, volume: Vol export const IsosurfaceMeshParams = { ...Mesh.Params, ...VolumeIsosurfaceParams -} +}; export type IsosurfaceMeshParams = typeof IsosurfaceMeshParams export function IsosurfaceMeshVisual(materialId: number): VolumeVisual<IsosurfaceMeshParams> { @@ -98,10 +98,10 @@ export function IsosurfaceMeshVisual(materialId: number): VolumeVisual<Isosurfac getLoci: () => EmptyLoci, eachLocation: () => false, setUpdateState: (state: VisualUpdateState, volume: VolumeData, newProps: PD.Values<IsosurfaceMeshParams>, currentProps: PD.Values<IsosurfaceMeshParams>) => { - if (!VolumeIsoValue.areSame(newProps.isoValue, currentProps.isoValue, volume.dataStats)) state.createGeometry = true + if (!VolumeIsoValue.areSame(newProps.isoValue, currentProps.isoValue, volume.dataStats)) state.createGeometry = true; }, geometryUtils: Mesh.Utils - }, materialId) + }, materialId); } // @@ -112,10 +112,10 @@ export async function createVolumeIsosurfaceWireframe(ctx: VisualContext, volume const wireframe = await computeMarchingCubesLines({ isoLevel: VolumeIsoValue.toAbsolute(props.isoValue, volume.dataStats).absoluteValue, scalarField: volume.data - }, lines).runAsChild(ctx.runtime) + }, lines).runAsChild(ctx.runtime); const transform = VolumeData.getGridToCartesianTransform(volume); - Lines.transform(wireframe, transform) + Lines.transform(wireframe, transform); return wireframe; } @@ -124,7 +124,7 @@ export const IsosurfaceWireframeParams = { ...Lines.Params, sizeFactor: PD.Numeric(1.5, { min: 0, max: 10, step: 0.1 }), ...VolumeIsosurfaceParams -} +}; export type IsosurfaceWireframeParams = typeof IsosurfaceWireframeParams export function IsosurfaceWireframeVisual(materialId: number): VolumeVisual<IsosurfaceWireframeParams> { @@ -135,10 +135,10 @@ export function IsosurfaceWireframeVisual(materialId: number): VolumeVisual<Isos getLoci: () => EmptyLoci, eachLocation: () => false, setUpdateState: (state: VisualUpdateState, volume: VolumeData, newProps: PD.Values<IsosurfaceWireframeParams>, currentProps: PD.Values<IsosurfaceWireframeParams>) => { - if (!VolumeIsoValue.areSame(newProps.isoValue, currentProps.isoValue, volume.dataStats)) state.createGeometry = true + if (!VolumeIsoValue.areSame(newProps.isoValue, currentProps.isoValue, volume.dataStats)) state.createGeometry = true; }, geometryUtils: Lines.Utils - }, materialId) + }, materialId); } // @@ -146,23 +146,23 @@ export function IsosurfaceWireframeVisual(materialId: number): VolumeVisual<Isos const IsosurfaceVisuals = { 'solid': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<VolumeData, IsosurfaceMeshParams>) => VolumeRepresentation('Isosurface mesh', ctx, getParams, IsosurfaceMeshVisual), 'wireframe': (ctx: RepresentationContext, getParams: RepresentationParamsGetter<VolumeData, IsosurfaceWireframeParams>) => VolumeRepresentation('Isosurface wireframe', ctx, getParams, IsosurfaceWireframeVisual), -} +}; export const IsosurfaceParams = { ...IsosurfaceMeshParams, ...IsosurfaceWireframeParams, visuals: PD.MultiSelect(['solid'], PD.objectToOptions(IsosurfaceVisuals)), -} +}; export type IsosurfaceParams = typeof IsosurfaceParams export function getIsosurfaceParams(ctx: ThemeRegistryContext, volume: VolumeData) { const p = PD.clone(IsosurfaceParams); p.isoValue = createIsoValueParam(VolumeIsoValue.relative(2), volume.dataStats); - return p + return p; } export type IsosurfaceRepresentation = VolumeRepresentation<IsosurfaceParams> export function IsosurfaceRepresentation(ctx: RepresentationContext, getParams: RepresentationParamsGetter<VolumeData, IsosurfaceParams>): IsosurfaceRepresentation { - return Representation.createMulti('Isosurface', ctx, getParams, Representation.StateBuilder, IsosurfaceVisuals as unknown as Representation.Def<VolumeData, IsosurfaceParams>) + return Representation.createMulti('Isosurface', ctx, getParams, Representation.StateBuilder, IsosurfaceVisuals as unknown as Representation.Def<VolumeData, IsosurfaceParams>); } export const IsosurfaceRepresentationProvider = VolumeRepresentationProvider({ @@ -175,4 +175,4 @@ export const IsosurfaceRepresentationProvider = VolumeRepresentationProvider({ defaultColorTheme: { name: 'uniform' }, defaultSizeTheme: { name: 'uniform' }, isApplicable: (volume: VolumeData) => volume.data.data.length > 0 -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/src/mol-repr/volume/registry.ts b/src/mol-repr/volume/registry.ts index 758371e1eaedf23318d7d2921a601abcd67bda43..5f68bfbb6ca0ee4460af5a47fcea9fc8eb729eb8 100644 --- a/src/mol-repr/volume/registry.ts +++ b/src/mol-repr/volume/registry.ts @@ -11,11 +11,11 @@ import { objectForEach } from '../../mol-util/object'; export class VolumeRepresentationRegistry extends RepresentationRegistry<VolumeData, Representation.State> { constructor() { - super() + super(); objectForEach(VolumeRepresentationRegistry.BuiltIn, (p, k) => { if (p.name !== k) throw new Error(`Fix BuiltInVolumeRepresentations to have matching names. ${p.name} ${k}`); - this.add(p as any) - }) + this.add(p as any); + }); } } @@ -23,7 +23,7 @@ export namespace VolumeRepresentationRegistry { export const BuiltIn = { 'isosurface': IsosurfaceRepresentationProvider, // 'direct-volume': DirectVolumeRepresentationProvider, // TODO disabled for now, needs more work - } + }; type _BuiltIn = typeof BuiltIn export type BuiltIn = keyof _BuiltIn diff --git a/src/mol-repr/volume/representation.ts b/src/mol-repr/volume/representation.ts index 762f3a0a44b066022fd95e2910d36e3ec4e03aa3..0804cdb05315e82fb1d6b040a55d0f7e95584b8a 100644 --- a/src/mol-repr/volume/representation.ts +++ b/src/mol-repr/volume/representation.ts @@ -33,11 +33,11 @@ import { SizeValues } from '../../mol-gl/renderable/schema'; export interface VolumeVisual<P extends VolumeParams> extends Visual<VolumeData, P> { } function createVolumeRenderObject<G extends Geometry>(volume: VolumeData, geometry: G, locationIt: LocationIterator, theme: Theme, props: PD.Values<Geometry.Params<G>>, materialId: number) { - const { createValues, createRenderableState } = Geometry.getUtils(geometry) - const transform = createIdentityTransform() - const values = createValues(geometry, transform, locationIt, theme, props) - const state = createRenderableState(props) - return createRenderObject(geometry.kind, values, state, materialId) + const { createValues, createRenderableState } = Geometry.getUtils(geometry); + const transform = createIdentityTransform(); + const values = createValues(geometry, transform, locationIt, theme, props); + const state = createRenderableState(props); + return createRenderObject(geometry.kind, values, state, materialId); } interface VolumeVisualBuilder<P extends VolumeParams, G extends Geometry> { @@ -54,148 +54,148 @@ interface VolumeVisualGeometryBuilder<P extends VolumeParams, G extends Geometry } export function VolumeVisual<G extends Geometry, P extends VolumeParams & Geometry.Params<G>>(builder: VolumeVisualGeometryBuilder<P, G>, materialId: number): VolumeVisual<P> { - const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState } = builder - const { updateValues, updateBoundingSphere, updateRenderableState } = builder.geometryUtils - const updateState = VisualUpdateState.create() + const { defaultProps, createGeometry, createLocationIterator, getLoci, eachLocation, setUpdateState } = builder; + const { updateValues, updateBoundingSphere, updateRenderableState } = builder.geometryUtils; + const updateState = VisualUpdateState.create(); - let renderObject: GraphicsRenderObject<G['kind']> | undefined + let renderObject: GraphicsRenderObject<G['kind']> | undefined; - let newProps: PD.Values<P> - let newTheme: Theme - let newVolume: VolumeData + let newProps: PD.Values<P>; + let newTheme: Theme; + let newVolume: VolumeData; - let currentProps: PD.Values<P> = Object.assign({}, defaultProps) - let currentTheme: Theme = Theme.createEmpty() - let currentVolume: VolumeData + let currentProps: PD.Values<P> = Object.assign({}, defaultProps); + let currentTheme: Theme = Theme.createEmpty(); + let currentVolume: VolumeData; - let geometry: G - let locationIt: LocationIterator + let geometry: G; + let locationIt: LocationIterator; function prepareUpdate(theme: Theme, props: Partial<PD.Values<P>>, volume: VolumeData) { if (!volume && !currentVolume) { - throw new Error('missing volume') + throw new Error('missing volume'); } - newProps = Object.assign({}, currentProps, props) - newTheme = theme - newVolume = volume + newProps = Object.assign({}, currentProps, props); + newTheme = theme; + newVolume = volume; - VisualUpdateState.reset(updateState) + VisualUpdateState.reset(updateState); if (!renderObject) { - updateState.createNew = true + updateState.createNew = true; } else if (!currentVolume || !VolumeData.areEquivalent(newVolume, currentVolume)) { - updateState.createNew = true + updateState.createNew = true; } if (updateState.createNew) { - updateState.createGeometry = true - return + updateState.createGeometry = true; + return; } - setUpdateState(updateState, volume, newProps, currentProps, newTheme, currentTheme) + setUpdateState(updateState, volume, newProps, currentProps, newTheme, currentTheme); - if (!ColorTheme.areEqual(theme.color, currentTheme.color)) updateState.updateColor = true + if (!ColorTheme.areEqual(theme.color, currentTheme.color)) updateState.updateColor = true; if (updateState.createGeometry) { - updateState.updateColor = true + updateState.updateColor = true; } } function update(newGeometry?: G) { if (updateState.createNew) { - locationIt = createLocationIterator(newVolume) + locationIt = createLocationIterator(newVolume); if (newGeometry) { - renderObject = createVolumeRenderObject(newVolume, newGeometry, locationIt, newTheme, newProps, materialId) + renderObject = createVolumeRenderObject(newVolume, newGeometry, locationIt, newTheme, newProps, materialId); } else { - throw new Error('expected geometry to be given') + throw new Error('expected geometry to be given'); } } else { if (!renderObject) { - throw new Error('expected renderObject to be available') + throw new Error('expected renderObject to be available'); } - locationIt.reset() + locationIt.reset(); if (updateState.createGeometry) { if (newGeometry) { - ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(newGeometry)) - updateBoundingSphere(renderObject.values as RenderObjectValues<G['kind']>, newGeometry) + ValueCell.update(renderObject.values.drawCount, Geometry.getDrawCount(newGeometry)); + updateBoundingSphere(renderObject.values as RenderObjectValues<G['kind']>, newGeometry); } else { - throw new Error('expected geometry to be given') + throw new Error('expected geometry to be given'); } } if (updateState.updateSize) { // not all geometries have size data, so check here if ('uSize' in renderObject.values) { - createSizes(locationIt, newTheme.size, renderObject.values as SizeValues) + createSizes(locationIt, newTheme.size, renderObject.values as SizeValues); } } if (updateState.updateColor) { - createColors(locationIt, newTheme.color, renderObject.values) + createColors(locationIt, newTheme.color, renderObject.values); } - updateValues(renderObject.values, newProps) - updateRenderableState(renderObject.state, newProps) + updateValues(renderObject.values, newProps); + updateRenderableState(renderObject.state, newProps); } - currentProps = newProps - currentTheme = newTheme - currentVolume = newVolume - if (newGeometry) geometry = newGeometry + currentProps = newProps; + currentTheme = newTheme; + currentVolume = newVolume; + if (newGeometry) geometry = newGeometry; } function lociApply(loci: Loci, apply: (interval: Interval) => boolean) { if (isEveryLoci(loci)) { - return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount)) + return apply(Interval.ofBounds(0, locationIt.groupCount * locationIt.instanceCount)); } else { - return eachLocation(loci, apply) + return eachLocation(loci, apply); } } return { - get groupCount() { return locationIt ? locationIt.count : 0 }, - get renderObject () { return renderObject }, + get groupCount() { return locationIt ? locationIt.count : 0; }, + get renderObject () { return renderObject; }, async createOrUpdate(ctx: VisualContext, theme: Theme, props: Partial<PD.Values<P>> = {}, volume?: VolumeData) { - prepareUpdate(theme, props, volume || currentVolume) + prepareUpdate(theme, props, volume || currentVolume); if (updateState.createGeometry) { - const newGeometry = createGeometry(ctx, newVolume, newTheme, newProps, geometry) - return newGeometry instanceof Promise ? newGeometry.then(update) : update(newGeometry) + const newGeometry = createGeometry(ctx, newVolume, newTheme, newProps, geometry); + return newGeometry instanceof Promise ? newGeometry.then(update) : update(newGeometry); } else { - update() + update(); } }, getLoci(pickingId: PickingId) { - return renderObject ? getLoci(pickingId, renderObject.id) : EmptyLoci + return renderObject ? getLoci(pickingId, renderObject.id) : EmptyLoci; }, mark(loci: Loci, action: MarkerAction) { - return Visual.mark(renderObject, loci, action, lociApply) + return Visual.mark(renderObject, loci, action, lociApply); }, setVisibility(visible: boolean) { - Visual.setVisibility(renderObject, visible) + Visual.setVisibility(renderObject, visible); }, setAlphaFactor(alphaFactor: number) { - Visual.setAlphaFactor(renderObject, alphaFactor) + Visual.setAlphaFactor(renderObject, alphaFactor); }, setPickable(pickable: boolean) { - Visual.setPickable(renderObject, pickable) + Visual.setPickable(renderObject, pickable); }, setTransform(matrix?: Mat4, instanceMatrices?: Float32Array | null) { - Visual.setTransform(renderObject, matrix, instanceMatrices) + Visual.setTransform(renderObject, matrix, instanceMatrices); }, setOverpaint(overpaint: Overpaint) { - return Visual.setOverpaint(renderObject, overpaint, lociApply, true) + return Visual.setOverpaint(renderObject, overpaint, lociApply, true); }, setTransparency(transparency: Transparency) { - return Visual.setTransparency(renderObject, transparency, lociApply, true) + return Visual.setTransparency(renderObject, transparency, lociApply, true); }, destroy() { // TODO - renderObject = undefined + renderObject = undefined; } - } + }; } export interface VolumeRepresentation<P extends VolumeParams> extends Representation<VolumeData, P> { } @@ -207,79 +207,79 @@ export function VolumeRepresentationProvider<P extends VolumeParams, Id extends export const VolumeParams = { ...BaseGeometry.Params, -} +}; export type VolumeParams = typeof VolumeParams export function VolumeRepresentation<P extends VolumeParams>(label: string, ctx: RepresentationContext, getParams: RepresentationParamsGetter<VolumeData, P>, visualCtor: (materialId: number) => VolumeVisual<P>): VolumeRepresentation<P> { - let version = 0 - const updated = new Subject<number>() - const materialId = getNextMaterialId() - const renderObjects: GraphicsRenderObject[] = [] - const _state = Representation.createState() - let visual: VolumeVisual<P> | undefined - - let _volume: VolumeData - let _params: P - let _props: PD.Values<P> - let _theme = Theme.createEmpty() + let version = 0; + const updated = new Subject<number>(); + const materialId = getNextMaterialId(); + const renderObjects: GraphicsRenderObject[] = []; + const _state = Representation.createState(); + let visual: VolumeVisual<P> | undefined; + + let _volume: VolumeData; + let _params: P; + let _props: PD.Values<P>; + let _theme = Theme.createEmpty(); function createOrUpdate(props: Partial<PD.Values<P>> = {}, volume?: VolumeData) { if (volume && volume !== _volume) { - _params = getParams(ctx, volume) - _volume = volume - if (!_props) _props = PD.getDefaultValues(_params) + _params = getParams(ctx, volume); + _volume = volume; + if (!_props) _props = PD.getDefaultValues(_params); } - _props = Object.assign({}, _props, props) + _props = Object.assign({}, _props, props); return Task.create('Creating or updating VolumeRepresentation', async runtime => { - if (!visual) visual = visualCtor(materialId) - const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, volume) - if (promise) await promise + if (!visual) visual = visualCtor(materialId); + const promise = visual.createOrUpdate({ webgl: ctx.webgl, runtime }, _theme, _props, volume); + if (promise) await promise; // update list of renderObjects - renderObjects.length = 0 - if (visual && visual.renderObject) renderObjects.push(visual.renderObject) + renderObjects.length = 0; + if (visual && visual.renderObject) renderObjects.push(visual.renderObject); // increment version - updated.next(version++) + updated.next(version++); }); } function getLoci(pickingId?: PickingId) { - if (pickingId === undefined) return EmptyLoci // TODO add Volume.Loci when available - return visual ? visual.getLoci(pickingId) : EmptyLoci + if (pickingId === undefined) return EmptyLoci; // TODO add Volume.Loci when available + return visual ? visual.getLoci(pickingId) : EmptyLoci; } function mark(loci: Loci, action: MarkerAction) { - return visual ? visual.mark(loci, action) : false + return visual ? visual.mark(loci, action) : false; } function setState(state: Partial<Representation.State>) { - if (state.visible !== undefined && visual) visual.setVisibility(state.visible) - if (state.alphaFactor !== undefined && visual) visual.setAlphaFactor(state.alphaFactor) - if (state.pickable !== undefined && visual) visual.setPickable(state.pickable) - if (state.overpaint !== undefined && visual) visual.setOverpaint(state.overpaint) - if (state.transparency !== undefined && visual) visual.setTransparency(state.transparency) - if (state.transform !== undefined && visual) visual.setTransform(state.transform) - - Representation.updateState(_state, state) + if (state.visible !== undefined && visual) visual.setVisibility(state.visible); + if (state.alphaFactor !== undefined && visual) visual.setAlphaFactor(state.alphaFactor); + if (state.pickable !== undefined && visual) visual.setPickable(state.pickable); + if (state.overpaint !== undefined && visual) visual.setOverpaint(state.overpaint); + if (state.transparency !== undefined && visual) visual.setTransparency(state.transparency); + if (state.transform !== undefined && visual) visual.setTransform(state.transform); + + Representation.updateState(_state, state); } function setTheme(theme: Theme) { - _theme = theme + _theme = theme; } function destroy() { - if (visual) visual.destroy() + if (visual) visual.destroy(); } return { label, get groupCount() { - return visual ? visual.groupCount : 0 + return visual ? visual.groupCount : 0; }, - get props () { return _props }, - get params() { return _params }, - get state() { return _state }, - get theme() { return _theme }, + get props () { return _props; }, + get params() { return _params; }, + get state() { return _state; }, + get theme() { return _theme; }, renderObjects, updated, createOrUpdate, @@ -288,5 +288,5 @@ export function VolumeRepresentation<P extends VolumeParams>(label: string, ctx: getLoci, mark, destroy - } + }; } \ No newline at end of file diff --git a/src/mol-script/language/builder.ts b/src/mol-script/language/builder.ts index 16038e3837ddc1f39468220af151a7a1dc252197..d739ca6b87fbfcc2b57fe75d8d84d7addcdc22d1 100644 --- a/src/mol-script/language/builder.ts +++ b/src/mol-script/language/builder.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Expression from './expression' -import { MSymbol } from './symbol' -import { MolScriptSymbolTable as SymbolTable } from './symbol-table' +import Expression from './expression'; +import { MSymbol } from './symbol'; +import { MolScriptSymbolTable as SymbolTable } from './symbol-table'; export namespace MolScriptBuilder { export const core = SymbolTable.core; @@ -30,19 +30,19 @@ export namespace MolScriptBuilder { const _acp = struct.atomProperty.core, _ammp = struct.atomProperty.macromolecular, _atp = struct.atomProperty.topology; /** atom core property */ - export function acp(p: keyof typeof _acp) { return (_acp[p] as MSymbol<any>)() }; + export function acp(p: keyof typeof _acp) { return (_acp[p] as MSymbol<any>)(); }; /** atom topology property */ - export function atp(p: keyof typeof _atp) { return (_atp[p] as MSymbol<any>)() }; + export function atp(p: keyof typeof _atp) { return (_atp[p] as MSymbol<any>)(); }; /** atom macromolecular property */ - export function ammp(p: keyof typeof _ammp) { return (_ammp[p] as MSymbol<any>)() }; + export function ammp(p: keyof typeof _ammp) { return (_ammp[p] as MSymbol<any>)(); }; - const _aps = struct.atomSet.propertySet + const _aps = struct.atomSet.propertySet; /** atom core property set */ - export function acpSet(p: keyof typeof _acp) { return _aps([ acp(p) ]) }; + export function acpSet(p: keyof typeof _acp) { return _aps([ acp(p) ]); }; /** atom topology property set */ - export function atpSet(p: keyof typeof _atp) { return _aps([ atp(p) ]) }; + export function atpSet(p: keyof typeof _atp) { return _aps([ atp(p) ]); }; /** atom macromolecular property set */ - export function ammpSet(p: keyof typeof _ammp) { return _aps([ ammp(p) ]) }; + export function ammpSet(p: keyof typeof _ammp) { return _aps([ ammp(p) ]); }; } \ No newline at end of file diff --git a/src/mol-script/language/container.ts b/src/mol-script/language/container.ts index f03655aa965ff19c85da5e3c4ffb3641b8e26e7b..8757f3f10017fb5780157080dbb7b7e8e8236fc5 100644 --- a/src/mol-script/language/container.ts +++ b/src/mol-script/language/container.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Expression from './expression' +import Expression from './expression'; interface Container { source?: string, @@ -12,4 +12,4 @@ interface Container { expression: Expression } -export default Container \ No newline at end of file +export default Container; \ No newline at end of file diff --git a/src/mol-script/language/expression-formatter.ts b/src/mol-script/language/expression-formatter.ts index 93c1aa0366d0acd8ab5a35cd86527f4168ec4ae5..a9e4fff9e754b81e9c34e82b4afd8e3087dcb373 100644 --- a/src/mol-script/language/expression-formatter.ts +++ b/src/mol-script/language/expression-formatter.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Expression from './expression' +import Expression from './expression'; const { isLiteral, isSymbol, isArgumentsArray } = Expression; @@ -107,7 +107,7 @@ function _format(e: Expression, writer: Writer) { } if (keys.length === 1 && isLiteral(e.args[keys[0]])) { - writer.whitespace() + writer.whitespace(); writer.append(`:${keys[0]}`); writer.whitespace(); _format(e.args[keys[0]], writer); diff --git a/src/mol-script/language/expression.ts b/src/mol-script/language/expression.ts index ba6f77367e17b2c2dc018d550922ab58ac061a5a..8563cca6390945661245cec3bfd31d2ba4006065 100644 --- a/src/mol-script/language/expression.ts +++ b/src/mol-script/language/expression.ts @@ -22,7 +22,7 @@ namespace Expression { export function isArgumentsMap(e?: Arguments): e is { [name: string]: Expression } { return !!e && !Array.isArray(e); } export function isLiteral(e: Expression): e is Expression.Literal { return !isApply(e) && !isSymbol(e); } export function isApply(e: Expression): e is Expression.Apply { return !!e && !!(e as Expression.Apply).head && typeof e === 'object'; } - export function isSymbol(e: Expression): e is Expression.Symbol { return !!e && typeof (e as any).name === 'string' } + export function isSymbol(e: Expression): e is Expression.Symbol { return !!e && typeof (e as any).name === 'string'; } } -export default Expression \ No newline at end of file +export default Expression; \ No newline at end of file diff --git a/src/mol-script/language/helpers.ts b/src/mol-script/language/helpers.ts index 926cb216c211e90251628a8052605d896d6d4fbc..aee8e590a48541e2099143167c46fdf3bd4f97e7 100644 --- a/src/mol-script/language/helpers.ts +++ b/src/mol-script/language/helpers.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Type from './type' -import { MSymbol, Arguments, isSymbol } from './symbol' +import Type from './type'; +import { MSymbol, Arguments, isSymbol } from './symbol'; export function symbol<A extends Arguments, T extends Type<S>, S>(args: A, type: T, description?: string) { return MSymbol('', args, type, description); diff --git a/src/mol-script/language/parser.ts b/src/mol-script/language/parser.ts index 5fdfbee14f7e7c3fc7c41b729081fffdb42956e0..ec23e5147899b504ad1a941b53301c690e9bbc9e 100644 --- a/src/mol-script/language/parser.ts +++ b/src/mol-script/language/parser.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { MonadicParser as P } from '../../mol-util/monadic-parser' -import Expression from './expression' -import { MolScriptBuilder as B } from './builder' +import { MonadicParser as P } from '../../mol-util/monadic-parser'; +import Expression from './expression'; +import { MolScriptBuilder as B } from './builder'; export function parseMolScript(input: string) { return Language.parse(input); @@ -42,7 +42,7 @@ namespace Language { export function str(value: string): Str { return { kind: 'string', value }; } export function symb(value: string): Symb { return { kind: 'symbol', value }; } export function list(bracket: '(' | '[' | '{', nodes: Expression[]): List { return { kind: 'list', bracket, nodes }; } - export function comment(value: string): Comment { return { kind: 'comment', value } } + export function comment(value: string): Comment { return { kind: 'comment', value }; } } const ws = P.regexp(/[\n\r\s]*/); diff --git a/src/mol-script/language/symbol-table.ts b/src/mol-script/language/symbol-table.ts index b8fde22ab30653331273d04ba027a6a649221489..76295b4c767388336f99507f6ae94707461ee9ff 100644 --- a/src/mol-script/language/symbol-table.ts +++ b/src/mol-script/language/symbol-table.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import core from './symbol-table/core' -import structureQuery from './symbol-table/structure-query' -import internal from './symbol-table/internal' -import { normalizeTable, symbolList } from './helpers' -import { MSymbol } from './symbol' +import core from './symbol-table/core'; +import structureQuery from './symbol-table/structure-query'; +import internal from './symbol-table/internal'; +import { normalizeTable, symbolList } from './helpers'; +import { MSymbol } from './symbol'; const MolScriptSymbolTable = { core, structureQuery, internal }; @@ -22,4 +22,4 @@ export const SymbolMap = (function() { return map; })(); -export { MolScriptSymbolTable } \ No newline at end of file +export { MolScriptSymbolTable }; \ No newline at end of file diff --git a/src/mol-script/language/symbol-table/core.ts b/src/mol-script/language/symbol-table/core.ts index bf1ca0d0bbf3e3e8cdf23545b88ec13445ba0241..c98a43e7bf20c29eadc836e790eb50f1cf8251fe 100644 --- a/src/mol-script/language/symbol-table/core.ts +++ b/src/mol-script/language/symbol-table/core.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Type from '../type' -import { MSymbol, Arguments, Argument } from '../symbol' -import { symbol, normalizeTable, symbolList } from '../helpers' +import Type from '../type'; +import { MSymbol, Arguments, Argument } from '../symbol'; +import { symbol, normalizeTable, symbolList } from '../helpers'; export namespace Types { export type List<T = any> = ArrayLike<T> @@ -44,11 +44,11 @@ function binRel<A extends Type, T extends Type>(src: A, target: T, description?: export const TTargs = Arguments.Dictionary({ 0: Argument(Type.Num), 1: Argument(Type.Num) -}) +}); const XX = { test: Argument(Type.Str) }; const t: Arguments.PropTypes<typeof XX> = 0 as any; -t.test +t.test; const type = { '@header': 'Types', @@ -164,7 +164,7 @@ const flags = { 0: Argument(Types.Flags(Types.ConstrainedVar)), 1: Argument(Types.Flags(Types.ConstrainedVar)) }), Type.Bool, 'Check if the the 1st argument has all 2nd one\'s flags.'), -} +}; const table = { '@header': 'Language Primitives', @@ -177,7 +177,7 @@ const table = { list, set, flags -} +}; normalizeTable(table); diff --git a/src/mol-script/language/symbol-table/internal.ts b/src/mol-script/language/symbol-table/internal.ts index 756822b145ca1fd4d506ea81a57dc804cb7db793..11adc1064d864c2db5e2a0656eccc9632b49002d 100644 --- a/src/mol-script/language/symbol-table/internal.ts +++ b/src/mol-script/language/symbol-table/internal.ts @@ -4,10 +4,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Type from '../type' -import * as Struct from './structure-query' -import { Arguments, Argument } from '../symbol' -import { symbol } from '../helpers' +import Type from '../type'; +import * as Struct from './structure-query'; +import { Arguments, Argument } from '../symbol'; +import { symbol } from '../helpers'; const generator = { '@header': 'Generators', @@ -26,9 +26,9 @@ const generator = { // Use with caution as this is not "state saveable" // This query should never be used in any State Transform! current: symbol(Arguments.None, Struct.Types.ElementSelectionQuery, 'Current selection provided by the query context. Avoid using this in State Transforms.') -} +}; export default { '@header': 'Internal Queries', generator -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-script/language/symbol-table/structure-query.ts b/src/mol-script/language/symbol-table/structure-query.ts index d76329a1fa56f11a7ea2836da78dc498cf706c2a..091c564b196012f30143dec4c54550b7b3616b40 100644 --- a/src/mol-script/language/symbol-table/structure-query.ts +++ b/src/mol-script/language/symbol-table/structure-query.ts @@ -5,10 +5,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import Type from '../type' -import * as Core from './core' -import { Arguments, Argument } from '../symbol' -import { symbol } from '../helpers' +import Type from '../type'; +import * as Core from './core'; +import { Arguments, Argument } from '../symbol'; +import { symbol } from '../helpers'; export namespace Types { export const ElementSymbol = Type.Value('Structure', 'ElementSymbol'); @@ -79,7 +79,7 @@ const slot = { '@header': 'Iteration Slots', element: symbol(Arguments.None, Types.ElementReference, 'A reference to the current element.'), elementSetReduce: symbol(Arguments.None, Type.Variable('a', Type.AnyValue, true), 'Current value of the element set reducer.') -} +}; const generator = { '@header': 'Generators', @@ -111,7 +111,7 @@ const generator = { }), Types.ElementSelectionQuery, 'Executes query only on atoms that are in the source selection.'), empty: symbol(Arguments.None, Types.ElementSelectionQuery, 'Nada.'), -} +}; const modifier = { '@header': 'Selection Modifications', @@ -170,7 +170,7 @@ const modifier = { 0: Argument(Types.ElementSelectionQuery), property: Argument(Type.AnyValue) }), Types.ElementSelectionQuery, 'To each atom set in the selection, add all atoms that have the same property value that was already present in the set.') -} +}; const filter = { '@header': 'Selection Filters', @@ -210,7 +210,7 @@ const filter = { disjunct: Argument(Type.Bool, { isOptional: true, defaultValue: true, description: 'If true, there must exist a bond to an atom that lies outside the given atom set to pass test.' }), invert: Argument(Type.Bool, { isOptional: true, defaultValue: false, description: 'If true, return atom sets that are not connected.' }) }), Types.ElementSelectionQuery, 'Pick all atom sets that are connected to the target.'), -} +}; const combinator = { '@header': 'Selection Combinators', @@ -220,7 +220,7 @@ const combinator = { matrix: Argument(Core.Types.List(Core.Types.List(Type.Num)), { description: 'Distance matrix, represented as list of rows (num[][])). Lower triangle is min distance, upper triangle is max distance.' }), selections: Argument(Core.Types.List(Types.ElementSelectionQuery), { description: 'A list of held selections.' }) }), Types.ElementSelectionQuery, 'Pick combinations of atom sets from the source sequences that are mutually within distances specified by a matrix.') -} +}; const atomSet = { '@header': 'Atom Sets', @@ -239,7 +239,7 @@ const atomSet = { propertySet: symbol(Arguments.Dictionary({ 0: Argument(Core.Types.ConstrainedVar), }), Core.Types.Set(Core.Types.ConstrainedVar), 'Returns a set with all values of the given property in the current atom set.'), -} +}; const atomProperty = { '@header': 'Atom Properties', @@ -317,7 +317,7 @@ const atomProperty = { isNonStandard: atomProp(Type.Bool, 'True if this is a non-standard residue.'), chemCompType: atomProp(Type.Str, `Type of the chemical component as defined in mmCIF.`), } -} +}; const bondProperty = { '@header': 'Bond Properties', @@ -327,7 +327,7 @@ const bondProperty = { length: bondProp(Type.Num), atomA: bondProp(Types.ElementReference), atomB: bondProp(Types.ElementReference) -} +}; function atomProp(type: Type, description?: string) { return symbol(Arguments.Dictionary({ 0: Argument(Types.ElementReference, { isOptional: true, defaultValue: 'slot.current-atom' }) }), type, description); @@ -348,4 +348,4 @@ export default { atomSet, atomProperty, bondProperty: bondProperty -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-script/language/symbol.ts b/src/mol-script/language/symbol.ts index bb935ee6f90b46f622459b68fe982eae660a58e1..8ae18ccbb98e9533e42ffa76d5ebcda39e1f4e69 100644 --- a/src/mol-script/language/symbol.ts +++ b/src/mol-script/language/symbol.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import Type from './type' -import Expression from './expression' +import Type from './type'; +import Expression from './expression'; export type Argument<T extends Type = Type> = { type: T, @@ -15,7 +15,7 @@ export type Argument<T extends Type = Type> = { description: string | undefined } export function Argument<T extends Type>(type: T, params?: { description?: string, defaultValue?: T['@type'], isOptional?: boolean, isRest?: boolean }): Argument<T> { - const { description = void 0, isOptional = false, isRest = false, defaultValue = void 0 } = params || {} + const { description = void 0, isOptional = false, isRest = false, defaultValue = void 0 } = params || {}; return { type, isOptional, isRest, defaultValue, description }; } @@ -44,7 +44,7 @@ export namespace Arguments { } export function List<T extends Type>(type: T, params?: { nonEmpty?: boolean }): Arguments<{ [key: string]: T['@type'] }> { - const { nonEmpty = false } = params || { } + const { nonEmpty = false } = params || { }; return { kind: 'list', type, nonEmpty, '@type': 0 as any }; } } diff --git a/src/mol-script/language/type.ts b/src/mol-script/language/type.ts index 90465ec4df5420823eb3e82f0e0ed80a52b31833..df95e8346a0b579d55f5e96dc4652924f4f82b35 100644 --- a/src/mol-script/language/type.ts +++ b/src/mol-script/language/type.ts @@ -37,4 +37,4 @@ namespace Type { export function oneOfValues({ values }: OneOf<any>) { return Object.keys(values).sort(); } } -export default Type \ No newline at end of file +export default Type; \ No newline at end of file diff --git a/src/mol-script/runtime/query/base.ts b/src/mol-script/runtime/query/base.ts index a64c3a6af0bd2ab6bd453742eedda3eb028de0f7..b9982624de919880b9ede41c136eebfd3381e329 100644 --- a/src/mol-script/runtime/query/base.ts +++ b/src/mol-script/runtime/query/base.ts @@ -51,7 +51,7 @@ export type CompiledQueryFn<T = any> = { isConst: boolean, fn: QueryFn } export namespace QueryCompiledSymbol { export function Const(value: any): QueryCompiledSymbolRuntime { - return { kind: 'const', value } + return { kind: 'const', value }; } export function Dynamic(runtime: QuerySymbolFn): QueryCompiledSymbolRuntime { @@ -61,7 +61,7 @@ export namespace QueryCompiledSymbol { export namespace CompiledQueryFn { export function Const(value: any): CompiledQueryFn { - return { isConst: true, fn: function CompiledQueryFn_Const(ctx) { return value } }; + return { isConst: true, fn: function CompiledQueryFn_Const(ctx) { return value; } }; } export function Dynamic(fn: QueryFn): CompiledQueryFn { @@ -125,7 +125,7 @@ class SymbolRuntimeImpl<S extends MSymbol> implements QuerySymbolRuntime { if (this.isConst) { if (this.isConst && constArgs) { - return CompiledQueryFn.Const(this.fn(ctx.constQueryContext, args)) + return CompiledQueryFn.Const(this.fn(ctx.constQueryContext, args)); } return CompiledQueryFn.Dynamic(createDynamicFn(this.fn, args)); @@ -140,7 +140,7 @@ class SymbolRuntimeImpl<S extends MSymbol> implements QuerySymbolRuntime { } function createDynamicFn<S extends MSymbol>(fn: QuerySymbolFn<S>, args: any): QueryFn { - return function DynamicFn(ctx) { return fn(ctx, args) }; + return function DynamicFn(ctx) { return fn(ctx, args); }; } function _compile(ctx: QueryCompilerCtx, expression: Expression): CompiledQueryFn { diff --git a/src/mol-script/runtime/query/compiler.ts b/src/mol-script/runtime/query/compiler.ts index 2c799c3efd8dad115d33112cc78ed326f012271b..3e7842567d4b6aa6ffe6a5169a6bbab5bcf788d3 100644 --- a/src/mol-script/runtime/query/compiler.ts +++ b/src/mol-script/runtime/query/compiler.ts @@ -4,5 +4,5 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './base' -import './table' \ No newline at end of file +export * from './base'; +import './table'; \ No newline at end of file diff --git a/src/mol-script/runtime/query/table.ts b/src/mol-script/runtime/query/table.ts index 4cac2762a67249d07aabb2e29d9e8c0427605205..d8e879207cdb8e111d6d457ae187a1ac272d9e4d 100644 --- a/src/mol-script/runtime/query/table.ts +++ b/src/mol-script/runtime/query/table.ts @@ -15,20 +15,20 @@ import { VdwRadius, AtomWeight, AtomNumber } from '../../../mol-model/structure/ import { cantorPairing } from '../../../mol-data/util'; import { bundleElementImpl, bundleGenerator } from '../../../mol-model/structure/query/queries/internal'; -const C = QuerySymbolRuntime.Const -const D = QuerySymbolRuntime.Dynamic +const C = QuerySymbolRuntime.Const; +const D = QuerySymbolRuntime.Dynamic; const symbols = [ // ============= TYPES ============= - C(MolScript.core.type.bool, function core_type_bool(ctx, v) { return !!v[0](ctx) }), - C(MolScript.core.type.num, function core_type_num(ctx, v) { return +v[0](ctx) }), - C(MolScript.core.type.str, function core_type_str(ctx, v) { return '' + v[0](ctx) }), - C(MolScript.core.type.list, function core_type_list(ctx, xs) { return QueryRuntimeArguments.forEachEval(xs, ctx, (v, i, list) => list[i] = v, [] as any[]) }), - C(MolScript.core.type.set, function core_type_set(ctx, xs) { return QueryRuntimeArguments.forEachEval(xs, ctx, function core_type_set_argEval(v, i, set) { return set.add(v) }, new Set<any>()) }), - C(MolScript.core.type.regex, function core_type_regex(ctx, v) { return new RegExp(v[0](ctx), (v[1] && v[1](ctx)) || '') }), - C(MolScript.core.type.bitflags, function core_type_bitflags(ctx, v) { return +v[0](ctx) }), - C(MolScript.core.type.compositeKey, function core_type_compositeKey(ctx, xs) { return QueryRuntimeArguments.forEachEval(xs, ctx, (v, i, list) => list[i] = '' + v, [] as string[]).join('-') }), + C(MolScript.core.type.bool, function core_type_bool(ctx, v) { return !!v[0](ctx); }), + C(MolScript.core.type.num, function core_type_num(ctx, v) { return +v[0](ctx); }), + C(MolScript.core.type.str, function core_type_str(ctx, v) { return '' + v[0](ctx); }), + C(MolScript.core.type.list, function core_type_list(ctx, xs) { return QueryRuntimeArguments.forEachEval(xs, ctx, (v, i, list) => list[i] = v, [] as any[]); }), + C(MolScript.core.type.set, function core_type_set(ctx, xs) { return QueryRuntimeArguments.forEachEval(xs, ctx, function core_type_set_argEval(v, i, set) { return set.add(v); }, new Set<any>()); }), + C(MolScript.core.type.regex, function core_type_regex(ctx, v) { return new RegExp(v[0](ctx), (v[1] && v[1](ctx)) || ''); }), + C(MolScript.core.type.bitflags, function core_type_bitflags(ctx, v) { return +v[0](ctx); }), + C(MolScript.core.type.compositeKey, function core_type_compositeKey(ctx, xs) { return QueryRuntimeArguments.forEachEval(xs, ctx, (v, i, list) => list[i] = '' + v, [] as string[]).join('-'); }), // ============= LOGIC ================ C(MolScript.core.logic.not, (ctx, v) => !v[0](ctx)), @@ -103,7 +103,7 @@ const symbols = [ if (typeof xs.length === 'number') { for (let i = 0, _i = xs.length; i < _i; i++) ret = Math.min(xs[i](ctx), ret); } else { - for (const k of Object.keys(xs)) ret = Math.min(xs[k](ctx), ret) + for (const k of Object.keys(xs)) ret = Math.min(xs[k](ctx), ret); } return ret; }), @@ -112,7 +112,7 @@ const symbols = [ if (typeof xs.length === 'number') { for (let i = 0, _i = xs.length; i < _i; i++) ret = Math.max(xs[i](ctx), ret); } else { - for (const k of Object.keys(xs)) ret = Math.max(xs[k](ctx), ret) + for (const k of Object.keys(xs)) ret = Math.max(xs[k](ctx), ret); } return ret; }), @@ -153,8 +153,8 @@ const symbols = [ C(MolScript.core.list.getAt, (ctx, v) => v[0](ctx)[v[1](ctx)]), // ============= SET ================ - C(MolScript.core.set.has, function core_set_has(ctx, v) { return v[0](ctx).has(v[1](ctx)) }), - C(MolScript.core.set.isSubset, function core_set_isSubset(ctx, v) { return SetUtils.isSuperset(v[1](ctx) as Set<any>, v[0](ctx) as Set<any>) }), + C(MolScript.core.set.has, function core_set_has(ctx, v) { return v[0](ctx).has(v[1](ctx)); }), + C(MolScript.core.set.isSubset, function core_set_isSubset(ctx, v) { return SetUtils.isSuperset(v[1](ctx) as Set<any>, v[0](ctx) as Set<any>); }), // ============= FLAGS ================ C(MolScript.core.flags.hasAny, (ctx, v) => { @@ -235,16 +235,16 @@ const symbols = [ residueTest: xs['residue-test'], atomTest: xs['atom-test'], groupBy: xs['group-by'] - })(ctx) + })(ctx); }), - D(MolScript.structureQuery.generator.all, function structureQuery_generator_all(ctx) { return Queries.generators.all(ctx) }), - D(MolScript.structureQuery.generator.empty, function structureQuery_generator_empty(ctx) { return Queries.generators.none(ctx) }), + D(MolScript.structureQuery.generator.all, function structureQuery_generator_all(ctx) { return Queries.generators.all(ctx); }), + D(MolScript.structureQuery.generator.empty, function structureQuery_generator_empty(ctx) { return Queries.generators.none(ctx); }), D(MolScript.structureQuery.generator.bondedAtomicPairs, function structureQuery_generator_bondedAtomicPairs(ctx, xs) { - return Queries.generators.bondedAtomicPairs(xs && xs[0])(ctx) + return Queries.generators.bondedAtomicPairs(xs && xs[0])(ctx); }), D(MolScript.structureQuery.generator.rings, function structureQuery_generator_rings(ctx, xs) { - return Queries.generators.rings(xs?.['fingerprint']?.(ctx) as any, xs?.['only-aromatic']?.(ctx))(ctx) + return Queries.generators.rings(xs?.['fingerprint']?.(ctx) as any, xs?.['only-aromatic']?.(ctx))(ctx); }), // ============= MODIFIERS ================ @@ -254,19 +254,19 @@ const symbols = [ radius: xs['radius'](ctx), wholeResidues: !!(xs['as-whole-residues'] && xs['as-whole-residues'](ctx)), elementRadius: xs['atom-radius'] - })(ctx) + })(ctx); }), - D(MolScript.structureQuery.modifier.wholeResidues, function structureQuery_modifier_wholeResidues(ctx, xs) { return Queries.modifiers.wholeResidues(xs[0] as any)(ctx) }), - D(MolScript.structureQuery.modifier.union, function structureQuery_modifier_union(ctx, xs) { return Queries.modifiers.union(xs[0] as any)(ctx) }), - D(MolScript.structureQuery.modifier.expandProperty, function structureQuery_modifier_expandProperty(ctx, xs) { return Queries.modifiers.expandProperty(xs[0] as any, xs['property'])(ctx) }), - D(MolScript.structureQuery.modifier.exceptBy, function structureQuery_modifier_exceptBy(ctx, xs) { return Queries.modifiers.exceptBy(xs[0] as any, xs['by'] as any)(ctx) }), + D(MolScript.structureQuery.modifier.wholeResidues, function structureQuery_modifier_wholeResidues(ctx, xs) { return Queries.modifiers.wholeResidues(xs[0] as any)(ctx); }), + D(MolScript.structureQuery.modifier.union, function structureQuery_modifier_union(ctx, xs) { return Queries.modifiers.union(xs[0] as any)(ctx); }), + D(MolScript.structureQuery.modifier.expandProperty, function structureQuery_modifier_expandProperty(ctx, xs) { return Queries.modifiers.expandProperty(xs[0] as any, xs['property'])(ctx); }), + D(MolScript.structureQuery.modifier.exceptBy, function structureQuery_modifier_exceptBy(ctx, xs) { return Queries.modifiers.exceptBy(xs[0] as any, xs['by'] as any)(ctx); }), D(MolScript.structureQuery.modifier.includeConnected, function structureQuery_modifier_includeConnected(ctx, xs) { return Queries.modifiers.includeConnected({ query: xs[0] as any, bondTest: xs['bond-test'], wholeResidues: !!(xs['as-whole-residues'] && xs['as-whole-residues'](ctx)), layerCount: (xs['layer-count'] && xs['layer-count'](ctx)) || 1 - })(ctx) + })(ctx); }), // ============= COMBINATORS ================ @@ -289,7 +289,7 @@ const symbols = [ D(MolScript.structureQuery.atomProperty.core.modelLabel, atomProp(StructureProperties.unit.model_label)), D(MolScript.structureQuery.atomProperty.core.atomKey, (ctx, xs) => { const e = (xs && xs[0] && xs[0](ctx) as any) || ctx.element; - return cantorPairing(e.unit.id, e.element) + return cantorPairing(e.unit.id, e.element); }), // TODO: @@ -349,9 +349,9 @@ const symbols = [ D(MolScript.structureQuery.bondProperty.length, (ctx, xs) => ctx.atomicBond.length), // Internal - D(MolScript.internal.generator.bundleElement, function internal_generator_bundleElement(ctx, xs) { return bundleElementImpl(xs.groupedUnits(ctx), xs.ranges(ctx), xs.set(ctx)) }), - D(MolScript.internal.generator.bundle, function internal_generator_bundle(ctx, xs) { return bundleGenerator(xs.elements(ctx))(ctx) }), - D(MolScript.internal.generator.current, function internal_generator_current(ctx, xs) { return ctx.tryGetCurrentSelection() }), + D(MolScript.internal.generator.bundleElement, function internal_generator_bundleElement(ctx, xs) { return bundleElementImpl(xs.groupedUnits(ctx), xs.ranges(ctx), xs.set(ctx)); }), + D(MolScript.internal.generator.bundle, function internal_generator_bundle(ctx, xs) { return bundleGenerator(xs.elements(ctx))(ctx); }), + D(MolScript.internal.generator.current, function internal_generator_current(ctx, xs) { return ctx.tryGetCurrentSelection(); }), ]; function atomProp(p: (e: StructureElement.Location) => any): (ctx: QueryContext, xs: any) => any { @@ -359,7 +359,7 @@ function atomProp(p: (e: StructureElement.Location) => any): (ctx: QueryContext, } function bondFlag(current: BondType, f: string): BondType { - return current | (BondType.isName(f) ? BondType.fromName(f) : BondType.Flag.None) + return current | (BondType.isName(f) ? BondType.fromName(f) : BondType.Flag.None); } function secondaryStructureFlag(current: SecondaryStructureType, f: string): SecondaryStructureType { diff --git a/src/mol-script/script.ts b/src/mol-script/script.ts index 2c156d1344ecd0cbac8b470aa693de0340dd41d8..08335886f5bff0fd90cdf009c0f194163bf76593 100644 --- a/src/mol-script/script.ts +++ b/src/mol-script/script.ts @@ -11,12 +11,12 @@ import { StructureElement, QueryContext, StructureSelection, Structure, QueryFn, import { compile } from './runtime/query/compiler'; import { MolScriptBuilder } from './language/builder'; -export { Script } +export { Script }; interface Script { expression: string, language: Script.Language } function Script(expression: string, language: Script.Language): Script { - return { expression, language } + return { expression, language }; } namespace Script { @@ -27,28 +27,28 @@ namespace Script { } export function areEqual(a: Script, b: Script) { - return a.language === b.language && a.expression === b.expression + return a.language === b.language && a.expression === b.expression; } export function toExpression(script: Script): Expression { switch (script.language) { case 'mol-script': - const parsed = parseMolScript(script.expression) - if (parsed.length === 0) throw new Error('No query') - return transpileMolScript(parsed[0]) + const parsed = parseMolScript(script.expression); + if (parsed.length === 0) throw new Error('No query'); + return transpileMolScript(parsed[0]); } - throw new Error('unsupported script language') + throw new Error('unsupported script language'); } export function toQuery(script: Script): QueryFn<StructureSelection> { - const expression = toExpression(script) + const expression = toExpression(script); return compile<StructureSelection>(expression); } export function toLoci(script: Script, structure: Structure): StructureElement.Loci { - const query = toQuery(script) - const result = query(new QueryContext(structure)) - return StructureSelection.toLociWithSourceUnits(result) + const query = toQuery(script); + const result = query(new QueryContext(structure)); + return StructureSelection.toLociWithSourceUnits(result); } export function getStructureSelection(expr: Expression | ((builder: typeof MolScriptBuilder) => Expression), structure: Structure, options?: QueryContextOptions) { diff --git a/src/mol-script/script/mol-script/symbols.ts b/src/mol-script/script/mol-script/symbols.ts index eec5049df3b1d456af47a8fff3ea38663a7ef237..e1cd54f1647589cf10bce3a70dc36ca43904130f 100644 --- a/src/mol-script/script/mol-script/symbols.ts +++ b/src/mol-script/script/mol-script/symbols.ts @@ -298,7 +298,7 @@ const normalized = (function () { } } - return { symbolList, symbolMap, namedArgs: namedArgs.array, constants: constants.array } + return { symbolList, symbolMap, namedArgs: namedArgs.array, constants: constants.array }; })(); export const MolScriptSymbols = list; diff --git a/src/mol-script/script/parser.ts b/src/mol-script/script/parser.ts index d318080d5e63112703f7f0de40293ae2c55ede0c..a0a0cad1cc4500d731f440ea24bafdb775f53579 100644 --- a/src/mol-script/script/parser.ts +++ b/src/mol-script/script/parser.ts @@ -5,8 +5,8 @@ * @author Alexander Rose <alexanderose@weirdbyte.de> */ -import Expression from '../language/expression' +import Expression from '../language/expression'; type Parser = (source: string) => Expression -export default Parser \ No newline at end of file +export default Parser; \ No newline at end of file diff --git a/src/mol-state/action.ts b/src/mol-state/action.ts index bd1d25767421c5a47ec8d85bd59f9c2251b23d80..5233b91afd828d79cafda09b32428231ed3ed90d 100644 --- a/src/mol-state/action.ts +++ b/src/mol-state/action.ts @@ -80,7 +80,7 @@ namespace StateAction { const tree = state.build().to(cell.transform.ref).apply(transformer, params); return state.updateTree(tree) as unknown as Task<void>; } - }) + }); } export namespace Builder { diff --git a/src/mol-state/action/manager.ts b/src/mol-state/action/manager.ts index a285a1a7ef6963acb23f59681396f9f8913f4550..ec51c1bebd626f4abe809277702275d87d6a86eb 100644 --- a/src/mol-state/action/manager.ts +++ b/src/mol-state/action/manager.ts @@ -10,7 +10,7 @@ import { StateTransformer } from '../transformer'; import { UUID } from '../../mol-util'; import { arraySetRemove } from '../../mol-util/array'; -export { StateActionManager } +export { StateActionManager }; class StateActionManager { private actions: Map<StateAction['id'], StateAction> = new Map(); diff --git a/src/mol-state/index.ts b/src/mol-state/index.ts index 5d8d630f6180271f2aa218fb35b5d4f391fdc3b9..a8a934f9d3468dc01ef98cba1c42ce9a6a37e7f1 100644 --- a/src/mol-state/index.ts +++ b/src/mol-state/index.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export * from './object' -export * from './tree' -export * from './state' -export * from './state/builder' -export * from './state/selection' -export * from './transformer' -export * from './transform' -export * from './action' \ No newline at end of file +export * from './object'; +export * from './tree'; +export * from './state'; +export * from './state/builder'; +export * from './state/selection'; +export * from './transformer'; +export * from './transform'; +export * from './action'; \ No newline at end of file diff --git a/src/mol-state/object.ts b/src/mol-state/object.ts index e8e97ae699c210c148b85cba123ad7b649af56d2..4fab797ed112669bd34fb05ce6f49745c23c89b8 100644 --- a/src/mol-state/object.ts +++ b/src/mol-state/object.ts @@ -11,7 +11,7 @@ import { State } from './state'; import { StateSelection, StateTransformer } from '../mol-state'; import { StateBuilder } from './state/builder'; -export { StateObject, StateObjectCell } +export { StateObject, StateObjectCell }; interface StateObject<D = any, T extends StateObject.Type = StateObject.Type<any>> { readonly id: UUID, @@ -44,7 +44,7 @@ namespace StateObject { this.label = props && props.label || type.name; this.description = props && props.description; } - } + }; } export function hasTag(o: StateObject, t: string) { diff --git a/src/mol-state/state.ts b/src/mol-state/state.ts index b72476c25ec0ffdb1a37039f3bd409c790ee402d..57517382c57f4a1633f80a0ccbe71f50a252ee1f 100644 --- a/src/mol-state/state.ts +++ b/src/mol-state/state.ts @@ -20,12 +20,12 @@ import { now, formatTimespan } from '../mol-util/now'; import { ParamDefinition } from '../mol-util/param-definition'; import { StateTreeSpine } from './tree/spine'; import { AsyncQueue } from '../mol-util/async-queue'; -import { isProductionMode } from '../mol-util/debug' +import { isProductionMode } from '../mol-util/debug'; import { arraySetAdd, arraySetRemove } from '../mol-util/array'; import { UniqueArray } from '../mol-data/generic'; import { assignIfUndefined } from '../mol-util/object'; -export { State } +export { State }; class State { private _tree: TransientTree; @@ -146,7 +146,7 @@ class State { * @example state.query('test') */ select<C extends StateObjectCell>(selector: StateSelection.Selector<C>) { - return StateSelection.select(selector, this) + return StateSelection.select(selector, this); } /** @@ -155,7 +155,7 @@ class State { */ selectQ<C extends StateObjectCell>(selector: (q: typeof StateSelection.Generators) => StateSelection.Selector<C>) { if (typeof selector === 'string') return StateSelection.select(selector, this); - return StateSelection.select(selector(StateSelection.Generators), this) + return StateSelection.select(selector(StateSelection.Generators), this); } /** diff --git a/src/mol-state/state/builder.ts b/src/mol-state/state/builder.ts index e249ee738ec42ddcebf871da6dccf74aca584f81..345c05f655a8712366323ba99552545ccf7d80c9 100644 --- a/src/mol-state/state/builder.ts +++ b/src/mol-state/state/builder.ts @@ -12,7 +12,7 @@ import { StateTransformer } from '../transformer'; import { State } from '../state'; import { produce } from 'immer'; -export { StateBuilder } +export { StateBuilder }; interface StateBuilder { readonly editInfo: StateBuilder.EditInfo, @@ -109,7 +109,7 @@ namespace StateBuilder { return this.state.state.runTask(this.state.state.updateTree(this, options)); } - constructor(tree: StateTree, state?: State) { this.state = { state, tree: tree.asTransient(), actions: [], editInfo: { applied: false, sourceTree: tree, count: 0, lastUpdate: void 0 } } } + constructor(tree: StateTree, state?: State) { this.state = { state, tree: tree.asTransient(), actions: [], editInfo: { applied: false, sourceTree: tree, count: 0, lastUpdate: void 0 } }; } } export class To<A extends StateObject, T extends StateTransformer = StateTransformer> implements StateBuilder { diff --git a/src/mol-state/state/selection.ts b/src/mol-state/state/selection.ts index 54af33fe1c5a254521be4450a689ffe32d0d1d01..9cc9a1d1cb4236b3842fb338a91a1f3933ca4d8a 100644 --- a/src/mol-state/state/selection.ts +++ b/src/mol-state/state/selection.ts @@ -68,7 +68,7 @@ namespace StateSelection { }; function registerModifier(name: string, f: Function) { - BuilderPrototype[name] = function (this: any, ...args: any[]) { return f.call(void 0, this, ...args) }; + BuilderPrototype[name] = function (this: any, ...args: any[]) { return f.call(void 0, this, ...args); }; } function build<C extends StateObjectCell>(compile: () => Query<C>): Builder<C> { @@ -199,7 +199,7 @@ namespace StateSelection { } } return ret; - }) + }); } registerModifier('first', first); @@ -224,7 +224,7 @@ namespace StateSelection { export function subtree(b: Selector) { return flatMap(b, (n, s) => { const nodes = [] as string[]; - StateTree.doPreOrder(s.tree, s.tree.transforms.get(n.transform.ref), nodes, (x, _, ctx) => { ctx.push(x.ref) }); + StateTree.doPreOrder(s.tree, s.tree.transforms.get(n.transform.ref), nodes, (x, _, ctx) => { ctx.push(x.ref); }); return nodes.map(x => s.cells.get(x)!); }); } @@ -333,4 +333,4 @@ namespace StateSelection { } } -export { StateSelection } \ No newline at end of file +export { StateSelection }; \ No newline at end of file diff --git a/src/mol-state/transform.ts b/src/mol-state/transform.ts index cde378f5822513addab2a879159f8ec9a9a3a845..c1cce1fa255569073595944ae90969038e390d9f 100644 --- a/src/mol-state/transform.ts +++ b/src/mol-state/transform.ts @@ -7,7 +7,7 @@ import { StateTransformer } from './transformer'; import { UUID } from '../mol-util'; -export { Transform as StateTransform } +export { Transform as StateTransform }; interface Transform<T extends StateTransformer = StateTransformer> { readonly parent: Transform.Ref, @@ -111,7 +111,7 @@ namespace Transform { dependsOn: options && options.dependsOn, params, version: UUID.create22() - } + }; } export function withParams(t: Transform, params: any): Transform { diff --git a/src/mol-state/transformer.ts b/src/mol-state/transformer.ts index 15d5eabd84d81d645438f32b55719bdd4a0c3e6b..aceb10ffb443e2e300d779e8355a62857712fc54 100644 --- a/src/mol-state/transformer.ts +++ b/src/mol-state/transformer.ts @@ -12,7 +12,7 @@ import { StateAction } from './action'; import { capitalize } from '../mol-util/string'; import { StateTreeSpine } from './tree/spine'; -export { Transformer as StateTransformer } +export { Transformer as StateTransformer }; interface Transformer<A extends StateObject = StateObject, B extends StateObject = StateObject, P extends {} = any> { apply(parent: StateTransform.Ref, params?: P, props?: Partial<StateTransform.Options>): StateTransform<this>, @@ -241,5 +241,5 @@ namespace Transformer { display: { name: 'Root', description: 'For internal use.' }, apply() { throw new Error('should never be applied'); }, update() { return UpdateResult.Unchanged; } - }) + }); } \ No newline at end of file diff --git a/src/mol-state/tree.ts b/src/mol-state/tree.ts index 837524f80a910c6006e8a8790ddda132431507ff..89ef28dca81e68b317b6918a7f3605f1c803b6a1 100644 --- a/src/mol-state/tree.ts +++ b/src/mol-state/tree.ts @@ -7,4 +7,4 @@ import { StateTree } from './tree/immutable'; import { TransientTree } from './tree/transient'; -export { StateTree, TransientTree } \ No newline at end of file +export { StateTree, TransientTree }; \ No newline at end of file diff --git a/src/mol-state/tree/immutable.ts b/src/mol-state/tree/immutable.ts index 43959e59c141559ec39404f03a7763b030ff8eb4..ea164a94d57daf54a8c5fd8cf765784dafcfd4ae 100644 --- a/src/mol-state/tree/immutable.ts +++ b/src/mol-state/tree/immutable.ts @@ -8,7 +8,7 @@ import { Map as ImmutableMap, OrderedSet } from 'immutable'; import { StateTransform } from '../transform'; import { TransientTree } from './transient'; -export { StateTree } +export { StateTree }; /** * An immutable tree where each node requires a unique reference. @@ -48,7 +48,7 @@ namespace StateTree { export interface Dependencies extends _Map<ChildSet> { } class Impl implements StateTree { - get root() { return this.transforms.get(StateTransform.RootRef)! } + get root() { return this.transforms.get(StateTransform.RootRef)!; } asTransient(): TransientTree { return new TransientTree(this); diff --git a/src/mol-state/tree/spine.ts b/src/mol-state/tree/spine.ts index b0c959c36704a045530e4312005a1e65cd474b7a..f2167a86f185454e9ef43e99ecabadd55f04e363 100644 --- a/src/mol-state/tree/spine.ts +++ b/src/mol-state/tree/spine.ts @@ -8,7 +8,7 @@ import { State } from '../state'; import { StateTransform } from '../transform'; import { StateObject, StateObjectCell } from '../object'; -export { StateTreeSpine } +export { StateTreeSpine }; /** The tree spine allows access to ancestor of a node during reconciliation. */ interface StateTreeSpine { @@ -65,7 +65,7 @@ namespace StateTreeSpine { export function getRootOfType<T extends StateObject.Ctor>(state: State, t: T, ref: string): StateObject.From<T> | undefined { let ret: StateObjectCell | undefined = void 0; - let cell = state.cells.get(ref) + let cell = state.cells.get(ref); if (!cell) return void 0; while (true) { if (!cell.obj) return void 0; diff --git a/src/mol-state/tree/transient.ts b/src/mol-state/tree/transient.ts index a401fa41a3593f230dec1494ebc45c71144edaab..3e15d8639fd3fe0adf146da097b802059b49916d 100644 --- a/src/mol-state/tree/transient.ts +++ b/src/mol-state/tree/transient.ts @@ -10,7 +10,7 @@ import { StateTree } from './immutable'; import { shallowEqual } from '../../mol-util/object'; import { arrayEqual } from '../../mol-util/array'; -export { TransientTree } +export { TransientTree }; class TransientTree implements StateTree { transforms = this.tree.transforms as ImmutableMap<StateTransform.Ref, StateTransform>; @@ -55,7 +55,7 @@ class TransientTree implements StateTree { this.dependencies = this.dependencies.asMutable(); } - get root() { return this.transforms.get(StateTransform.RootRef)! } + get root() { return this.transforms.get(StateTransform.RootRef)!; } asTransient() { return this.asImmutable().asTransient(); @@ -188,7 +188,7 @@ class TransientTree implements StateTree { const transform = this.transforms.get(ref)!; - const withTags = StateTransform.withParams(transform, tags) + const withTags = StateTransform.withParams(transform, tags); // TODO: should this be here? if (arrayEqual(transform.tags, withTags.tags)) { return false; diff --git a/src/mol-task/execution/observable.ts b/src/mol-task/execution/observable.ts index 9fc9dea0584b38b3fa7318f7f465cb32d504ec67..11d013b2377baa6a378d1bf56c9080b6c5cfc3f0 100644 --- a/src/mol-task/execution/observable.ts +++ b/src/mol-task/execution/observable.ts @@ -4,13 +4,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Task } from '../task' -import { RuntimeContext } from './runtime-context' -import { Progress } from './progress' +import { Task } from '../task'; +import { RuntimeContext } from './runtime-context'; +import { Progress } from './progress'; import { now } from '../../mol-util/now'; -import { Scheduler } from '../util/scheduler' -import { UserTiming } from '../util/user-timing' -import { isDebugMode } from '../../mol-util/debug' +import { Scheduler } from '../util/scheduler'; +import { UserTiming } from '../util/user-timing'; +import { isDebugMode } from '../../mol-util/debug'; interface ExposedTask<T> extends Task<T> { f: (ctx: RuntimeContext) => Promise<T>, @@ -94,12 +94,12 @@ function snapshotProgress(info: ProgressInfo): Progress { } async function execute<T>(task: ExposedTask<T>, ctx: ObservableRuntimeContext) { - UserTiming.markStart(task) + UserTiming.markStart(task); ctx.node.progress.startedTime = now(); try { const ret = await task.f(ctx); - UserTiming.markEnd(task) - UserTiming.measure(task) + UserTiming.markEnd(task); + UserTiming.measure(task); if (ctx.info.abortToken.abortRequested) { abort(ctx.info); } diff --git a/src/mol-task/execution/progress.ts b/src/mol-task/execution/progress.ts index 4bf829dcb94c35de288a0fdf92b61a89213f8c0c..616c3baa96c4bee857592fc26696c234ce8224e9 100644 --- a/src/mol-task/execution/progress.ts +++ b/src/mol-task/execution/progress.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Task } from '../task' +import { Task } from '../task'; interface Progress { root: Progress.Node, @@ -36,4 +36,4 @@ namespace Progress { export function format(p: Progress) { return _format(p.root); } } -export { Progress } \ No newline at end of file +export { Progress }; \ No newline at end of file diff --git a/src/mol-task/execution/runtime-context.ts b/src/mol-task/execution/runtime-context.ts index eb28777e2fc8a31654e0b161067e0fdfe061e8e0..3c2fd943b658949aa2487dca0bb35ffcb5932731 100644 --- a/src/mol-task/execution/runtime-context.ts +++ b/src/mol-task/execution/runtime-context.ts @@ -32,4 +32,4 @@ namespace RuntimeContext { export const Synchronous = SyncRuntimeContext; } -export { RuntimeContext } \ No newline at end of file +export { RuntimeContext }; \ No newline at end of file diff --git a/src/mol-task/execution/synchronous.ts b/src/mol-task/execution/synchronous.ts index 9ba6db28e13016207a6d8cfe7f8cbe86f80b3edb..a6d26257b6ef73d46535a4ad30f53ca61eb673d6 100644 --- a/src/mol-task/execution/synchronous.ts +++ b/src/mol-task/execution/synchronous.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { RuntimeContext } from './runtime-context' +import { RuntimeContext } from './runtime-context'; export class SynchronousRuntimeContext implements RuntimeContext { shouldUpdate = false; diff --git a/src/mol-task/index.ts b/src/mol-task/index.ts index 62d09e84692b7a2195d41b5295647bdd610d51b7..cd87e979fc70ecbda3f88c890c555a89d89ab8b2 100644 --- a/src/mol-task/index.ts +++ b/src/mol-task/index.ts @@ -4,11 +4,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Task } from './task' -import { RuntimeContext } from './execution/runtime-context' -import { Progress } from './execution/progress' -import { Scheduler } from './util/scheduler' -import { MultistepTask } from './util/multistep' -import { chunkedSubtask } from './util/chunked' +import { Task } from './task'; +import { RuntimeContext } from './execution/runtime-context'; +import { Progress } from './execution/progress'; +import { Scheduler } from './util/scheduler'; +import { MultistepTask } from './util/multistep'; +import { chunkedSubtask } from './util/chunked'; -export { Task, RuntimeContext, Progress, Scheduler, MultistepTask, chunkedSubtask } \ No newline at end of file +export { Task, RuntimeContext, Progress, Scheduler, MultistepTask, chunkedSubtask }; \ No newline at end of file diff --git a/src/mol-task/task.ts b/src/mol-task/task.ts index 0ce0414ecf0aae3b749842afe0a94b7e013521c9..da0bf7228c7323c9b1220178d13150b6f5dab32d 100644 --- a/src/mol-task/task.ts +++ b/src/mol-task/task.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { RuntimeContext } from './execution/runtime-context' -import { Progress } from './execution/progress' +import { RuntimeContext } from './execution/runtime-context'; +import { Progress } from './execution/progress'; import { ExecuteObservable, ExecuteObservableChild, ExecuteInContext } from './execution/observable'; import { SyncRuntimeContext } from './execution/synchronous'; import { idFactory } from '../mol-util/id-factory'; @@ -82,7 +82,7 @@ namespace Task { max: number } - const getNextId = idFactory(0, 0x3fffffff) + const getNextId = idFactory(0, 0x3fffffff); } -export { Task } \ No newline at end of file +export { Task }; \ No newline at end of file diff --git a/src/mol-task/util/chunked.ts b/src/mol-task/util/chunked.ts index 3545c48368f3e8478a09b5c723d1a76052d87d60..4de174877900211a47ee79bce02bf31e9b83a95f 100644 --- a/src/mol-task/util/chunked.ts +++ b/src/mol-task/util/chunked.ts @@ -5,7 +5,7 @@ */ import { now } from '../../mol-util/now'; -import { RuntimeContext } from '../execution/runtime-context' +import { RuntimeContext } from '../execution/runtime-context'; type UniformlyChunkedFn<S> = (chunkSize: number, state: S) => number @@ -43,4 +43,4 @@ async function chunkedSubtask<S>(ctx: RuntimeContext, initialChunk: number, stat return state; } -export { chunkedSubtask } \ No newline at end of file +export { chunkedSubtask }; \ No newline at end of file diff --git a/src/mol-task/util/multistep.ts b/src/mol-task/util/multistep.ts index dba09e8485627d5e3c08bbf703ca6af7994df750..15d315e88126e19102271a388169085bef31cc8f 100644 --- a/src/mol-task/util/multistep.ts +++ b/src/mol-task/util/multistep.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { Task } from '../task' -import { RuntimeContext } from '../execution/runtime-context' +import { Task } from '../task'; +import { RuntimeContext } from '../execution/runtime-context'; export type MultistepFn<P, T> = (params: P, step: (s: number) => Promise<void> | void, ctx: RuntimeContext) => Promise<T> @@ -14,4 +14,4 @@ function MultistepTask<P, T>(name: string, steps: string[], f: MultistepFn<P, T> return (params: P) => Task.create(name, async ctx => f(params, n => ctx.update({ message: `${steps[n]}`, current: n + 1, max: steps.length }), ctx), onAbort); } -export { MultistepTask } \ No newline at end of file +export { MultistepTask }; \ No newline at end of file diff --git a/src/mol-task/util/scheduler.ts b/src/mol-task/util/scheduler.ts index 94cbb531e8712507d5cc7b438d11311d94e2f278..065379501206bd2a2012469d488b4e52c080bec8 100644 --- a/src/mol-task/util/scheduler.ts +++ b/src/mol-task/util/scheduler.ts @@ -182,7 +182,7 @@ const immediateActions = (function () { clearImmediate: (handle: any) => (window as any).clearImmediate(handle) }; } else { - return { setImmediate, clearImmediate } + return { setImmediate, clearImmediate }; } } return createImmediateActions(); @@ -197,7 +197,7 @@ const Scheduler = { clearImmediate: immediateActions.clearImmediate, immediatePromise() { return new Promise<void>(resolveImmediate); }, - delay<T>(timeout: number, value: T | undefined = void 0): Promise<T> { return new Promise(r => setTimeout(r, timeout, value)) } -} + delay<T>(timeout: number, value: T | undefined = void 0): Promise<T> { return new Promise(r => setTimeout(r, timeout, value)); } +}; -export { Scheduler } +export { Scheduler }; diff --git a/src/mol-task/util/user-timing.ts b/src/mol-task/util/user-timing.ts index 554e67ebc95a4637ad891e9392a61c08d1900def..ea20f13cefecfdf9ab5638841e9e9692d4f718f0 100644 --- a/src/mol-task/util/user-timing.ts +++ b/src/mol-task/util/user-timing.ts @@ -4,22 +4,22 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Task } from '../task' +import { Task } from '../task'; import { isProductionMode } from '../../mol-util/debug'; -const hasPerformance = (typeof performance !== 'undefined') && performance.mark && performance.measure -const timingEnabled = hasPerformance && !isProductionMode +const hasPerformance = (typeof performance !== 'undefined') && performance.mark && performance.measure; +const timingEnabled = hasPerformance && !isProductionMode; export namespace UserTiming { - function startMarkName(task: Task<any>) { return `startTask${task.id}` } - function endMarkName(task: Task<any>) { return `endTask${task.id}` } + function startMarkName(task: Task<any>) { return `startTask${task.id}`; } + function endMarkName(task: Task<any>) { return `endTask${task.id}`; } export function markStart(task: Task<any>) { - if (timingEnabled) performance.mark(startMarkName(task)) + if (timingEnabled) performance.mark(startMarkName(task)); } export function markEnd(task: Task<any>) { - if (timingEnabled) performance.mark(endMarkName(task)) + if (timingEnabled) performance.mark(endMarkName(task)); } export function measure(task: Task<any>) { - if (timingEnabled) performance.measure(`âœ³ï¸ ${task.name}`, startMarkName(task), endMarkName(task)) + if (timingEnabled) performance.measure(`âœ³ï¸ ${task.name}`, startMarkName(task), endMarkName(task)); } } \ No newline at end of file diff --git a/src/mol-theme/color.ts b/src/mol-theme/color.ts index 6aeed8353f8e452e8b6536d7c9586e46e9b27ff7..938f7e2ef553a29ba8936e342636647b0073f3ed 100644 --- a/src/mol-theme/color.ts +++ b/src/mol-theme/color.ts @@ -35,7 +35,7 @@ import { OperatorHklColorThemeProvider } from './color/operator-hkl'; export type LocationColor = (location: Location, isSecondary: boolean) => Color -export { ColorTheme } +export { ColorTheme }; interface ColorTheme<P extends PD.Params> { readonly factory: ColorTheme.Factory<P> readonly granularity: ColorType @@ -57,25 +57,25 @@ namespace ColorTheme { export type Props = { [k: string]: any } export type Factory<P extends PD.Params> = (ctx: ThemeDataContext, props: PD.Values<P>) => ColorTheme<P> - export const EmptyFactory = () => Empty - const EmptyColor = Color(0xCCCCCC) + export const EmptyFactory = () => Empty; + const EmptyColor = Color(0xCCCCCC); export const Empty: ColorTheme<{}> = { factory: EmptyFactory, granularity: 'uniform', color: () => EmptyColor, props: {} - } + }; export function areEqual(themeA: ColorTheme<any>, themeB: ColorTheme<any>) { - return themeA.contextHash === themeB.contextHash && themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props) + return themeA.contextHash === themeB.contextHash && themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props); } export interface Provider<P extends PD.Params = any, Id extends string = string> extends ThemeProvider<ColorTheme<P>, P, Id> { } - export const EmptyProvider: Provider<{}> = { name: '', label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } + export const EmptyProvider: Provider<{}> = { name: '', label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true }; export type Registry = ThemeRegistry<ColorTheme<any>> export function createRegistry() { - return new ThemeRegistry(BuiltIn as { [k: string]: Provider<any> }, EmptyProvider) + return new ThemeRegistry(BuiltIn as { [k: string]: Provider<any> }, EmptyProvider); } export const BuiltIn = { @@ -100,7 +100,7 @@ namespace ColorTheme { 'uncertainty': UncertaintyColorThemeProvider, 'unit-index': UnitIndexColorThemeProvider, 'uniform': UniformColorThemeProvider, - } + }; type _BuiltIn = typeof BuiltIn export type BuiltIn = keyof _BuiltIn export type ParamValues<C extends ColorTheme.Provider<any>> = C extends ColorTheme.Provider<infer P> ? PD.Values<P> : never diff --git a/src/mol-theme/color/carbohydrate-symbol.ts b/src/mol-theme/color/carbohydrate-symbol.ts index 55f6963d51c946679388a52c9a25131fc0428494..38bb69c658dfa1dc4dfbe9af342ae4f62891ad10 100644 --- a/src/mol-theme/color/carbohydrate-symbol.ts +++ b/src/mol-theme/color/carbohydrate-symbol.ts @@ -9,45 +9,45 @@ import { SaccharideColors, MonosaccharidesColorTable } from '../../mol-model/str import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; import { Color } from '../../mol-util/color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { TableLegend } from '../../mol-util/legend'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Assigns colors according to the Symbol Nomenclature for Glycans (SNFG).' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Assigns colors according to the Symbol Nomenclature for Glycans (SNFG).'; -export const CarbohydrateSymbolColorThemeParams = { } +export const CarbohydrateSymbolColorThemeParams = { }; export type CarbohydrateSymbolColorThemeParams = typeof CarbohydrateSymbolColorThemeParams export function getCarbohydrateSymbolColorThemeParams(ctx: ThemeDataContext) { - return CarbohydrateSymbolColorThemeParams // TODO return copy + return CarbohydrateSymbolColorThemeParams; // TODO return copy } export function CarbohydrateSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<CarbohydrateSymbolColorThemeParams>): ColorTheme<CarbohydrateSymbolColorThemeParams> { - let color: LocationColor + let color: LocationColor; if (ctx.structure) { - const { elements, getElementIndices } = ctx.structure.carbohydrates + const { elements, getElementIndices } = ctx.structure.carbohydrates; const getColor = (unit: Unit, index: ElementIndex) => { - if (!Unit.isAtomic(unit)) return DefaultColor - const carbs = getElementIndices(unit, index) - return carbs.length > 0 ? elements[carbs[0]].component.color : DefaultColor - } + if (!Unit.isAtomic(unit)) return DefaultColor; + const carbs = getElementIndices(unit, index); + return carbs.length > 0 ? elements[carbs[0]].component.color : DefaultColor; + }; color = (location: Location, isSecondary: boolean) => { if (isSecondary) { - return SaccharideColors.Secondary + return SaccharideColors.Secondary; } else { if (StructureElement.Location.is(location)) { - return getColor(location.unit, location.element) + return getColor(location.unit, location.element); } else if (Bond.isLocation(location)) { - return getColor(location.aUnit, location.aUnit.elements[location.aIndex]) + return getColor(location.aUnit, location.aUnit.elements[location.aIndex]); } } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -57,7 +57,7 @@ export function CarbohydrateSymbolColorTheme(ctx: ThemeDataContext, props: PD.Va props: props, description: Description, legend: TableLegend(MonosaccharidesColorTable) - } + }; } export const CarbohydrateSymbolColorThemeProvider: ColorTheme.Provider<CarbohydrateSymbolColorThemeParams, 'carbohydrate-symbol'> = { @@ -68,6 +68,6 @@ export const CarbohydrateSymbolColorThemeProvider: ColorTheme.Provider<Carbohydr getParams: getCarbohydrateSymbolColorThemeParams, defaultValues: PD.getDefaultValues(CarbohydrateSymbolColorThemeParams), isApplicable: (ctx: ThemeDataContext) => { - return !!ctx.structure && ctx.structure.models.reduce((a, v) => a + v.properties.saccharideComponentMap.size, 0) > 0 + return !!ctx.structure && ctx.structure.models.reduce((a, v) => a + v.properties.saccharideComponentMap.size, 0) > 0; } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/chain-id.ts b/src/mol-theme/color/chain-id.ts index 306efc88d78c39e452985efed868d812ae8feb36..146491d75d2ca148468bcf9db9873f577a95abe4 100644 --- a/src/mol-theme/color/chain-id.ts +++ b/src/mol-theme/color/chain-id.ts @@ -8,103 +8,103 @@ import { Unit, StructureProperties, StructureElement, Bond, Structure } from '.. import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { Segmentation } from '../../mol-data/int'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xFAFAFA) -const Description = 'Gives every chain a color based on its `asym_id` value.' +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xFAFAFA); +const Description = 'Gives every chain a color based on its `asym_id` value.'; export const ChainIdColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type ChainIdColorThemeParams = typeof ChainIdColorThemeParams export function getChainIdColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(ChainIdColorThemeParams) + const params = PD.clone(ChainIdColorThemeParams); if (ctx.structure) { if (getAsymIdSerialMap(ctx.structure.root).size > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } function getAsymId(unit: Unit): StructureElement.Property<string> { switch (unit.kind) { case Unit.Kind.Atomic: - return StructureProperties.chain.label_asym_id + return StructureProperties.chain.label_asym_id; case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return StructureProperties.coarse.asym_id + return StructureProperties.coarse.asym_id; } } function getAsymIdSerialMap(structure: Structure) { - const map = new Map<string, number>() + const map = new Map<string, number>(); for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const unit = structure.unitSymmetryGroups[i].units[0] - const { model } = unit + const unit = structure.unitSymmetryGroups[i].units[0]; + const { model } = unit; if (Unit.isAtomic(unit)) { - const { chainAtomSegments, chains } = model.atomicHierarchy - const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements) + const { chainAtomSegments, chains } = model.atomicHierarchy; + const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements); while (chainIt.hasNext) { - const { index: chainIndex } = chainIt.move() - const asymId = chains.label_asym_id.value(chainIndex) - if (!map.has(asymId)) map.set(asymId, map.size) + const { index: chainIndex } = chainIt.move(); + const asymId = chains.label_asym_id.value(chainIndex); + if (!map.has(asymId)) map.set(asymId, map.size); } } else if (Unit.isCoarse(unit)) { const { chainElementSegments, asym_id } = Unit.isSpheres(unit) ? model.coarseHierarchy.spheres - : model.coarseHierarchy.gaussians - const chainIt = Segmentation.transientSegments(chainElementSegments, unit.elements) + : model.coarseHierarchy.gaussians; + const chainIt = Segmentation.transientSegments(chainElementSegments, unit.elements); while (chainIt.hasNext) { - const { index: chainIndex } = chainIt.move() - const elementIndex = chainElementSegments.offsets[chainIndex] - const asymId = asym_id.value(elementIndex) - if (!map.has(asymId)) map.set(asymId, map.size) + const { index: chainIndex } = chainIt.move(); + const elementIndex = chainElementSegments.offsets[chainIndex]; + const asymId = asym_id.value(elementIndex); + if (!map.has(asymId)) map.set(asymId, map.size); } } } - return map + return map; } export function ChainIdColorTheme(ctx: ThemeDataContext, props: PD.Values<ChainIdColorThemeParams>): ColorTheme<ChainIdColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const l = StructureElement.Location.create(ctx.structure) - const asymIdSerialMap = getAsymIdSerialMap(ctx.structure.root) + const l = StructureElement.Location.create(ctx.structure); + const asymIdSerialMap = getAsymIdSerialMap(ctx.structure.root); - const labelTable = Array.from(asymIdSerialMap.keys()) - props.palette.params.valueLabel = (i: number) => labelTable[i] + const labelTable = Array.from(asymIdSerialMap.keys()); + props.palette.params.valueLabel = (i: number) => labelTable[i]; - const palette = getPalette(asymIdSerialMap.size, props) - legend = palette.legend + const palette = getPalette(asymIdSerialMap.size, props); + legend = palette.legend; color = (location: Location): Color => { - let serial: number | undefined = undefined + let serial: number | undefined = undefined; if (StructureElement.Location.is(location)) { - const asym_id = getAsymId(location.unit) - serial = asymIdSerialMap.get(asym_id(location)) + const asym_id = getAsymId(location.unit); + serial = asymIdSerialMap.get(asym_id(location)); } else if (Bond.isLocation(location)) { - const asym_id = getAsymId(location.aUnit) - l.unit = location.aUnit - l.element = location.aUnit.elements[location.aIndex] - serial = asymIdSerialMap.get(asym_id(l)) + const asym_id = getAsymId(location.aUnit); + l.unit = location.aUnit; + l.element = location.aUnit.elements[location.aIndex]; + serial = asymIdSerialMap.get(asym_id(l)); } - return serial === undefined ? DefaultColor : palette.color(serial) - } + return serial === undefined ? DefaultColor : palette.color(serial); + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -114,7 +114,7 @@ export function ChainIdColorTheme(ctx: ThemeDataContext, props: PD.Values<ChainI props, description: Description, legend - } + }; } export const ChainIdColorThemeProvider: ColorTheme.Provider<ChainIdColorThemeParams, 'chain-id'> = { @@ -125,4 +125,4 @@ export const ChainIdColorThemeProvider: ColorTheme.Provider<ChainIdColorThemePar getParams: getChainIdColorThemeParams, defaultValues: PD.getDefaultValues(ChainIdColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/element-index.ts b/src/mol-theme/color/element-index.ts index 141317bc75a266fd37ff7ac2fcfd63f63aee2b22..f3797a3765a124096178e2f217d67ef28b860627 100644 --- a/src/mol-theme/color/element-index.ts +++ b/src/mol-theme/color/element-index.ts @@ -9,56 +9,56 @@ import { Location } from '../../mol-model/location'; import { StructureElement, Bond } from '../../mol-model/structure'; import { OrderedSet } from '../../mol-data/int'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { TableLegend, ScaleLegend } from '../../mol-util/legend'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives every element (atom or coarse sphere/gaussian) a unique color based on the position (index) of the element in the list of elements in the structure.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives every element (atom or coarse sphere/gaussian) a unique color based on the position (index) of the element in the list of elements in the structure.'; export const ElementIndexColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: 'red-yellow-blue' }), -} +}; export type ElementIndexColorThemeParams = typeof ElementIndexColorThemeParams export function getElementIndexColorThemeParams(ctx: ThemeDataContext) { - return ElementIndexColorThemeParams // TODO return copy + return ElementIndexColorThemeParams; // TODO return copy } export function ElementIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<ElementIndexColorThemeParams>): ColorTheme<ElementIndexColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const { units } = ctx.structure.root - const unitCount = units.length - const cummulativeElementCount = new Map<number, number>() - const unitIdIndex = new Map<number, number>() + const { units } = ctx.structure.root; + const unitCount = units.length; + const cummulativeElementCount = new Map<number, number>(); + const unitIdIndex = new Map<number, number>(); - let elementCount = 0 + let elementCount = 0; for (let i = 0; i < unitCount; ++i) { - cummulativeElementCount.set(i, elementCount) - elementCount += units[i].elements.length - unitIdIndex.set(units[i].id, i) + cummulativeElementCount.set(i, elementCount); + elementCount += units[i].elements.length; + unitIdIndex.set(units[i].id, i); } - const palette = getPalette(elementCount, props) - legend = palette.legend + const palette = getPalette(elementCount, props); + legend = palette.legend; color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - const unitIndex = unitIdIndex.get(location.unit.id)! - const unitElementIndex = OrderedSet.findPredecessorIndex(units[unitIndex].elements, location.element) - return palette.color(cummulativeElementCount.get(unitIndex)! + unitElementIndex) + const unitIndex = unitIdIndex.get(location.unit.id)!; + const unitElementIndex = OrderedSet.findPredecessorIndex(units[unitIndex].elements, location.element); + return palette.color(cummulativeElementCount.get(unitIndex)! + unitElementIndex); } else if (Bond.isLocation(location)) { - const unitIndex = unitIdIndex.get(location.aUnit.id)! - const unitElementIndex = OrderedSet.findPredecessorIndex(units[unitIndex].elements, location.aUnit.elements[location.aIndex]) - return palette.color(cummulativeElementCount.get(unitIndex)! + unitElementIndex) + const unitIndex = unitIdIndex.get(location.aUnit.id)!; + const unitElementIndex = OrderedSet.findPredecessorIndex(units[unitIndex].elements, location.aUnit.elements[location.aIndex]); + return palette.color(cummulativeElementCount.get(unitIndex)! + unitElementIndex); } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -68,7 +68,7 @@ export function ElementIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<E props, description: Description, legend - } + }; } export const ElementIndexColorThemeProvider: ColorTheme.Provider<ElementIndexColorThemeParams, 'element-index'> = { @@ -79,4 +79,4 @@ export const ElementIndexColorThemeProvider: ColorTheme.Provider<ElementIndexCol getParams: getElementIndexColorThemeParams, defaultValues: PD.getDefaultValues(ElementIndexColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/element-symbol.ts b/src/mol-theme/color/element-symbol.ts index 906bf70af4df5bab81e955fc0ea107cf506d8256..361e6636f2d8c62efdd9d40ca9a587654cb38b83 100644 --- a/src/mol-theme/color/element-symbol.ts +++ b/src/mol-theme/color/element-symbol.ts @@ -9,7 +9,7 @@ import { Color, ColorMap } from '../../mol-util/color'; import { StructureElement, Unit, Bond } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { TableLegend } from '../../mol-util/legend'; import { getAdjustedColorMap } from '../../mol-util/color/color'; @@ -17,42 +17,42 @@ import { getAdjustedColorMap } from '../../mol-util/color/color'; // from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF) export const ElementSymbolColors = ColorMap({ 'H': 0xFFFFFF, 'D': 0xFFFFC0, 'T': 0xFFFFA0, 'HE': 0xD9FFFF, 'LI': 0xCC80FF, 'BE': 0xC2FF00, 'B': 0xFFB5B5, 'C': 0x909090, 'N': 0x3050F8, 'O': 0xFF0D0D, 'F': 0x90E050, 'NE': 0xB3E3F5, 'NA': 0xAB5CF2, 'MG': 0x8AFF00, 'AL': 0xBFA6A6, 'SI': 0xF0C8A0, 'P': 0xFF8000, 'S': 0xFFFF30, 'CL': 0x1FF01F, 'AR': 0x80D1E3, 'K': 0x8F40D4, 'CA': 0x3DFF00, 'SC': 0xE6E6E6, 'TI': 0xBFC2C7, 'V': 0xA6A6AB, 'CR': 0x8A99C7, 'MN': 0x9C7AC7, 'FE': 0xE06633, 'CO': 0xF090A0, 'NI': 0x50D050, 'CU': 0xC88033, 'ZN': 0x7D80B0, 'GA': 0xC28F8F, 'GE': 0x668F8F, 'AS': 0xBD80E3, 'SE': 0xFFA100, 'BR': 0xA62929, 'KR': 0x5CB8D1, 'RB': 0x702EB0, 'SR': 0x00FF00, 'Y': 0x94FFFF, 'ZR': 0x94E0E0, 'NB': 0x73C2C9, 'MO': 0x54B5B5, 'TC': 0x3B9E9E, 'RU': 0x248F8F, 'RH': 0x0A7D8C, 'PD': 0x006985, 'AG': 0xC0C0C0, 'CD': 0xFFD98F, 'IN': 0xA67573, 'SN': 0x668080, 'SB': 0x9E63B5, 'TE': 0xD47A00, 'I': 0x940094, 'XE': 0x940094, 'CS': 0x57178F, 'BA': 0x00C900, 'LA': 0x70D4FF, 'CE': 0xFFFFC7, 'PR': 0xD9FFC7, 'ND': 0xC7FFC7, 'PM': 0xA3FFC7, 'SM': 0x8FFFC7, 'EU': 0x61FFC7, 'GD': 0x45FFC7, 'TB': 0x30FFC7, 'DY': 0x1FFFC7, 'HO': 0x00FF9C, 'ER': 0x00E675, 'TM': 0x00D452, 'YB': 0x00BF38, 'LU': 0x00AB24, 'HF': 0x4DC2FF, 'TA': 0x4DA6FF, 'W': 0x2194D6, 'RE': 0x267DAB, 'OS': 0x266696, 'IR': 0x175487, 'PT': 0xD0D0E0, 'AU': 0xFFD123, 'HG': 0xB8B8D0, 'TL': 0xA6544D, 'PB': 0x575961, 'BI': 0x9E4FB5, 'PO': 0xAB5C00, 'AT': 0x754F45, 'RN': 0x428296, 'FR': 0x420066, 'RA': 0x007D00, 'AC': 0x70ABFA, 'TH': 0x00BAFF, 'PA': 0x00A1FF, 'U': 0x008FFF, 'NP': 0x0080FF, 'PU': 0x006BFF, 'AM': 0x545CF2, 'CM': 0x785CE3, 'BK': 0x8A4FE3, 'CF': 0xA136D4, 'ES': 0xB31FD4, 'FM': 0xB31FBA, 'MD': 0xB30DA6, 'NO': 0xBD0D87, 'LR': 0xC70066, 'RF': 0xCC0059, 'DB': 0xD1004F, 'SG': 0xD90045, 'BH': 0xE00038, 'HS': 0xE6002E, 'MT': 0xEB0026, 'DS': 0xFFFFFF, 'RG': 0xFFFFFF, 'CN': 0xFFFFFF, 'UUT': 0xFFFFFF, 'FL': 0xFFFFFF, 'UUP': 0xFFFFFF, 'LV': 0xFFFFFF, 'UUH': 0xFFFFFF -}) +}); export type ElementSymbolColors = typeof ElementSymbolColors -const DefaultElementSymbolColor = Color(0xFFFFFF) -const Description = 'Assigns a color to every atom according to its chemical element.' +const DefaultElementSymbolColor = Color(0xFFFFFF); +const Description = 'Assigns a color to every atom according to its chemical element.'; export const ElementSymbolColorThemeParams = { saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }), lightness: PD.Numeric(0.7, { min: -6, max: 6, step: 0.1 }) -} +}; export type ElementSymbolColorThemeParams = typeof ElementSymbolColorThemeParams export function getElementSymbolColorThemeParams(ctx: ThemeDataContext) { - return ElementSymbolColorThemeParams // TODO return copy + return ElementSymbolColorThemeParams; // TODO return copy } export function elementSymbolColor(colorMap: ElementSymbolColors, element: ElementSymbol): Color { - const c = colorMap[element as keyof ElementSymbolColors] - return c === undefined ? DefaultElementSymbolColor : c + const c = colorMap[element as keyof ElementSymbolColors]; + return c === undefined ? DefaultElementSymbolColor : c; } export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values<ElementSymbolColorThemeParams>): ColorTheme<ElementSymbolColorThemeParams> { - const colorMap = getAdjustedColorMap(ElementSymbolColors, props.saturation, props.lightness) + const colorMap = getAdjustedColorMap(ElementSymbolColors, props.saturation, props.lightness); function color(location: Location): Color { if (StructureElement.Location.is(location)) { if (Unit.isAtomic(location.unit)) { - const { type_symbol } = location.unit.model.atomicHierarchy.atoms - return elementSymbolColor(colorMap, type_symbol.value(location.element)) + const { type_symbol } = location.unit.model.atomicHierarchy.atoms; + return elementSymbolColor(colorMap, type_symbol.value(location.element)); } } else if (Bond.isLocation(location)) { if (Unit.isAtomic(location.aUnit)) { - const { type_symbol } = location.aUnit.model.atomicHierarchy.atoms - return elementSymbolColor(colorMap, type_symbol.value(location.aUnit.elements[location.aIndex])) + const { type_symbol } = location.aUnit.model.atomicHierarchy.atoms; + return elementSymbolColor(colorMap, type_symbol.value(location.aUnit.elements[location.aIndex])); } } - return DefaultElementSymbolColor + return DefaultElementSymbolColor; } return { @@ -62,9 +62,9 @@ export function ElementSymbolColorTheme(ctx: ThemeDataContext, props: PD.Values< props, description: Description, legend: TableLegend(Object.keys(ElementSymbolColors).map(name => { - return [name, (ElementSymbolColors as any)[name] as Color] as [string, Color] + return [name, (ElementSymbolColors as any)[name] as Color] as [string, Color]; })) - } + }; } export const ElementSymbolColorThemeProvider: ColorTheme.Provider<ElementSymbolColorThemeParams, 'element-symbol'> = { @@ -75,4 +75,4 @@ export const ElementSymbolColorThemeProvider: ColorTheme.Provider<ElementSymbolC getParams: getElementSymbolColorThemeParams, defaultValues: PD.getDefaultValues(ElementSymbolColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/entity-source.ts b/src/mol-theme/color/entity-source.ts index f8b4d65e5166cd71ac412a5eedc172b317eac80b..226307e75afc2cea9a0e79e28114f1f9306fecd5 100644 --- a/src/mol-theme/color/entity-source.ts +++ b/src/mol-theme/color/entity-source.ts @@ -8,7 +8,7 @@ import { StructureProperties, StructureElement, Bond, Model } from '../../mol-mo import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { Table, Column } from '../../mol-data/db'; import { mmCIF_Schema } from '../../mol-io/reader/cif/schema/mmcif'; @@ -18,30 +18,30 @@ import { isInteger } from '../../mol-util/number'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; import { MmcifFormat } from '../../mol-model-formats/structure/mmcif'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xFAFAFA) -const Description = 'Gives ranges of a polymer chain a color based on the entity source it originates from (e.g. gene, plasmid, organism).' +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xFAFAFA); +const Description = 'Gives ranges of a polymer chain a color based on the entity source it originates from (e.g. gene, plasmid, organism).'; export const EntitySourceColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type EntitySourceColorThemeParams = typeof EntitySourceColorThemeParams export function getEntitySourceColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(EntitySourceColorThemeParams) + const params = PD.clone(EntitySourceColorThemeParams); if (ctx.structure) { if (getMaps(ctx.structure.root.models).srcKeySerialMap.size > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } function modelEntityKey(modelIndex: number, entityId: string) { - return `${modelIndex}|${entityId}` + return `${modelIndex}|${entityId}`; } type EntitySrc = Table<{ @@ -55,112 +55,112 @@ type GeneSrcGene = Column<mmCIF_Schema['entity_src_gen']['pdbx_gene_src_gene'][' type PlasmidName = Column<mmCIF_Schema['entity_src_gen']['plasmid_name']['T']> function srcKey(modelIndex: number, entityId: string, organism: string, srcId: number, plasmid: string, gene: string) { - return `${modelIndex}|${entityId}|${organism}|${gene ? gene : (plasmid ? plasmid : srcId)}` + return `${modelIndex}|${entityId}|${organism}|${gene ? gene : (plasmid ? plasmid : srcId)}`; } function addSrc(seqToSrcByModelEntity: Map<string, Int16Array>, srcKeySerialMap: Map<string, number>, modelIndex: number, model: Model, entity_src: EntitySrc, scientific_name: ScientificName, plasmid_name?: PlasmidName, gene_src_gene?: GeneSrcGene) { - const { entity_id, pdbx_src_id, pdbx_beg_seq_num, pdbx_end_seq_num } = entity_src + const { entity_id, pdbx_src_id, pdbx_beg_seq_num, pdbx_end_seq_num } = entity_src; for (let j = 0, jl = entity_src._rowCount; j < jl; ++j) { - const entityId = entity_id.value(j) - const mK = modelEntityKey(modelIndex, entityId) - let seqToSrc: Int16Array + const entityId = entity_id.value(j); + const mK = modelEntityKey(modelIndex, entityId); + let seqToSrc: Int16Array; if (!seqToSrcByModelEntity.has(mK)) { - const entityIndex = model.entities.getEntityIndex(entityId) - const seq = model.sequence.sequences[entityIndex].sequence - seqToSrc = new Int16Array(seq.length) - seqToSrcByModelEntity.set(mK, seqToSrc) + const entityIndex = model.entities.getEntityIndex(entityId); + const seq = model.sequence.sequences[entityIndex].sequence; + seqToSrc = new Int16Array(seq.length); + seqToSrcByModelEntity.set(mK, seqToSrc); } else { - seqToSrc = seqToSrcByModelEntity.get(mK)! + seqToSrc = seqToSrcByModelEntity.get(mK)!; } - const plasmid = plasmid_name ? plasmid_name.value(j) : '' - const gene = gene_src_gene ? gene_src_gene.value(j)[0] : '' - const sK = srcKey(modelIndex, entityId, scientific_name.value(j), pdbx_src_id.value(j), plasmid, gene) + const plasmid = plasmid_name ? plasmid_name.value(j) : ''; + const gene = gene_src_gene ? gene_src_gene.value(j)[0] : ''; + const sK = srcKey(modelIndex, entityId, scientific_name.value(j), pdbx_src_id.value(j), plasmid, gene); // may not be given (= 0) indicating src is for the whole seq - const beg = pdbx_beg_seq_num.valueKind(j) === Column.ValueKind.Present ? pdbx_beg_seq_num.value(j) : 1 - const end = pdbx_end_seq_num.valueKind(j) === Column.ValueKind.Present ? pdbx_end_seq_num.value(j) : seqToSrc.length + const beg = pdbx_beg_seq_num.valueKind(j) === Column.ValueKind.Present ? pdbx_beg_seq_num.value(j) : 1; + const end = pdbx_end_seq_num.valueKind(j) === Column.ValueKind.Present ? pdbx_end_seq_num.value(j) : seqToSrc.length; - let srcIndex: number // serial no starting from 1 + let srcIndex: number; // serial no starting from 1 if (srcKeySerialMap.has(sK)) { - srcIndex = srcKeySerialMap.get(sK)! + srcIndex = srcKeySerialMap.get(sK)!; } else { - srcIndex = srcKeySerialMap.size + 1 - srcKeySerialMap.set(sK, srcIndex) + srcIndex = srcKeySerialMap.size + 1; + srcKeySerialMap.set(sK, srcIndex); } // set src index for (let i = beg, il = end; i <= il; ++i) { - seqToSrc[i - 1] = srcIndex + seqToSrc[i - 1] = srcIndex; } } } function getMaps(models: ReadonlyArray<Model>) { - const seqToSrcByModelEntity = new Map<string, Int16Array>() - const srcKeySerialMap = new Map<string, number>() // serial no starting from 1 + const seqToSrcByModelEntity = new Map<string, Int16Array>(); + const srcKeySerialMap = new Map<string, number>(); // serial no starting from 1 for (let i = 0, il = models.length; i < il; ++i) { - const m = models[i] - if (!MmcifFormat.is(m.sourceData)) continue - const { entity_src_gen, entity_src_nat, pdbx_entity_src_syn } = m.sourceData.data.db - addSrc(seqToSrcByModelEntity, srcKeySerialMap, i, m, entity_src_gen, entity_src_gen.pdbx_gene_src_scientific_name, entity_src_gen.plasmid_name, entity_src_gen.pdbx_gene_src_gene) - addSrc(seqToSrcByModelEntity, srcKeySerialMap, i, m, entity_src_nat, entity_src_nat.pdbx_organism_scientific, entity_src_nat.pdbx_plasmid_name) - addSrc(seqToSrcByModelEntity, srcKeySerialMap, i, m, pdbx_entity_src_syn, pdbx_entity_src_syn.organism_scientific) + const m = models[i]; + if (!MmcifFormat.is(m.sourceData)) continue; + const { entity_src_gen, entity_src_nat, pdbx_entity_src_syn } = m.sourceData.data.db; + addSrc(seqToSrcByModelEntity, srcKeySerialMap, i, m, entity_src_gen, entity_src_gen.pdbx_gene_src_scientific_name, entity_src_gen.plasmid_name, entity_src_gen.pdbx_gene_src_gene); + addSrc(seqToSrcByModelEntity, srcKeySerialMap, i, m, entity_src_nat, entity_src_nat.pdbx_organism_scientific, entity_src_nat.pdbx_plasmid_name); + addSrc(seqToSrcByModelEntity, srcKeySerialMap, i, m, pdbx_entity_src_syn, pdbx_entity_src_syn.organism_scientific); } - return { seqToSrcByModelEntity, srcKeySerialMap } + return { seqToSrcByModelEntity, srcKeySerialMap }; } function getLabelTable(srcKeySerialMap: Map<string, number>) { - let unnamedCount = 0 + let unnamedCount = 0; return Array.from(srcKeySerialMap.keys()).map(v => { - const vs = v.split('|') - const organism = vs[2] - const name = isInteger(vs[3]) ? `Unnamed ${++unnamedCount}` : vs[3] - return `${name}${organism ? ` (${organism})` : ''}` - }) + const vs = v.split('|'); + const organism = vs[2]; + const name = isInteger(vs[3]) ? `Unnamed ${++unnamedCount}` : vs[3]; + return `${name}${organism ? ` (${organism})` : ''}`; + }); } export function EntitySourceColorTheme(ctx: ThemeDataContext, props: PD.Values<EntitySourceColorThemeParams>): ColorTheme<EntitySourceColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const l = StructureElement.Location.create(ctx.structure) - const { models } = ctx.structure.root - const { seqToSrcByModelEntity, srcKeySerialMap } = getMaps(models) + const l = StructureElement.Location.create(ctx.structure); + const { models } = ctx.structure.root; + const { seqToSrcByModelEntity, srcKeySerialMap } = getMaps(models); - const labelTable = getLabelTable(srcKeySerialMap) - props.palette.params.valueLabel = (i: number) => labelTable[i] + const labelTable = getLabelTable(srcKeySerialMap); + props.palette.params.valueLabel = (i: number) => labelTable[i]; - const palette = getPalette(srcKeySerialMap.size, props) - legend = palette.legend + const palette = getPalette(srcKeySerialMap.size, props); + legend = palette.legend; const getSrcColor = (location: StructureElement.Location) => { - const modelIndex = models.indexOf(location.unit.model) - const entityId = StructureProperties.entity.id(location) - const mK = modelEntityKey(modelIndex, entityId) - const seqToSrc = seqToSrcByModelEntity.get(mK) + const modelIndex = models.indexOf(location.unit.model); + const entityId = StructureProperties.entity.id(location); + const mK = modelEntityKey(modelIndex, entityId); + const seqToSrc = seqToSrcByModelEntity.get(mK); if (seqToSrc) { // minus 1 to convert seqId to array index - return palette.color(seqToSrc[StructureProperties.residue.label_seq_id(location) - 1] - 1) + return palette.color(seqToSrc[StructureProperties.residue.label_seq_id(location) - 1] - 1); } else { - return DefaultColor + return DefaultColor; } - } + }; color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - return getSrcColor(location) + return getSrcColor(location); } else if (Bond.isLocation(location)) { - l.unit = location.aUnit - l.element = location.aUnit.elements[location.aIndex] - return getSrcColor(l) + l.unit = location.aUnit; + l.element = location.aUnit.elements[location.aIndex]; + return getSrcColor(l); } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -170,7 +170,7 @@ export function EntitySourceColorTheme(ctx: ThemeDataContext, props: PD.Values<E props, description: Description, legend - } + }; } export const EntitySourceColorThemeProvider: ColorTheme.Provider<EntitySourceColorThemeParams, 'entity-source'> = { @@ -181,4 +181,4 @@ export const EntitySourceColorThemeProvider: ColorTheme.Provider<EntitySourceCol getParams: getEntitySourceColorThemeParams, defaultValues: PD.getDefaultValues(EntitySourceColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/hydrophobicity.ts b/src/mol-theme/color/hydrophobicity.ts index 5c952c29d59541585f7d891bdb1ccf04eb60ae2b..f4904aca8502af64e84cd56e41895c44ee20e4db 100644 --- a/src/mol-theme/color/hydrophobicity.ts +++ b/src/mol-theme/color/hydrophobicity.ts @@ -8,52 +8,52 @@ import { Color, ColorScale } from '../../mol-util/color'; import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { ResidueHydrophobicity } from '../../mol-model/structure/model/types'; -const Description = 'Assigns a color to every amino acid according to the "Experimentally determined hydrophobicity scale for proteins at membrane interfaces" by Wimely and White (doi:10.1038/nsb1096-842).' +const Description = 'Assigns a color to every amino acid according to the "Experimentally determined hydrophobicity scale for proteins at membrane interfaces" by Wimely and White (doi:10.1038/nsb1096-842).'; export const HydrophobicityColorThemeParams = { list: PD.ColorList('red-yellow-green', { presetKind: 'scale' }), scale: PD.Select('DGwif', [['DGwif', 'DG water-membrane'], ['DGwoct', 'DG water-octanol'], ['Oct-IF', 'DG difference']] as const) -} +}; export type HydrophobicityColorThemeParams = typeof HydrophobicityColorThemeParams export function getHydrophobicityColorThemeParams(ctx: ThemeDataContext) { - return HydrophobicityColorThemeParams // TODO return copy + return HydrophobicityColorThemeParams; // TODO return copy } -const scaleIndexMap = { 'DGwif': 0, 'DGwoct': 1, 'Oct-IF': 2 } +const scaleIndexMap = { 'DGwif': 0, 'DGwoct': 1, 'Oct-IF': 2 }; export function hydrophobicity(compId: string, scaleIndex: number): number { const c = (ResidueHydrophobicity as { [k: string]: number[] })[compId]; - return c === undefined ? 0 : c[scaleIndex] + return c === undefined ? 0 : c[scaleIndex]; } function getAtomicCompId(unit: Unit.Atomic, element: ElementIndex) { - return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element]) + return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element]); } function getCoarseCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIndex) { - const seqIdBegin = unit.coarseElements.seq_id_begin.value(element) - const seqIdEnd = unit.coarseElements.seq_id_end.value(element) + const seqIdBegin = unit.coarseElements.seq_id_begin.value(element); + const seqIdEnd = unit.coarseElements.seq_id_end.value(element); if (seqIdBegin === seqIdEnd) { - const entityKey = unit.coarseElements.entityKey[element] - const seq = unit.model.sequence.byEntityKey[entityKey].sequence - return seq.compId.value(seqIdBegin - 1) // 1-indexed + const entityKey = unit.coarseElements.entityKey[element]; + const seq = unit.model.sequence.byEntityKey[entityKey].sequence; + return seq.compId.value(seqIdBegin - 1); // 1-indexed } } export function HydrophobicityColorTheme(ctx: ThemeDataContext, props: PD.Values<HydrophobicityColorThemeParams>): ColorTheme<HydrophobicityColorThemeParams> { - const scaleIndex = scaleIndexMap[props.scale] + const scaleIndex = scaleIndexMap[props.scale]; // get domain - let min = Infinity - let max = -Infinity + let min = Infinity; + let max = -Infinity; for (const name in ResidueHydrophobicity) { - const val = (ResidueHydrophobicity as { [k: string]: number[] })[name][scaleIndex] - min = Math.min(min, val) - max = Math.max(max, val) + const val = (ResidueHydrophobicity as { [k: string]: number[] })[name][scaleIndex]; + min = Math.min(min, val); + max = Math.max(max, val); } const scale = ColorScale.create({ @@ -61,24 +61,24 @@ export function HydrophobicityColorTheme(ctx: ThemeDataContext, props: PD.Values domain: [ max, min ], minLabel: 'Hydrophobic', maxLabel: 'Hydrophilic' - }) + }); function color(location: Location): Color { - let compId: string | undefined + let compId: string | undefined; if (StructureElement.Location.is(location)) { if (Unit.isAtomic(location.unit)) { - compId = getAtomicCompId(location.unit, location.element) + compId = getAtomicCompId(location.unit, location.element); } else { - compId = getCoarseCompId(location.unit, location.element) + compId = getCoarseCompId(location.unit, location.element); } } else if (Bond.isLocation(location)) { if (Unit.isAtomic(location.aUnit)) { - compId = getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex]) + compId = getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex]); } else { - compId = getCoarseCompId(location.aUnit, location.aUnit.elements[location.aIndex]) + compId = getCoarseCompId(location.aUnit, location.aUnit.elements[location.aIndex]); } } - return scale.color(compId ? hydrophobicity(compId, scaleIndex) : 0) + return scale.color(compId ? hydrophobicity(compId, scaleIndex) : 0); } return { @@ -88,7 +88,7 @@ export function HydrophobicityColorTheme(ctx: ThemeDataContext, props: PD.Values props, description: Description, legend: scale ? scale.legend : undefined - } + }; } export const HydrophobicityColorThemeProvider: ColorTheme.Provider<HydrophobicityColorThemeParams, 'hydrophobicity'> = { @@ -99,4 +99,4 @@ export const HydrophobicityColorThemeProvider: ColorTheme.Provider<Hydrophobicit getParams: getHydrophobicityColorThemeParams, defaultValues: PD.getDefaultValues(HydrophobicityColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/illustrative.ts b/src/mol-theme/color/illustrative.ts index cee5e8e87c5638cde2cb336821a4f2bc6eeabaf7..fb0f146100e1c62856476b2f5a1b2fca30ffe7d1 100644 --- a/src/mol-theme/color/illustrative.ts +++ b/src/mol-theme/color/illustrative.ts @@ -9,59 +9,59 @@ import { Color } from '../../mol-util/color'; import { StructureElement, Unit, Bond } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { elementSymbolColor, ElementSymbolColors } from './element-symbol'; import { getAdjustedColorMap } from '../../mol-util/color/color'; -const DefaultIllustrativeColor = Color(0xFFFFFF) -const Description = `Assigns an illustrative color similar to David Goodsell's Molecule of the Month style.` +const DefaultIllustrativeColor = Color(0xFFFFFF); +const Description = `Assigns an illustrative color similar to David Goodsell's Molecule of the Month style.`; -export const IllustrativeColorThemeParams = {} +export const IllustrativeColorThemeParams = {}; export type IllustrativeColorThemeParams = typeof IllustrativeColorThemeParams export function getIllustrativeColorThemeParams(ctx: ThemeDataContext) { - return IllustrativeColorThemeParams // TODO return copy + return IllustrativeColorThemeParams; // TODO return copy } export function illustrativeColor(colorMap: ElementSymbolColors, typeSymbol: ElementSymbol, moleculeType: MoleculeType) { if (isNucleic(moleculeType)) { if (typeSymbol === 'O') { - return Color(0xFF8C8C) + return Color(0xFF8C8C); } else if (typeSymbol === 'P') { - return Color(0xFF7D7D) + return Color(0xFF7D7D); } else { - return Color(0xFFA6A6) + return Color(0xFFA6A6); } } else if (isProtein(moleculeType)) { if (typeSymbol === 'C') { - return Color(0x7FB2FF) + return Color(0x7FB2FF); } else { - return Color(0x6699FF) + return Color(0x6699FF); } } else { - return elementSymbolColor(colorMap, typeSymbol) + return elementSymbolColor(colorMap, typeSymbol); } } export function IllustrativeColorTheme(ctx: ThemeDataContext, props: PD.Values<IllustrativeColorThemeParams>): ColorTheme<IllustrativeColorThemeParams> { - const colorMap = getAdjustedColorMap(ElementSymbolColors, 0, 0.7) + const colorMap = getAdjustedColorMap(ElementSymbolColors, 0, 0.7); function color(location: Location): Color { if (StructureElement.Location.is(location)) { if (Unit.isAtomic(location.unit)) { - const moleculeType = location.unit.model.atomicHierarchy.derived.residue.moleculeType[location.unit.residueIndex[location.element]] - const typeSymbol = location.unit.model.atomicHierarchy.atoms.type_symbol.value(location.element) - return illustrativeColor(colorMap, typeSymbol, moleculeType) + const moleculeType = location.unit.model.atomicHierarchy.derived.residue.moleculeType[location.unit.residueIndex[location.element]]; + const typeSymbol = location.unit.model.atomicHierarchy.atoms.type_symbol.value(location.element); + return illustrativeColor(colorMap, typeSymbol, moleculeType); } } else if (Bond.isLocation(location)) { if (Unit.isAtomic(location.aUnit)) { - const elementIndex = location.aUnit.elements[location.aIndex] - const moleculeType = location.aUnit.model.atomicHierarchy.derived.residue.moleculeType[location.aUnit.residueIndex[elementIndex]] - const typeSymbol = location.aUnit.model.atomicHierarchy.atoms.type_symbol.value(elementIndex) - return illustrativeColor(colorMap, typeSymbol, moleculeType) + const elementIndex = location.aUnit.elements[location.aIndex]; + const moleculeType = location.aUnit.model.atomicHierarchy.derived.residue.moleculeType[location.aUnit.residueIndex[elementIndex]]; + const typeSymbol = location.aUnit.model.atomicHierarchy.atoms.type_symbol.value(elementIndex); + return illustrativeColor(colorMap, typeSymbol, moleculeType); } } - return DefaultIllustrativeColor + return DefaultIllustrativeColor; } return { @@ -71,7 +71,7 @@ export function IllustrativeColorTheme(ctx: ThemeDataContext, props: PD.Values<I props, description: Description, // TODO add legend - } + }; } export const IllustrativeColorThemeProvider: ColorTheme.Provider<IllustrativeColorThemeParams, 'illustrative'> = { @@ -82,4 +82,4 @@ export const IllustrativeColorThemeProvider: ColorTheme.Provider<IllustrativeCol getParams: getIllustrativeColorThemeParams, defaultValues: PD.getDefaultValues(IllustrativeColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/model-index.ts b/src/mol-theme/color/model-index.ts index 34e49314be03dcd56e2cbf67b90aca7cb8366b56..f842988dd91330ae0505fbb863857184ee22dcd7 100644 --- a/src/mol-theme/color/model-index.ts +++ b/src/mol-theme/color/model-index.ts @@ -8,50 +8,50 @@ import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { StructureElement, Bond } from '../../mol-model/structure'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { TableLegend, ScaleLegend } from '../../mol-util/legend'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives every model a unique color based on the position (index) of the model in the list of models in the structure.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives every model a unique color based on the position (index) of the model in the list of models in the structure.'; export const ModelIndexColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: 'purples' }), -} +}; export type ModelIndexColorThemeParams = typeof ModelIndexColorThemeParams export function getModelIndexColorThemeParams(ctx: ThemeDataContext) { - return ModelIndexColorThemeParams // TODO return copy + return ModelIndexColorThemeParams; // TODO return copy } export function ModelIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<ModelIndexColorThemeParams>): ColorTheme<ModelIndexColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const { models } = ctx.structure.root + const { models } = ctx.structure.root; let size = 0; for (const m of models) size = Math.max(size, m.trajectoryInfo.size); - const palette = getPalette(size, props) - legend = palette.legend - const modelColor = new Map<number, Color>() + const palette = getPalette(size, props); + legend = palette.legend; + const modelColor = new Map<number, Color>(); for (let i = 0, il = models.length; i < il; ++i) { const idx = models[i].trajectoryInfo.index; - modelColor.set(models[i].trajectoryInfo.index, palette.color(idx)) + modelColor.set(models[i].trajectoryInfo.index, palette.color(idx)); } color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - return modelColor.get(location.unit.model.trajectoryInfo.index)! + return modelColor.get(location.unit.model.trajectoryInfo.index)!; } else if (Bond.isLocation(location)) { - return modelColor.get(location.aUnit.model.trajectoryInfo.index)! + return modelColor.get(location.aUnit.model.trajectoryInfo.index)!; } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -61,7 +61,7 @@ export function ModelIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<Mod props, description: Description, legend - } + }; } export const ModelIndexColorThemeProvider: ColorTheme.Provider<ModelIndexColorThemeParams, 'model-index'> = { @@ -72,4 +72,4 @@ export const ModelIndexColorThemeProvider: ColorTheme.Provider<ModelIndexColorTh getParams: getModelIndexColorThemeParams, defaultValues: PD.getDefaultValues(ModelIndexColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.elementCount > 0 && ctx.structure.models[0].trajectoryInfo.size > 1 -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/molecule-type.ts b/src/mol-theme/color/molecule-type.ts index 74a700999187ba2dd1d18d5146899cc917089529..9ed619acb329c6e709e9ad7ddfd22cee0c9f8a3d 100644 --- a/src/mol-theme/color/molecule-type.ts +++ b/src/mol-theme/color/molecule-type.ts @@ -10,7 +10,7 @@ import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; import { MoleculeType } from '../../mol-model/structure/model/types'; import { getElementMoleculeType } from '../../mol-model/structure/util'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { TableLegend } from '../../mol-util/legend'; import { getAdjustedColorMap } from '../../mol-util/color/color'; @@ -23,45 +23,45 @@ export const MoleculeTypeColors = ColorMap({ DNA: 0xbf5b17, PNA: 0x42A49A, saccharide: 0x7fc97f, -}) +}); export type MoleculeTypeColors = typeof MoleculeTypeColors -const DefaultMoleculeTypeColor = Color(0xffff99) -const Description = 'Assigns a color based on the molecule type of a residue.' +const DefaultMoleculeTypeColor = Color(0xffff99); +const Description = 'Assigns a color based on the molecule type of a residue.'; export const MoleculeTypeColorThemeParams = { saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }), lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }) -} +}; export type MoleculeTypeColorThemeParams = typeof MoleculeTypeColorThemeParams export function getMoleculeTypeColorThemeParams(ctx: ThemeDataContext) { - return MoleculeTypeColorThemeParams // TODO return copy + return MoleculeTypeColorThemeParams; // TODO return copy } export function moleculeTypeColor(colorMap: MoleculeTypeColors, unit: Unit, element: ElementIndex): Color { - const moleculeType = getElementMoleculeType(unit, element) + const moleculeType = getElementMoleculeType(unit, element); switch (moleculeType) { - case MoleculeType.Water: return colorMap.water - case MoleculeType.Ion: return colorMap.ion - case MoleculeType.Protein: return colorMap.protein - case MoleculeType.RNA: return colorMap.RNA - case MoleculeType.DNA: return colorMap.DNA - case MoleculeType.PNA: return colorMap.PNA - case MoleculeType.Saccharide: return colorMap.saccharide + case MoleculeType.Water: return colorMap.water; + case MoleculeType.Ion: return colorMap.ion; + case MoleculeType.Protein: return colorMap.protein; + case MoleculeType.RNA: return colorMap.RNA; + case MoleculeType.DNA: return colorMap.DNA; + case MoleculeType.PNA: return colorMap.PNA; + case MoleculeType.Saccharide: return colorMap.saccharide; } - return DefaultMoleculeTypeColor + return DefaultMoleculeTypeColor; } export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<MoleculeTypeColorThemeParams>): ColorTheme<MoleculeTypeColorThemeParams> { - const colorMap = getAdjustedColorMap(MoleculeTypeColors, props.saturation, props.lightness) + const colorMap = getAdjustedColorMap(MoleculeTypeColors, props.saturation, props.lightness); function color(location: Location): Color { if (StructureElement.Location.is(location)) { - return moleculeTypeColor(colorMap, location.unit, location.element) + return moleculeTypeColor(colorMap, location.unit, location.element); } else if (Bond.isLocation(location)) { - return moleculeTypeColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex]) + return moleculeTypeColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex]); } - return DefaultMoleculeTypeColor + return DefaultMoleculeTypeColor; } return { @@ -71,9 +71,9 @@ export function MoleculeTypeColorTheme(ctx: ThemeDataContext, props: PD.Values<M props, description: Description, legend: TableLegend(Object.keys(MoleculeTypeColors).map(name => { - return [name, (MoleculeTypeColors as any)[name] as Color] as [string, Color] + return [name, (MoleculeTypeColors as any)[name] as Color] as [string, Color]; }).concat([[ 'Other/unknown', DefaultMoleculeTypeColor ]])) - } + }; } export const MoleculeTypeColorThemeProvider: ColorTheme.Provider<MoleculeTypeColorThemeParams, 'molecule-type'> = { @@ -84,4 +84,4 @@ export const MoleculeTypeColorThemeProvider: ColorTheme.Provider<MoleculeTypeCol getParams: getMoleculeTypeColorThemeParams, defaultValues: PD.getDefaultValues(MoleculeTypeColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/occupancy.ts b/src/mol-theme/color/occupancy.ts index a72ec3f1ee94992af0cbf47f71077e94ca905228..ea8189bfa77e563f7b3adbe67c00c8e38b160e27 100644 --- a/src/mol-theme/color/occupancy.ts +++ b/src/mol-theme/color/occupancy.ts @@ -8,26 +8,26 @@ import { Color, ColorScale } from '../../mol-util/color'; import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; -const DefaultOccupancyColor = Color(0xCCCCCC) -const Description = `Assigns a color based on the occupancy of an atom.` +const DefaultOccupancyColor = Color(0xCCCCCC); +const Description = `Assigns a color based on the occupancy of an atom.`; export const OccupancyColorThemeParams = { domain: PD.Interval([0, 1]), list: PD.ColorList('purples', { presetKind: 'scale' }), -} +}; export type OccupancyColorThemeParams = typeof OccupancyColorThemeParams export function getOccupancyColorThemeParams(ctx: ThemeDataContext) { - return OccupancyColorThemeParams // TODO return copy + return OccupancyColorThemeParams; // TODO return copy } export function getOccupancy(unit: Unit, element: ElementIndex): number { if (Unit.isAtomic(unit)) { - return unit.model.atomicConformation.occupancy.value(element) + return unit.model.atomicConformation.occupancy.value(element); } else { - return 0 + return 0; } } @@ -36,15 +36,15 @@ export function OccupancyColorTheme(ctx: ThemeDataContext, props: PD.Values<Occu reverse: false, domain: props.domain, listOrName: props.list.colors, - }) + }); function color(location: Location): Color { if (StructureElement.Location.is(location)) { - return scale.color(getOccupancy(location.unit, location.element)) + return scale.color(getOccupancy(location.unit, location.element)); } else if (Bond.isLocation(location)) { - return scale.color(getOccupancy(location.aUnit, location.aUnit.elements[location.aIndex])) + return scale.color(getOccupancy(location.aUnit, location.aUnit.elements[location.aIndex])); } - return DefaultOccupancyColor + return DefaultOccupancyColor; } return { @@ -54,7 +54,7 @@ export function OccupancyColorTheme(ctx: ThemeDataContext, props: PD.Values<Occu props, description: Description, legend: scale ? scale.legend : undefined - } + }; } export const OccupancyColorThemeProvider: ColorTheme.Provider<OccupancyColorThemeParams, 'occupancy'> = { @@ -65,4 +65,4 @@ export const OccupancyColorThemeProvider: ColorTheme.Provider<OccupancyColorThem getParams: getOccupancyColorThemeParams, defaultValues: PD.getDefaultValues(OccupancyColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.models.some(m => m.atomicConformation.occupancy.isDefined) -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/operator-hkl.ts b/src/mol-theme/color/operator-hkl.ts index 83d099a1d4c191e005f41695d808367c2d0d64f5..3cf86483b8b4915cdb4d7ecdae0632c323a18757 100644 --- a/src/mol-theme/color/operator-hkl.ts +++ b/src/mol-theme/color/operator-hkl.ts @@ -8,7 +8,7 @@ import { Color } from '../../mol-util/color'; import { StructureElement, Bond, Structure } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { ScaleLegend, TableLegend } from '../../mol-util/legend'; @@ -16,95 +16,95 @@ import { Vec3 } from '../../mol-math/linear-algebra'; import { integerDigitCount } from '../../mol-util/number'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xCCCCCC) -const Description = `Assigns a color based on the operator HKL value of a transformed chain.` +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xCCCCCC); +const Description = `Assigns a color based on the operator HKL value of a transformed chain.`; export const OperatorHklColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type OperatorHklColorThemeParams = typeof OperatorHklColorThemeParams export function getOperatorHklColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(OperatorHklColorThemeParams) + const params = PD.clone(OperatorHklColorThemeParams); if (ctx.structure) { if (getOperatorHklSerialMap(ctx.structure.root).map.size > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } -const hklOffset = 10000 +const hklOffset = 10000; function hklKey(hkl: Vec3) { - return hkl.map(v => `${v + hklOffset}`.padStart(5, '0')).join('') + return hkl.map(v => `${v + hklOffset}`.padStart(5, '0')).join(''); } function hklKeySplit(key: string) { - const len = integerDigitCount(hklOffset, 0) - const h = parseInt(key.substr(0, len)) - const k = parseInt(key.substr(len, len)) - const l = parseInt(key.substr(len + len, len)) - return [ h - hklOffset, k - hklOffset, l - hklOffset ] as Vec3 + const len = integerDigitCount(hklOffset, 0); + const h = parseInt(key.substr(0, len)); + const k = parseInt(key.substr(len, len)); + const l = parseInt(key.substr(len + len, len)); + return [ h - hklOffset, k - hklOffset, l - hklOffset ] as Vec3; } function formatHkl(hkl: Vec3) { - return hkl.map(v => v + 5).join('') + return hkl.map(v => v + 5).join(''); } function getOperatorHklSerialMap(structure: Structure) { - const map = new Map<string, number>() - const set = new Set<string>() + const map = new Map<string, number>(); + const set = new Set<string>(); for (let i = 0, il = structure.units.length; i < il; ++i) { - const k = hklKey(structure.units[i].conformation.operator.hkl) - set.add(k) + const k = hklKey(structure.units[i].conformation.operator.hkl); + set.add(k); } - const arr = Array.from(set.values()).sort() - arr.forEach(k => map.set(k, map.size)) - const min = hklKeySplit(arr[0]) - const max = hklKeySplit(arr[arr.length - 1]) - return { min, max, map } + const arr = Array.from(set.values()).sort(); + arr.forEach(k => map.set(k, map.size)); + const min = hklKeySplit(arr[0]); + const max = hklKeySplit(arr[arr.length - 1]); + return { min, max, map }; } export function OperatorHklColorTheme(ctx: ThemeDataContext, props: PD.Values<OperatorHklColorThemeParams>): ColorTheme<OperatorHklColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const { min, max, map } = getOperatorHklSerialMap(ctx.structure.root) + const { min, max, map } = getOperatorHklSerialMap(ctx.structure.root); - const labelTable: string[] = [] + const labelTable: string[] = []; map.forEach((v, k) => { - const i = v % map.size - const label = formatHkl(hklKeySplit(k)) - if (labelTable[i] === undefined) labelTable[i] = label - else labelTable[i] += `, ${label}` - }) + const i = v % map.size; + const label = formatHkl(hklKeySplit(k)); + if (labelTable[i] === undefined) labelTable[i] = label; + else labelTable[i] += `, ${label}`; + }); - props.palette.params.minLabel = formatHkl(min) - props.palette.params.maxLabel = formatHkl(max) - props.palette.params.valueLabel = (i: number) => labelTable[i] + props.palette.params.minLabel = formatHkl(min); + props.palette.params.maxLabel = formatHkl(max); + props.palette.params.valueLabel = (i: number) => labelTable[i]; - const palette = getPalette(map.size, props) - legend = palette.legend + const palette = getPalette(map.size, props); + legend = palette.legend; color = (location: Location): Color => { - let serial: number | undefined = undefined + let serial: number | undefined = undefined; if (StructureElement.Location.is(location)) { - const k = hklKey(location.unit.conformation.operator.hkl) - serial = map.get(k) + const k = hklKey(location.unit.conformation.operator.hkl); + serial = map.get(k); } else if (Bond.isLocation(location)) { - const k = hklKey(location.aUnit.conformation.operator.hkl) - serial = map.get(k) + const k = hklKey(location.aUnit.conformation.operator.hkl); + serial = map.get(k); } - return serial === undefined ? DefaultColor : palette.color(serial) - } + return serial === undefined ? DefaultColor : palette.color(serial); + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -114,7 +114,7 @@ export function OperatorHklColorTheme(ctx: ThemeDataContext, props: PD.Values<Op props, description: Description, legend - } + }; } export const OperatorHklColorThemeProvider: ColorTheme.Provider<OperatorHklColorThemeParams, 'operator-hkl'> = { @@ -125,4 +125,4 @@ export const OperatorHklColorThemeProvider: ColorTheme.Provider<OperatorHklColor getParams: getOperatorHklColorThemeParams, defaultValues: PD.getDefaultValues(OperatorHklColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/operator-name.ts b/src/mol-theme/color/operator-name.ts index 4d9c754e208923293cd7a8610cee1f18d0b5fe76..1e1b91ac34dd0c0eb9f2c75b1e1b0e240c81f3cf 100644 --- a/src/mol-theme/color/operator-name.ts +++ b/src/mol-theme/color/operator-name.ts @@ -8,69 +8,69 @@ import { Color } from '../../mol-util/color'; import { StructureElement, Bond, Structure } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { ScaleLegend, TableLegend } from '../../mol-util/legend'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xCCCCCC) -const Description = `Assigns a color based on the operator name of a transformed chain.` +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xCCCCCC); +const Description = `Assigns a color based on the operator name of a transformed chain.`; export const OperatorNameColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type OperatorNameColorThemeParams = typeof OperatorNameColorThemeParams export function getOperatorNameColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(OperatorNameColorThemeParams) + const params = PD.clone(OperatorNameColorThemeParams); if (ctx.structure) { if (getOperatorNameSerialMap(ctx.structure.root).size > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } function getOperatorNameSerialMap(structure: Structure) { - const map = new Map<string, number>() + const map = new Map<string, number>(); for (let i = 0, il = structure.units.length; i < il; ++i) { - const name = structure.units[i].conformation.operator.name - if (!map.has(name)) map.set(name, map.size) + const name = structure.units[i].conformation.operator.name; + if (!map.has(name)) map.set(name, map.size); } - return map + return map; } export function OperatorNameColorTheme(ctx: ThemeDataContext, props: PD.Values<OperatorNameColorThemeParams>): ColorTheme<OperatorNameColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const operatorNameSerialMap = getOperatorNameSerialMap(ctx.structure.root) + const operatorNameSerialMap = getOperatorNameSerialMap(ctx.structure.root); - const labelTable = Array.from(operatorNameSerialMap.keys()) - props.palette.params.valueLabel = (i: number) => labelTable[i] + const labelTable = Array.from(operatorNameSerialMap.keys()); + props.palette.params.valueLabel = (i: number) => labelTable[i]; - const palette = getPalette(operatorNameSerialMap.size, props) - legend = palette.legend + const palette = getPalette(operatorNameSerialMap.size, props); + legend = palette.legend; color = (location: Location): Color => { - let serial: number | undefined = undefined + let serial: number | undefined = undefined; if (StructureElement.Location.is(location)) { - const name = location.unit.conformation.operator.name - serial = operatorNameSerialMap.get(name) + const name = location.unit.conformation.operator.name; + serial = operatorNameSerialMap.get(name); } else if (Bond.isLocation(location)) { - const name = location.aUnit.conformation.operator.name - serial = operatorNameSerialMap.get(name) + const name = location.aUnit.conformation.operator.name; + serial = operatorNameSerialMap.get(name); } - return serial === undefined ? DefaultColor : palette.color(serial) - } + return serial === undefined ? DefaultColor : palette.color(serial); + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -80,7 +80,7 @@ export function OperatorNameColorTheme(ctx: ThemeDataContext, props: PD.Values<O props, description: Description, legend - } + }; } export const OperatorNameColorThemeProvider: ColorTheme.Provider<OperatorNameColorThemeParams, 'operator-name'> = { @@ -91,4 +91,4 @@ export const OperatorNameColorThemeProvider: ColorTheme.Provider<OperatorNameCol getParams: getOperatorNameColorThemeParams, defaultValues: PD.getDefaultValues(OperatorNameColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/polymer-id.ts b/src/mol-theme/color/polymer-id.ts index 27a0fb2f6e0d7f3c4e7477bd7f42101463422d51..75e068b1a8ac8117703eaf93d13c0a73e59a034c 100644 --- a/src/mol-theme/color/polymer-id.ts +++ b/src/mol-theme/color/polymer-id.ts @@ -9,111 +9,111 @@ import { Unit, StructureProperties, StructureElement, Bond, Structure } from '.. import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { getPalette, getPaletteParams } from '../../mol-util/color/palette'; import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { Segmentation } from '../../mol-data/int'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xFAFAFA) -const Description = 'Gives every polymer chain a color based on its `asym_id` value.' +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xFAFAFA); +const Description = 'Gives every polymer chain a color based on its `asym_id` value.'; export const PolymerIdColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type PolymerIdColorThemeParams = typeof PolymerIdColorThemeParams export function getPolymerIdColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(PolymerIdColorThemeParams) + const params = PD.clone(PolymerIdColorThemeParams); if (ctx.structure) { if (getPolymerAsymIdSerialMap(ctx.structure.root).size > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } function getAsymId(unit: Unit): StructureElement.Property<string> { switch (unit.kind) { case Unit.Kind.Atomic: - return StructureProperties.chain.label_asym_id + return StructureProperties.chain.label_asym_id; case Unit.Kind.Spheres: case Unit.Kind.Gaussians: - return StructureProperties.coarse.asym_id + return StructureProperties.coarse.asym_id; } } function getPolymerAsymIdSerialMap(structure: Structure) { - const map = new Map<string, number>() + const map = new Map<string, number>(); for (let i = 0, il = structure.unitSymmetryGroups.length; i < il; ++i) { - const unit = structure.unitSymmetryGroups[i].units[0] - const { model } = unit + const unit = structure.unitSymmetryGroups[i].units[0]; + const { model } = unit; if (Unit.isAtomic(unit)) { - const { chainAtomSegments, chains } = model.atomicHierarchy - const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements) + const { chainAtomSegments, chains } = model.atomicHierarchy; + const chainIt = Segmentation.transientSegments(chainAtomSegments, unit.elements); while (chainIt.hasNext) { - const { index: chainIndex } = chainIt.move() - const entityId = chains.label_entity_id.value(chainIndex) - const eI = model.entities.getEntityIndex(entityId) + const { index: chainIndex } = chainIt.move(); + const entityId = chains.label_entity_id.value(chainIndex); + const eI = model.entities.getEntityIndex(entityId); if (model.entities.data.type.value(eI) === 'polymer') { - const asymId = chains.label_asym_id.value(chainIndex) - if (!map.has(asymId)) map.set(asymId, map.size) + const asymId = chains.label_asym_id.value(chainIndex); + if (!map.has(asymId)) map.set(asymId, map.size); } } } else if (Unit.isCoarse(unit)) { const { chainElementSegments, asym_id, entity_id } = Unit.isSpheres(unit) ? model.coarseHierarchy.spheres - : model.coarseHierarchy.gaussians - const chainIt = Segmentation.transientSegments(chainElementSegments, unit.elements) + : model.coarseHierarchy.gaussians; + const chainIt = Segmentation.transientSegments(chainElementSegments, unit.elements); while (chainIt.hasNext) { - const { index: chainIndex } = chainIt.move() - const elementIndex = chainElementSegments.offsets[chainIndex] - const entityId = entity_id.value(elementIndex) - const eI = model.entities.getEntityIndex(entityId) + const { index: chainIndex } = chainIt.move(); + const elementIndex = chainElementSegments.offsets[chainIndex]; + const entityId = entity_id.value(elementIndex); + const eI = model.entities.getEntityIndex(entityId); if (model.entities.data.type.value(eI) === 'polymer') { - const asymId = asym_id.value(elementIndex) - if (!map.has(asymId)) map.set(asymId, map.size) + const asymId = asym_id.value(elementIndex); + if (!map.has(asymId)) map.set(asymId, map.size); } } } } - return map + return map; } export function PolymerIdColorTheme(ctx: ThemeDataContext, props: PD.Values<PolymerIdColorThemeParams>): ColorTheme<PolymerIdColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const l = StructureElement.Location.create(ctx.structure) - const polymerAsymIdSerialMap = getPolymerAsymIdSerialMap(ctx.structure.root) + const l = StructureElement.Location.create(ctx.structure); + const polymerAsymIdSerialMap = getPolymerAsymIdSerialMap(ctx.structure.root); - const labelTable = Array.from(polymerAsymIdSerialMap.keys()) - props.palette.params.valueLabel = (i: number) => labelTable[i] + const labelTable = Array.from(polymerAsymIdSerialMap.keys()); + props.palette.params.valueLabel = (i: number) => labelTable[i]; - const palette = getPalette(polymerAsymIdSerialMap.size, props) - legend = palette.legend + const palette = getPalette(polymerAsymIdSerialMap.size, props); + legend = palette.legend; color = (location: Location): Color => { - let serial: number | undefined = undefined + let serial: number | undefined = undefined; if (StructureElement.Location.is(location)) { - const asym_id = getAsymId(location.unit) - serial = polymerAsymIdSerialMap.get(asym_id(location)) + const asym_id = getAsymId(location.unit); + serial = polymerAsymIdSerialMap.get(asym_id(location)); } else if (Bond.isLocation(location)) { - const asym_id = getAsymId(location.aUnit) - l.unit = location.aUnit - l.element = location.aUnit.elements[location.aIndex] - serial = polymerAsymIdSerialMap.get(asym_id(l)) + const asym_id = getAsymId(location.aUnit); + l.unit = location.aUnit; + l.element = location.aUnit.elements[location.aIndex]; + serial = polymerAsymIdSerialMap.get(asym_id(l)); } - return serial === undefined ? DefaultColor : palette.color(serial) - } + return serial === undefined ? DefaultColor : palette.color(serial); + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -123,7 +123,7 @@ export function PolymerIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Poly props, description: Description, legend - } + }; } export const PolymerIdColorThemeProvider: ColorTheme.Provider<PolymerIdColorThemeParams, 'polymer-id'> = { @@ -134,4 +134,4 @@ export const PolymerIdColorThemeProvider: ColorTheme.Provider<PolymerIdColorThem getParams: getPolymerIdColorThemeParams, defaultValues: PD.getDefaultValues(PolymerIdColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/polymer-index.ts b/src/mol-theme/color/polymer-index.ts index 944adc4a9bef42bd508cf4ea1f1d92e8c6bfd4dc..aaf23e15384a177033a772c8d06946a4715a97eb 100644 --- a/src/mol-theme/color/polymer-index.ts +++ b/src/mol-theme/color/polymer-index.ts @@ -8,72 +8,72 @@ import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { StructureElement, Bond, Structure } from '../../mol-model/structure'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives every polymer chain instance a unique color based on the position (index) of the polymer in the list of polymers in the structure.' +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives every polymer chain instance a unique color based on the position (index) of the polymer in the list of polymers in the structure.'; export const PolymerIndexColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type PolymerIndexColorThemeParams = typeof PolymerIndexColorThemeParams export function getPolymerIndexColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(PolymerIndexColorThemeParams) + const params = PD.clone(PolymerIndexColorThemeParams); if (ctx.structure) { if (getPolymerChainCount(ctx.structure.root) > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } export type PolymerIndexColorThemeProps = PD.Values<typeof PolymerIndexColorThemeParams> function getPolymerChainCount(structure: Structure) { - let polymerChainCount = 0 - const { units } = structure + let polymerChainCount = 0; + const { units } = structure; for (let i = 0, il = units.length; i < il; ++i) { - if (units[i].polymerElements.length > 0) ++polymerChainCount + if (units[i].polymerElements.length > 0) ++polymerChainCount; } - return polymerChainCount + return polymerChainCount; } export function PolymerIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<PolymerIndexColorThemeParams>): ColorTheme<PolymerIndexColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const palette = getPalette(getPolymerChainCount(ctx.structure.root), props) - legend = palette.legend + const palette = getPalette(getPolymerChainCount(ctx.structure.root), props); + legend = palette.legend; - const { units } = ctx.structure.root - const unitIdColor = new Map<number, Color>() + const { units } = ctx.structure.root; + const unitIdColor = new Map<number, Color>(); for (let i = 0, j = 0, il = units.length; i < il; ++i) { if (units[i].polymerElements.length > 0) { - unitIdColor.set(units[i].id, palette.color(j)) - ++j + unitIdColor.set(units[i].id, palette.color(j)); + ++j; } } color = (location: Location): Color => { - let color: Color | undefined + let color: Color | undefined; if (StructureElement.Location.is(location)) { - color = unitIdColor.get(location.unit.id) + color = unitIdColor.get(location.unit.id); } else if (Bond.isLocation(location)) { - color = unitIdColor.get(location.aUnit.id) + color = unitIdColor.get(location.aUnit.id); } - return color !== undefined ? color : DefaultColor - } + return color !== undefined ? color : DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -83,7 +83,7 @@ export function PolymerIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<P props, description: Description, legend - } + }; } export const PolymerIndexColorThemeProvider: ColorTheme.Provider<PolymerIndexColorThemeParams, 'polymer-index'> = { @@ -94,4 +94,4 @@ export const PolymerIndexColorThemeProvider: ColorTheme.Provider<PolymerIndexCol getParams: getPolymerIndexColorThemeParams, defaultValues: PD.getDefaultValues(PolymerIndexColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/residue-name.ts b/src/mol-theme/color/residue-name.ts index dc341a3112288acdf64366475de46bf6d0a67194..ea16e93b6b1deb5b9a16501b8bb3396fec756648 100644 --- a/src/mol-theme/color/residue-name.ts +++ b/src/mol-theme/color/residue-name.ts @@ -8,7 +8,7 @@ import { Color, ColorMap } from '../../mol-util/color'; import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { TableLegend } from '../../mol-util/legend'; import { getAdjustedColorMap } from '../../mol-util/color/color'; @@ -58,62 +58,62 @@ export const ResidueNameColors = ColorMap({ 'GPN': 0x32CD32, 'CPN': 0xFFD700, 'TPN': 0x4169E1, -}) +}); export type ResidueNameColors = typeof ResidueNameColors -const DefaultResidueNameColor = Color(0xFF00FF) -const Description = 'Assigns a color to every residue according to its name.' +const DefaultResidueNameColor = Color(0xFF00FF); +const Description = 'Assigns a color to every residue according to its name.'; export const ResidueNameColorThemeParams = { saturation: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }), lightness: PD.Numeric(1, { min: -6, max: 6, step: 0.1 }) -} +}; export type ResidueNameColorThemeParams = typeof ResidueNameColorThemeParams export function getResidueNameColorThemeParams(ctx: ThemeDataContext) { - return ResidueNameColorThemeParams // TODO return copy + return ResidueNameColorThemeParams; // TODO return copy } function getAtomicCompId(unit: Unit.Atomic, element: ElementIndex) { - return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element]) + return unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element]); } function getCoarseCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIndex) { - const seqIdBegin = unit.coarseElements.seq_id_begin.value(element) - const seqIdEnd = unit.coarseElements.seq_id_end.value(element) + const seqIdBegin = unit.coarseElements.seq_id_begin.value(element); + const seqIdEnd = unit.coarseElements.seq_id_end.value(element); if (seqIdBegin === seqIdEnd) { - const entityKey = unit.coarseElements.entityKey[element] - const seq = unit.model.sequence.byEntityKey[entityKey].sequence - return seq.compId.value(seqIdBegin - 1) // 1-indexed + const entityKey = unit.coarseElements.entityKey[element]; + const seq = unit.model.sequence.byEntityKey[entityKey].sequence; + return seq.compId.value(seqIdBegin - 1); // 1-indexed } } export function residueNameColor(colorMap: ResidueNameColors, residueName: string): Color { - const c = colorMap[residueName as keyof ResidueNameColors] - return c === undefined ? DefaultResidueNameColor : c + const c = colorMap[residueName as keyof ResidueNameColors]; + return c === undefined ? DefaultResidueNameColor : c; } export function ResidueNameColorTheme(ctx: ThemeDataContext, props: PD.Values<ResidueNameColorThemeParams>): ColorTheme<ResidueNameColorThemeParams> { - const colorMap = getAdjustedColorMap(ResidueNameColors, props.saturation, props.lightness) + const colorMap = getAdjustedColorMap(ResidueNameColors, props.saturation, props.lightness); function color(location: Location): Color { if (StructureElement.Location.is(location)) { if (Unit.isAtomic(location.unit)) { - const compId = getAtomicCompId(location.unit, location.element) - return residueNameColor(colorMap, compId) + const compId = getAtomicCompId(location.unit, location.element); + return residueNameColor(colorMap, compId); } else { - const compId = getCoarseCompId(location.unit, location.element) - if (compId) return residueNameColor(colorMap, compId) + const compId = getCoarseCompId(location.unit, location.element); + if (compId) return residueNameColor(colorMap, compId); } } else if (Bond.isLocation(location)) { if (Unit.isAtomic(location.aUnit)) { - const compId = getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex]) - return residueNameColor(colorMap, compId) + const compId = getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex]); + return residueNameColor(colorMap, compId); } else { - const compId = getCoarseCompId(location.aUnit, location.aUnit.elements[location.aIndex]) - if (compId) return residueNameColor(colorMap, compId) + const compId = getCoarseCompId(location.aUnit, location.aUnit.elements[location.aIndex]); + if (compId) return residueNameColor(colorMap, compId); } } - return DefaultResidueNameColor + return DefaultResidueNameColor; } return { @@ -123,9 +123,9 @@ export function ResidueNameColorTheme(ctx: ThemeDataContext, props: PD.Values<Re props, description: Description, legend: TableLegend(Object.keys(ResidueNameColors).map(name => { - return [name, (ResidueNameColors as any)[name] as Color] as [string, Color] + return [name, (ResidueNameColors as any)[name] as Color] as [string, Color]; }).concat([[ 'Unknown', DefaultResidueNameColor ]])) - } + }; } export const ResidueNameColorThemeProvider: ColorTheme.Provider<ResidueNameColorThemeParams, 'residue-name'> = { @@ -136,4 +136,4 @@ export const ResidueNameColorThemeProvider: ColorTheme.Provider<ResidueNameColor getParams: getResidueNameColorThemeParams, defaultValues: PD.getDefaultValues(ResidueNameColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/secondary-structure.ts b/src/mol-theme/color/secondary-structure.ts index fce598262f0a3a99589240b6db082eae23fba000..4eefdafc42987b17e65d29893ca9c6b515ad1069 100644 --- a/src/mol-theme/color/secondary-structure.ts +++ b/src/mol-theme/color/secondary-structure.ts @@ -10,7 +10,7 @@ import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; import { SecondaryStructureType, MoleculeType } from '../../mol-model/structure/model/types'; import { getElementMoleculeType } from '../../mol-model/structure/util'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { TableLegend } from '../../mol-util/legend'; import { SecondaryStructureProvider, SecondaryStructureValue } from '../../mol-model-props/computed/secondary-structure'; @@ -32,70 +32,70 @@ const SecondaryStructureColors = ColorMap({ 'rna': 0xFD0162, 'carbohydrate': 0xA6A6FA -}) +}); export type SecondaryStructureColors = typeof SecondaryStructureColors -const DefaultSecondaryStructureColor = Color(0x808080) -const Description = 'Assigns a color based on the type of secondary structure and basic molecule type.' +const DefaultSecondaryStructureColor = Color(0x808080); +const Description = 'Assigns a color based on the type of secondary structure and basic molecule type.'; export const SecondaryStructureColorThemeParams = { saturation: PD.Numeric(-1, { min: -6, max: 6, step: 0.1 }), lightness: PD.Numeric(0, { min: -6, max: 6, step: 0.1 }) -} +}; export type SecondaryStructureColorThemeParams = typeof SecondaryStructureColorThemeParams export function getSecondaryStructureColorThemeParams(ctx: ThemeDataContext) { - return SecondaryStructureColorThemeParams // TODO return copy + return SecondaryStructureColorThemeParams; // TODO return copy } export function secondaryStructureColor(colorMap: SecondaryStructureColors, unit: Unit, element: ElementIndex, computedSecondaryStructure?: SecondaryStructureValue): Color { - let secStrucType = SecondaryStructureType.create(SecondaryStructureType.Flag.None) + let secStrucType = SecondaryStructureType.create(SecondaryStructureType.Flag.None); if (computedSecondaryStructure && Unit.isAtomic(unit)) { - const secondaryStructure = computedSecondaryStructure.get(unit.invariantId) - if (secondaryStructure) secStrucType = secondaryStructure.type[secondaryStructure.getIndex(unit.residueIndex[element])] + const secondaryStructure = computedSecondaryStructure.get(unit.invariantId); + if (secondaryStructure) secStrucType = secondaryStructure.type[secondaryStructure.getIndex(unit.residueIndex[element])]; } if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Helix)) { if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Helix3Ten)) { - return colorMap.threeTenHelix + return colorMap.threeTenHelix; } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.HelixPi)) { - return colorMap.piHelix + return colorMap.piHelix; } - return colorMap.alphaHelix + return colorMap.alphaHelix; } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Beta)) { - return colorMap.betaStrand + return colorMap.betaStrand; } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Bend)) { - return colorMap.bend + return colorMap.bend; } else if (SecondaryStructureType.is(secStrucType, SecondaryStructureType.Flag.Turn)) { - return colorMap.turn + return colorMap.turn; } else { - const moleculeType = getElementMoleculeType(unit, element) + const moleculeType = getElementMoleculeType(unit, element); if (moleculeType === MoleculeType.DNA) { - return colorMap.dna + return colorMap.dna; } else if (moleculeType === MoleculeType.RNA) { - return colorMap.rna + return colorMap.rna; } else if (moleculeType === MoleculeType.Saccharide) { - return colorMap.carbohydrate + return colorMap.carbohydrate; } else if (moleculeType === MoleculeType.Protein) { - return colorMap.coil + return colorMap.coil; } } - return DefaultSecondaryStructureColor + return DefaultSecondaryStructureColor; } export function SecondaryStructureColorTheme(ctx: ThemeDataContext, props: PD.Values<SecondaryStructureColorThemeParams>): ColorTheme<SecondaryStructureColorThemeParams> { - const computedSecondaryStructure = ctx.structure && SecondaryStructureProvider.get(ctx.structure) - const contextHash = computedSecondaryStructure && computedSecondaryStructure.version + const computedSecondaryStructure = ctx.structure && SecondaryStructureProvider.get(ctx.structure); + const contextHash = computedSecondaryStructure && computedSecondaryStructure.version; - const colorMap = getAdjustedColorMap(SecondaryStructureColors, props.saturation, props.lightness) + const colorMap = getAdjustedColorMap(SecondaryStructureColors, props.saturation, props.lightness); function color(location: Location): Color { if (StructureElement.Location.is(location)) { - return secondaryStructureColor(colorMap, location.unit, location.element, computedSecondaryStructure?.value) + return secondaryStructureColor(colorMap, location.unit, location.element, computedSecondaryStructure?.value); } else if (Bond.isLocation(location)) { - return secondaryStructureColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex], computedSecondaryStructure?.value) + return secondaryStructureColor(colorMap, location.aUnit, location.aUnit.elements[location.aIndex], computedSecondaryStructure?.value); } - return DefaultSecondaryStructureColor + return DefaultSecondaryStructureColor; } return { @@ -106,9 +106,9 @@ export function SecondaryStructureColorTheme(ctx: ThemeDataContext, props: PD.Va contextHash, description: Description, legend: TableLegend(Object.keys(SecondaryStructureColors).map(name => { - return [name, (SecondaryStructureColors as any)[name] as Color] as [string, Color] + return [name, (SecondaryStructureColors as any)[name] as Color] as [string, Color]; }).concat([[ 'Other', DefaultSecondaryStructureColor ]])) - } + }; } export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<SecondaryStructureColorThemeParams, 'secondary-structure'> = { @@ -123,4 +123,4 @@ export const SecondaryStructureColorThemeProvider: ColorTheme.Provider<Secondary attach: (ctx: CustomProperty.Context, data: ThemeDataContext) => data.structure ? SecondaryStructureProvider.attach(ctx, data.structure, void 0, true) : Promise.resolve(), detach: (data) => data.structure && data.structure.customPropertyDescriptors.reference(SecondaryStructureProvider.descriptor, false) } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/sequence-id.ts b/src/mol-theme/color/sequence-id.ts index 61dd644e5e2c41ffe30d4c18091ae9c29a34d04a..0520e0677a6e0fb110a167d39e81cb0f81b371f9 100644 --- a/src/mol-theme/color/sequence-id.ts +++ b/src/mol-theme/color/sequence-id.ts @@ -9,58 +9,58 @@ import { Unit, StructureElement, Bond, ElementIndex } from '../../mol-model/stru import { ColorScale, Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives every polymer residue a color based on its `seq_id` value.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives every polymer residue a color based on its `seq_id` value.'; export const SequenceIdColorThemeParams = { list: PD.ColorList('turbo', { presetKind: 'scale' }), -} +}; export type SequenceIdColorThemeParams = typeof SequenceIdColorThemeParams export function getSequenceIdColorThemeParams(ctx: ThemeDataContext) { - return SequenceIdColorThemeParams // TODO return copy + return SequenceIdColorThemeParams; // TODO return copy } function getSeqId(unit: Unit, element: ElementIndex): number { - const { model } = unit + const { model } = unit; switch (unit.kind) { case Unit.Kind.Atomic: - const residueIndex = model.atomicHierarchy.residueAtomSegments.index[element] - return model.atomicHierarchy.residues.label_seq_id.value(residueIndex) + const residueIndex = model.atomicHierarchy.residueAtomSegments.index[element]; + return model.atomicHierarchy.residues.label_seq_id.value(residueIndex); case Unit.Kind.Spheres: return Math.round( (model.coarseHierarchy.spheres.seq_id_begin.value(element) + model.coarseHierarchy.spheres.seq_id_end.value(element)) / 2 - ) + ); case Unit.Kind.Gaussians: return Math.round( (model.coarseHierarchy.gaussians.seq_id_begin.value(element) + model.coarseHierarchy.gaussians.seq_id_end.value(element)) / 2 - ) + ); } } function getSequenceLength(unit: Unit, element: ElementIndex) { - const { model } = unit - let entityId = '' + const { model } = unit; + let entityId = ''; switch (unit.kind) { case Unit.Kind.Atomic: - const chainIndex = model.atomicHierarchy.chainAtomSegments.index[element] - entityId = model.atomicHierarchy.chains.label_entity_id.value(chainIndex) - break + const chainIndex = model.atomicHierarchy.chainAtomSegments.index[element]; + entityId = model.atomicHierarchy.chains.label_entity_id.value(chainIndex); + break; case Unit.Kind.Spheres: - entityId = model.coarseHierarchy.spheres.entity_id.value(element) - break + entityId = model.coarseHierarchy.spheres.entity_id.value(element); + break; case Unit.Kind.Gaussians: - entityId = model.coarseHierarchy.gaussians.entity_id.value(element) - break + entityId = model.coarseHierarchy.gaussians.entity_id.value(element); + break; } - if (entityId === '') return 0 - const entityIndex = model.entities.getEntityIndex(entityId) - if (entityIndex === -1) return 0 - return model.sequence.byEntityKey[entityIndex].sequence.length + if (entityId === '') return 0; + const entityIndex = model.entities.getEntityIndex(entityId); + if (entityIndex === -1) return 0; + return model.sequence.byEntityKey[entityIndex].sequence.length; } export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<SequenceIdColorThemeParams>): ColorTheme<SequenceIdColorThemeParams> { @@ -68,25 +68,25 @@ export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Seq listOrName: props.list.colors, minLabel: 'Start', maxLabel: 'End', - }) + }); const color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - const { unit, element } = location - const seq_id = getSeqId(unit, element) + const { unit, element } = location; + const seq_id = getSeqId(unit, element); if (seq_id > 0) { - scale.setDomain(0, getSequenceLength(unit, element) - 1) - return scale.color(seq_id) + scale.setDomain(0, getSequenceLength(unit, element) - 1); + return scale.color(seq_id); } } else if (Bond.isLocation(location)) { - const { aUnit, aIndex } = location - const seq_id = getSeqId(aUnit, aUnit.elements[aIndex]) + const { aUnit, aIndex } = location; + const seq_id = getSeqId(aUnit, aUnit.elements[aIndex]); if (seq_id > 0) { - scale.setDomain(0, getSequenceLength(aUnit, aUnit.elements[aIndex]) - 1) - return scale.color(seq_id) + scale.setDomain(0, getSequenceLength(aUnit, aUnit.elements[aIndex]) - 1); + return scale.color(seq_id); } } - return DefaultColor - } + return DefaultColor; + }; return { factory: SequenceIdColorTheme, @@ -95,7 +95,7 @@ export function SequenceIdColorTheme(ctx: ThemeDataContext, props: PD.Values<Seq props, description: Description, legend: scale ? scale.legend : undefined - } + }; } export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorThemeParams, 'sequence-id'> = { @@ -106,4 +106,4 @@ export const SequenceIdColorThemeProvider: ColorTheme.Provider<SequenceIdColorTh getParams: getSequenceIdColorThemeParams, defaultValues: PD.getDefaultValues(SequenceIdColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/shape-group.ts b/src/mol-theme/color/shape-group.ts index 12900fa1390e35cf3b517fa876f1845cf43791b8..68d1b840a19664d2156b590da3a82a47cfd1a869 100644 --- a/src/mol-theme/color/shape-group.ts +++ b/src/mol-theme/color/shape-group.ts @@ -8,16 +8,16 @@ import { ColorTheme } from '../color'; import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { ShapeGroup } from '../../mol-model/shape'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Assigns colors as defined by the shape object.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Assigns colors as defined by the shape object.'; -export const ShapeGroupColorThemeParams = {} +export const ShapeGroupColorThemeParams = {}; export type ShapeGroupColorThemeParams = typeof ShapeGroupColorThemeParams export function getShapeGroupColorThemeParams(ctx: ThemeDataContext) { - return ShapeGroupColorThemeParams // TODO return copy + return ShapeGroupColorThemeParams; // TODO return copy } export function ShapeGroupColorTheme(ctx: ThemeDataContext, props: PD.Values<ShapeGroupColorThemeParams>): ColorTheme<ShapeGroupColorThemeParams> { @@ -26,13 +26,13 @@ export function ShapeGroupColorTheme(ctx: ThemeDataContext, props: PD.Values<Sha granularity: 'groupInstance', color: (location: Location): Color => { if (ShapeGroup.isLocation(location)) { - return location.shape.getColor(location.group, location.instance) + return location.shape.getColor(location.group, location.instance); } - return DefaultColor + return DefaultColor; }, props, description: Description - } + }; } export const ShapeGroupColorThemeProvider: ColorTheme.Provider<ShapeGroupColorThemeParams, 'shape-group'> = { @@ -43,4 +43,4 @@ export const ShapeGroupColorThemeProvider: ColorTheme.Provider<ShapeGroupColorTh getParams: getShapeGroupColorThemeParams, defaultValues: PD.getDefaultValues(ShapeGroupColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.shape -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/uncertainty.ts b/src/mol-theme/color/uncertainty.ts index ec9272e0afb06da80251fb50cd10e14fd2512cd0..0134a32c421ff3c474f7702d456ee4154a557ed4 100644 --- a/src/mol-theme/color/uncertainty.ts +++ b/src/mol-theme/color/uncertainty.ts @@ -8,28 +8,28 @@ import { Color, ColorScale } from '../../mol-util/color'; import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { ColorTheme } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; -const DefaultUncertaintyColor = Color(0xffff99) -const Description = `Assigns a color based on the uncertainty or disorder of an element's position, e.g. B-factor or RMSF, depending on the data availability and experimental technique.` +const DefaultUncertaintyColor = Color(0xffff99); +const Description = `Assigns a color based on the uncertainty or disorder of an element's position, e.g. B-factor or RMSF, depending on the data availability and experimental technique.`; export const UncertaintyColorThemeParams = { domain: PD.Interval([0, 100]), list: PD.ColorList('red-white-blue', { presetKind: 'scale' }), -} +}; export type UncertaintyColorThemeParams = typeof UncertaintyColorThemeParams export function getUncertaintyColorThemeParams(ctx: ThemeDataContext) { - return UncertaintyColorThemeParams // TODO return copy + return UncertaintyColorThemeParams; // TODO return copy } export function getUncertainty(unit: Unit, element: ElementIndex): number { if (Unit.isAtomic(unit)) { - return unit.model.atomicConformation.B_iso_or_equiv.value(element) + return unit.model.atomicConformation.B_iso_or_equiv.value(element); } else if (Unit.isSpheres(unit)) { - return unit.model.coarseConformation.spheres.rmsf[element] + return unit.model.coarseConformation.spheres.rmsf[element]; } else { - return 0 + return 0; } } @@ -38,17 +38,17 @@ export function UncertaintyColorTheme(ctx: ThemeDataContext, props: PD.Values<Un reverse: true, domain: props.domain, listOrName: props.list.colors, - }) + }); // TODO calc domain based on data, set min/max as 10/90 percentile to be robust against outliers function color(location: Location): Color { if (StructureElement.Location.is(location)) { - return scale.color(getUncertainty(location.unit, location.element)) + return scale.color(getUncertainty(location.unit, location.element)); } else if (Bond.isLocation(location)) { - return scale.color(getUncertainty(location.aUnit, location.aUnit.elements[location.aIndex])) + return scale.color(getUncertainty(location.aUnit, location.aUnit.elements[location.aIndex])); } - return DefaultUncertaintyColor + return DefaultUncertaintyColor; } return { @@ -58,7 +58,7 @@ export function UncertaintyColorTheme(ctx: ThemeDataContext, props: PD.Values<Un props, description: Description, legend: scale ? scale.legend : undefined - } + }; } export const UncertaintyColorThemeProvider: ColorTheme.Provider<UncertaintyColorThemeParams, 'uncertainty'> = { @@ -69,4 +69,4 @@ export const UncertaintyColorThemeProvider: ColorTheme.Provider<UncertaintyColor getParams: getUncertaintyColorThemeParams, defaultValues: PD.getDefaultValues(UncertaintyColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.models.some(m => m.atomicConformation.B_iso_or_equiv.isDefined || m.coarseHierarchy.isDefined) -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/uniform.ts b/src/mol-theme/color/uniform.ts index e86b5fbc0b2a84b77d8dbc9adccd42f38db9bc0d..a3cbb003e190aa7df0cb40b1e7db421baead14cc 100644 --- a/src/mol-theme/color/uniform.ts +++ b/src/mol-theme/color/uniform.ts @@ -6,24 +6,24 @@ import { ColorTheme } from '../color'; import { Color } from '../../mol-util/color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../theme'; import { TableLegend } from '../../mol-util/legend'; import { defaults } from '../../mol-util'; -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives everything the same, uniform color.' +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives everything the same, uniform color.'; export const UniformColorThemeParams = { value: PD.Color(DefaultColor), -} +}; export type UniformColorThemeParams = typeof UniformColorThemeParams export function getUniformColorThemeParams(ctx: ThemeDataContext) { - return UniformColorThemeParams // TODO return copy + return UniformColorThemeParams; // TODO return copy } export function UniformColorTheme(ctx: ThemeDataContext, props: PD.Values<UniformColorThemeParams>): ColorTheme<UniformColorThemeParams> { - const color = defaults(props.value, DefaultColor) + const color = defaults(props.value, DefaultColor); return { factory: UniformColorTheme, @@ -32,7 +32,7 @@ export function UniformColorTheme(ctx: ThemeDataContext, props: PD.Values<Unifor props: props, description: Description, legend: TableLegend([['uniform', color]]) - } + }; } export const UniformColorThemeProvider: ColorTheme.Provider<UniformColorThemeParams, 'uniform'> = { @@ -43,4 +43,4 @@ export const UniformColorThemeProvider: ColorTheme.Provider<UniformColorThemePar getParams: getUniformColorThemeParams, defaultValues: PD.getDefaultValues(UniformColorThemeParams), isApplicable: (ctx: ThemeDataContext) => true -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/color/unit-index.ts b/src/mol-theme/color/unit-index.ts index 0cf9463e5619bacda457352bca8d672ebd137265..54c5ef83588198bc97aaa0d4e8c45a6d1498ca1d 100644 --- a/src/mol-theme/color/unit-index.ts +++ b/src/mol-theme/color/unit-index.ts @@ -8,57 +8,57 @@ import { Color } from '../../mol-util/color'; import { Location } from '../../mol-model/location'; import { StructureElement, Bond } from '../../mol-model/structure'; import { ColorTheme, LocationColor } from '../color'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { getPaletteParams, getPalette } from '../../mol-util/color/palette'; import { TableLegend, ScaleLegend } from '../../mol-util/legend'; import { ColorLists, getColorListFromName } from '../../mol-util/color/lists'; -const DefaultList = 'dark-2' -const DefaultColor = Color(0xCCCCCC) -const Description = 'Gives every chain instance (single chain or collection of single elements) a unique color based on the position (index) of the chain in the list of chains in the structure.' +const DefaultList = 'dark-2'; +const DefaultColor = Color(0xCCCCCC); +const Description = 'Gives every chain instance (single chain or collection of single elements) a unique color based on the position (index) of the chain in the list of chains in the structure.'; export const UnitIndexColorThemeParams = { ...getPaletteParams({ type: 'colors', colorList: DefaultList }), -} +}; export type UnitIndexColorThemeParams = typeof UnitIndexColorThemeParams export function getUnitIndexColorThemeParams(ctx: ThemeDataContext) { - const params = PD.clone(UnitIndexColorThemeParams) + const params = PD.clone(UnitIndexColorThemeParams); if (ctx.structure) { if (ctx.structure.root.units.length > ColorLists[DefaultList].list.length) { - params.palette.defaultValue.name = 'colors' + params.palette.defaultValue.name = 'colors'; params.palette.defaultValue.params = { ...params.palette.defaultValue.params, list: { kind: 'interpolate', colors: getColorListFromName(DefaultList).list } - } + }; } } - return params + return params; } export function UnitIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<UnitIndexColorThemeParams>): ColorTheme<UnitIndexColorThemeParams> { - let color: LocationColor - let legend: ScaleLegend | TableLegend | undefined + let color: LocationColor; + let legend: ScaleLegend | TableLegend | undefined; if (ctx.structure) { - const { units } = ctx.structure.root - const palette = getPalette(units.length, props) - legend = palette.legend - const unitIdColor = new Map<number, Color>() + const { units } = ctx.structure.root; + const palette = getPalette(units.length, props); + legend = palette.legend; + const unitIdColor = new Map<number, Color>(); for (let i = 0, il = units.length; i < il; ++i) { - unitIdColor.set(units[i].id, palette.color(i)) + unitIdColor.set(units[i].id, palette.color(i)); } color = (location: Location): Color => { if (StructureElement.Location.is(location)) { - return unitIdColor.get(location.unit.id)! + return unitIdColor.get(location.unit.id)!; } else if (Bond.isLocation(location)) { - return unitIdColor.get(location.aUnit.id)! + return unitIdColor.get(location.aUnit.id)!; } - return DefaultColor - } + return DefaultColor; + }; } else { - color = () => DefaultColor + color = () => DefaultColor; } return { @@ -68,7 +68,7 @@ export function UnitIndexColorTheme(ctx: ThemeDataContext, props: PD.Values<Unit props, description: Description, legend - } + }; } export const UnitIndexColorThemeProvider: ColorTheme.Provider<UnitIndexColorThemeParams, 'unit-index'> = { @@ -79,4 +79,4 @@ export const UnitIndexColorThemeProvider: ColorTheme.Provider<UnitIndexColorThem getParams: getUnitIndexColorThemeParams, defaultValues: PD.getDefaultValues(UnitIndexColorThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/label.ts b/src/mol-theme/label.ts index 7152d13ea8dddd87bae874482aea6e02f1ebd9b7..6e78c59cca5fd7ac0883fba04ebdba61ff80b602 100644 --- a/src/mol-theme/label.ts +++ b/src/mol-theme/label.ts @@ -22,97 +22,97 @@ export const DefaultLabelOptions = { countsOnly: false, hidePrefix: false, htmlStyling: true, -} +}; export type LabelOptions = typeof DefaultLabelOptions export function lociLabel(loci: Loci, options: Partial<LabelOptions> = {}): string { switch (loci.kind) { case 'structure-loci': - return loci.structure.models.map(m => m.entry).filter(l => !!l).join(', ') + return loci.structure.models.map(m => m.entry).filter(l => !!l).join(', '); case 'element-loci': - return structureElementStatsLabel(StructureElement.Stats.ofLoci(loci), options) + return structureElementStatsLabel(StructureElement.Stats.ofLoci(loci), options); case 'bond-loci': - const bond = loci.bonds[0] - return bond ? bondLabel(bond) : '' + const bond = loci.bonds[0]; + return bond ? bondLabel(bond) : ''; case 'shape-loci': - return loci.shape.name + return loci.shape.name; case 'group-loci': - const g = loci.groups[0] - return g ? loci.shape.getLabel(OrderedSet.start(g.ids), g.instance) : '' + const g = loci.groups[0]; + return g ? loci.shape.getLabel(OrderedSet.start(g.ids), g.instance) : ''; case 'every-loci': - return 'Everything' + return 'Everything'; case 'empty-loci': - return 'Nothing' + return 'Nothing'; case 'data-loci': - return loci.getLabel() + return loci.getLabel(); } } function countLabel(count: number, label: string) { - return count === 1 ? `1 ${label}` : `${count} ${label}s` + return count === 1 ? `1 ${label}` : `${count} ${label}s`; } function otherLabel(count: number, location: StructureElement.Location, granularity: LabelGranularity, hidePrefix: boolean, reverse: boolean, condensed: boolean) { - return `${elementLabel(location, { granularity, hidePrefix, reverse, condensed })} <small>[+ ${countLabel(count - 1, `other ${capitalize(granularity)}`)}]</small>` + return `${elementLabel(location, { granularity, hidePrefix, reverse, condensed })} <small>[+ ${countLabel(count - 1, `other ${capitalize(granularity)}`)}]</small>`; } /** Gets residue count of the model chain segments the unit is a subset of */ function getResidueCount(unit: Unit.Atomic) { - const { elements, model } = unit - const { chainAtomSegments, residueAtomSegments } = model.atomicHierarchy - const elementStart = chainAtomSegments.offsets[chainAtomSegments.index[elements[0]]] - const elementEnd = chainAtomSegments.offsets[chainAtomSegments.index[elements[elements.length - 1]] + 1] - 1 - return residueAtomSegments.index[elementEnd] - residueAtomSegments.index[elementStart] + 1 + const { elements, model } = unit; + const { chainAtomSegments, residueAtomSegments } = model.atomicHierarchy; + const elementStart = chainAtomSegments.offsets[chainAtomSegments.index[elements[0]]]; + const elementEnd = chainAtomSegments.offsets[chainAtomSegments.index[elements[elements.length - 1]] + 1] - 1; + return residueAtomSegments.index[elementEnd] - residueAtomSegments.index[elementStart] + 1; } export function structureElementStatsLabel(stats: StructureElement.Stats, options: Partial<LabelOptions> = {}): string { - const o = { ...DefaultLabelOptions, ...options } - const label = _structureElementStatsLabel(stats, o.countsOnly, o.hidePrefix, o.condensed, o.reverse) - return o.htmlStyling ? label : stripTags(label) + const o = { ...DefaultLabelOptions, ...options }; + const label = _structureElementStatsLabel(stats, o.countsOnly, o.hidePrefix, o.condensed, o.reverse); + return o.htmlStyling ? label : stripTags(label); } function _structureElementStatsLabel(stats: StructureElement.Stats, countsOnly = false, hidePrefix = false, condensed = false, reverse = false): string { - const { structureCount, chainCount, residueCount, conformationCount, elementCount } = stats + const { structureCount, chainCount, residueCount, conformationCount, elementCount } = stats; if (!countsOnly && elementCount === 1 && residueCount === 0 && chainCount === 0) { - return elementLabel(stats.firstElementLoc, { hidePrefix, condensed, granularity: 'element', reverse }) + return elementLabel(stats.firstElementLoc, { hidePrefix, condensed, granularity: 'element', reverse }); } else if (!countsOnly && elementCount === 0 && residueCount === 1 && chainCount === 0) { - return elementLabel(stats.firstResidueLoc, { hidePrefix, condensed, granularity: 'residue', reverse }) + return elementLabel(stats.firstResidueLoc, { hidePrefix, condensed, granularity: 'residue', reverse }); } else if (!countsOnly && elementCount === 0 && residueCount === 0 && chainCount === 1) { - const { unit } = stats.firstChainLoc + const { unit } = stats.firstChainLoc; const granularity = (Unit.isAtomic(unit) && getResidueCount(unit) === 1) ? 'residue' : Unit.Traits.is(unit.traits, Unit.Trait.MultiChain) - ? 'residue' : 'chain' - return elementLabel(stats.firstChainLoc, { hidePrefix, condensed, granularity, reverse }) + ? 'residue' : 'chain'; + return elementLabel(stats.firstChainLoc, { hidePrefix, condensed, granularity, reverse }); } else if (!countsOnly) { - const label: string[] = [] + const label: string[] = []; if (structureCount > 0) { - label.push(structureCount === 1 ? elementLabel(stats.firstStructureLoc, { hidePrefix, condensed, granularity: 'structure', reverse }) : otherLabel(structureCount, stats.firstStructureLoc, 'structure', hidePrefix, reverse, condensed)) + label.push(structureCount === 1 ? elementLabel(stats.firstStructureLoc, { hidePrefix, condensed, granularity: 'structure', reverse }) : otherLabel(structureCount, stats.firstStructureLoc, 'structure', hidePrefix, reverse, condensed)); } if (chainCount > 0) { - label.push(chainCount === 1 ? elementLabel(stats.firstChainLoc, { condensed, granularity: 'chain', hidePrefix, reverse }) : otherLabel(chainCount, stats.firstChainLoc, 'chain', hidePrefix, reverse, condensed)) + label.push(chainCount === 1 ? elementLabel(stats.firstChainLoc, { condensed, granularity: 'chain', hidePrefix, reverse }) : otherLabel(chainCount, stats.firstChainLoc, 'chain', hidePrefix, reverse, condensed)); hidePrefix = true; } if (residueCount > 0) { - label.push(residueCount === 1 ? elementLabel(stats.firstResidueLoc, { condensed, granularity: 'residue', hidePrefix, reverse }) : otherLabel(residueCount, stats.firstResidueLoc, 'residue', hidePrefix, reverse, condensed)) + label.push(residueCount === 1 ? elementLabel(stats.firstResidueLoc, { condensed, granularity: 'residue', hidePrefix, reverse }) : otherLabel(residueCount, stats.firstResidueLoc, 'residue', hidePrefix, reverse, condensed)); hidePrefix = true; } if (conformationCount > 0) { - label.push(conformationCount === 1 ? elementLabel(stats.firstConformationLoc, { condensed, granularity: 'conformation', hidePrefix, reverse }) : otherLabel(conformationCount, stats.firstConformationLoc, 'conformation', hidePrefix, reverse, condensed)) + label.push(conformationCount === 1 ? elementLabel(stats.firstConformationLoc, { condensed, granularity: 'conformation', hidePrefix, reverse }) : otherLabel(conformationCount, stats.firstConformationLoc, 'conformation', hidePrefix, reverse, condensed)); hidePrefix = true; } if (elementCount > 0) { - label.push(elementCount === 1 ? elementLabel(stats.firstElementLoc, { condensed, granularity: 'element', hidePrefix, reverse }) : otherLabel(elementCount, stats.firstElementLoc, 'element', hidePrefix, reverse, condensed)) + label.push(elementCount === 1 ? elementLabel(stats.firstElementLoc, { condensed, granularity: 'element', hidePrefix, reverse }) : otherLabel(elementCount, stats.firstElementLoc, 'element', hidePrefix, reverse, condensed)); } - return label.join('<small> + </small>') + return label.join('<small> + </small>'); } else { - const label: string[] = [] - if (structureCount > 0) label.push(countLabel(structureCount, 'Structure')) - if (chainCount > 0) label.push(countLabel(chainCount, 'Chain')) - if (residueCount > 0) label.push(countLabel(residueCount, 'Residue')) - if (conformationCount > 0) label.push(countLabel(conformationCount, 'Conformation')) - if (elementCount > 0) label.push(countLabel(elementCount, 'Element')) - return label.join('<small> + </small>') + const label: string[] = []; + if (structureCount > 0) label.push(countLabel(structureCount, 'Structure')); + if (chainCount > 0) label.push(countLabel(chainCount, 'Chain')); + if (residueCount > 0) label.push(countLabel(residueCount, 'Residue')); + if (conformationCount > 0) label.push(countLabel(conformationCount, 'Conformation')); + if (elementCount > 0) label.push(countLabel(elementCount, 'Element')); + return label.join('<small> + </small>'); } } @@ -120,70 +120,70 @@ export function bondLabel(bond: Bond.Location, options: Partial<LabelOptions> = return bundleLabel({ loci: [ StructureElement.Loci(bond.aStructure, [{ unit: bond.aUnit, indices: OrderedSet.ofSingleton(bond.aIndex) }]), StructureElement.Loci(bond.bStructure, [{ unit: bond.bUnit, indices: OrderedSet.ofSingleton(bond.bIndex) }]) - ]}, options) + ]}, options); } export function bundleLabel(bundle: Loci.Bundle<any>, options: Partial<LabelOptions> = {}): string { - const o = { ...DefaultLabelOptions, ...options } - const label = _bundleLabel(bundle, o) - return o.htmlStyling ? label : stripTags(label) + const o = { ...DefaultLabelOptions, ...options }; + const label = _bundleLabel(bundle, o); + return o.htmlStyling ? label : stripTags(label); } export function _bundleLabel(bundle: Loci.Bundle<any>, options: LabelOptions) { - const { granularity, hidePrefix, reverse, condensed } = options + const { granularity, hidePrefix, reverse, condensed } = options; - let isSingleElements = true + let isSingleElements = true; for (const l of bundle.loci) { if (!StructureElement.Loci.is(l) || StructureElement.Loci.size(l) !== 1) { - isSingleElements = false - break + isSingleElements = false; + break; } } if (isSingleElements) { const locations = (bundle.loci as StructureElement.Loci[]).map(l => { - const { unit, indices } = l.elements[0] - return StructureElement.Location.create(l.structure, unit, unit.elements[OrderedSet.start(indices)]) - }) - const labels = locations.map(l => _elementLabel(l, granularity, hidePrefix, reverse || condensed)) + const { unit, indices } = l.elements[0]; + return StructureElement.Location.create(l.structure, unit, unit.elements[OrderedSet.start(indices)]); + }); + const labels = locations.map(l => _elementLabel(l, granularity, hidePrefix, reverse || condensed)); if (condensed) { - return labels.map(l => l[0].replace(/\[.*\]/g, '').trim()).filter(l => !!l).join(' \u2014 ') + return labels.map(l => l[0].replace(/\[.*\]/g, '').trim()).filter(l => !!l).join(' \u2014 '); } - let offset = 0 + let offset = 0; for (let i = 0, il = Math.min(...labels.map(l => l.length)); i < il; ++i) { - let areIdentical = true + let areIdentical = true; for (let j = 1, jl = labels.length; j < jl; ++j) { if (labels[0][i] !== labels[j][i]) { - areIdentical = false - break + areIdentical = false; + break; } } - if (areIdentical) offset += 1 - else break + if (areIdentical) offset += 1; + else break; } if (offset > 0) { - const offsetLabels = [labels[0].join(' | ')] + const offsetLabels = [labels[0].join(' | ')]; for (let j = 1, jl = labels.length; j < jl; ++j) { - offsetLabels.push(labels[j].slice(offset).filter(l => !!l).join(' | ')) + offsetLabels.push(labels[j].slice(offset).filter(l => !!l).join(' | ')); } - return offsetLabels.join(' \u2014 ') + return offsetLabels.join(' \u2014 '); } else { - return labels.map(l => l.filter(l => !!l).join(' | ')).filter(l => !!l).join('</br>') + return labels.map(l => l.filter(l => !!l).join(' | ')).filter(l => !!l).join('</br>'); } } else { - const labels = bundle.loci.map(l => lociLabel(l, options)) - return labels.filter(l => !!l).join(condensed ? ' \u2014 ' : '</br>') + const labels = bundle.loci.map(l => lociLabel(l, options)); + return labels.filter(l => !!l).join(condensed ? ' \u2014 ' : '</br>'); } } export function elementLabel(location: StructureElement.Location, options: Partial<LabelOptions> = {}): string { - const o = { ...DefaultLabelOptions, ...options } - const _label = _elementLabel(location, o.granularity, o.hidePrefix, o.reverse || o.condensed) - const label = o.condensed ? _label[0].replace(/\[.*\]/g, '').trim() : _label.filter(l => !!l).join(' | ') - return o.htmlStyling ? label : stripTags(label) + const o = { ...DefaultLabelOptions, ...options }; + const _label = _elementLabel(location, o.granularity, o.hidePrefix, o.reverse || o.condensed); + const label = o.condensed ? _label[0].replace(/\[.*\]/g, '').trim() : _label.filter(l => !!l).join(' | '); + return o.htmlStyling ? label : stripTags(label); } function _elementLabel(location: StructureElement.Location, granularity: LabelGranularity = 'element', hidePrefix = false, reverse = false): string[] { @@ -191,62 +191,62 @@ function _elementLabel(location: StructureElement.Location, granularity: LabelGr if (!hidePrefix) { let entry = location.unit.model.entry; if (entry.length > 30) entry = entry.substr(0, 27) + '\u2026'; // ellipsis - label.push(`<small>${entry}</small>`) // entry + label.push(`<small>${entry}</small>`); // entry if (granularity !== 'structure') { - label.push(`<small>Model ${location.unit.model.modelNum}</small>`) // model - label.push(`<small>Instance ${location.unit.conformation.operator.name}</small>`) // instance + label.push(`<small>Model ${location.unit.model.modelNum}</small>`); // model + label.push(`<small>Instance ${location.unit.conformation.operator.name}</small>`); // instance } } if (Unit.isAtomic(location.unit)) { - label.push(..._atomicElementLabel(location as StructureElement.Location<Unit.Atomic>, granularity, reverse)) + label.push(..._atomicElementLabel(location as StructureElement.Location<Unit.Atomic>, granularity, reverse)); } else if (Unit.isCoarse(location.unit)) { - label.push(..._coarseElementLabel(location as StructureElement.Location<Unit.Spheres | Unit.Gaussians>, granularity)) + label.push(..._coarseElementLabel(location as StructureElement.Location<Unit.Spheres | Unit.Gaussians>, granularity)); } else { - label.push('Unknown') + label.push('Unknown'); } - return reverse ? label.reverse() : label + return reverse ? label.reverse() : label; } function _atomicElementLabel(location: StructureElement.Location<Unit.Atomic>, granularity: LabelGranularity, hideOccupancy = false): string[] { const rI = StructureElement.Location.residueIndex(location); - const label_asym_id = Props.chain.label_asym_id(location) - const auth_asym_id = Props.chain.auth_asym_id(location) + const label_asym_id = Props.chain.label_asym_id(location); + const auth_asym_id = Props.chain.auth_asym_id(location); const has_label_seq_id = location.unit.model.atomicHierarchy.residues.label_seq_id.valueKind(rI) === Column.ValueKind.Present; - const label_seq_id = Props.residue.label_seq_id(location) - const auth_seq_id = Props.residue.auth_seq_id(location) - const ins_code = Props.residue.pdbx_PDB_ins_code(location) - const comp_id = Props.residue.label_comp_id(location) - const atom_id = Props.atom.label_atom_id(location) - const alt_id = Props.atom.label_alt_id(location) + const label_seq_id = Props.residue.label_seq_id(location); + const auth_seq_id = Props.residue.auth_seq_id(location); + const ins_code = Props.residue.pdbx_PDB_ins_code(location); + const comp_id = Props.residue.label_comp_id(location); + const atom_id = Props.atom.label_atom_id(location); + const alt_id = Props.atom.label_alt_id(location); const occupancy = Props.atom.occupancy(location); - const microHetCompIds = Props.residue.microheterogeneityCompIds(location) + const microHetCompIds = Props.residue.microheterogeneityCompIds(location); const compId = granularity === 'residue' && microHetCompIds.length > 1 ? - `(${microHetCompIds.join('|')})` : comp_id + `(${microHetCompIds.join('|')})` : comp_id; - const label: string[] = [] + const label: string[] = []; switch (granularity) { case 'element': - label.push(`<b>${atom_id}</b>${alt_id ? `%${alt_id}` : ''}`) + label.push(`<b>${atom_id}</b>${alt_id ? `%${alt_id}` : ''}`); case 'conformation': if (granularity === 'conformation' && alt_id) { - label.push(`<small>Conformation</small> <b>${alt_id}</b>`) + label.push(`<small>Conformation</small> <b>${alt_id}</b>`); } case 'residue': - const seq_id = label_seq_id === auth_seq_id || !has_label_seq_id ? auth_seq_id : label_seq_id - label.push(`<b>${compId} ${seq_id}</b>${seq_id !== auth_seq_id ? ` <small>[auth</small> <b>${auth_seq_id}</b><small>]</small>` : ''}<b>${ins_code ? ins_code : ''}</b>`) + const seq_id = label_seq_id === auth_seq_id || !has_label_seq_id ? auth_seq_id : label_seq_id; + label.push(`<b>${compId} ${seq_id}</b>${seq_id !== auth_seq_id ? ` <small>[auth</small> <b>${auth_seq_id}</b><small>]</small>` : ''}<b>${ins_code ? ins_code : ''}</b>`); case 'chain': if (label_asym_id === auth_asym_id) { - label.push(`<b>${label_asym_id}</b>`) + label.push(`<b>${label_asym_id}</b>`); } else { if (granularity === 'chain' && Unit.Traits.is(location.unit.traits, Unit.Trait.MultiChain)) { - label.push(`<small>[auth</small> <b>${auth_asym_id}</b><small>]</small>`) + label.push(`<small>[auth</small> <b>${auth_asym_id}</b><small>]</small>`); } else { - label.push(`<b>${label_asym_id}</b> <small>[auth</small> <b>${auth_asym_id}</b><small>]</small>`) + label.push(`<b>${label_asym_id}</b> <small>[auth</small> <b>${auth_asym_id}</b><small>]</small>`); } } } @@ -255,62 +255,62 @@ function _atomicElementLabel(location: StructureElement.Location<Unit.Atomic>, g label[0] = `${label[0]} <small>[occupancy</small> <b>${Math.round(100 * occupancy) / 100}</b><small>]</small>`; } - return label.reverse() + return label.reverse(); } function _coarseElementLabel(location: StructureElement.Location<Unit.Spheres | Unit.Gaussians>, granularity: LabelGranularity): string[] { - const asym_id = Props.coarse.asym_id(location) - const seq_id_begin = Props.coarse.seq_id_begin(location) - const seq_id_end = Props.coarse.seq_id_end(location) + const asym_id = Props.coarse.asym_id(location); + const seq_id_begin = Props.coarse.seq_id_begin(location); + const seq_id_end = Props.coarse.seq_id_end(location); - const label: string[] = [] + const label: string[] = []; switch (granularity) { case 'element': case 'conformation': case 'residue': if (seq_id_begin === seq_id_end) { - const entityIndex = Props.coarse.entityKey(location) - const seq = location.unit.model.sequence.byEntityKey[entityIndex] - const comp_id = seq.sequence.compId.value(seq_id_begin - 1) // 1-indexed - label.push(`<b>${comp_id} ${seq_id_begin}-${seq_id_end}</b>`) + const entityIndex = Props.coarse.entityKey(location); + const seq = location.unit.model.sequence.byEntityKey[entityIndex]; + const comp_id = seq.sequence.compId.value(seq_id_begin - 1); // 1-indexed + label.push(`<b>${comp_id} ${seq_id_begin}-${seq_id_end}</b>`); } else { - label.push(`<b>${seq_id_begin}-${seq_id_end}</b>`) + label.push(`<b>${seq_id_begin}-${seq_id_end}</b>`); } case 'chain': - label.push(`<b>${asym_id}</b>`) + label.push(`<b>${asym_id}</b>`); } - return label.reverse() + return label.reverse(); } // export function distanceLabel(pair: Loci.Bundle<2>, options: Partial<LabelOptions & { measureOnly: boolean, unitLabel: string }> = {}) { - const o = { ...DefaultLabelOptions, measureOnly: false, unitLabel: '\u212B', ...options } - const [cA, cB] = pair.loci.map(l => Loci.getCenter(l)!) - const distance = `${Vec3.distance(cA, cB).toFixed(2)} ${o.unitLabel}` - if (o.measureOnly) return distance - const label = bundleLabel(pair, o) - return o.condensed ? `${distance} | ${label}` : `Distance ${distance}</br>${label}` + const o = { ...DefaultLabelOptions, measureOnly: false, unitLabel: '\u212B', ...options }; + const [cA, cB] = pair.loci.map(l => Loci.getCenter(l)!); + const distance = `${Vec3.distance(cA, cB).toFixed(2)} ${o.unitLabel}`; + if (o.measureOnly) return distance; + const label = bundleLabel(pair, o); + return o.condensed ? `${distance} | ${label}` : `Distance ${distance}</br>${label}`; } export function angleLabel(triple: Loci.Bundle<3>, options: Partial<LabelOptions & { measureOnly: boolean }> = {}) { - const o = { ...DefaultLabelOptions, measureOnly: false, ...options } - const [cA, cB, cC] = triple.loci.map(l => Loci.getCenter(l)!) - const vAB = Vec3.sub(Vec3(), cA, cB) - const vCB = Vec3.sub(Vec3(), cC, cB) - const angle = `${radToDeg(Vec3.angle(vAB, vCB)).toFixed(2)}\u00B0` - if (o.measureOnly) return angle - const label = bundleLabel(triple, o) - return o.condensed ? `${angle} | ${label}` : `Angle ${angle}</br>${label}` + const o = { ...DefaultLabelOptions, measureOnly: false, ...options }; + const [cA, cB, cC] = triple.loci.map(l => Loci.getCenter(l)!); + const vAB = Vec3.sub(Vec3(), cA, cB); + const vCB = Vec3.sub(Vec3(), cC, cB); + const angle = `${radToDeg(Vec3.angle(vAB, vCB)).toFixed(2)}\u00B0`; + if (o.measureOnly) return angle; + const label = bundleLabel(triple, o); + return o.condensed ? `${angle} | ${label}` : `Angle ${angle}</br>${label}`; } export function dihedralLabel(quad: Loci.Bundle<4>, options: Partial<LabelOptions & { measureOnly: boolean }> = {}) { - const o = { ...DefaultLabelOptions, measureOnly: false, ...options } - const [cA, cB, cC, cD] = quad.loci.map(l => Loci.getCenter(l)!) - const dihedral = `${radToDeg(Vec3.dihedralAngle(cA, cB, cC, cD)).toFixed(2)}\u00B0` - if (o.measureOnly) return dihedral - const label = bundleLabel(quad, o) - return o.condensed ? `${dihedral} | ${label}` : `Dihedral ${dihedral}</br>${label}` + const o = { ...DefaultLabelOptions, measureOnly: false, ...options }; + const [cA, cB, cC, cD] = quad.loci.map(l => Loci.getCenter(l)!); + const dihedral = `${radToDeg(Vec3.dihedralAngle(cA, cB, cC, cD)).toFixed(2)}\u00B0`; + if (o.measureOnly) return dihedral; + const label = bundleLabel(quad, o); + return o.condensed ? `${dihedral} | ${label}` : `Dihedral ${dihedral}</br>${label}`; } \ No newline at end of file diff --git a/src/mol-theme/overpaint.ts b/src/mol-theme/overpaint.ts index 1263e585d327f68f68840e4d3a86f8b56498a90c..38d2cfc44043605526e54ee3163036eb75f86d35 100644 --- a/src/mol-theme/overpaint.ts +++ b/src/mol-theme/overpaint.ts @@ -9,120 +9,120 @@ import { Color } from '../mol-util/color'; import { Structure, StructureElement } from '../mol-model/structure'; import { Script } from '../mol-script/script'; -export { Overpaint } +export { Overpaint }; type Overpaint = { readonly layers: ReadonlyArray<Overpaint.Layer>, readonly alpha: number } function Overpaint(layers: ReadonlyArray<Overpaint.Layer>, alpha: number): Overpaint { - return { layers, alpha } + return { layers, alpha }; } namespace Overpaint { export type Layer = { readonly loci: StructureElement.Loci, readonly color: Color, readonly clear: boolean } - export const Empty: Overpaint = { layers: [], alpha: 1 } + export const Empty: Overpaint = { layers: [], alpha: 1 }; export function areEqual(oA: Overpaint, oB: Overpaint) { - if (oA.layers.length === 0 && oB.layers.length === 0) return true - if (oA.layers.length !== oB.layers.length) return false - if (oA.alpha !== oB.alpha) return false + if (oA.layers.length === 0 && oB.layers.length === 0) return true; + if (oA.layers.length !== oB.layers.length) return false; + if (oA.alpha !== oB.alpha) return false; for (let i = 0, il = oA.layers.length; i < il; ++i) { - if (oA.layers[i].clear !== oB.layers[i].clear) return false - if (oA.layers[i].color !== oB.layers[i].color) return false - if (!Loci.areEqual(oA.layers[i].loci, oB.layers[i].loci)) return false + if (oA.layers[i].clear !== oB.layers[i].clear) return false; + if (oA.layers[i].color !== oB.layers[i].color) return false; + if (!Loci.areEqual(oA.layers[i].loci, oB.layers[i].loci)) return false; } - return true + return true; } export function isEmpty(overpaint: Overpaint) { - return overpaint.layers.length === 0 + return overpaint.layers.length === 0; } export function remap(overpaint: Overpaint, structure: Structure) { - const layers: Overpaint.Layer[] = [] + const layers: Overpaint.Layer[] = []; for (const layer of overpaint.layers) { - let { loci, color, clear } = layer - loci = StructureElement.Loci.remap(loci, structure) + let { loci, color, clear } = layer; + loci = StructureElement.Loci.remap(loci, structure); if (!StructureElement.Loci.isEmpty(loci)) { - layers.push({ loci, color, clear }) + layers.push({ loci, color, clear }); } } - return { layers, alpha: overpaint.alpha } + return { layers, alpha: overpaint.alpha }; } export function merge(overpaint: Overpaint): Overpaint { - if (isEmpty(overpaint)) return overpaint - const { structure } = overpaint.layers[0].loci - const map = new Map<Color | -1, StructureElement.Loci>() - let shadowed = StructureElement.Loci.none(structure) + if (isEmpty(overpaint)) return overpaint; + const { structure } = overpaint.layers[0].loci; + const map = new Map<Color | -1, StructureElement.Loci>(); + let shadowed = StructureElement.Loci.none(structure); for (let i = 0, il = overpaint.layers.length; i < il; ++i) { - let { loci, color, clear } = overpaint.layers[il - i - 1] // process from end - loci = StructureElement.Loci.subtract(loci, shadowed) - shadowed = StructureElement.Loci.union(loci, shadowed) + let { loci, color, clear } = overpaint.layers[il - i - 1]; // process from end + loci = StructureElement.Loci.subtract(loci, shadowed); + shadowed = StructureElement.Loci.union(loci, shadowed); if (!StructureElement.Loci.isEmpty(loci)) { - const colorOrClear = clear ? -1 : color + const colorOrClear = clear ? -1 : color; if (map.has(colorOrClear)) { - loci = StructureElement.Loci.union(loci, map.get(colorOrClear)!) + loci = StructureElement.Loci.union(loci, map.get(colorOrClear)!); } - map.set(colorOrClear, loci) + map.set(colorOrClear, loci); } } - const layers: Overpaint.Layer[] = [] + const layers: Overpaint.Layer[] = []; map.forEach((loci, colorOrClear) => { - const clear = colorOrClear === -1 - const color = colorOrClear === -1 ? Color(0) : colorOrClear - layers.push({ loci, color, clear }) - }) - return { layers, alpha: overpaint.alpha } + const clear = colorOrClear === -1; + const color = colorOrClear === -1 ? Color(0) : colorOrClear; + layers.push({ loci, color, clear }); + }); + return { layers, alpha: overpaint.alpha }; } export function filter(overpaint: Overpaint, filter: Structure): Overpaint { - if (isEmpty(overpaint)) return overpaint - const { structure } = overpaint.layers[0].loci - const layers: Overpaint.Layer[] = [] + if (isEmpty(overpaint)) return overpaint; + const { structure } = overpaint.layers[0].loci; + const layers: Overpaint.Layer[] = []; for (const layer of overpaint.layers) { - let { loci, color, clear } = layer + let { loci, color, clear } = layer; // filter by first map to the `filter` structure and // then map back to the original structure of the overpaint loci - const filtered = StructureElement.Loci.remap(loci, filter) - loci = StructureElement.Loci.remap(filtered, structure) + const filtered = StructureElement.Loci.remap(loci, filter); + loci = StructureElement.Loci.remap(filtered, structure); if (!StructureElement.Loci.isEmpty(loci)) { - layers.push({ loci, color, clear }) + layers.push({ loci, color, clear }); } } - return { layers, alpha: overpaint.alpha } + return { layers, alpha: overpaint.alpha }; } export type ScriptLayer = { script: Script, color: Color, clear: boolean } export function ofScript(scriptLayers: ScriptLayer[], alpha: number, structure: Structure): Overpaint { - const layers: Overpaint.Layer[] = [] + const layers: Overpaint.Layer[] = []; for (let i = 0, il = scriptLayers.length; i < il; ++i) { - const { script, color, clear } = scriptLayers[i] - const loci = Script.toLoci(script, structure) + const { script, color, clear } = scriptLayers[i]; + const loci = Script.toLoci(script, structure); if (!StructureElement.Loci.isEmpty(loci)) { - layers.push({ loci, color, clear }) + layers.push({ loci, color, clear }); } } - return { layers, alpha } + return { layers, alpha }; } export type BundleLayer = { bundle: StructureElement.Bundle, color: Color, clear: boolean } export function ofBundle(bundleLayers: BundleLayer[], alpha: number, structure: Structure): Overpaint { - const layers: Overpaint.Layer[] = [] + const layers: Overpaint.Layer[] = []; for (let i = 0, il = bundleLayers.length; i < il; ++i) { - const { bundle, color, clear } = bundleLayers[i] - const loci = StructureElement.Bundle.toLoci(bundle, structure.root) - layers.push({ loci, color, clear }) + const { bundle, color, clear } = bundleLayers[i]; + const loci = StructureElement.Bundle.toLoci(bundle, structure.root); + layers.push({ loci, color, clear }); } - return { layers, alpha } + return { layers, alpha }; } export function toBundle(overpaint: Overpaint, alpha: number) { - const layers: BundleLayer[] = [] + const layers: BundleLayer[] = []; for (let i = 0, il = overpaint.layers.length; i < il; ++i) { - let { loci, color, clear } = overpaint.layers[i] - const bundle = StructureElement.Bundle.fromLoci(loci) - layers.push({ bundle, color, clear }) + let { loci, color, clear } = overpaint.layers[i]; + const bundle = StructureElement.Bundle.fromLoci(loci); + layers.push({ bundle, color, clear }); } - return { layers, alpha } + return { layers, alpha }; } } \ No newline at end of file diff --git a/src/mol-theme/size.ts b/src/mol-theme/size.ts index 748577ce3f33261838c8e1775bc51792a5b571af..c92a4199426ed13d4658a529a7526f84e9778bb2 100644 --- a/src/mol-theme/size.ts +++ b/src/mol-theme/size.ts @@ -13,7 +13,7 @@ import { deepEqual } from '../mol-util'; import { ShapeGroupSizeThemeProvider } from './size/shape-group'; import { UncertaintySizeThemeProvider } from './size/uncertainty'; -export { SizeTheme } +export { SizeTheme }; interface SizeTheme<P extends PD.Params> { readonly factory: SizeTheme.Factory<P> readonly granularity: SizeType @@ -24,19 +24,19 @@ interface SizeTheme<P extends PD.Params> { namespace SizeTheme { export type Props = { [k: string]: any } export type Factory<P extends PD.Params> = (ctx: ThemeDataContext, props: PD.Values<P>) => SizeTheme<P> - export const EmptyFactory = () => Empty - export const Empty: SizeTheme<{}> = { factory: EmptyFactory, granularity: 'uniform', size: () => 1, props: {} } + export const EmptyFactory = () => Empty; + export const Empty: SizeTheme<{}> = { factory: EmptyFactory, granularity: 'uniform', size: () => 1, props: {} }; export function areEqual(themeA: SizeTheme<any>, themeB: SizeTheme<any>) { - return themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props) + return themeA.factory === themeB.factory && deepEqual(themeA.props, themeB.props); } export interface Provider<P extends PD.Params = any, Id extends string = string> extends ThemeProvider<SizeTheme<P>, P, Id> { } - export const EmptyProvider: Provider<{}> = { name: '', label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true } + export const EmptyProvider: Provider<{}> = { name: '', label: '', category: '', factory: EmptyFactory, getParams: () => ({}), defaultValues: {}, isApplicable: () => true }; export type Registry = ThemeRegistry<SizeTheme<any>> export function createRegistry() { - return new ThemeRegistry(BuiltIn as { [k: string]: Provider<any> }, EmptyProvider) + return new ThemeRegistry(BuiltIn as { [k: string]: Provider<any> }, EmptyProvider); } export const BuiltIn = { @@ -44,7 +44,7 @@ namespace SizeTheme { 'shape-group': ShapeGroupSizeThemeProvider, 'uncertainty': UncertaintySizeThemeProvider, 'uniform': UniformSizeThemeProvider - } + }; type _BuiltIn = typeof BuiltIn export type BuiltIn = keyof _BuiltIn export type ParamValues<C extends SizeTheme.Provider<any>> = C extends SizeTheme.Provider<infer P> ? PD.Values<P> : never diff --git a/src/mol-theme/size/physical.ts b/src/mol-theme/size/physical.ts index 441c555c6a5be2f18b0d2105d223d75e358b2283..c75a06ea5b6413ed9b08924cd6b59ad471cc9e57 100644 --- a/src/mol-theme/size/physical.ts +++ b/src/mol-theme/size/physical.ts @@ -8,25 +8,25 @@ import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/stru import { Location } from '../../mol-model/location'; import { SizeTheme } from '../size'; import { VdwRadius } from '../../mol-model/structure/model/properties/atomic'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; -const DefaultSize = 1 -const Description = 'Assigns a physical size, i.e. vdW radius for atoms or given radius for coarse spheres.' +const DefaultSize = 1; +const Description = 'Assigns a physical size, i.e. vdW radius for atoms or given radius for coarse spheres.'; -export const PhysicalSizeThemeParams = {} +export const PhysicalSizeThemeParams = {}; export type PhysicalSizeThemeParams = typeof PhysicalSizeThemeParams export function getPhysicalSizeThemeParams(ctx: ThemeDataContext) { - return PhysicalSizeThemeParams // TODO return copy + return PhysicalSizeThemeParams; // TODO return copy } export function getPhysicalRadius(unit: Unit, element: ElementIndex): number { if (Unit.isAtomic(unit)) { - return VdwRadius(unit.model.atomicHierarchy.atoms.type_symbol.value(element)) + return VdwRadius(unit.model.atomicHierarchy.atoms.type_symbol.value(element)); } else if (Unit.isSpheres(unit)) { - return unit.model.coarseConformation.spheres.radius[element] + return unit.model.coarseConformation.spheres.radius[element]; } else { - return 0 + return 0; } } @@ -36,15 +36,15 @@ export function getPhysicalRadius(unit: Unit, element: ElementIndex): number { */ export function PhysicalSizeTheme(ctx: ThemeDataContext, props: PD.Values<PhysicalSizeThemeParams>): SizeTheme<PhysicalSizeThemeParams> { function size(location: Location): number { - let size: number + let size: number; if (StructureElement.Location.is(location)) { - size = getPhysicalRadius(location.unit, location.element) + size = getPhysicalRadius(location.unit, location.element); } else if (Bond.isLocation(location)) { - size = getPhysicalRadius(location.aUnit, location.aUnit.elements[location.aIndex]) + size = getPhysicalRadius(location.aUnit, location.aUnit.elements[location.aIndex]); } else { - size = DefaultSize + size = DefaultSize; } - return size + return size; } return { @@ -53,7 +53,7 @@ export function PhysicalSizeTheme(ctx: ThemeDataContext, props: PD.Values<Physic size, props, description: Description - } + }; } export const PhysicalSizeThemeProvider: SizeTheme.Provider<PhysicalSizeThemeParams, 'physical'> = { @@ -64,4 +64,4 @@ export const PhysicalSizeThemeProvider: SizeTheme.Provider<PhysicalSizeThemePara getParams: getPhysicalSizeThemeParams, defaultValues: PD.getDefaultValues(PhysicalSizeThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/size/shape-group.ts b/src/mol-theme/size/shape-group.ts index 9537c7bc5e95ea1010e5b9c256dff8bfed3fb53d..226d1c72a6afc361153a612c584b81289d88a1d4 100644 --- a/src/mol-theme/size/shape-group.ts +++ b/src/mol-theme/size/shape-group.ts @@ -6,17 +6,17 @@ import { Location } from '../../mol-model/location'; import { ShapeGroup } from '../../mol-model/shape'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; import { SizeTheme } from '../../mol-theme/size'; -const DefaultSize = 1 -const Description = 'Assigns sizes as defined by the shape object.' +const DefaultSize = 1; +const Description = 'Assigns sizes as defined by the shape object.'; -export const ShapeGroupSizeThemeParams = {} +export const ShapeGroupSizeThemeParams = {}; export type ShapeGroupSizeThemeParams = typeof ShapeGroupSizeThemeParams export function getShapeGroupSizeThemeParams(ctx: ThemeDataContext) { - return ShapeGroupSizeThemeParams // TODO return copy + return ShapeGroupSizeThemeParams; // TODO return copy } export function ShapeGroupSizeTheme(ctx: ThemeDataContext, props: PD.Values<ShapeGroupSizeThemeParams>): SizeTheme<ShapeGroupSizeThemeParams> { @@ -25,13 +25,13 @@ export function ShapeGroupSizeTheme(ctx: ThemeDataContext, props: PD.Values<Shap granularity: 'groupInstance', size: (location: Location): number => { if (ShapeGroup.isLocation(location)) { - return location.shape.getSize(location.group, location.instance) + return location.shape.getSize(location.group, location.instance); } - return DefaultSize + return DefaultSize; }, props, description: Description - } + }; } export const ShapeGroupSizeThemeProvider: SizeTheme.Provider<ShapeGroupSizeThemeParams, 'shape-group'> = { @@ -42,4 +42,4 @@ export const ShapeGroupSizeThemeProvider: SizeTheme.Provider<ShapeGroupSizeTheme getParams: getShapeGroupSizeThemeParams, defaultValues: PD.getDefaultValues(ShapeGroupSizeThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.shape -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/size/uncertainty.ts b/src/mol-theme/size/uncertainty.ts index 17d988096d37315551456eb2daf7b6798942bb45..1e042e8991bc4a3118c9ef432fbc4cfd021347e8 100644 --- a/src/mol-theme/size/uncertainty.ts +++ b/src/mol-theme/size/uncertainty.ts @@ -7,40 +7,40 @@ import { StructureElement, Unit, Bond, ElementIndex } from '../../mol-model/structure'; import { Location } from '../../mol-model/location'; import { SizeTheme } from '../size'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; -const Description = `Assigns a size reflecting the uncertainty or disorder of an element's position, e.g. B-factor or RMSF, depending on the data availability and experimental technique.` +const Description = `Assigns a size reflecting the uncertainty or disorder of an element's position, e.g. B-factor or RMSF, depending on the data availability and experimental technique.`; export const UncertaintySizeThemeParams = { bfactorFactor: PD.Numeric(0.1, { min: 0, max: 1, step: 0.01 }), rmsfFactor: PD.Numeric(0.05, { min: 0, max: 1, step: 0.01 }), baseSize: PD.Numeric(0.2, { min: 0, max: 2, step: 0.1 }), -} +}; export type UncertaintySizeThemeParams = typeof UncertaintySizeThemeParams export function getUncertaintySizeThemeParams(ctx: ThemeDataContext) { - return UncertaintySizeThemeParams // TODO return copy + return UncertaintySizeThemeParams; // TODO return copy } export function getUncertainty(unit: Unit, element: ElementIndex, props: PD.Values<UncertaintySizeThemeParams>): number { if (Unit.isAtomic(unit)) { - return unit.model.atomicConformation.B_iso_or_equiv.value(element) * props.bfactorFactor + return unit.model.atomicConformation.B_iso_or_equiv.value(element) * props.bfactorFactor; } else if (Unit.isSpheres(unit)) { - return unit.model.coarseConformation.spheres.rmsf[element] * props.rmsfFactor + return unit.model.coarseConformation.spheres.rmsf[element] * props.rmsfFactor; } else { - return 0 + return 0; } } export function UncertaintySizeTheme(ctx: ThemeDataContext, props: PD.Values<UncertaintySizeThemeParams>): SizeTheme<UncertaintySizeThemeParams> { function size(location: Location): number { - let size = props.baseSize + let size = props.baseSize; if (StructureElement.Location.is(location)) { - size += getUncertainty(location.unit, location.element, props) + size += getUncertainty(location.unit, location.element, props); } else if (Bond.isLocation(location)) { - size += getUncertainty(location.aUnit, location.aUnit.elements[location.aIndex], props) + size += getUncertainty(location.aUnit, location.aUnit.elements[location.aIndex], props); } - return size + return size; } return { @@ -49,7 +49,7 @@ export function UncertaintySizeTheme(ctx: ThemeDataContext, props: PD.Values<Unc size, props, description: Description - } + }; } export const UncertaintySizeThemeProvider: SizeTheme.Provider<UncertaintySizeThemeParams, 'uncertainty'> = { @@ -60,4 +60,4 @@ export const UncertaintySizeThemeProvider: SizeTheme.Provider<UncertaintySizeThe getParams: getUncertaintySizeThemeParams, defaultValues: PD.getDefaultValues(UncertaintySizeThemeParams), isApplicable: (ctx: ThemeDataContext) => !!ctx.structure && ctx.structure.models.some(m => m.atomicConformation.B_iso_or_equiv.isDefined || m.coarseHierarchy.isDefined) -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/size/uniform.ts b/src/mol-theme/size/uniform.ts index 05ca264927adc31f278cd044a4317e61e8b70c64..3bcbe98083e44cb3819fb973adae71c9f80ee656 100644 --- a/src/mol-theme/size/uniform.ts +++ b/src/mol-theme/size/uniform.ts @@ -5,21 +5,21 @@ */ import { SizeTheme } from '../size'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { ThemeDataContext } from '../../mol-theme/theme'; -const Description = 'Gives everything the same, uniform size.' +const Description = 'Gives everything the same, uniform size.'; export const UniformSizeThemeParams = { value: PD.Numeric(1, { min: 0, max: 20, step: 0.1 }), -} +}; export type UniformSizeThemeParams = typeof UniformSizeThemeParams export function getUniformSizeThemeParams(ctx: ThemeDataContext) { - return UniformSizeThemeParams // TODO return copy + return UniformSizeThemeParams; // TODO return copy } export function UniformSizeTheme(ctx: ThemeDataContext, props: PD.Values<UniformSizeThemeParams>): SizeTheme<UniformSizeThemeParams> { - const size = props.value + const size = props.value; return { factory: UniformSizeTheme, @@ -27,7 +27,7 @@ export function UniformSizeTheme(ctx: ThemeDataContext, props: PD.Values<Uniform size: () => size, props, description: Description - } + }; } export const UniformSizeThemeProvider: SizeTheme.Provider<UniformSizeThemeParams, 'uniform'> = { @@ -38,4 +38,4 @@ export const UniformSizeThemeProvider: SizeTheme.Provider<UniformSizeThemeParams getParams: getUniformSizeThemeParams, defaultValues: PD.getDefaultValues(UniformSizeThemeParams), isApplicable: (ctx: ThemeDataContext) => true -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/mol-theme/theme.ts b/src/mol-theme/theme.ts index bf5f3f6114e7abc6746d900860364f8e1d493d4f..83c4fe8bdf1826bab80d79a07853f6460171a738 100644 --- a/src/mol-theme/theme.ts +++ b/src/mol-theme/theme.ts @@ -25,7 +25,7 @@ export interface ThemeDataContext { shape?: Shape } -export { Theme } +export { Theme }; interface Theme { color: ColorTheme<any> @@ -37,29 +37,29 @@ namespace Theme { type Props = { [k: string]: any } export function create(ctx: ThemeRegistryContext, data: ThemeDataContext, props: Props, theme?: Theme) { - theme = theme || createEmpty() + theme = theme || createEmpty(); - const colorProps = props.colorTheme as PD.NamedParams - const sizeProps = props.sizeTheme as PD.NamedParams + const colorProps = props.colorTheme as PD.NamedParams; + const sizeProps = props.sizeTheme as PD.NamedParams; - theme.color = ctx.colorThemeRegistry.create(colorProps.name, data, colorProps.params) - theme.size = ctx.sizeThemeRegistry.create(sizeProps.name, data, sizeProps.params) + theme.color = ctx.colorThemeRegistry.create(colorProps.name, data, colorProps.params); + theme.size = ctx.sizeThemeRegistry.create(sizeProps.name, data, sizeProps.params); - return theme + return theme; } export function createEmpty(): Theme { - return { color: ColorTheme.Empty, size: SizeTheme.Empty } + return { color: ColorTheme.Empty, size: SizeTheme.Empty }; } export async function ensureDependencies(ctx: CustomProperty.Context, theme: ThemeRegistryContext, data: ThemeDataContext, props: Props) { - await theme.colorThemeRegistry.get(props.colorTheme.name).ensureCustomProperties?.attach(ctx, data) - await theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.attach(ctx, data) + await theme.colorThemeRegistry.get(props.colorTheme.name).ensureCustomProperties?.attach(ctx, data); + await theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.attach(ctx, data); } export function releaseDependencies(theme: ThemeRegistryContext, data: ThemeDataContext, props: Props) { - theme.colorThemeRegistry.get(props.colorTheme.name).ensureCustomProperties?.detach(data) - theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.detach(data) + theme.colorThemeRegistry.get(props.colorTheme.name).ensureCustomProperties?.detach(data); + theme.sizeThemeRegistry.get(props.sizeTheme.name).ensureCustomProperties?.detach(data); } } @@ -88,15 +88,15 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { private _map = new Map<string, ThemeProvider<T, any>>() private _name = new Map<ThemeProvider<T, any>, string>() - get default() { return this._list[0] } - get list() { return this._list } - get types(): [string, string, string][] { return getTypes(this._list) } + get default() { return this._list[0]; } + get list() { return this._list; } + get types(): [string, string, string][] { return getTypes(this._list); } constructor(builtInThemes: { [k: string]: ThemeProvider<T, any> }, private emptyProvider: ThemeProvider<T, any>) { objectForEach(builtInThemes, (p, k) => { if (p.name !== k) throw new Error(`Fix build in themes to have matching names. ${p.name} ${k}`); - this.add(p as any) - }) + this.add(p as any); + }); } private sort() { @@ -114,14 +114,14 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { } const name = provider.name; - this._list.push({ name, provider }) - this._map.set(name, provider) - this._name.set(provider, name) + this._list.push({ name, provider }); + this._map.set(name, provider); + this._name.set(provider, name); this.sort(); } remove(provider: ThemeProvider<T, any>) { - this._list.splice(this._list.findIndex(e => e.name === provider.name), 1) + this._list.splice(this._list.findIndex(e => e.name === provider.name), 1); const p = this._map.get(provider.name); if (p) { this._map.delete(provider.name); @@ -130,11 +130,11 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { } has(provider: ThemeProvider<T, any>): boolean { - return this._map.has(provider.name) + return this._map.has(provider.name); } get<P extends PD.Params>(name: string): ThemeProvider<T, P> { - return this._map.get(name) || this.emptyProvider + return this._map.get(name) || this.emptyProvider; } getName(provider: ThemeProvider<T, any>): string { @@ -144,8 +144,8 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { create(name: string, ctx: ThemeDataContext, props = {}) { - const provider = this.get(name) - return provider.factory(ctx, { ...PD.getDefaultValues(provider.getParams(ctx)), ...props }) + const provider = this.get(name); + return provider.factory(ctx, { ...PD.getDefaultValues(provider.getParams(ctx)), ...props }); } getApplicableList(ctx: ThemeDataContext) { @@ -153,6 +153,6 @@ export class ThemeRegistry<T extends ColorTheme<any> | SizeTheme<any>> { } getApplicableTypes(ctx: ThemeDataContext) { - return getTypes(this.getApplicableList(ctx)) + return getTypes(this.getApplicableList(ctx)); } } \ No newline at end of file diff --git a/src/mol-theme/transparency.ts b/src/mol-theme/transparency.ts index 8bf1032ca3c6946db889b2fc406d7c0efb63941a..4be6fb3889a07c6f2b76c71778f7a0bd544ec832 100644 --- a/src/mol-theme/transparency.ts +++ b/src/mol-theme/transparency.ts @@ -8,7 +8,7 @@ import { Loci, EmptyLoci } from '../mol-model/loci'; import { StructureElement, Structure } from '../mol-model/structure'; import { Script } from '../mol-script/script'; -export { Transparency } +export { Transparency }; interface Transparency { readonly loci: Loci @@ -18,20 +18,20 @@ interface Transparency { namespace Transparency { export type Variant = 'single' | 'multi' - export const Empty: Transparency = { loci: EmptyLoci, value: 0, variant: 'single' } + export const Empty: Transparency = { loci: EmptyLoci, value: 0, variant: 'single' }; export function areEqual(tA: Transparency, tB: Transparency) { - if (tA.value !== tB.value) return false - if (tA.variant !== tB.variant) return false - if (!Loci.areEqual(tA.loci, tB.loci)) return false - return true + if (tA.value !== tB.value) return false; + if (tA.variant !== tB.variant) return false; + if (!Loci.areEqual(tA.loci, tB.loci)) return false; + return true; } export function ofScript(script: Script, value: number, variant: Transparency.Variant, structure: Structure): Transparency { - return { loci: Script.toLoci(script, structure), value, variant } + return { loci: Script.toLoci(script, structure), value, variant }; } export function ofBundle(bundle: StructureElement.Bundle, value: number, variant: Transparency.Variant, structure: Structure): Transparency { - return { loci: StructureElement.Bundle.toLoci(bundle, structure), value, variant } + return { loci: StructureElement.Bundle.toLoci(bundle, structure), value, variant }; } } \ No newline at end of file diff --git a/src/mol-util/_spec/id-factory.spec.ts b/src/mol-util/_spec/id-factory.spec.ts index a5ad68bdd4fc6fa559a407d3e11299169a097797..7b7227cbf7098af06a0cc6c5173b33c7234e9d17 100644 --- a/src/mol-util/_spec/id-factory.spec.ts +++ b/src/mol-util/_spec/id-factory.spec.ts @@ -4,32 +4,32 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { idFactory } from '../id-factory' +import { idFactory } from '../id-factory'; describe('id-factory', () => { it('basic', () => { - const getNextId = idFactory() - expect(getNextId()).toBe(0) - expect(getNextId()).toBe(1) - }) + const getNextId = idFactory(); + expect(getNextId()).toBe(0); + expect(getNextId()).toBe(1); + }); it('start-id', () => { - const getNextId = idFactory(5) - expect(getNextId()).toBe(5) - expect(getNextId()).toBe(6) - }) + const getNextId = idFactory(5); + expect(getNextId()).toBe(5); + expect(getNextId()).toBe(6); + }); it('negative-start-id', () => { - const getNextId = idFactory(-1) - expect(getNextId()).toBe(-1) - expect(getNextId()).toBe(0) - }) + const getNextId = idFactory(-1); + expect(getNextId()).toBe(-1); + expect(getNextId()).toBe(0); + }); it('max-id', () => { - const getNextId = idFactory(0, 2) - expect(getNextId()).toBe(0) - expect(getNextId()).toBe(1) - expect(getNextId()).toBe(0) - expect(getNextId()).toBe(1) - }) + const getNextId = idFactory(0, 2); + expect(getNextId()).toBe(0); + expect(getNextId()).toBe(1); + expect(getNextId()).toBe(0); + expect(getNextId()).toBe(1); + }); }); \ No newline at end of file diff --git a/src/mol-util/_spec/monadic-parser.spec.ts b/src/mol-util/_spec/monadic-parser.spec.ts index 4268d627c1c2e3b12251d338327ecd65f5beb2cc..d30ea43484f82315877e7e215c9301d85376b2f4 100644 --- a/src/mol-util/_spec/monadic-parser.spec.ts +++ b/src/mol-util/_spec/monadic-parser.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { MonadicParser as P } from '../monadic-parser' +import { MonadicParser as P } from '../monadic-parser'; describe('parser', () => { it('string', () => { diff --git a/src/mol-util/_spec/reference-cache.spec.ts b/src/mol-util/_spec/reference-cache.spec.ts index 0dc3bf4b03d870ca162a5773a12e5ce438efdbd5..03e18da19e57d308059401f4cc112ad91ede2742 100644 --- a/src/mol-util/_spec/reference-cache.spec.ts +++ b/src/mol-util/_spec/reference-cache.spec.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { createReferenceCache } from '../reference-cache' +import { createReferenceCache } from '../reference-cache'; describe('reference-cache', () => { it('basic', () => { @@ -12,28 +12,28 @@ describe('reference-cache', () => { (x: number) => x.toString(), (x) => x, () => {} - ) - expect(refCache.count).toBe(0) + ); + expect(refCache.count).toBe(0); - const ref2a = refCache.get(2) - expect(refCache.count).toBe(1) + const ref2a = refCache.get(2); + expect(refCache.count).toBe(1); - const ref2b = refCache.get(2) - expect(refCache.count).toBe(1) - expect(ref2b.value).toBe(2) + const ref2b = refCache.get(2); + expect(refCache.count).toBe(1); + expect(ref2b.value).toBe(2); - const ref3 = refCache.get(3) - expect(refCache.count).toBe(2) - expect(ref3.value).toBe(3) + const ref3 = refCache.get(3); + expect(refCache.count).toBe(2); + expect(ref3.value).toBe(3); - ref2a.free() - refCache.clear() - expect(refCache.count).toBe(2) - ref2b.free() - refCache.clear() - expect(refCache.count).toBe(1) + ref2a.free(); + refCache.clear(); + expect(refCache.count).toBe(2); + ref2b.free(); + refCache.clear(); + expect(refCache.count).toBe(1); - refCache.dispose() - expect(refCache.count).toBe(0) - }) + refCache.dispose(); + expect(refCache.count).toBe(0); + }); }); \ No newline at end of file diff --git a/src/mol-util/_spec/string-builder.spec.ts b/src/mol-util/_spec/string-builder.spec.ts index bd0feb28b2d1fe634cca714740fe88c2b2a4e35d..227d0e1f3f2d4945e3a5977d2bc50bb775c7f72c 100644 --- a/src/mol-util/_spec/string-builder.spec.ts +++ b/src/mol-util/_spec/string-builder.spec.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import SB from '../string-builder' +import SB from '../string-builder'; describe('string-builder', () => { @@ -32,5 +32,5 @@ describe('string-builder', () => { expect(SB.getChunks(sb)).toEqual(['12', '3']); expect(SB.getString(sb)).toEqual('123'); - }) + }); }); \ No newline at end of file diff --git a/src/mol-util/_spec/zip.spec.ts b/src/mol-util/_spec/zip.spec.ts index 2ef6901d415caa9319dc671e5059db909d55db26..fd5708d9981db0008566fc10982d7f7dd358a156 100644 --- a/src/mol-util/_spec/zip.spec.ts +++ b/src/mol-util/_spec/zip.spec.ts @@ -4,23 +4,23 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { deflate, inflate, unzip, zip } from '../zip/zip' -import { SyncRuntimeContext } from '../../mol-task/execution/synchronous' +import { deflate, inflate, unzip, zip } from '../zip/zip'; +import { SyncRuntimeContext } from '../../mol-task/execution/synchronous'; describe('zip', () => { it('roundtrip deflate/inflate', async () => { - const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7]) - const deflated = deflate(data) - const inflated = await inflate(SyncRuntimeContext, deflated) - expect(inflated).toEqual(data) - }) + const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7]); + const deflated = deflate(data); + const inflated = await inflate(SyncRuntimeContext, deflated); + expect(inflated).toEqual(data); + }); it('roundtrip zip', async () => { const data = { 'test.foo': new Uint8Array([1, 2, 3, 4, 5, 6, 7]) - } - const zipped = zip(data) - const unzipped = await unzip(SyncRuntimeContext, zipped) - expect(unzipped).toEqual(data) - }) -}) \ No newline at end of file + }; + const zipped = zip(data); + const unzipped = await unzip(SyncRuntimeContext, zipped); + expect(unzipped).toEqual(data); + }); +}); \ No newline at end of file diff --git a/src/mol-util/array.ts b/src/mol-util/array.ts index 653df6aa22d329ed4b8ff54243d60f1f67189da2..88ca499497fc53499c253b251af9dfb01364efec 100644 --- a/src/mol-util/array.ts +++ b/src/mol-util/array.ts @@ -10,63 +10,63 @@ import { NumberArray } from './type-helpers'; /** Get the maximum value in an array */ export function arrayMax(array: ArrayLike<number>) { - let max = -Infinity + let max = -Infinity; for (let i = 0, il = array.length; i < il; ++i) { - if (array[i] > max) max = array[i] + if (array[i] > max) max = array[i]; } - return max + return max; } /** Get the minimum value in an array */ export function arrayMin(array: ArrayLike<number>) { - let min = Infinity + let min = Infinity; for (let i = 0, il = array.length; i < il; ++i) { - if (array[i] < min) min = array[i] + if (array[i] < min) min = array[i]; } - return min + return min; } /** Get the minimum & maximum value in an array */ export function arrayMinMax(array: ArrayLike<number>) { - let min = Infinity - let max = -Infinity + let min = Infinity; + let max = -Infinity; for (let i = 0, il = array.length; i < il; ++i) { - if (array[i] < min) min = array[i] - if (array[i] > max) max = array[i] + if (array[i] < min) min = array[i]; + if (array[i] > max) max = array[i]; } - return [min, max] + return [min, max]; } /** Get the sum of values in an array */ export function arraySum(array: ArrayLike<number>, stride = 1, offset = 0) { - const n = array.length - let sum = 0 + const n = array.length; + let sum = 0; for (let i = offset; i < n; i += stride) { - sum += array[i] + sum += array[i]; } - return sum + return sum; } /** Get the mean of values in an array */ export function arrayMean(array: ArrayLike<number>, stride = 1, offset = 0) { - return arraySum(array, stride, offset) / (array.length / stride) + return arraySum(array, stride, offset) / (array.length / stride); } /** Get the root mean square of values in an array */ export function arrayRms(array: ArrayLike<number>) { - const n = array.length - let sumSq = 0 + const n = array.length; + let sumSq = 0; for (let i = 0; i < n; ++i) { - const di = array[i] - sumSq += di * di + const di = array[i]; + sumSq += di * di; } - return Math.sqrt(sumSq / n) + return Math.sqrt(sumSq / n); } /** Fill an array with serial numbers starting from 0 until n - 1 (defaults to array.length) */ export function fillSerial<T extends NumberArray> (array: T, n?: number) { - for (let i = 0, il = n ? Math.min(n, array.length) : array.length; i < il; ++i) array[i] = i - return array + for (let i = 0, il = n ? Math.min(n, array.length) : array.length; i < il; ++i) array[i] = i; + return array; } export function arrayRemoveInPlace<T>(xs: T[], x: T) { diff --git a/src/mol-util/async-queue.ts b/src/mol-util/async-queue.ts index 2551fe58be781e8b4d7338b5519eaf1687ec38b7..ad2f72235589d793f6f0cabb5f828684643820ac 100644 --- a/src/mol-util/async-queue.ts +++ b/src/mol-util/async-queue.ts @@ -11,7 +11,7 @@ export class AsyncQueue<T> { private queue: T[] = []; private signal = new Subject<{ v: T, stillPresent: boolean }>(); - get length() { return this.queue.length } + get length() { return this.queue.length; } enqueue(v: T) { this.queue.push(v); @@ -29,7 +29,7 @@ export class AsyncQueue<T> { remove(v: T) { const rem = arrayRemoveInPlace(this.queue, v); if (rem) - this.signal.next({ v, stillPresent: false }) + this.signal.next({ v, stillPresent: false }); return rem; } @@ -41,6 +41,6 @@ export class AsyncQueue<T> { res(removed); } }); - }) + }); } } \ No newline at end of file diff --git a/src/mol-util/binding.ts b/src/mol-util/binding.ts index 407a6e772e869a7679cf2274ff1b8e3ed57cf437..3ca2e97da24ad2e4f94087fb2aef71ab9b8c5d80 100644 --- a/src/mol-util/binding.ts +++ b/src/mol-util/binding.ts @@ -7,7 +7,7 @@ import { ButtonsType, ModifiersKeys } from './input/input-observer'; import { interpolate, stringToWords } from './string'; -export { Binding } +export { Binding }; interface Binding { triggers: Binding.Trigger[] @@ -16,22 +16,22 @@ interface Binding { } function Binding(triggers: Binding.Trigger[], action = '', description = '') { - return Binding.create(triggers, action, description) + return Binding.create(triggers, action, description); } namespace Binding { export function create(triggers: Trigger[], action = '', description = ''): Binding { - return { triggers, action, description } + return { triggers, action, description }; } - export const Empty: Binding = { triggers: [], action: '', description: '' } + export const Empty: Binding = { triggers: [], action: '', description: '' }; export function isEmpty(binding: Binding) { return binding.triggers.length === 0 || - binding.triggers.every(t => t.buttons === undefined && t.modifiers === undefined) + binding.triggers.every(t => t.buttons === undefined && t.modifiers === undefined); } export function match(binding: Binding, buttons: ButtonsType, modifiers: ModifiersKeys) { - return binding.triggers.some(t => Trigger.match(t, buttons, modifiers)) + return binding.triggers.some(t => Trigger.match(t, buttons, modifiers)); } export function formatTriggers(binding: Binding) { @@ -39,8 +39,8 @@ namespace Binding { } export function format(binding: Binding, name = '') { - const help = binding.description || stringToWords(name) - return interpolate(help, { triggers: '<i>' + formatTriggers(binding) + '</i>' }) + const help = binding.description || stringToWords(name); + return interpolate(help, { triggers: '<i>' + formatTriggers(binding) + '</i>' }); } export interface Trigger { @@ -49,61 +49,61 @@ namespace Binding { } export function Trigger(buttons?: ButtonsType, modifiers?: ModifiersKeys) { - return Trigger.create(buttons, modifiers) + return Trigger.create(buttons, modifiers); } export namespace Trigger { export function create(buttons?: ButtonsType, modifiers?: ModifiersKeys): Trigger { - return { buttons, modifiers } + return { buttons, modifiers }; } - export const Empty: Trigger = {} + export const Empty: Trigger = {}; export function match(trigger: Trigger, buttons: ButtonsType, modifiers: ModifiersKeys): boolean { - const { buttons: b, modifiers: m } = trigger + const { buttons: b, modifiers: m } = trigger; return b !== undefined && (b === buttons || ButtonsType.has(b, buttons)) && - (!m || ModifiersKeys.areEqual(m, modifiers)) + (!m || ModifiersKeys.areEqual(m, modifiers)); } export function format(trigger: Trigger) { - const s: string[] = [] - const b = formatButtons(trigger.buttons) - if (b) s.push(b) - const m = formatModifiers(trigger.modifiers) - if (m) s.push(m) - return s.join(' + ') + const s: string[] = []; + const b = formatButtons(trigger.buttons); + if (b) s.push(b); + const m = formatModifiers(trigger.modifiers); + if (m) s.push(m); + return s.join(' + '); } } } -const B = ButtonsType +const B = ButtonsType; function formatButtons(buttons?: ButtonsType) { - const s: string[] = [] + const s: string[] = []; if (buttons === undefined) { - s.push('any mouse button') + s.push('any mouse button'); } else if (buttons === 0) { - s.push('mouse hover') + s.push('mouse hover'); } else { - if (B.has(buttons, B.Flag.Primary)) s.push('left mouse button') - if (B.has(buttons, B.Flag.Secondary)) s.push('right mouse button') - if (B.has(buttons, B.Flag.Auxilary)) s.push('wheel/middle mouse button') - if (B.has(buttons, B.Flag.Forth)) s.push('three fingers') + if (B.has(buttons, B.Flag.Primary)) s.push('left mouse button'); + if (B.has(buttons, B.Flag.Secondary)) s.push('right mouse button'); + if (B.has(buttons, B.Flag.Auxilary)) s.push('wheel/middle mouse button'); + if (B.has(buttons, B.Flag.Forth)) s.push('three fingers'); } - return s.join(' + ') + return s.join(' + '); } function formatModifiers(modifiers?: ModifiersKeys, verbose?: boolean) { - const s: string[] = [] + const s: string[] = []; if (modifiers) { - if (modifiers.alt) s.push('alt key') - if (modifiers.control) s.push('control key') - if (modifiers.meta) s.push('meta/command key') - if (modifiers.shift) s.push('shift key') + if (modifiers.alt) s.push('alt key'); + if (modifiers.control) s.push('control key'); + if (modifiers.meta) s.push('meta/command key'); + if (modifiers.shift) s.push('shift key'); - if (verbose && s.length === 0) s.push('no key') + if (verbose && s.length === 0) s.push('no key'); } else { - if (verbose) s.push('any key') + if (verbose) s.push('any key'); } - return s.join(' + ') + return s.join(' + '); } \ No newline at end of file diff --git a/src/mol-util/bit-flags.ts b/src/mol-util/bit-flags.ts index 2a76338f92d25dc047fee6abcfe769c07b5756f5..ae505f4973414795a3785a247266503d064082f9 100644 --- a/src/mol-util/bit-flags.ts +++ b/src/mol-util/bit-flags.ts @@ -14,4 +14,4 @@ namespace BitFlags { export function hasAll<F>(flags: BitFlags<F>, toCheck: BitFlags<F>) { return !!toCheck && ((flags as any) & (toCheck as any)) === (toCheck as any); } } -export default BitFlags \ No newline at end of file +export default BitFlags; \ No newline at end of file diff --git a/src/mol-util/color/color.ts b/src/mol-util/color/color.ts index fdd000edc5ce7c9eaea1e1916728577ba2fcc13f..05a451d108a1ff28be5d030d4e5e722d79cc3349 100644 --- a/src/mol-util/color/color.ts +++ b/src/mol-util/color/color.ts @@ -12,111 +12,111 @@ import { Lab } from './spaces/lab'; /** RGB color triplet expressed as a single number */ export type Color = { readonly '@type': 'color' } & number -export function Color(hex: number) { return hex as Color } +export function Color(hex: number) { return hex as Color; } export namespace Color { export function toStyle(hexColor: Color) { - return `rgb(${hexColor >> 16 & 255}, ${hexColor >> 8 & 255}, ${hexColor & 255})` + return `rgb(${hexColor >> 16 & 255}, ${hexColor >> 8 & 255}, ${hexColor & 255})`; } export function toHexString(hexColor: Color) { - return '0x' + ('000000' + hexColor.toString(16)).slice(-6) + return '0x' + ('000000' + hexColor.toString(16)).slice(-6); } export function toRgbString(hexColor: Color) { - return `RGB: ${Color.toRgb(hexColor).join(', ')}` + return `RGB: ${Color.toRgb(hexColor).join(', ')}`; } export function toRgb(hexColor: Color): [number, number, number] { - return [ hexColor >> 16 & 255, hexColor >> 8 & 255, hexColor & 255 ] + return [ hexColor >> 16 & 255, hexColor >> 8 & 255, hexColor & 255 ]; } export function toRgbNormalized(hexColor: Color): [number, number, number] { - return [ (hexColor >> 16 & 255) / 255, (hexColor >> 8 & 255) / 255, (hexColor & 255) / 255 ] + return [ (hexColor >> 16 & 255) / 255, (hexColor >> 8 & 255) / 255, (hexColor & 255) / 255 ]; } export function fromRgb(r: number, g: number, b: number): Color { - return ((r << 16) | (g << 8) | b) as Color + return ((r << 16) | (g << 8) | b) as Color; } export function fromNormalizedRgb(r: number, g: number, b: number): Color { - return (((r * 255) << 16) | ((g * 255) << 8) | (b * 255)) as Color + return (((r * 255) << 16) | ((g * 255) << 8) | (b * 255)) as Color; } export function fromArray(array: NumberArray, offset: number): Color { - return fromRgb(array[offset], array[offset + 1], array[offset + 2]) + return fromRgb(array[offset], array[offset + 1], array[offset + 2]); } export function fromNormalizedArray(array: NumberArray, offset: number): Color { - return fromNormalizedRgb(array[offset], array[offset + 1], array[offset + 2]) + return fromNormalizedRgb(array[offset], array[offset + 1], array[offset + 2]); } /** Copies hex color to rgb array */ export function toArray(hexColor: Color, array: NumberArray, offset: number) { - array[ offset ] = (hexColor >> 16 & 255) - array[ offset + 1 ] = (hexColor >> 8 & 255) - array[ offset + 2 ] = (hexColor & 255) - return array + array[ offset ] = (hexColor >> 16 & 255); + array[ offset + 1 ] = (hexColor >> 8 & 255); + array[ offset + 2 ] = (hexColor & 255); + return array; } /** Copies normalized (0 to 1) hex color to rgb array */ export function toArrayNormalized<T extends NumberArray>(hexColor: Color, array: T, offset: number) { - array[ offset ] = (hexColor >> 16 & 255) / 255 - array[ offset + 1 ] = (hexColor >> 8 & 255) / 255 - array[ offset + 2 ] = (hexColor & 255) / 255 - return array + array[ offset ] = (hexColor >> 16 & 255) / 255; + array[ offset + 1 ] = (hexColor >> 8 & 255) / 255; + array[ offset + 2 ] = (hexColor & 255) / 255; + return array; } /** Copies hex color to rgb vec3 */ export function toVec3(out: Vec3, hexColor: Color) { - out[0] = (hexColor >> 16 & 255) - out[1] = (hexColor >> 8 & 255) - out[2] = (hexColor & 255) - return out + out[0] = (hexColor >> 16 & 255); + out[1] = (hexColor >> 8 & 255); + out[2] = (hexColor & 255); + return out; } /** Copies normalized (0 to 1) hex color to rgb vec3 */ export function toVec3Normalized(out: Vec3, hexColor: Color) { - out[0] = (hexColor >> 16 & 255) / 255 - out[1] = (hexColor >> 8 & 255) / 255 - out[2] = (hexColor & 255) / 255 - return out + out[0] = (hexColor >> 16 & 255) / 255; + out[1] = (hexColor >> 8 & 255) / 255; + out[2] = (hexColor & 255) / 255; + return out; } /** Linear interpolation between two colors in rgb space */ export function interpolate(c1: Color, c2: Color, t: number): Color { - const r1 = c1 >> 16 & 255 - const g1 = c1 >> 8 & 255 - const b1 = c1 & 255 - const r2 = c2 >> 16 & 255 - const g2 = c2 >> 8 & 255 - const b2 = c2 & 255 + const r1 = c1 >> 16 & 255; + const g1 = c1 >> 8 & 255; + const b1 = c1 & 255; + const r2 = c2 >> 16 & 255; + const g2 = c2 >> 8 & 255; + const b2 = c2 & 255; - const r = r1 + (r2 - r1) * t - const g = g1 + (g2 - g1) * t - const b = b1 + (b2 - b1) * t + const r = r1 + (r2 - r1) * t; + const g = g1 + (g2 - g1) * t; + const b = b1 + (b2 - b1) * t; - return ((r << 16) | (g << 8) | b) as Color + return ((r << 16) | (g << 8) | b) as Color; } - const tmpSaturateHcl = [0, 0, 0] as Hcl + const tmpSaturateHcl = [0, 0, 0] as Hcl; export function saturate(c: Color, amount: number): Color { - Hcl.fromColor(tmpSaturateHcl, c) - return Hcl.toColor(Hcl.saturate(tmpSaturateHcl, tmpSaturateHcl, amount)) + Hcl.fromColor(tmpSaturateHcl, c); + return Hcl.toColor(Hcl.saturate(tmpSaturateHcl, tmpSaturateHcl, amount)); } export function desaturate(c: Color, amount: number): Color { - return saturate(c, -amount) + return saturate(c, -amount); } - const tmpDarkenLab = [0, 0, 0] as Lab + const tmpDarkenLab = [0, 0, 0] as Lab; export function darken(c: Color, amount: number): Color { - Lab.fromColor(tmpDarkenLab, c) - return Lab.toColor(Lab.darken(tmpDarkenLab, tmpDarkenLab, amount)) + Lab.fromColor(tmpDarkenLab, c); + return Lab.toColor(Lab.darken(tmpDarkenLab, tmpDarkenLab, amount)); } export function lighten(c: Color, amount: number): Color { - return darken(c, -amount) + return darken(c, -amount); } } @@ -127,24 +127,24 @@ export interface ColorList { type: 'sequential' | 'diverging' | 'qualitative' } export function ColorList(label: string, type: 'sequential' | 'diverging' | 'qualitative', description: string, list: number[]): ColorList { - return { label, description, list: list as Color[], type } + return { label, description, list: list as Color[], type }; } export type ColorTable<T extends { [k: string]: number[] }> = { [k in keyof T]: Color[] } -export function ColorTable<T extends { [k: string]: number[] }>(o: T) { return o as unknown as ColorTable<T> } +export function ColorTable<T extends { [k: string]: number[] }>(o: T) { return o as unknown as ColorTable<T>; } export type ColorMap<T extends { [k: string]: number }> = { [k in keyof T]: Color } -export function ColorMap<T extends { [k: string]: number }>(o: T) { return o as unknown as ColorMap<T> } +export function ColorMap<T extends { [k: string]: number }>(o: T) { return o as unknown as ColorMap<T>; } export function getAdjustedColorMap<T extends { [k: string]: number }>(map: ColorMap<T>, saturation: number, lightness: number) { - const adjustedMap: { [k: string]: Color } = {} + const adjustedMap: { [k: string]: Color } = {}; for (const e in map) { - let c = map[e] - c = Color.saturate(c, saturation) - c = Color.darken(c, -lightness) - adjustedMap[e] = c + let c = map[e]; + c = Color.saturate(c, saturation); + c = Color.darken(c, -lightness); + adjustedMap[e] = c; } - return adjustedMap as ColorMap<T> + return adjustedMap as ColorMap<T>; } export type ColorSwatch = [string, Color][] -export function ColorSwatch(l: [string, number][]) { return l as unknown as ColorSwatch } \ No newline at end of file +export function ColorSwatch(l: [string, number][]) { return l as unknown as ColorSwatch; } \ No newline at end of file diff --git a/src/mol-util/color/distinct.ts b/src/mol-util/color/distinct.ts index 693e576576c33fc78c9faffc9ced818e10872e55..94db4f9bbbe9338d70a6e25c0c4d4e281cd3b81e 100644 --- a/src/mol-util/color/distinct.ts +++ b/src/mol-util/color/distinct.ts @@ -12,7 +12,7 @@ import { Hcl } from './spaces/hcl'; import { deepClone } from '../../mol-util/object'; import { deepEqual } from '../../mol-util'; import { arraySum } from '../../mol-util/array'; -import { ParamDefinition as PD } from '../../mol-util/param-definition' +import { ParamDefinition as PD } from '../../mol-util/param-definition'; export const DistinctColorsParams = { hue: PD.Interval([1, 360], { min: 0, max: 360, step: 1 }), @@ -21,7 +21,7 @@ export const DistinctColorsParams = { clusteringStepCount: PD.Numeric(50, { min: 10, max: 200, step: 1 }, { isHidden: true }), minSampleCount: PD.Numeric(800, { min: 100, max: 5000, step: 100 }, { isHidden: true }) -} +}; export type DistinctColorsParams = typeof DistinctColorsParams export type DistinctColorsProps = PD.Values<typeof DistinctColorsParams> @@ -30,16 +30,16 @@ function distance(colorA: Lab, colorB: Lab) { Math.pow(Math.abs(colorA[0] - colorB[0]), 2) + Math.pow(Math.abs(colorA[1] - colorB[1]), 2) + Math.pow(Math.abs(colorA[2] - colorB[2]), 2) - ) + ); } -const LabTolerance = 2 -const tmpCheckColorHcl = [0, 0, 0] as Hcl -const tmpCheckColorLab = [0, 0, 0] as Lab +const LabTolerance = 2; +const tmpCheckColorHcl = [0, 0, 0] as Hcl; +const tmpCheckColorLab = [0, 0, 0] as Lab; function checkColor(lab: Lab, props: DistinctColorsProps) { - Lab.toHcl(tmpCheckColorHcl, lab) + Lab.toHcl(tmpCheckColorHcl, lab); // roundtrip to RGB for conversion tolerance testing - Lab.fromColor(tmpCheckColorLab, Lab.toColor(lab)) + Lab.fromColor(tmpCheckColorLab, Lab.toColor(lab)); return ( tmpCheckColorHcl[0] >= props.hue[0] && @@ -54,111 +54,111 @@ function checkColor(lab: Lab, props: DistinctColorsProps) { tmpCheckColorLab[1] <= (lab[1] + LabTolerance) && tmpCheckColorLab[2] >= (lab[2] - LabTolerance) && tmpCheckColorLab[2] <= (lab[2] + LabTolerance) - ) + ); } function sortByContrast(colors: Lab[]) { - const unsortedColors = colors.slice(0) - const sortedColors = [unsortedColors.shift()!] + const unsortedColors = colors.slice(0); + const sortedColors = [unsortedColors.shift()!]; while (unsortedColors.length > 0) { - const lastColor = sortedColors[sortedColors.length - 1] - let nearest = 0 - let maxDist = Number.MIN_SAFE_INTEGER + const lastColor = sortedColors[sortedColors.length - 1]; + let nearest = 0; + let maxDist = Number.MIN_SAFE_INTEGER; for (let i = 0; i < unsortedColors.length; ++i) { - const dist = distance(lastColor, unsortedColors[i]) + const dist = distance(lastColor, unsortedColors[i]); if (dist > maxDist) { - maxDist = dist - nearest = i + maxDist = dist; + nearest = i; } } - sortedColors.push(unsortedColors.splice(nearest, 1)[0]) + sortedColors.push(unsortedColors.splice(nearest, 1)[0]); } - return sortedColors + return sortedColors; } function getSamples(count: number, p: DistinctColorsProps) { - const samples = new Map<string, Lab>() - const rangeDivider = Math.cbrt(count) * 1.001 + const samples = new Map<string, Lab>(); + const rangeDivider = Math.cbrt(count) * 1.001; - const hStep = (p.hue[1] - p.hue[0]) / rangeDivider - const cStep = (p.chroma[1] - p.chroma[0]) / rangeDivider - const lStep = (p.luminance[1] - p.luminance[0]) / rangeDivider + const hStep = (p.hue[1] - p.hue[0]) / rangeDivider; + const cStep = (p.chroma[1] - p.chroma[0]) / rangeDivider; + const lStep = (p.luminance[1] - p.luminance[0]) / rangeDivider; for (let h = p.hue[0]; h <= p.hue[1]; h += hStep) { for (let c = p.chroma[0]; c <= p.chroma[1]; c += cStep) { for (let l = p.luminance[0]; l <= p.luminance[1]; l += lStep) { - const lab = Lab.fromHcl(Lab(), Hcl.create(h, c, l)) - if (checkColor(lab, p)) samples.set(lab.toString(), lab) + const lab = Lab.fromHcl(Lab(), Hcl.create(h, c, l)); + if (checkColor(lab, p)) samples.set(lab.toString(), lab); } } } - return Array.from(samples.values()) + return Array.from(samples.values()); } /** * Create a list of visually distinct colors */ export function distinctColors(count: number, props: Partial<DistinctColorsProps> = {}) { - const p = { ...PD.getDefaultValues(DistinctColorsParams), ...props } + const p = { ...PD.getDefaultValues(DistinctColorsParams), ...props }; - if (count <= 0) return [] + if (count <= 0) return []; - const samples = getSamples(Math.max(p.minSampleCount, count * 5), p) + const samples = getSamples(Math.max(p.minSampleCount, count * 5), p); if (samples.length < count) { - throw new Error('Not enough samples to generate distinct colors, increase sample count.') + throw new Error('Not enough samples to generate distinct colors, increase sample count.'); } - const colors: Lab[] = [] - const zonesProto: (Lab[])[] = [] - const sliceSize = Math.floor(samples.length / count) + const colors: Lab[] = []; + const zonesProto: (Lab[])[] = []; + const sliceSize = Math.floor(samples.length / count); for (let i = 0; i < samples.length; i += sliceSize) { - colors.push(samples[i]) - zonesProto.push([]) - if (colors.length >= count) break + colors.push(samples[i]); + zonesProto.push([]); + if (colors.length >= count) break; } for (let step = 1; step <= p.clusteringStepCount; ++step) { - const zones = deepClone(zonesProto) + const zones = deepClone(zonesProto); // Find closest color for each sample for (let i = 0; i < samples.length; ++i) { - let minDist = Number.MAX_SAFE_INTEGER - let nearest = 0 + let minDist = Number.MAX_SAFE_INTEGER; + let nearest = 0; for (let j = 0; j < colors.length; j++) { - const dist = distance(samples[i], colors[j]) + const dist = distance(samples[i], colors[j]); if (dist < minDist) { - minDist = dist - nearest = j + minDist = dist; + nearest = j; } } - zones[nearest].push(samples[i]) + zones[nearest].push(samples[i]); } - const lastColors = deepClone(colors) + const lastColors = deepClone(colors); for (let i = 0; i < zones.length; ++i) { - const zone = zones[i] - const size = zone.length - const Ls: number[] = [] - const As: number[] = [] - const Bs: number[] = [] + const zone = zones[i]; + const size = zone.length; + const Ls: number[] = []; + const As: number[] = []; + const Bs: number[] = []; for (let sample of zone) { - Ls.push(sample[0]) - As.push(sample[1]) - Bs.push(sample[2]) + Ls.push(sample[0]); + As.push(sample[1]); + Bs.push(sample[2]); } - const lAvg = arraySum(Ls) / size - const aAvg = arraySum(As) / size - const bAvg = arraySum(Bs) / size + const lAvg = arraySum(Ls) / size; + const aAvg = arraySum(As) / size; + const bAvg = arraySum(Bs) / size; - colors[i] = [lAvg, aAvg, bAvg] as Lab + colors[i] = [lAvg, aAvg, bAvg] as Lab; } - if (deepEqual(lastColors, colors)) break + if (deepEqual(lastColors, colors)) break; } - return sortByContrast(colors).map(c => Lab.toColor(c)) + return sortByContrast(colors).map(c => Lab.toColor(c)); } \ No newline at end of file diff --git a/src/mol-util/color/lists.ts b/src/mol-util/color/lists.ts index c625ac2e9cb71719b06115047477fc7c92722ba5..4d2dc82958b75d21c0d6ad76c541c3b5e594f5a4 100644 --- a/src/mol-util/color/lists.ts +++ b/src/mol-util/color/lists.ts @@ -202,17 +202,17 @@ export const ColorLists = { '', [ 0xBF2222, 0xFFFFFF, 0x3361E1 ] ), -} +}; export type ColorListName = keyof typeof ColorLists -export const ColorListNames = Object.keys(ColorLists) -export const ColorListOptions = ColorListNames.map(n => [n, ColorLists[n as ColorListName].label, capitalize(ColorLists[n as ColorListName].type)] as [ColorListName, string, string]) +export const ColorListNames = Object.keys(ColorLists); +export const ColorListOptions = ColorListNames.map(n => [n, ColorLists[n as ColorListName].label, capitalize(ColorLists[n as ColorListName].type)] as [ColorListName, string, string]); -export const ColorListOptionsScale = ColorListOptions.filter(v => ColorLists[v[0]].type === 'diverging' || ColorLists[v[0]].type === 'sequential') -export const ColorListOptionsSet = ColorListOptions.filter(v => ColorLists[v[0]].type === 'qualitative') +export const ColorListOptionsScale = ColorListOptions.filter(v => ColorLists[v[0]].type === 'diverging' || ColorLists[v[0]].type === 'sequential'); +export const ColorListOptionsSet = ColorListOptions.filter(v => ColorLists[v[0]].type === 'qualitative'); export function getColorListFromName(name: ColorListName) { - if (name in ColorLists) return ColorLists[name as ColorListName] - console.warn(`unknown color list named '${name}'`) - return ColorLists['red-yellow-blue'] + if (name in ColorLists) return ColorLists[name as ColorListName]; + console.warn(`unknown color list named '${name}'`); + return ColorLists['red-yellow-blue']; } diff --git a/src/mol-util/color/names.ts b/src/mol-util/color/names.ts index 83730283e240fea8d448b2195423248de23fd4e1..f9c5e9feb49036b7f04b60e3ecdfe5cb05c2277a 100644 --- a/src/mol-util/color/names.ts +++ b/src/mol-util/color/names.ts @@ -163,13 +163,13 @@ export const ColorNames = ColorMap({ whitesmoke: 0xf5f5f5, yellow: 0xffff00, yellowgreen: 0x9acd32 -}) +}); export type ColorNames = typeof ColorNames export type ColorName = keyof ColorNames export const ColorNamesValueMap = (function() { - const map = new Map<Color, ColorName>() + const map = new Map<Color, ColorName>(); Object.keys(ColorNames).forEach(name => { - map.set(ColorNames[name as ColorName], name as ColorName) - }) - return map -})() + map.set(ColorNames[name as ColorName], name as ColorName); + }); + return map; +})(); diff --git a/src/mol-util/color/palette.ts b/src/mol-util/color/palette.ts index 6123d2f3bf5b2cbbbb239655a57a1a854b1e6802..5eab403a7fbda4216db122cfc0d7357563f31a13 100644 --- a/src/mol-util/color/palette.ts +++ b/src/mol-util/color/palette.ts @@ -17,17 +17,17 @@ type PaletteType = 'generate' | 'colors' const DefaultGetPaletteProps = { type: 'generate' as PaletteType, colorList: 'red-yellow-blue' as ColorListName -} +}; type GetPaletteProps = typeof DefaultGetPaletteProps const LabelParams = { valueLabel: PD.Value((i: number) => `${i + 1}`, { isHidden: true }), minLabel: PD.Value('Start', { isHidden: true }), maxLabel: PD.Value('End', { isHidden: true }) -} +}; export function getPaletteParams(props: Partial<GetPaletteProps> = {}) { - const p = { ...DefaultGetPaletteProps, ...props } + const p = { ...DefaultGetPaletteProps, ...props }; return { palette: PD.MappedStatic(p.type, { colors: PD.Group({ @@ -45,10 +45,10 @@ export function getPaletteParams(props: Partial<GetPaletteProps> = {}) { ['generate', 'Generate Distinct'] ] }) - } + }; } -const DefaultPaletteProps = PD.getDefaultValues(getPaletteParams()) +const DefaultPaletteProps = PD.getDefaultValues(getPaletteParams()); type PaletteProps = typeof DefaultPaletteProps export interface Palette { @@ -57,42 +57,42 @@ export interface Palette { } export function getPalette(count: number, props: PaletteProps) { - let color: (i: number) => Color - let legend: ScaleLegend | TableLegend | undefined + let color: (i: number) => Color; + let legend: ScaleLegend | TableLegend | undefined; if (props.palette.name === 'colors' && props.palette.params.list.kind === 'interpolate') { - const { list, minLabel, maxLabel } = props.palette.params - const domain: [number, number] = [0, count - 1] + const { list, minLabel, maxLabel } = props.palette.params; + const domain: [number, number] = [0, count - 1]; let colors = list.colors; - if (colors.length === 0) colors = getColorListFromName(DefaultGetPaletteProps.colorList).list + if (colors.length === 0) colors = getColorListFromName(DefaultGetPaletteProps.colorList).list; - const scale = ColorScale.create({ listOrName: colors, domain, minLabel, maxLabel }) - legend = scale.legend - color = scale.color + const scale = ColorScale.create({ listOrName: colors, domain, minLabel, maxLabel }); + legend = scale.legend; + color = scale.color; } else { - let colors: Color[] + let colors: Color[]; if (props.palette.name === 'colors') { colors = props.palette.params.list.colors; - if (colors.length === 0) colors = getColorListFromName('dark-2').list + if (colors.length === 0) colors = getColorListFromName('dark-2').list; } else { - count = Math.min(count, props.palette.params.maxCount) - colors = distinctColors(count, props.palette.params) + count = Math.min(count, props.palette.params.maxCount); + colors = distinctColors(count, props.palette.params); } const valueLabel = props.palette.params.valueLabel || (i => '' + i); - const colorsLength = colors.length - const table: [string, Color][] = [] + const colorsLength = colors.length; + const table: [string, Color][] = []; for (let i = 0; i < count; ++i) { - const j = i % colorsLength + const j = i % colorsLength; if (table[j] === undefined) { - table[j] = [valueLabel(i), colors[j]] + table[j] = [valueLabel(i), colors[j]]; } else { - table[j][0] += `, ${valueLabel(i)}` + table[j][0] += `, ${valueLabel(i)}`; } } - legend = TableLegend(table) - color = (i: number) => colors[i % colorsLength] + legend = TableLegend(table); + color = (i: number) => colors[i % colorsLength]; } - return { color, legend } + return { color, legend }; } \ No newline at end of file diff --git a/src/mol-util/color/scale.ts b/src/mol-util/color/scale.ts index 9745506ae6e6278337d174602869d14857261ccf..29bc97dd76c44be9b357574df36a3aa5e0245586 100644 --- a/src/mol-util/color/scale.ts +++ b/src/mol-util/color/scale.ts @@ -4,8 +4,8 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { Color } from './color' -import { getColorListFromName, ColorListName } from './lists' +import { Color } from './color'; +import { getColorListFromName, ColorListName } from './lists'; import { defaults } from '../../mol-util'; import { NumberArray } from '../../mol-util/type-helpers'; import { ScaleLegend } from '../legend'; @@ -29,45 +29,45 @@ export const DefaultColorScaleProps = { listOrName: 'red-yellow-blue' as Color[] | ColorListName, minLabel: '' as string | undefined, maxLabel: '' as string | undefined, -} +}; export type ColorScaleProps = Partial<typeof DefaultColorScaleProps> export namespace ColorScale { export function create(props: ColorScaleProps): ColorScale { - const { domain, reverse, listOrName } = { ...DefaultColorScaleProps, ...props } - const list = typeof listOrName === 'string' ? getColorListFromName(listOrName).list : listOrName + const { domain, reverse, listOrName } = { ...DefaultColorScaleProps, ...props }; + const list = typeof listOrName === 'string' ? getColorListFromName(listOrName).list : listOrName; - const colors = reverse ? list.slice().reverse() : list - const count1 = colors.length - 1 + const colors = reverse ? list.slice().reverse() : list; + const count1 = colors.length - 1; - let diff = 0, min = 0, max = 0 + let diff = 0, min = 0, max = 0; function setDomain(_min: number, _max: number) { - min = _min - max = _max - diff = (max - min) || 1 + min = _min; + max = _max; + diff = (max - min) || 1; } - setDomain(domain[0], domain[1]) + setDomain(domain[0], domain[1]); - const minLabel = defaults(props.minLabel, min.toString()) - const maxLabel = defaults(props.maxLabel, max.toString()) + const minLabel = defaults(props.minLabel, min.toString()); + const maxLabel = defaults(props.maxLabel, max.toString()); function color(value: number) { - const t = Math.min(colors.length - 1, Math.max(0, ((value - min) / diff) * count1)) - const tf = Math.floor(t) - const c1 = colors[tf] - const c2 = colors[Math.ceil(t)] - return Color.interpolate(c1, c2, t - tf) + const t = Math.min(colors.length - 1, Math.max(0, ((value - min) / diff) * count1)); + const tf = Math.floor(t); + const c1 = colors[tf]; + const c2 = colors[Math.ceil(t)]; + return Color.interpolate(c1, c2, t - tf); } return { color, colorToArray: (value: number, array: NumberArray, offset: number) => { - Color.toArray(color(value), array, offset) + Color.toArray(color(value), array, offset); }, normalizedColorToArray: (value: number, array: NumberArray, offset: number) => { - Color.toArrayNormalized(color(value), array, offset) + Color.toArrayNormalized(color(value), array, offset); }, setDomain, - get legend() { return ScaleLegend(minLabel, maxLabel, colors) } - } + get legend() { return ScaleLegend(minLabel, maxLabel, colors); } + }; } } diff --git a/src/mol-util/color/spaces/hcl.ts b/src/mol-util/color/spaces/hcl.ts index 266d70376aa4e8a4de0335515358116d164a8cfa..a6978817108f8081c2e5d23fea051a366fb0a571 100644 --- a/src/mol-util/color/spaces/hcl.ts +++ b/src/mol-util/color/spaces/hcl.ts @@ -11,7 +11,7 @@ import { Color } from '../color'; import { degToRad } from '../../../mol-math/misc'; import { Lab } from './lab'; -export { Hcl } +export { Hcl }; interface Hcl extends Array<number> { [d: number]: number, '@type': 'hcl', length: 3 } @@ -25,36 +25,36 @@ interface Hcl extends Array<number> { [d: number]: number, '@type': 'hcl', lengt * Cylindrical representation of CIELUV (see https://en.wikipedia.org/wiki/CIELUV) */ function Hcl() { - return Hcl.zero() + return Hcl.zero(); } namespace Hcl { export function zero(): Hcl { - const out = [0.1, 0.0, 0.0] - out[0] = 0 + const out = [0.1, 0.0, 0.0]; + out[0] = 0; return out as Hcl; } export function create(h: number, c: number, l: number): Hcl { - const out = zero() - out[0] = h - out[1] = c - out[2] = l - return out + const out = zero(); + out[0] = h; + out[1] = c; + out[2] = l; + return out; } - const tmpFromColorLab = [0, 0, 0] as Lab + const tmpFromColorLab = [0, 0, 0] as Lab; export function fromColor(out: Hcl, color: Color): Hcl { - return Lab.toHcl(out, Lab.fromColor(tmpFromColorLab, color)) + return Lab.toHcl(out, Lab.fromColor(tmpFromColorLab, color)); } export function fromLab(hcl: Hcl, lab: Lab): Hcl { - return Lab.toHcl(hcl, lab) + return Lab.toHcl(hcl, lab); } - const tmpToColorLab = [0, 0, 0] as Lab + const tmpToColorLab = [0, 0, 0] as Lab; export function toColor(hcl: Hcl): Color { - return Lab.toColor(toLab(tmpToColorLab, hcl)) + return Lab.toColor(toLab(tmpToColorLab, hcl)); } /** @@ -65,43 +65,43 @@ namespace Hcl { * A saturation multiplier was added by Gregor Aisch */ export function toLab(out: Lab, hcl: Hcl): Lab { - let [h, c, l] = hcl - if (isNaN(h)) h = 0 - h = degToRad(h) - out[0] = l - out[1] = Math.cos(h) * c - out[2] = Math.sin(h) * c - return out + let [h, c, l] = hcl; + if (isNaN(h)) h = 0; + h = degToRad(h); + out[0] = l; + out[1] = Math.cos(h) * c; + out[2] = Math.sin(h) * c; + return out; } export function copy(out: Hcl, c: Hcl): Hcl { - out[0] = c[0] - out[1] = c[1] - out[2] = c[2] - return out + out[0] = c[0]; + out[1] = c[1]; + out[2] = c[2]; + return out; } export function saturate(out: Hcl, c: Hcl, amount: number): Hcl { - out[0] = c[0] - out[1] = Math.max(0, c[1] + Kn * amount) - out[2] = c[2] - return out + out[0] = c[0]; + out[1] = Math.max(0, c[1] + Kn * amount); + out[2] = c[2]; + return out; } export function desaturate(out: Hcl, c: Hcl, amount: number): Hcl { - return saturate(out, c, -amount) + return saturate(out, c, -amount); } - const tmpDarkenLab = [0, 0, 0] as Lab + const tmpDarkenLab = [0, 0, 0] as Lab; export function darken(out: Hcl, c: Hcl, amount: number): Hcl { - toLab(tmpDarkenLab, c) - return Lab.toHcl(out, Lab.darken(tmpDarkenLab, tmpDarkenLab, amount)) + toLab(tmpDarkenLab, c); + return Lab.toHcl(out, Lab.darken(tmpDarkenLab, tmpDarkenLab, amount)); } export function lighten(out: Hcl, c: Hcl, amount: number): Hcl { - return darken(out, c, -amount) + return darken(out, c, -amount); } // Corresponds roughly to RGB brighter/darker - const Kn = 18 + const Kn = 18; } \ No newline at end of file diff --git a/src/mol-util/color/spaces/lab.ts b/src/mol-util/color/spaces/lab.ts index 856e744b1c6856cca32697369c764745243a9b62..1b97c8987aca4abc820af2d24d449101149789b5 100644 --- a/src/mol-util/color/spaces/lab.ts +++ b/src/mol-util/color/spaces/lab.ts @@ -12,7 +12,7 @@ import { Hcl } from './hcl'; import { radToDeg } from '../../../mol-math/misc'; import { clamp } from '../../../mol-math/interpolate'; -export { Lab } +export { Lab }; interface Lab extends Array<number> { [d: number]: number, '@type': 'lab', length: 3 } @@ -26,139 +26,139 @@ interface Lab extends Array<number> { [d: number]: number, '@type': 'lab', lengt * see https://en.wikipedia.org/wiki/CIELAB_color_space */ function Lab() { - return Lab.zero() + return Lab.zero(); } namespace Lab { export function zero(): Lab { - const out = [0.1, 0.0, 0.0] - out[0] = 0 + const out = [0.1, 0.0, 0.0]; + out[0] = 0; return out as Lab; } export function create(l: number, a: number, b: number): Lab { - const out = zero() - out[0] = l - out[1] = a - out[2] = b - return out + const out = zero(); + out[0] = l; + out[1] = a; + out[2] = b; + return out; } export function fromColor(out: Lab, color: Color): Lab { - const [r, g, b] = Color.toRgb(color) - const [x, y, z] = rgbToXyz(r, g, b) - const l = 116 * y - 16 - out[0] = l < 0 ? 0 : l - out[1] = 500 * (x - y) - out[2] = 200 * (y - z) - return out + const [r, g, b] = Color.toRgb(color); + const [x, y, z] = rgbToXyz(r, g, b); + const l = 116 * y - 16; + out[0] = l < 0 ? 0 : l; + out[1] = 500 * (x - y); + out[2] = 200 * (y - z); + return out; } export function fromHcl(out: Lab, hcl: Hcl): Lab { - return Hcl.toLab(out, hcl) + return Hcl.toLab(out, hcl); } export function toColor(lab: Lab): Color { - let y = (lab[0] + 16) / 116 - let x = isNaN(lab[1]) ? y : y + lab[1] / 500 - let z = isNaN(lab[2]) ? y : y - lab[2] / 200 + let y = (lab[0] + 16) / 116; + let x = isNaN(lab[1]) ? y : y + lab[1] / 500; + let z = isNaN(lab[2]) ? y : y - lab[2] / 200; - y = Yn * lab_xyz(y) - x = Xn * lab_xyz(x) - z = Zn * lab_xyz(z) + y = Yn * lab_xyz(y); + x = Xn * lab_xyz(x); + z = Zn * lab_xyz(z); - const r = xyz_rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z) // D65 -> sRGB - const g = xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z) - const b = xyz_rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z) + const r = xyz_rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z); // D65 -> sRGB + const g = xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z); + const b = xyz_rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z); return Color.fromRgb( Math.round(clamp(r, 0, 255)), Math.round(clamp(g, 0, 255)), Math.round(clamp(b, 0, 255)) - ) + ); } export function toHcl(out: Hcl, lab: Lab): Hcl { - const [l, a, b] = lab - const c = Math.sqrt(a * a + b * b) - let h = (radToDeg(Math.atan2(b, a)) + 360) % 360 - if (Math.round(c * 10000) === 0) h = Number.NaN - out[0] = h - out[1] = c - out[2] = l - return out + const [l, a, b] = lab; + const c = Math.sqrt(a * a + b * b); + let h = (radToDeg(Math.atan2(b, a)) + 360) % 360; + if (Math.round(c * 10000) === 0) h = Number.NaN; + out[0] = h; + out[1] = c; + out[2] = l; + return out; } export function copy(out: Lab, c: Lab): Lab { - out[0] = c[0] - out[1] = c[1] - out[2] = c[2] - return out + out[0] = c[0]; + out[1] = c[1]; + out[2] = c[2]; + return out; } export function darken(out: Lab, c: Lab, amount: number): Lab { - out[0] = c[0] - Kn * amount - out[1] = c[1] - out[2] = c[2] - return out + out[0] = c[0] - Kn * amount; + out[1] = c[1]; + out[2] = c[2]; + return out; } export function lighten(out: Lab, c: Lab, amount: number): Lab { - return darken(out, c, -amount) + return darken(out, c, -amount); } - const tmpSaturateHcl = [0, 0, 0] as Hcl + const tmpSaturateHcl = [0, 0, 0] as Hcl; export function saturate(out: Lab, c: Lab, amount: number): Lab { - toHcl(tmpSaturateHcl, c) - return Hcl.toLab(out, Hcl.saturate(tmpSaturateHcl, tmpSaturateHcl, amount)) + toHcl(tmpSaturateHcl, c); + return Hcl.toLab(out, Hcl.saturate(tmpSaturateHcl, tmpSaturateHcl, amount)); } export function desaturate(out: Lab, c: Lab, amount: number): Lab { - return saturate(out, c, -amount) + return saturate(out, c, -amount); } // Corresponds roughly to RGB brighter/darker - const Kn = 18 + const Kn = 18; /** D65 standard referent */ - const Xn = 0.950470 - const Yn = 1 - const Zn = 1.088830 + const Xn = 0.950470; + const Yn = 1; + const Zn = 1.088830; - const T0 = 0.137931034 // 4 / 29 - const T1 = 0.206896552 // 6 / 29 - const T2 = 0.12841855 // 3 * t1 * t1 - const T3 = 0.008856452 // t1 * t1 * t1 + const T0 = 0.137931034; // 4 / 29 + const T1 = 0.206896552; // 6 / 29 + const T2 = 0.12841855; // 3 * t1 * t1 + const T3 = 0.008856452; // t1 * t1 * t1 /** convert component from xyz to rgb */ function xyz_rgb(c: number) { - return 255 * (c <= 0.00304 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055) + return 255 * (c <= 0.00304 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055); } /** convert component from lab to xyz */ function lab_xyz(t: number) { - return t > T1 ? t * t * t : T2 * (t - T0) + return t > T1 ? t * t * t : T2 * (t - T0); } /** convert component from rgb to xyz */ function rgb_xyz(c: number) { - if ((c /= 255) <= 0.04045) return c / 12.92 - return Math.pow((c + 0.055) / 1.055, 2.4) + if ((c /= 255) <= 0.04045) return c / 12.92; + return Math.pow((c + 0.055) / 1.055, 2.4); } /** convert component from xyz to lab */ function xyz_lab(t: number) { - if (t > T3) return Math.pow(t, 1 / 3) - return t / T2 + T0 + if (t > T3) return Math.pow(t, 1 / 3); + return t / T2 + T0; } function rgbToXyz(r: number, g: number, b: number) { - r = rgb_xyz(r) - g = rgb_xyz(g) - b = rgb_xyz(b) - const x = xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / Xn) - const y = xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / Yn) - const z = xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / Zn) - return [x, y, z] + r = rgb_xyz(r); + g = rgb_xyz(g); + b = rgb_xyz(b); + const x = xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / Xn); + const y = xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / Yn); + const z = xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / Zn); + return [x, y, z]; } } \ No newline at end of file diff --git a/src/mol-util/color/swatches.ts b/src/mol-util/color/swatches.ts index df619006400f0cd36f1cb7c82498a516f99f8217..2e10a0de4d9e0dbabcd0f4da6341d29bd8af3e0c 100644 --- a/src/mol-util/color/swatches.ts +++ b/src/mol-util/color/swatches.ts @@ -20,4 +20,4 @@ export const DefaultColorSwatch = ColorSwatch([ ['purple', 0x7B64FF], ['magenta', 0xFA28FF], ['violet', 0x7D2187] -]) \ No newline at end of file +]); \ No newline at end of file diff --git a/src/mol-util/data-source.ts b/src/mol-util/data-source.ts index d12b2a91d58abf243ed21c95e6ca4bc275c7c67f..6c370f4a9b5c7cda1dfefd187f22dcced56789bc 100644 --- a/src/mol-util/data-source.ts +++ b/src/mol-util/data-source.ts @@ -20,7 +20,7 @@ const XHR = typeof document === 'undefined' ? require('xhr2') as { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; -} : XMLHttpRequest +} : XMLHttpRequest; export enum DataCompressionMethod { None, @@ -66,11 +66,11 @@ export type AjaxTask = typeof ajaxGet function isDone(data: XMLHttpRequest | FileReader) { if (data instanceof FileReader) { - return data.readyState === FileReader.DONE + return data.readyState === FileReader.DONE; } else if (data instanceof XMLHttpRequest) { - return data.readyState === XMLHttpRequest.DONE + return data.readyState === XMLHttpRequest.DONE; } - throw new Error('unknown data type') + throw new Error('unknown data type'); } function genericError(isDownload: boolean) { @@ -88,7 +88,7 @@ function readData<T extends XMLHttpRequest | FileReader>(ctx: RuntimeContext, ac } else { resolve(data); } - return + return; } let hasError = false; @@ -113,60 +113,60 @@ function readData<T extends XMLHttpRequest | FileReader>(ctx: RuntimeContext, ac hasError = true; reject(e); } - } + }; data.onload = (e: ProgressEvent) => { resolve(data); - } + }; }); } function getCompression(name: string) { return /\.gz$/i.test(name) ? DataCompressionMethod.Gzip : /\.zip$/i.test(name) ? DataCompressionMethod.Zip : - DataCompressionMethod.None + DataCompressionMethod.None; } async function decompress(ctx: RuntimeContext, data: Uint8Array, compression: DataCompressionMethod): Promise<Uint8Array> { switch (compression) { - case DataCompressionMethod.None: return data - case DataCompressionMethod.Gzip: return ungzip(ctx, data) + case DataCompressionMethod.None: return data; + case DataCompressionMethod.Gzip: return ungzip(ctx, data); case DataCompressionMethod.Zip: - const parsed = await unzip(ctx, data.buffer) - const names = Object.keys(parsed) - if (names.length !== 1) throw new Error('can only decompress zip files with a single entry') - return parsed[names[0]] as Uint8Array + const parsed = await unzip(ctx, data.buffer); + const names = Object.keys(parsed); + if (names.length !== 1) throw new Error('can only decompress zip files with a single entry'); + return parsed[names[0]] as Uint8Array; } } async function processFile<T extends DataType>(ctx: RuntimeContext, reader: FileReader, type: T, compression: DataCompressionMethod): Promise<DataResponse<T>> { - const { result } = reader + const { result } = reader; - let data = result instanceof ArrayBuffer ? new Uint8Array(result) : result - if (data === null) throw new Error('no data given') + let data = result instanceof ArrayBuffer ? new Uint8Array(result) : result; + if (data === null) throw new Error('no data given'); if (compression !== DataCompressionMethod.None) { - if (!(data instanceof Uint8Array)) throw new Error('need Uint8Array for decompression') + if (!(data instanceof Uint8Array)) throw new Error('need Uint8Array for decompression'); const decompressed = await decompress(ctx, data, compression); if (type === 'string') { await ctx.update({ message: 'Decoding text...' }); - data = utf8Read(decompressed, 0, decompressed.length) + data = utf8Read(decompressed, 0, decompressed.length); } else { - data = decompressed + data = decompressed; } } if (type === 'binary' && data instanceof Uint8Array) { - return data as DataResponse<T> + return data as DataResponse<T>; } else if (type === 'string' && typeof data === 'string') { - return data as DataResponse<T> + return data as DataResponse<T>; } else if (type === 'xml' && typeof data === 'string') { const parser = new DOMParser(); - return parser.parseFromString(data, 'application/xml') as DataResponse<T> + return parser.parseFromString(data, 'application/xml') as DataResponse<T>; } else if (type === 'json' && typeof data === 'string') { - return JSON.parse(data) as DataResponse<T> + return JSON.parse(data) as DataResponse<T>; } - throw new Error(`could not get requested response data '${type}'`) + throw new Error(`could not get requested response data '${type}'`); } function readFromFileInternal<T extends DataType>(file: File, type: T): Task<DataResponse<T>> { @@ -174,12 +174,12 @@ function readFromFileInternal<T extends DataType>(file: File, type: T): Task<Dat return Task.create('Read File', async ctx => { try { reader = new FileReader(); - const compression = getCompression(file.name) + const compression = getCompression(file.name); if (type === 'binary' || compression !== DataCompressionMethod.None) { - reader.readAsArrayBuffer(file) + reader.readAsArrayBuffer(file); } else { - reader.readAsText(file) + reader.readAsText(file); } await ctx.update({ message: 'Opening file...', canAbort: true }); @@ -225,15 +225,15 @@ function processAjax<T extends DataType>(req: XMLHttpRequest, type: T): DataResp RequestPool.deposit(req); if (type === 'binary' && response instanceof ArrayBuffer) { - return new Uint8Array(response) as DataResponse<T> + return new Uint8Array(response) as DataResponse<T>; } else if (type === 'string' && typeof response === 'string') { - return response as DataResponse<T> + return response as DataResponse<T>; } else if (type === 'xml' && response instanceof XMLDocument) { - return response as DataResponse<T> + return response as DataResponse<T>; } else if (type === 'json' && typeof response === 'object') { - return response as DataResponse<T> + return response as DataResponse<T>; } - throw new Error(`could not get requested response data '${type}'`) + throw new Error(`could not get requested response data '${type}'`); } else { const status = req.statusText; RequestPool.deposit(req); @@ -243,10 +243,10 @@ function processAjax<T extends DataType>(req: XMLHttpRequest, type: T): DataResp function getRequestResponseType(type: DataType): XMLHttpRequestResponseType { switch(type) { - case 'json': return 'json' - case 'xml': return 'document' - case 'string': return 'text' - case 'binary': return 'arraybuffer' + case 'json': return 'json'; + case 'xml': return 'document'; + case 'string': return 'text'; + case 'binary': return 'arraybuffer'; } } @@ -264,7 +264,7 @@ function ajaxGetInternal<T extends DataType>(title: string | undefined, url: str xhttp = void 0; // guard against reuse, help garbage collector await ctx.update({ message: 'Parsing response...', canAbort: false }); - const result = processAjax(req, type) + const result = processAjax(req, type); return result; }, () => { @@ -325,6 +325,6 @@ async function wrapPromise<T>(index: number, id: string, p: Promise<T>): Promise const result = await p; return { kind: 'ok', result, index, id }; } catch (error) { - return { kind: 'error', error, index, id } + return { kind: 'error', error, index, id }; } } \ No newline at end of file diff --git a/src/mol-util/debug.ts b/src/mol-util/debug.ts index 7f1b6679a0c00164b7e306d3150e419e96dca0fc..e9c40765fa142d55054c463f82d2de4c78b2b639 100644 --- a/src/mol-util/debug.ts +++ b/src/mol-util/debug.ts @@ -8,13 +8,13 @@ * on node `process.env.NODE_ENV` is available, in webpack build it is automatically set * by the DefinePlugin to the webpack `mode` value */ -let isProductionMode = process.env.NODE_ENV === 'production' +let isProductionMode = process.env.NODE_ENV === 'production'; /** * set to true to enable more comprehensive checks and assertions, * mostly used in `mol-gl` and in valence-model calculation */ -let isDebugMode = process.env.DEBUG === '*' || process.env.DEBUG === 'molstar' +let isDebugMode = process.env.DEBUG === '*' || process.env.DEBUG === 'molstar'; if (typeof window !== 'undefined' && !(window as any).setMolStarDebugMode) { try { @@ -25,4 +25,4 @@ if (typeof window !== 'undefined' && !(window as any).setMolStarDebugMode) { } catch { } } -export { isProductionMode, isDebugMode } \ No newline at end of file +export { isProductionMode, isDebugMode }; \ No newline at end of file diff --git a/src/mol-util/download.ts b/src/mol-util/download.ts index f59cb0fdac3abb8d8412f38551124305d54ef0bd..eb65b4a6f5737200063702bde49815fb415b1862 100644 --- a/src/mol-util/download.ts +++ b/src/mol-util/download.ts @@ -5,65 +5,65 @@ */ function openUrl (url: string) { - const opened = window.open(url, '_blank') + const opened = window.open(url, '_blank'); if (!opened) { - window.location.href = url + window.location.href = url; } } function click(node: HTMLAnchorElement) { try { - node.dispatchEvent(new MouseEvent('click')) + node.dispatchEvent(new MouseEvent('click')); } catch (e) { - const evt = document.createEvent('MouseEvents') - evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null) - node.dispatchEvent(evt) + const evt = document.createEvent('MouseEvents'); + evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); + node.dispatchEvent(evt); } } export function download (data: Blob | string, downloadName = 'download') { // using ideas from https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js - if (!data) return + if (!data) return; if ('download' in HTMLAnchorElement.prototype) { - const a = document.createElement('a') - a.download = downloadName - a.rel = 'noopener' + const a = document.createElement('a'); + a.download = downloadName; + a.rel = 'noopener'; if (typeof data === 'string') { a.href = data; - click(a) + click(a); } else { a.href = URL.createObjectURL(data); - setTimeout(() => URL.revokeObjectURL(a.href), 4E4) // 40s - setTimeout(() => click(a)) + setTimeout(() => URL.revokeObjectURL(a.href), 4E4); // 40s + setTimeout(() => click(a)); } } else if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) { // native saveAs in IE 10+ - navigator.msSaveOrOpenBlob(data, downloadName) + navigator.msSaveOrOpenBlob(data, downloadName); } else { - const ua = window.navigator.userAgent - const isSafari = /Safari/i.test(ua) - const isChromeIos = /CriOS\/[\d]+/.test(ua) + const ua = window.navigator.userAgent; + const isSafari = /Safari/i.test(ua); + const isChromeIos = /CriOS\/[\d]+/.test(ua); const open = (str: string) => { - openUrl(isChromeIos ? str : str.replace(/^data:[^;]*;/, 'data:attachment/file;')) - } + openUrl(isChromeIos ? str : str.replace(/^data:[^;]*;/, 'data:attachment/file;')); + }; if ((isSafari || isChromeIos) && FileReader) { if (data instanceof Blob) { // no downloading of blob urls in Safari - const reader = new FileReader() - reader.onloadend = () => open(reader.result as string) - reader.readAsDataURL(data) + const reader = new FileReader(); + reader.onloadend = () => open(reader.result as string); + reader.readAsDataURL(data); } else { - open(data) + open(data); } } else { - const url = URL.createObjectURL(data) - location.href = url - setTimeout(() => URL.revokeObjectURL(url), 4E4) // 40s + const url = URL.createObjectURL(data); + location.href = url; + setTimeout(() => URL.revokeObjectURL(url), 4E4); // 40s } } } \ No newline at end of file diff --git a/src/mol-util/file-info.ts b/src/mol-util/file-info.ts index 193c2091ed8a124ca56bc458183c5c6d67c3b4e5..5ef434ad18fb4b840696237ddaf9169649ff08e9 100644 --- a/src/mol-util/file-info.ts +++ b/src/mol-util/file-info.ts @@ -9,10 +9,10 @@ export type FileInput = File | Blob | string // TODO only support compressed files for which uncompression support is available??? // TODO store globally with decompression plugins? -const compressedExtList = [ 'gz', 'zip' ] +const compressedExtList = [ 'gz', 'zip' ]; // TODO store globally with parser plugins? -const binaryExtList = [ 'bcif', 'ccp4', 'dcd' ] +const binaryExtList = [ 'bcif', 'ccp4', 'dcd' ]; export interface FileInfo { path: string @@ -28,46 +28,46 @@ export interface FileInfo { } export function getFileInfo (file: FileInput): FileInfo { - let path: string - let compressed: string|false - let protocol = '' + let path: string; + let compressed: string|false; + let protocol = ''; if (file instanceof File) { - path = file.name + path = file.name; } else if (file instanceof Blob) { - path = '' + path = ''; } else { - path = file + path = file; } - const queryIndex = path.lastIndexOf('?') - const query = queryIndex !== -1 ? path.substring(queryIndex) : '' - path = path.substring(0, queryIndex === -1 ? path.length : queryIndex) + const queryIndex = path.lastIndexOf('?'); + const query = queryIndex !== -1 ? path.substring(queryIndex) : ''; + path = path.substring(0, queryIndex === -1 ? path.length : queryIndex); - const name = path.replace(/^.*[\\/]/, '') - let base = name.substring(0, name.lastIndexOf('.')) + const name = path.replace(/^.*[\\/]/, ''); + let base = name.substring(0, name.lastIndexOf('.')); - const nameSplit = name.split('.') - let ext = nameSplit.length > 1 ? (nameSplit.pop() || '').toLowerCase() : '' + const nameSplit = name.split('.'); + let ext = nameSplit.length > 1 ? (nameSplit.pop() || '').toLowerCase() : ''; - const protocolMatch = path.match(/^(.+):\/\/(.+)$/) + const protocolMatch = path.match(/^(.+):\/\/(.+)$/); if (protocolMatch) { - protocol = protocolMatch[ 1 ].toLowerCase() - path = protocolMatch[ 2 ] || '' + protocol = protocolMatch[ 1 ].toLowerCase(); + path = protocolMatch[ 2 ] || ''; } - const dir = path.substring(0, path.lastIndexOf('/') + 1) + const dir = path.substring(0, path.lastIndexOf('/') + 1); if (compressedExtList.includes(ext)) { - compressed = ext - const n = path.length - ext.length - 1 - ext = (path.substr(0, n).split('.').pop() || '').toLowerCase() - const m = base.length - ext.length - 1 - base = base.substr(0, m) + compressed = ext; + const n = path.length - ext.length - 1; + ext = (path.substr(0, n).split('.').pop() || '').toLowerCase(); + const m = base.length - ext.length - 1; + base = base.substr(0, m); } else { - compressed = false + compressed = false; } - const binary = binaryExtList.includes(ext) + const binary = binaryExtList.includes(ext); - return { path, name, ext, base, dir, compressed, binary, protocol, query, src: file } + return { path, name, ext, base, dir, compressed, binary, protocol, query, src: file }; } \ No newline at end of file diff --git a/src/mol-util/float-packing.ts b/src/mol-util/float-packing.ts index 66f484c41a330e7bf51b71a1ee6a592bbf8cc246..1e6190bc4af2e84dec47d7a9f9fd41fad441ff2b 100644 --- a/src/mol-util/float-packing.ts +++ b/src/mol-util/float-packing.ts @@ -10,23 +10,23 @@ const maxFloat = 10000.0; // NOTE same constant is set in shaders const floatLogFactor = Math.log(maxFloat + 1.0); /** encode float logarithmically */ -export function encodeFloatLog(value: number) { return Math.log(value + 1.0) / floatLogFactor } +export function encodeFloatLog(value: number) { return Math.log(value + 1.0) / floatLogFactor; } /** decode logarithmically encoded float */ -export function decodeFloatLog(value: number) { return Math.exp(value * floatLogFactor) - 1.0 } +export function decodeFloatLog(value: number) { return Math.exp(value * floatLogFactor) - 1.0; } /** encode float as normalized rgb triplet */ export function encodeFloatRGB(value: number) { - value = clamp(value, 0.0, 16777216.0 - 1.0) + 1.0 - const b = (value % 256) / 255.0 - value = Math.floor(value / 256.0) - const g = (value % 256) / 255.0 - value = Math.floor(value / 256.0) - const r = (value % 256) / 255.0 - return [r, g, b] + value = clamp(value, 0.0, 16777216.0 - 1.0) + 1.0; + const b = (value % 256) / 255.0; + value = Math.floor(value / 256.0); + const g = (value % 256) / 255.0; + value = Math.floor(value / 256.0); + const r = (value % 256) / 255.0; + return [r, g, b]; } /** decode float encoded as rgb triplet */ export function decodeFloatRGB(r: number, g: number, b: number) { - return (Math.floor(r) * 256 * 256 + Math.floor(g) * 256 + Math.floor(b)) - 1 + return (Math.floor(r) * 256 * 256 + Math.floor(g) * 256 + Math.floor(b)) - 1; } \ No newline at end of file diff --git a/src/mol-util/graphql-client.ts b/src/mol-util/graphql-client.ts index 45d0602b6e59c9a1aea83122707e3c8cc021c848..9fc1708a21db79f1a97344200cbaf49812cc0f2d 100644 --- a/src/mol-util/graphql-client.ts +++ b/src/mol-util/graphql-client.ts @@ -34,32 +34,32 @@ export class ClientError extends Error { request: GraphQLRequestContext constructor (response: GraphQLResponse, request: GraphQLRequestContext) { - const message = `${ClientError.extractMessage(response)}: ${JSON.stringify({ response, request })}` + const message = `${ClientError.extractMessage(response)}: ${JSON.stringify({ response, request })}`; - super(message) + super(message); - this.response = response - this.request = request + this.response = response; + this.request = request; // this is needed as Safari doesn't support .captureStackTrace /* tslint:disable-next-line */ if (typeof Error.captureStackTrace === 'function') { - Error.captureStackTrace(this, ClientError) + Error.captureStackTrace(this, ClientError); } } private static extractMessage (response: GraphQLResponse): string { try { - return response.errors![0].message + return response.errors![0].message; } catch (e) { - return `GraphQL Error (Code: ${response.status})` + return `GraphQL Error (Code: ${response.status})`; } } } export class GraphQLClient { constructor(private url: string, private fetch: import('../mol-util/data-source').AjaxTask) { - this.url = url + this.url = url; } async request<T extends any>(ctx: RuntimeContext, query: string, variables?: Variables): Promise<T> { @@ -67,19 +67,19 @@ export class GraphQLClient { const body = JSON.stringify({ query, variables: variables ? variables : undefined, - }) + }); - const resultStr = await this.fetch({ url: this.url, body }).runInContext(ctx) - const result = JSON.parse(resultStr) + const resultStr = await this.fetch({ url: this.url, body }).runInContext(ctx); + const result = JSON.parse(resultStr); if (!result.errors && result.data) { - return result.data + return result.data; } else { - const errorResult = typeof result === 'string' ? { error: result } : result + const errorResult = typeof result === 'string' ? { error: result } : result; throw new ClientError( { ...errorResult }, { query, variables }, - ) + ); } } } \ No newline at end of file diff --git a/src/mol-util/id-factory.ts b/src/mol-util/id-factory.ts index 0c7ad893b57f7aa5aef1a12ba178a840117c6248..83fb2833b8dfda9383e889245138240f5bc30d48 100644 --- a/src/mol-util/id-factory.ts +++ b/src/mol-util/id-factory.ts @@ -6,10 +6,10 @@ /** Builds id function returning ids within [firstId, maxId) */ export function idFactory(firstId = 0, maxId = Number.MAX_SAFE_INTEGER) { - let _nextId = firstId + let _nextId = firstId; return () => { - const ret = _nextId - _nextId = (_nextId + 1) % maxId - return ret - } + const ret = _nextId; + _nextId = (_nextId + 1) % maxId; + return ret; + }; } \ No newline at end of file diff --git a/src/mol-util/image.ts b/src/mol-util/image.ts index dcbe39a8b71a345d50dc850acdbd553cf473f706..35a2f3e0a96112af3bba6a3ada384c3aba85ac94 100644 --- a/src/mol-util/image.ts +++ b/src/mol-util/image.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -export { PixelData } +export { PixelData }; interface PixelData { readonly array: Uint8Array @@ -14,22 +14,22 @@ interface PixelData { namespace PixelData { export function create(array: Uint8Array, width: number, height: number): PixelData { - return { array, width, height } + return { array, width, height }; } /** horizontally flips the pixel data in-place */ export function flipY(pixelData: PixelData): PixelData { - const { array, width, height } = pixelData - const width4 = width * 4 + const { array, width, height } = pixelData; + const width4 = width * 4; for (let i = 0, maxI = height / 2; i < maxI; ++i) { for (let j = 0, maxJ = width4; j < maxJ; ++j) { const index1 = i * width4 + j; const index2 = (height - i - 1) * width4 + j; - const tmp = array[index1] - array[index1] = array[index2] - array[index2] = tmp + const tmp = array[index1]; + array[index1] = array[index2]; + array[index2] = tmp; } } - return pixelData + return pixelData; } } \ No newline at end of file diff --git a/src/mol-util/index.ts b/src/mol-util/index.ts index d7291afaa038f99660f32270459d5c7f0c58b5b2..52c0eb210ee5b0cf9a8d173ab8916e64d41d80cb 100644 --- a/src/mol-util/index.ts +++ b/src/mol-util/index.ts @@ -5,31 +5,31 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import BitFlags from './bit-flags' -import StringBuilder from './string-builder' -import UUID from './uuid' -import Mask from './mask' +import BitFlags from './bit-flags'; +import StringBuilder from './string-builder'; +import UUID from './uuid'; +import Mask from './mask'; import { Progress } from '../mol-task'; -export * from './value-cell' -export { BitFlags, StringBuilder, UUID, Mask } +export * from './value-cell'; +export { BitFlags, StringBuilder, UUID, Mask }; export const noop = function () { }; export function round(n: number, d: number) { - let f = Math.pow(10, d) - return Math.round(f * n) / f + let f = Math.pow(10, d); + return Math.round(f * n) / f; } export function arrayEqual<T>(arr1: T[], arr2: T[]) { - const length = arr1.length - if (length !== arr2.length) return false + const length = arr1.length; + if (length !== arr2.length) return false; for (let i = 0; i < length; i++) { if (arr1[i] !== arr2[i]) { - return false + return false; } } - return true + return true; } const hasOwnProperty = Object.prototype.hasOwnProperty; @@ -38,57 +38,57 @@ export function deepEqual(a: any, b: any) { // from https://github.com/epoberezkin/fast-deep-equal MIT if (a === b) return true; - const arrA = Array.isArray(a) - const arrB = Array.isArray(b) + const arrA = Array.isArray(a); + const arrB = Array.isArray(b); if (arrA && arrB) { - if (a.length !== b.length) return false + if (a.length !== b.length) return false; for (let i = 0; i < a.length; i++) { - if (!deepEqual(a[i], b[i])) return false + if (!deepEqual(a[i], b[i])) return false; } - return true + return true; } - if (arrA !== arrB) return false + if (arrA !== arrB) return false; if (a && b && typeof a === 'object' && typeof b === 'object') { - const keys = Object.keys(a) + const keys = Object.keys(a); if (keys.length !== Object.keys(b).length) return false; - const dateA = a instanceof Date - const dateB = b instanceof Date - if (dateA && dateB) return a.getTime() === b.getTime() - if (dateA !== dateB) return false + const dateA = a instanceof Date; + const dateB = b instanceof Date; + if (dateA && dateB) return a.getTime() === b.getTime(); + if (dateA !== dateB) return false; - const regexpA = a instanceof RegExp - const regexpB = b instanceof RegExp - if (regexpA && regexpB) return a.toString() === b.toString() - if (regexpA !== regexpB) return false + const regexpA = a instanceof RegExp; + const regexpB = b instanceof RegExp; + if (regexpA && regexpB) return a.toString() === b.toString(); + if (regexpA !== regexpB) return false; for (let i = 0; i < keys.length; i++) { - if (!hasOwnProperty.call(b, keys[i])) return false + if (!hasOwnProperty.call(b, keys[i])) return false; } for (let i = 0; i < keys.length; i++) { - if (!deepEqual(a[keys[i]], b[keys[i]])) return false + if (!deepEqual(a[keys[i]], b[keys[i]])) return false; } - return true + return true; } - return false + return false; } export function shallowEqual(a: any, b: any) { if (a === b) return true; - const arrA = Array.isArray(a) - const arrB = Array.isArray(b) - if (arrA && arrB) return shallowEqualArrays(a, b) - if (arrA !== arrB) return false + const arrA = Array.isArray(a); + const arrB = Array.isArray(b); + if (arrA && arrB) return shallowEqualArrays(a, b); + if (arrA !== arrB) return false; if (a && b && typeof a === 'object' && typeof b === 'object') { - return shallowEqualObjects(a, b) + return shallowEqualObjects(a, b); } - return false + return false; } export function shallowEqualObjects(a: {}, b: {}) { @@ -114,7 +114,7 @@ export default function shallowEqualArrays(a: any[], b: any[]) { /** Returns `value` if not `undefined`, otherwise returns `defaultValue` */ export function defaults<T>(value: T | undefined, defaultValue: T): T { - return value !== undefined ? value : defaultValue + return value !== undefined ? value : defaultValue; } export function extend<S, T, U>(object: S, source: T, guard?: U): S & T & U { @@ -191,14 +191,14 @@ function _shallowMerge<T>(source: T) { export const merge: (<T>(source: T, ...rest: Partial<T>[]) => T) = _shallowMerge; -function padTime(n: number) { return (n < 10 ? '0' : '') + n } +function padTime(n: number) { return (n < 10 ? '0' : '') + n; } export function formatTime(d: Date) { const h = d.getHours(), m = d.getMinutes(), s = d.getSeconds(); return `${h}:${padTime(m)}:${padTime(s)}`; } export function formatProgress(p: Progress) { - const tp = p.root.progress + const tp = p.root.progress; if (tp.isIndeterminate) return tp.message; const x = (100 * tp.current / tp.max).toFixed(2); return `${tp.message} ${x}%`; diff --git a/src/mol-util/input/event-offset.ts b/src/mol-util/input/event-offset.ts index 9c986e4343216267d91caff079fe41b4d1adf0b6..8d0858eedb55be2c3c1c530a207c1937e4f4fd6d 100644 --- a/src/mol-util/input/event-offset.ts +++ b/src/mol-util/input/event-offset.ts @@ -9,23 +9,23 @@ * copyright (c) 2014 Matt DesLauriers. MIT License */ -import { Vec2 } from '../../mol-math/linear-algebra' +import { Vec2 } from '../../mol-math/linear-algebra'; -const rootPosition = { left: 0, top: 0 } +const rootPosition = { left: 0, top: 0 }; export function eventOffset (out: Vec2, ev: MouseEvent | Touch, target: Element) { - const cx = ev.clientX || 0 - const cy = ev.clientY || 0 - const rect = getBoundingClientOffset(target) - out[0] = cx - rect.left - out[1] = cy - rect.top - return out + const cx = ev.clientX || 0; + const cy = ev.clientY || 0; + const rect = getBoundingClientOffset(target); + out[0] = cx - rect.left; + out[1] = cy - rect.top; + return out; } function getBoundingClientOffset (element: Element | Window | Document) { if (element instanceof Window || element instanceof Document || element === document.body) { - return rootPosition + return rootPosition; } else { - return (element as Element).getBoundingClientRect() + return (element as Element).getBoundingClientRect(); } } \ No newline at end of file diff --git a/src/mol-util/input/input-observer.ts b/src/mol-util/input/input-observer.ts index 08cc6d83d650265087175ef394762b7a79452b8a..9a21cd1de60f394885528ce15c8fae74f22fda25 100644 --- a/src/mol-util/input/input-observer.ts +++ b/src/mol-util/input/input-observer.ts @@ -13,35 +13,35 @@ import { BitFlags, noop } from '../../mol-util'; export function getButtons(event: MouseEvent | Touch) { if (typeof event === 'object') { if ('buttons' in event) { - return event.buttons + return event.buttons; } else if ('which' in event) { - const b = (event as any).which // 'any' to support older browsers + const b = (event as any).which; // 'any' to support older browsers if (b === 2) { - return 4 + return 4; } else if (b === 3) { - return 2 + return 2; } else if (b > 0) { - return 1 << (b - 1) + return 1 << (b - 1); } } } - return 0 + return 0; } export function getButton(event: MouseEvent | Touch) { if (typeof event === 'object') { if ('button' in event) { - const b = event.button + const b = event.button; if (b === 1) { - return 4 + return 4; } else if (b === 2) { - return 2 + return 2; } else if (b >= 0) { - return 1 << b + return 1 << b; } } } - return 0 + return 0; } export function getModifiers(event: MouseEvent | Touch): ModifiersKeys { @@ -50,7 +50,7 @@ export function getModifiers(event: MouseEvent | Touch): ModifiersKeys { shift: 'shiftKey' in event ? event.shiftKey : false, control: 'ctrlKey' in event ? event.ctrlKey : false, meta: 'metaKey' in event ? event.metaKey : false - } + }; } export const DefaultInputObserverProps = { @@ -58,7 +58,7 @@ export const DefaultInputObserverProps = { noMiddleClickScroll: true, noContextMenu: true, noPinchZoom: true -} +}; export type InputObserverProps = Partial<typeof DefaultInputObserverProps> export type ModifiersKeys = { @@ -90,15 +90,15 @@ export namespace ModifiersKeys { alt: !!modifierKeys.alt, control: !!modifierKeys.control, meta: !!modifierKeys.meta - } + }; } } export type ButtonsType = BitFlags<ButtonsType.Flag> export namespace ButtonsType { - export const has: (btn: ButtonsType, f: Flag) => boolean = BitFlags.has - export const create: (fs: Flag) => ButtonsType = BitFlags.create + export const has: (btn: ButtonsType, f: Flag) => boolean = BitFlags.has; + export const create: (fs: Flag) => ButtonsType = BitFlags.create; export const enum Flag { /** No button or un-initialized */ @@ -208,12 +208,12 @@ function createEvents() { leave: new Subject<undefined>(), enter: new Subject<undefined>(), modifiers: new Subject<ModifiersKeys>(), - } + }; } namespace InputObserver { export function create(props: InputObserverProps = {}): InputObserver { - const { noScroll, noContextMenu } = { ...DefaultInputObserverProps, ...props } + const { noScroll, noContextMenu } = { ...DefaultInputObserverProps, ...props }; return { noScroll, noContextMenu, @@ -221,119 +221,119 @@ namespace InputObserver { ...createEvents(), dispose: noop - } + }; } export function fromElement(element: Element, props: InputObserverProps = {}): InputObserver { - let { noScroll, noMiddleClickScroll, noContextMenu, noPinchZoom } = { ...DefaultInputObserverProps, ...props } - - let lastTouchDistance = 0 - const pointerDown = Vec2.zero() - const pointerStart = Vec2.zero() - const pointerEnd = Vec2.zero() - const pointerDelta = Vec2.zero() - const rectSize = Vec2.zero() + let { noScroll, noMiddleClickScroll, noContextMenu, noPinchZoom } = { ...DefaultInputObserverProps, ...props }; + + let lastTouchDistance = 0; + const pointerDown = Vec2.zero(); + const pointerStart = Vec2.zero(); + const pointerEnd = Vec2.zero(); + const pointerDelta = Vec2.zero(); + const rectSize = Vec2.zero(); const modifierKeys: ModifiersKeys = { shift: false, alt: false, control: false, meta: false - } + }; function getModifierKeys(): ModifiersKeys { return { ...modifierKeys }; } - let dragging: DraggingState = DraggingState.Stopped - let disposed = false - let buttons = ButtonsType.create(ButtonsType.Flag.None) - let button = ButtonsType.Flag.None - let isInside = false + let dragging: DraggingState = DraggingState.Stopped; + let disposed = false; + let buttons = ButtonsType.create(ButtonsType.Flag.None); + let button = ButtonsType.Flag.None; + let isInside = false; - const events = createEvents() - const { drag, interactionEnd, wheel, pinch, click, move, leave, enter, resize, modifiers } = events + const events = createEvents(); + const { drag, interactionEnd, wheel, pinch, click, move, leave, enter, resize, modifiers } = events; - attach() + attach(); return { - get noScroll () { return noScroll }, - set noScroll (value: boolean) { noScroll = value }, - get noContextMenu () { return noContextMenu }, - set noContextMenu (value: boolean) { noContextMenu = value }, + get noScroll () { return noScroll; }, + set noScroll (value: boolean) { noScroll = value; }, + get noContextMenu () { return noContextMenu; }, + set noContextMenu (value: boolean) { noContextMenu = value; }, ...events, dispose - } + }; function attach() { - element.addEventListener('contextmenu', onContextMenu, false ) + element.addEventListener('contextmenu', onContextMenu, false ); - element.addEventListener('wheel', onMouseWheel as any, false) - element.addEventListener('mousedown', onMouseDown as any, false) + element.addEventListener('wheel', onMouseWheel as any, false); + element.addEventListener('mousedown', onMouseDown as any, false); // for dragging to work outside canvas bounds, // mouse move/up events have to be added to a parent, i.e. window - window.addEventListener('mousemove', onMouseMove as any, false) - window.addEventListener('mouseup', onMouseUp as any, false) + window.addEventListener('mousemove', onMouseMove as any, false); + window.addEventListener('mouseup', onMouseUp as any, false); - element.addEventListener('mouseenter', onMouseEnter as any, false) - element.addEventListener('mouseleave', onMouseLeave as any, false) + element.addEventListener('mouseenter', onMouseEnter as any, false); + element.addEventListener('mouseleave', onMouseLeave as any, false); - element.addEventListener('touchstart', onTouchStart as any, false) - element.addEventListener('touchmove', onTouchMove as any, false) - element.addEventListener('touchend', onTouchEnd as any, false) + element.addEventListener('touchstart', onTouchStart as any, false); + element.addEventListener('touchmove', onTouchMove as any, false); + element.addEventListener('touchend', onTouchEnd as any, false); // reset buttons and modifier keys state when browser window looses focus - window.addEventListener('blur', handleBlur) - window.addEventListener('keyup', handleKeyUp as EventListener, false) - window.addEventListener('keydown', handleKeyDown as EventListener, false) + window.addEventListener('blur', handleBlur); + window.addEventListener('keyup', handleKeyUp as EventListener, false); + window.addEventListener('keydown', handleKeyDown as EventListener, false); - window.addEventListener('resize', onResize, false) + window.addEventListener('resize', onResize, false); } function dispose() { - if (disposed) return - disposed = true + if (disposed) return; + disposed = true; - element.removeEventListener( 'contextmenu', onContextMenu, false ) + element.removeEventListener( 'contextmenu', onContextMenu, false ); - element.removeEventListener('wheel', onMouseWheel as any, false) - element.removeEventListener('mousedown', onMouseDown as any, false) - window.removeEventListener('mousemove', onMouseMove as any, false) - window.removeEventListener('mouseup', onMouseUp as any, false) + element.removeEventListener('wheel', onMouseWheel as any, false); + element.removeEventListener('mousedown', onMouseDown as any, false); + window.removeEventListener('mousemove', onMouseMove as any, false); + window.removeEventListener('mouseup', onMouseUp as any, false); - element.removeEventListener('mouseenter', onMouseEnter as any, false) - element.removeEventListener('mouseleave', onMouseLeave as any, false) + element.removeEventListener('mouseenter', onMouseEnter as any, false); + element.removeEventListener('mouseleave', onMouseLeave as any, false); - element.removeEventListener('touchstart', onTouchStart as any, false) - element.removeEventListener('touchmove', onTouchMove as any, false) - element.removeEventListener('touchend', onTouchEnd as any, false) + element.removeEventListener('touchstart', onTouchStart as any, false); + element.removeEventListener('touchmove', onTouchMove as any, false); + element.removeEventListener('touchend', onTouchEnd as any, false); - window.removeEventListener('blur', handleBlur) - window.removeEventListener('keyup', handleKeyUp as EventListener, false) - window.removeEventListener('keydown', handleKeyDown as EventListener, false) + window.removeEventListener('blur', handleBlur); + window.removeEventListener('keyup', handleKeyUp as EventListener, false); + window.removeEventListener('keydown', handleKeyDown as EventListener, false); - window.removeEventListener('resize', onResize, false) + window.removeEventListener('resize', onResize, false); } function onContextMenu(event: Event) { if (noContextMenu) { - event.preventDefault() + event.preventDefault(); } } function updateModifierKeys(event: MouseEvent | WheelEvent | TouchEvent) { - modifierKeys.alt = event.altKey - modifierKeys.shift = event.shiftKey - modifierKeys.control = event.ctrlKey - modifierKeys.meta = event.metaKey + modifierKeys.alt = event.altKey; + modifierKeys.shift = event.shiftKey; + modifierKeys.control = event.ctrlKey; + modifierKeys.meta = event.metaKey; } function handleBlur() { if (buttons || modifierKeys.shift || modifierKeys.alt || modifierKeys.meta || modifierKeys.control) { - buttons = 0 as ButtonsType - modifierKeys.shift = modifierKeys.alt = modifierKeys.control = modifierKeys.meta = false + buttons = 0 as ButtonsType; + modifierKeys.shift = modifierKeys.alt = modifierKeys.control = modifierKeys.meta = false; } } @@ -359,14 +359,14 @@ namespace InputObserver { } function getCenterTouch(ev: TouchEvent): PointerEvent { - const t0 = ev.touches[0] - const t1 = ev.touches[1] + const t0 = ev.touches[0]; + const t1 = ev.touches[1]; return { clientX: (t0.clientX + t1.clientX) / 2, clientY: (t0.clientY + t1.clientY) / 2, pageX: (t0.pageX + t1.pageX) / 2, pageY: (t0.pageY + t1.pageY) / 2 - } + }; } function getTouchDistance(ev: TouchEvent) { @@ -377,15 +377,15 @@ namespace InputObserver { function onTouchStart(ev: TouchEvent) { if (ev.touches.length === 1) { - buttons = button = ButtonsType.Flag.Primary - onPointerDown(ev.touches[0]) + buttons = button = ButtonsType.Flag.Primary; + onPointerDown(ev.touches[0]); } else if (ev.touches.length === 2) { - buttons = ButtonsType.Flag.Secondary & ButtonsType.Flag.Auxilary - button = ButtonsType.Flag.Secondary - onPointerDown(getCenterTouch(ev)) + buttons = ButtonsType.Flag.Secondary & ButtonsType.Flag.Auxilary; + button = ButtonsType.Flag.Secondary; + onPointerDown(getCenterTouch(ev)); - const touchDistance = getTouchDistance(ev) - lastTouchDistance = touchDistance + const touchDistance = getTouchDistance(ev); + lastTouchDistance = touchDistance; pinch.next({ distance: touchDistance, fraction: 1, @@ -394,19 +394,19 @@ namespace InputObserver { buttons, button, modifiers: getModifierKeys() - }) + }); } else if (ev.touches.length === 3) { - buttons = button = ButtonsType.Flag.Forth - onPointerDown(getCenterTouch(ev)) + buttons = button = ButtonsType.Flag.Forth; + onPointerDown(getCenterTouch(ev)); } } function onTouchEnd(ev: TouchEvent) { - endDrag() + endDrag(); } function onTouchMove(ev: TouchEvent) { - button = ButtonsType.Flag.None + button = ButtonsType.Flag.None; if (noPinchZoom) { ev.preventDefault(); @@ -418,17 +418,17 @@ namespace InputObserver { } if (ev.touches.length === 1) { - buttons = ButtonsType.Flag.Primary - onPointerMove(ev.touches[0]) + buttons = ButtonsType.Flag.Primary; + onPointerMove(ev.touches[0]); } else if (ev.touches.length === 2) { - const touchDistance = getTouchDistance(ev) - const touchDelta = lastTouchDistance - touchDistance + const touchDistance = getTouchDistance(ev); + const touchDelta = lastTouchDistance - touchDistance; if (Math.abs(touchDelta) < 4) { - buttons = ButtonsType.Flag.Secondary - onPointerMove(getCenterTouch(ev)) + buttons = ButtonsType.Flag.Secondary; + onPointerMove(getCenterTouch(ev)); } else { - buttons = ButtonsType.Flag.Auxilary - updateModifierKeys(ev) + buttons = ButtonsType.Flag.Auxilary; + updateModifierKeys(ev); pinch.next({ delta: touchDelta, fraction: lastTouchDistance / touchDistance, @@ -437,105 +437,105 @@ namespace InputObserver { buttons, button, modifiers: getModifierKeys() - }) + }); } - lastTouchDistance = touchDistance + lastTouchDistance = touchDistance; } else if (ev.touches.length === 3) { - buttons = ButtonsType.Flag.Forth - onPointerMove(getCenterTouch(ev)) + buttons = ButtonsType.Flag.Forth; + onPointerMove(getCenterTouch(ev)); } } function onMouseDown(ev: MouseEvent) { - updateModifierKeys(ev) - buttons = getButtons(ev) - button = getButton(ev) + updateModifierKeys(ev); + buttons = getButtons(ev); + button = getButton(ev); if (noMiddleClickScroll && buttons === ButtonsType.Flag.Auxilary) { - ev.preventDefault + ev.preventDefault; } - onPointerDown(ev) + onPointerDown(ev); } function onMouseMove(ev: MouseEvent) { - updateModifierKeys(ev) - buttons = getButtons(ev) - button = ButtonsType.Flag.None - onPointerMove(ev) + updateModifierKeys(ev); + buttons = getButtons(ev); + button = ButtonsType.Flag.None; + onPointerMove(ev); } function onMouseUp(ev: MouseEvent) { - updateModifierKeys(ev) - buttons = getButtons(ev) - button = getButton(ev) - onPointerUp(ev) - endDrag() + updateModifierKeys(ev); + buttons = getButtons(ev); + button = getButton(ev); + onPointerUp(ev); + endDrag(); } function endDrag() { - interactionEnd.next() + interactionEnd.next(); } function onPointerDown(ev: PointerEvent) { - eventOffset(pointerStart, ev) - Vec2.copy(pointerDown, pointerStart) + eventOffset(pointerStart, ev); + Vec2.copy(pointerDown, pointerStart); if (insideBounds(pointerStart)) { - dragging = DraggingState.Started + dragging = DraggingState.Started; } } function onPointerUp(ev: PointerEvent) { - dragging = DraggingState.Stopped + dragging = DraggingState.Stopped; eventOffset(pointerEnd, ev); if (Vec2.distance(pointerEnd, pointerDown) < 4) { - const { pageX, pageY } = ev - const [ x, y ] = pointerEnd + const { pageX, pageY } = ev; + const [ x, y ] = pointerEnd; - click.next({ x, y, pageX, pageY, buttons, button, modifiers: getModifierKeys() }) + click.next({ x, y, pageX, pageY, buttons, button, modifiers: getModifierKeys() }); } } function onPointerMove(ev: PointerEvent) { - eventOffset(pointerEnd, ev) - const { pageX, pageY } = ev - const [ x, y ] = pointerEnd - const inside = insideBounds(pointerEnd) - move.next({ x, y, pageX, pageY, buttons, button, modifiers: getModifierKeys(), inside }) + eventOffset(pointerEnd, ev); + const { pageX, pageY } = ev; + const [ x, y ] = pointerEnd; + const inside = insideBounds(pointerEnd); + move.next({ x, y, pageX, pageY, buttons, button, modifiers: getModifierKeys(), inside }); - if (dragging === DraggingState.Stopped) return + if (dragging === DraggingState.Stopped) return; - Vec2.div(pointerDelta, Vec2.sub(pointerDelta, pointerEnd, pointerStart), getClientSize(rectSize)) - if (Vec2.magnitude(pointerDelta) < EPSILON) return + Vec2.div(pointerDelta, Vec2.sub(pointerDelta, pointerEnd, pointerStart), getClientSize(rectSize)); + if (Vec2.magnitude(pointerDelta) < EPSILON) return; - const isStart = dragging === DraggingState.Started - const [ dx, dy ] = pointerDelta - drag.next({ x, y, dx, dy, pageX, pageY, buttons, button, modifiers: getModifierKeys(), isStart }) + const isStart = dragging === DraggingState.Started; + const [ dx, dy ] = pointerDelta; + drag.next({ x, y, dx, dy, pageX, pageY, buttons, button, modifiers: getModifierKeys(), isStart }); - Vec2.copy(pointerStart, pointerEnd) - dragging = DraggingState.Moving + Vec2.copy(pointerStart, pointerEnd); + dragging = DraggingState.Moving; } function onMouseWheel(ev: WheelEvent) { if (noScroll) { - ev.preventDefault() + ev.preventDefault(); } - let scale = 1 + let scale = 1; switch (ev.deltaMode) { - case 0: scale = 1; break // pixels - case 1: scale = 40; break // lines - case 2: scale = 800; break // pages + case 0: scale = 1; break; // pixels + case 1: scale = 40; break; // lines + case 2: scale = 800; break; // pages } - const dx = (ev.deltaX || 0) * scale - const dy = (ev.deltaY || 0) * scale - const dz = (ev.deltaZ || 0) * scale + const dx = (ev.deltaX || 0) * scale; + const dy = (ev.deltaY || 0) * scale; + const dz = (ev.deltaZ || 0) * scale; - buttons = button = ButtonsType.Flag.Auxilary + buttons = button = ButtonsType.Flag.Auxilary; if (dx || dy || dz) { - wheel.next({ dx, dy, dz, buttons, button, modifiers: getModifierKeys() }) + wheel.next({ dx, dy, dz, buttons, button, modifiers: getModifierKeys() }); } } @@ -550,33 +550,33 @@ namespace InputObserver { } function onResize(ev: Event) { - resize.next() + resize.next(); } function insideBounds(pos: Vec2) { if (element instanceof Window || element instanceof Document || element === document.body) { - return true + return true; } else { - const rect = element.getBoundingClientRect() - return pos[0] >= 0 && pos[1] >= 0 && pos[0] < rect.width && pos[1] < rect.height + const rect = element.getBoundingClientRect(); + return pos[0] >= 0 && pos[1] >= 0 && pos[0] < rect.width && pos[1] < rect.height; } } function getClientSize(out: Vec2) { - out[0] = element.clientWidth - out[1] = element.clientHeight - return out + out[0] = element.clientWidth; + out[1] = element.clientHeight; + return out; } function eventOffset(out: Vec2, ev: PointerEvent) { - const cx = ev.clientX || 0 - const cy = ev.clientY || 0 - const rect = element.getBoundingClientRect() - out[0] = cx - rect.left - out[1] = cy - rect.top - return out + const cx = ev.clientX || 0; + const cy = ev.clientY || 0; + const rect = element.getBoundingClientRect(); + out[0] = cx - rect.left; + out[1] = cy - rect.top; + return out; } } } -export default InputObserver \ No newline at end of file +export default InputObserver; \ No newline at end of file diff --git a/src/mol-util/legend.ts b/src/mol-util/legend.ts index 4079fa8c3e7e8bc5511c1d189179538fbbd4c094..7538f85153ba2c259405b6036fef9d882e19dcd9 100644 --- a/src/mol-util/legend.ts +++ b/src/mol-util/legend.ts @@ -13,7 +13,7 @@ export interface TableLegend { table: [ string, Color ][] } export function TableLegend(table: [ string, Color ][]): TableLegend { - return { kind: 'table-legend', table } + return { kind: 'table-legend', table }; } export interface ScaleLegend { @@ -23,5 +23,5 @@ export interface ScaleLegend { colors: Color[] } export function ScaleLegend(minLabel: string, maxLabel: string, colors: Color[]): ScaleLegend { - return { kind: 'scale-legend', minLabel, maxLabel, colors } + return { kind: 'scale-legend', minLabel, maxLabel, colors }; } \ No newline at end of file diff --git a/src/mol-util/log-entry.ts b/src/mol-util/log-entry.ts index f54a277a9750b15540f9576c61c2366630553be7..42638c0c4ab57b3b7e4b749ebf8380bb771ce91a 100644 --- a/src/mol-util/log-entry.ts +++ b/src/mol-util/log-entry.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -export { LogEntry } +export { LogEntry }; interface LogEntry { type: LogEntry.Type, diff --git a/src/mol-util/lru-cache.ts b/src/mol-util/lru-cache.ts index d393006afb6861937cf833e1a3994c249cc8c5bc..b6f843503a4b76ec0a16f9876f0c179b374c5c94 100644 --- a/src/mol-util/lru-cache.ts +++ b/src/mol-util/lru-cache.ts @@ -8,7 +8,7 @@ import { LinkedList } from '../mol-data/generic'; -export { LRUCache } +export { LRUCache }; interface LRUCache<T> { entries: LinkedList<LRUCache.Entry<T>>, diff --git a/src/mol-util/map.ts b/src/mol-util/map.ts index 42c2589077afe4493ec9024721b844573bc42520..bab87d8c92f4ac14f6e4c50b292bdd9569b30e75 100644 --- a/src/mol-util/map.ts +++ b/src/mol-util/map.ts @@ -11,14 +11,14 @@ export interface DefaultMap<K, V> extends Map<K, V> { /** A `Map` instance with a `getDefault` method added. */ export function DefaultMap<K, V>(valueCtor: () => V) { - const map = new Map<K, V>() as DefaultMap<K, V> + const map = new Map<K, V>() as DefaultMap<K, V>; map.getDefault = (key: K) => { - if (map.has(key)) return map.get(key)! - const value = valueCtor() - map.set(key, value) - return value - } - return map + if (map.has(key)) return map.get(key)!; + const value = valueCtor(); + map.set(key, value); + return value; + }; + return map; } // TODO currently not working, see https://github.com/Microsoft/TypeScript/issues/10853 diff --git a/src/mol-util/marker-action.ts b/src/mol-util/marker-action.ts index ede4613690b37605d6f490452592f779f2b737aa..0741f2bae6c2143f6d3828075b81f3d5cd200797 100644 --- a/src/mol-util/marker-action.ts +++ b/src/mol-util/marker-action.ts @@ -19,21 +19,21 @@ export enum MarkerAction { export type MarkerActions = BitFlags<MarkerAction> export namespace MarkerActions { - export const is: (m: MarkerActions, f: MarkerAction) => boolean = BitFlags.has + export const is: (m: MarkerActions, f: MarkerAction) => boolean = BitFlags.has; export const All = ( MarkerAction.Highlight | MarkerAction.RemoveHighlight | MarkerAction.Select | MarkerAction.Deselect | MarkerAction.Toggle | MarkerAction.Clear - ) as MarkerActions + ) as MarkerActions; export const Highlighting = ( MarkerAction.Highlight | MarkerAction.RemoveHighlight | MarkerAction.Clear - ) as MarkerActions + ) as MarkerActions; export const Selecting = ( MarkerAction.Select | MarkerAction.Deselect | MarkerAction.Toggle | MarkerAction.Clear - ) as MarkerActions + ) as MarkerActions; } export function applyMarkerActionAtPosition(array: Uint8Array, i: number, action: MarkerAction) { diff --git a/src/mol-util/mask.ts b/src/mol-util/mask.ts index ff5c4a0c17e87023c69c9c9468005ae47ac73384..31db044098b4a7185af9ec3a51e829e01724883b 100644 --- a/src/mol-util/mask.ts +++ b/src/mol-util/mask.ts @@ -87,7 +87,7 @@ namespace Mask { private flatten() { if (this._flat) return this._flat; const indices = new Int32Array(this.size); - let offset = 0 + let offset = 0; this.set.forEach(i => indices[offset++] = i); sortAsc(indices); this._flat = indices as any as number[]; @@ -150,8 +150,8 @@ namespace Mask { } export function complement(mask: Mask, against: Mask) { - let count = 0 - let max = 0 + let count = 0; + let max = 0; against.forEach(i => { if (!mask.has(i)) { count++; @@ -161,7 +161,7 @@ namespace Mask { if (count / max < 1 / 12) { // set based - const set = new Set<number>() + const set = new Set<number>(); against.forEach(i => { if (!mask.has(i)) { set.add(i); diff --git a/src/mol-util/memoize.ts b/src/mol-util/memoize.ts index 0e9b8b82ade6b00dd12258bffffffc803ab112fc..92f5dd1512bdd87d6ea5cd8f39dd5a38d868c097 100644 --- a/src/mol-util/memoize.ts +++ b/src/mol-util/memoize.ts @@ -21,7 +21,7 @@ export function memoizeLatest<Args extends any[], T>(f: (...args: Args) => T): ( } } return value; - } + }; } /** Cache all results from calls to a function with a single argument */ @@ -32,5 +32,5 @@ export function memoize1<A, T>(f: (a: A) => T): (a: A) => T { const v = f(a); cache.set(a, v); return v; - } + }; } \ No newline at end of file diff --git a/src/mol-util/now.ts b/src/mol-util/now.ts index 1354ea96fc64947074c9a3fc7f702bf323e4945a..f87f8effea3ea1279a5f989eec7a1191c761175d 100644 --- a/src/mol-util/now.ts +++ b/src/mol-util/now.ts @@ -45,4 +45,4 @@ function formatTimespan(t: number, includeMsZeroes = true) { return `${t.toFixed(0)}ms`; } -export { now, formatTimespan } \ No newline at end of file +export { now, formatTimespan }; \ No newline at end of file diff --git a/src/mol-util/number.ts b/src/mol-util/number.ts index d9c4adf3d5ef301c5d9d5a8d6c676fa6039b3a1d..711e5d71ed5165076d504d4b746b36200783ad0f 100644 --- a/src/mol-util/number.ts +++ b/src/mol-util/number.ts @@ -50,22 +50,22 @@ export function getArrayDigitCount(xs: ArrayLike<number>, maxDigits: number, del } export function isInteger(s: string) { - s = s.trim() - const n = parseInt(s, 10) - return isNaN(n) ? false : n.toString() === s + s = s.trim(); + const n = parseInt(s, 10); + return isNaN(n) ? false : n.toString() === s; } export function getPrecision(v: number) { - if (!isFinite(v)) return 0 - let e = 1 - let p = 0 + if (!isFinite(v)) return 0; + let e = 1; + let p = 0; while (Math.round(v * e) / e !== v) { - e *= 10 - ++p + e *= 10; + ++p; } - return p + return p; } export function toPrecision(v: number, precision: number) { - return parseFloat(v.toPrecision(precision)) + return parseFloat(v.toPrecision(precision)); } \ No newline at end of file diff --git a/src/mol-util/param-definition.ts b/src/mol-util/param-definition.ts index c98526d2f0535ea664f952aef4c60331c16ed392..986dc1be35804aee1d667157845bc39dbcd7e870 100644 --- a/src/mol-util/param-definition.ts +++ b/src/mol-util/param-definition.ts @@ -78,7 +78,7 @@ export namespace ParamDefinition { cycle?: boolean } export function Select<T>(defaultValue: T, options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[], info?: Info & { cycle?: boolean }): Select<T> { - return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options, cycle: info?.cycle }, info) + return setInfo<Select<T>>({ type: 'select', defaultValue: checkDefaultKey(defaultValue, options), options, cycle: info?.cycle }, info); } export interface MultiSelect<E extends string, T = E[]> extends Base<T> { @@ -98,14 +98,14 @@ export namespace ParamDefinition { type: 'boolean' } export function Boolean(defaultValue: boolean, info?: Info): BooleanParam { - return setInfo<BooleanParam>({ type: 'boolean', defaultValue }, info) + return setInfo<BooleanParam>({ type: 'boolean', defaultValue }, info); } export interface Text<T extends string = string> extends Base<T> { type: 'text' } export function Text<T extends string = string>(defaultValue: string = '', info?: Info): Text<T> { - return setInfo<Text<T>>({ type: 'text', defaultValue: defaultValue as any }, info) + return setInfo<Text<T>>({ type: 'text', defaultValue: defaultValue as any }, info); } export interface Color extends Base<ColorData> { @@ -130,21 +130,21 @@ export namespace ParamDefinition { } else { def = defaultValue; } - return setInfo<ColorList>({ type: 'color-list', presetKind: info?.presetKind || 'all', defaultValue: def }, info) + return setInfo<ColorList>({ type: 'color-list', presetKind: info?.presetKind || 'all', defaultValue: def }, info); } export interface Vec3 extends Base<Vec3Data>, Range { type: 'vec3' } export function Vec3(defaultValue: Vec3Data, range?: { min?: number, max?: number, step?: number }, info?: Info): Vec3 { - return setInfo<Vec3>(setRange({ type: 'vec3', defaultValue }, range), info) + return setInfo<Vec3>(setRange({ type: 'vec3', defaultValue }, range), info); } export interface Mat4 extends Base<Mat4Data> { type: 'mat4' } export function Mat4(defaultValue: Mat4Data, info?: Info): Mat4 { - return setInfo<Mat4>({ type: 'mat4', defaultValue }, info) + return setInfo<Mat4>({ type: 'mat4', defaultValue }, info); } export interface FileParam extends Base<File | null> { @@ -190,21 +190,21 @@ export namespace ParamDefinition { type: 'number' } export function Numeric(defaultValue: number, range?: { min?: number, max?: number, step?: number }, info?: Info): Numeric { - return setInfo<Numeric>(setRange({ type: 'number', defaultValue }, range), info) + return setInfo<Numeric>(setRange({ type: 'number', defaultValue }, range), info); } export interface Interval extends Base<[number, number]>, Range { type: 'interval' } export function Interval(defaultValue: [number, number], range?: { min?: number, max?: number, step?: number }, info?: Info): Interval { - return setInfo<Interval>(setRange({ type: 'interval', defaultValue }, range), info) + return setInfo<Interval>(setRange({ type: 'interval', defaultValue }, range), info); } export interface LineGraph extends Base<Vec2Data[]> { type: 'line-graph' } export function LineGraph(defaultValue: Vec2Data[], info?: Info): LineGraph { - return setInfo<LineGraph>({ type: 'line-graph', defaultValue }, info) + return setInfo<LineGraph>({ type: 'line-graph', defaultValue }, info); } export interface Group<T> extends Base<T> { @@ -293,7 +293,7 @@ export namespace ParamDefinition { type: 'script' } export function Script(defaultValue: Script['defaultValue'], info?: Info): Script { - return setInfo<Script>({ type: 'script', defaultValue }, info) + return setInfo<Script>({ type: 'script', defaultValue }, info); } export type Any = @@ -317,7 +317,7 @@ export namespace ParamDefinition { } export function getDefaultValues<T extends Params>(params: T) { - const d: { [k: string]: any } = {} + const d: { [k: string]: any } = {}; for (const k of Object.keys(params)) { if (params[k].isOptional) continue; d[k] = params[k].defaultValue; @@ -326,7 +326,7 @@ export namespace ParamDefinition { } export function clone<P extends Params>(params: P): P { - return deepClone(params) + return deepClone(params); } /** @@ -417,9 +417,9 @@ export namespace ParamDefinition { if (a === undefined) return { ...b }; if (b === undefined) return { ...a }; - const o = Object.create(null) + const o = Object.create(null); for (const k of Object.keys(params)) { - o[k] = mergeParam(params[k], a[k], b[k]) + o[k] = mergeParam(params[k], a[k], b[k]); } return o; } @@ -441,7 +441,7 @@ export namespace ParamDefinition { } else if (typeof a === 'object' && typeof b === 'object') { return { ...a, ...b }; } else { - return b + return b; } } @@ -473,7 +473,7 @@ export namespace ParamDefinition { if (!f) { ret.push([x, f === null ? x : stringToWords(x)]); } else { - ret.push([x, f(x)]) + ret.push([x, f(x)]); } } return ret; @@ -481,9 +481,9 @@ export namespace ParamDefinition { export function optionLabel<T>(param: Select<T>, value: T) { for (const o of param.options) { - if (o[0] === value) return o[1] + if (o[0] === value) return o[1]; } - return '' + return ''; } function checkDefaultKey<T>(k: T, options: readonly (readonly [T, string] | readonly [T, string, string | undefined])[]) { diff --git a/src/mol-util/param-mapping.ts b/src/mol-util/param-mapping.ts index 861bb64c30795f7cd611a29d80c6da912ff4a43f..52a68bc4c96173723e0b4a9ef649700886bc8c24 100644 --- a/src/mol-util/param-mapping.ts +++ b/src/mol-util/param-mapping.ts @@ -5,7 +5,7 @@ */ import { ParamDefinition as PD } from './param-definition'; -import { produce } from 'immer' +import { produce } from 'immer'; import { Mutable } from './type-helpers'; export interface ParamMapping<S, T, Ctx> { diff --git a/src/mol-util/polyfill.ts b/src/mol-util/polyfill.ts index 403cf6b4763c6c08161dc966f6320f5c946fd828..c2b15b00bed3dfbc7cfdb447a80530a36a9053b3 100644 --- a/src/mol-util/polyfill.ts +++ b/src/mol-util/polyfill.ts @@ -10,21 +10,21 @@ if (typeof window !== 'undefined') { // https://github.com/paulmillr/console-polyfill // Make it safe to do console.log() always. - (window as any).console = window.console || {} - let con = window.console - let prop, method - let empty = {} - let dummy = function () {} - let properties = 'memory'.split(',') + (window as any).console = window.console || {}; + let con = window.console; + let prop, method; + let empty = {}; + let dummy = function () {}; + let properties = 'memory'.split(','); let methods = ( 'assert,clear,count,debug,dir,dirxml,error,exception,group,' + 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn' - ).split(',') + ).split(','); - while ((prop = properties.pop())) if (!(con as any)[prop]) (con as any)[prop] = empty - while ((method = methods.pop())) if (!(con as any)[method]) (con as any)[method] = dummy - })() + while ((prop = properties.pop())) if (!(con as any)[prop]) (con as any)[prop] = empty; + while ((method = methods.pop())) if (!(con as any)[method]) (con as any)[method] = dummy; + })(); } if (typeof window.HTMLCanvasElement !== 'undefined' && !window.HTMLCanvasElement.prototype.toBlob) { @@ -32,39 +32,39 @@ if (typeof window.HTMLCanvasElement !== 'undefined' && !window.HTMLCanvasElement Object.defineProperty(window.HTMLCanvasElement.prototype, 'toBlob', { value: function (callback: any, type: any, quality: any) { - let bin = window.atob(this.toDataURL(type, quality).split(',')[ 1 ]) - let len = bin.length - let len32 = len >> 2 - let a8 = new Uint8Array(len) - let a32 = new Uint32Array(a8.buffer, 0, len32) + let bin = window.atob(this.toDataURL(type, quality).split(',')[ 1 ]); + let len = bin.length; + let len32 = len >> 2; + let a8 = new Uint8Array(len); + let a32 = new Uint32Array(a8.buffer, 0, len32); - let j = 0 + let j = 0; for (let i = 0; i < len32; i++) { a32[i] = ( bin.charCodeAt(j++) | bin.charCodeAt(j++) << 8 | bin.charCodeAt(j++) << 16 | bin.charCodeAt(j++) << 24 - ) + ); } - let tailLength = len & 3 + let tailLength = len & 3; while (tailLength--) { - a8[ j ] = bin.charCodeAt(j++) + a8[ j ] = bin.charCodeAt(j++); } - callback(new window.Blob([ a8 ], { 'type': type || 'image/png' })) + callback(new window.Blob([ a8 ], { 'type': type || 'image/png' })); } - }) + }); } // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/cbrt Math.cbrt = Math.cbrt || function (x) { - let y = Math.pow(Math.abs(x), 1 / 3) - return x < 0 ? -y : y -} + let y = Math.pow(Math.abs(x), 1 / 3); + return x < 0 ? -y : y; +}; // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign if (!Math.sign) { @@ -74,26 +74,26 @@ if (!Math.sign) { // If x is +0, the result is +0. // If x is negative and not -0, the result is -1. // If x is positive and not +0, the result is +1. - x = +x // convert to a number + x = +x; // convert to a number if (x === 0 || isNaN(x)) { - return Number(x) + return Number(x); } - return x > 0 ? 1 : -1 - } + return x > 0 ? 1 : -1; + }; } if (!Number.isInteger) { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger Number.isInteger = function isInteger (nVal) { - return typeof nVal === 'number' && isFinite(nVal) && nVal > -9007199254740992 && nVal < 9007199254740992 && Math.floor(nVal) === nVal - } + return typeof nVal === 'number' && isFinite(nVal) && nVal > -9007199254740992 && nVal < 9007199254740992 && Math.floor(nVal) === nVal; + }; } if (!Number.isNaN) { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN Number.isNaN = function isNaN (value) { - return value !== value // eslint-disable-line no-self-compare - } + return value !== value; // eslint-disable-line no-self-compare + }; } if (!Object.assign) { @@ -105,286 +105,286 @@ if (!Object.assign) { writable: true, value: function (target: any/* , firstSource */) { - 'use strict' - if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object') } + 'use strict'; + if (target === undefined || target === null) { throw new TypeError('Cannot convert first argument to object'); } - let to = Object(target) + let to = Object(target); - let hasPendingException = false - let pendingException + let hasPendingException = false; + let pendingException; for (let i = 1; i < arguments.length; i++) { - let nextSource = arguments[i] - if (nextSource === undefined || nextSource === null) { continue } + let nextSource = arguments[i]; + if (nextSource === undefined || nextSource === null) { continue; } - let keysArray = Object.keys(Object(nextSource)) + let keysArray = Object.keys(Object(nextSource)); for (let nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { - let nextKey = keysArray[nextIndex] + let nextKey = keysArray[nextIndex]; try { - let desc = Object.getOwnPropertyDescriptor(nextSource, nextKey) - if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey] } + let desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); + if (desc !== undefined && desc.enumerable) { to[nextKey] = nextSource[nextKey]; } } catch (e) { if (!hasPendingException) { - hasPendingException = true - pendingException = e + hasPendingException = true; + pendingException = e; } } } - if (hasPendingException) { throw pendingException } + if (hasPendingException) { throw pendingException; } } - return to + return to; } - }) + }); } if (!String.prototype.startsWith) { /* ! https://mths.be/startswith v0.2.0 by @mathias */ (function () { - 'use strict' // needed to support `apply`/`call` with `undefined`/`null` + 'use strict'; // needed to support `apply`/`call` with `undefined`/`null` let defineProperty = (function () { // IE 8 only supports `Object.defineProperty` on DOM elements - let result + let result; try { - let object = {} - let $defineProperty = Object.defineProperty - result = $defineProperty(object, object as any, object) && $defineProperty + let object = {}; + let $defineProperty = Object.defineProperty; + result = $defineProperty(object, object as any, object) && $defineProperty; } catch (error) {} // eslint-disable-line no-empty - return result - }()) - let toString = {}.toString + return result; + }()); + let toString = {}.toString; let startsWith = function (this: any, search: any) { if (this === null) { - throw TypeError() + throw TypeError(); } - let string = String(this) + let string = String(this); if (search && toString.call(search) === '[object RegExp]') { - throw TypeError() + throw TypeError(); } - let stringLength = string.length - let searchString = String(search) - let searchLength = searchString.length - let position = arguments.length > 1 ? arguments[1] : undefined + let stringLength = string.length; + let searchString = String(search); + let searchLength = searchString.length; + let position = arguments.length > 1 ? arguments[1] : undefined; // `ToInteger` - let pos = position ? Number(position) : 0 + let pos = position ? Number(position) : 0; if (Number.isNaN(pos)) { - pos = 0 + pos = 0; } - let start = Math.min(Math.max(pos, 0), stringLength) + let start = Math.min(Math.max(pos, 0), stringLength); // Avoid the `indexOf` call if no match is possible if (searchLength + start > stringLength) { - return false + return false; } - let index = -1 + let index = -1; while (++index < searchLength) { if (string.charCodeAt(start + index) !== searchString.charCodeAt(index)) { - return false + return false; } } - return true - } + return true; + }; if (defineProperty) { defineProperty(String.prototype, 'startsWith', { 'value': startsWith, 'configurable': true, 'writable': true - }) + }); } else { // eslint-disable-next-line no-extend-native - String.prototype.startsWith = startsWith + String.prototype.startsWith = startsWith; } - }()) + }()); } if (!String.prototype.endsWith) { // eslint-disable-next-line no-extend-native String.prototype.endsWith = function (searchString, position) { - let subjectString = this.toString() + let subjectString = this.toString(); if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) { - position = subjectString.length + position = subjectString.length; } - position -= searchString.length - let lastIndex = subjectString.indexOf(searchString, position) - return lastIndex !== -1 && lastIndex === position - } + position -= searchString.length; + let lastIndex = subjectString.indexOf(searchString, position); + return lastIndex !== -1 && lastIndex === position; + }; } if (!String.prototype.repeat) { // eslint-disable-next-line no-extend-native String.prototype.repeat = function (count) { - 'use strict' + 'use strict'; if (this === null) { - throw new TypeError('can\'t convert ' + this + ' to object') + throw new TypeError('can\'t convert ' + this + ' to object'); } - let str = '' + this - count = +count + let str = '' + this; + count = +count; if (Number.isNaN(count)) { - count = 0 + count = 0; } if (count < 0) { - throw new RangeError('repeat count must be non-negative') + throw new RangeError('repeat count must be non-negative'); } if (count === Infinity) { - throw new RangeError('repeat count must be less than infinity') + throw new RangeError('repeat count must be less than infinity'); } - count = Math.floor(count) + count = Math.floor(count); if (str.length === 0 || count === 0) { - return '' + return ''; } // Ensuring count is a 31-bit integer allows us to heavily optimize the // main part. But anyway, most current (August 2014) browsers can't handle // strings 1 << 28 chars or longer, so: if (str.length * count >= 1 << 28) { - throw new RangeError('repeat count must not overflow maximum string size') + throw new RangeError('repeat count must not overflow maximum string size'); } - let rpt = '' + let rpt = ''; for (;;) { if ((count & 1) === 1) { - rpt += str + rpt += str; } - count >>>= 1 + count >>>= 1; if (count === 0) { - break + break; } - str += str + str += str; } // Could we try: // return Array(count + 1).join(this); - return rpt - } + return rpt; + }; } if (!String.prototype.includes) { // eslint-disable-next-line no-extend-native String.prototype.includes = function (search, start) { - 'use strict' + 'use strict'; if (typeof start !== 'number') { - start = 0 + start = 0; } if (start + search.length > this.length) { - return false + return false; } else { - return this.indexOf(search, start) !== -1 + return this.indexOf(search, start) !== -1; } - } + }; } if (!Array.prototype.includes) { // eslint-disable-next-line no-extend-native Array.prototype.includes = function (searchElement /* , fromIndex */) { - 'use strict' + 'use strict'; if (this == null) { - throw new TypeError('Array.prototype.includes called on null or undefined') + throw new TypeError('Array.prototype.includes called on null or undefined'); } - let O = Object(this) - let len = parseInt(O.length, 10) || 0 + let O = Object(this); + let len = parseInt(O.length, 10) || 0; if (len === 0) { - return false + return false; } - let n = parseInt(arguments[1], 10) || 0 - let k + let n = parseInt(arguments[1], 10) || 0; + let k; if (n >= 0) { - k = n + k = n; } else { - k = len + n - if (k < 0) { k = 0 } + k = len + n; + if (k < 0) { k = 0; } } - let currentElement + let currentElement; while (k < len) { - currentElement = O[k] + currentElement = O[k]; if (searchElement === currentElement || (Number.isNaN(searchElement) && Number.isNaN(currentElement)) ) { - return true + return true; } - k++ + k++; } - return false - } + return false; + }; } // Production steps of ECMA-262, Edition 6, 22.1.2.1 // Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from if (!Array.from) { Array.from = (function () { - let toStr = Object.prototype.toString + let toStr = Object.prototype.toString; let isCallable = function (fn: any) { - return typeof fn === 'function' || toStr.call(fn) === '[object Function]' - } + return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; + }; let toInteger = function (value: any) { - let number = Number(value) - if (isNaN(number)) { return 0 } - if (number === 0 || !isFinite(number)) { return number } - return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)) - } - let maxSafeInteger = Math.pow(2, 53) - 1 + let number = Number(value); + if (isNaN(number)) { return 0; } + if (number === 0 || !isFinite(number)) { return number; } + return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); + }; + let maxSafeInteger = Math.pow(2, 53) - 1; let toLength = function (value: any) { - let len = toInteger(value) - return Math.min(Math.max(len, 0), maxSafeInteger) - } + let len = toInteger(value); + return Math.min(Math.max(len, 0), maxSafeInteger); + }; // The length property of the from method is 1. return function from (this: any, arrayLike: any/* , mapFn, thisArg */) { // 1. Let C be the this value. - let C = this + let C = this; // 2. Let items be ToObject(arrayLike). - let items = Object(arrayLike) + let items = Object(arrayLike); // 3. ReturnIfAbrupt(items). if (arrayLike == null) { - throw new TypeError('Array.from requires an array-like object - not null or undefined') + throw new TypeError('Array.from requires an array-like object - not null or undefined'); } // 4. If mapfn is undefined, then let mapping be false. - let mapFn = arguments.length > 1 ? arguments[1] : void undefined - let T + let mapFn = arguments.length > 1 ? arguments[1] : void undefined; + let T; if (typeof mapFn !== 'undefined') { // 5. else // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. if (!isCallable(mapFn)) { - throw new TypeError('Array.from: when provided, the second argument must be a function') + throw new TypeError('Array.from: when provided, the second argument must be a function'); } // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. if (arguments.length > 2) { - T = arguments[2] + T = arguments[2]; } } // 10. Let lenValue be Get(items, "length"). // 11. Let len be ToLength(lenValue). - let len = toLength(items.length) + let len = toLength(items.length); // 13. If IsConstructor(C) is true, then // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. // 14. a. Else, Let A be ArrayCreate(len). - let A = isCallable(C) ? Object(new C(len)) : new Array(len) + let A = isCallable(C) ? Object(new C(len)) : new Array(len); // 16. Let k be 0. - let k = 0 + let k = 0; // 17. Repeat, while k < len… (also steps a - h) - let kValue + let kValue; while (k < len) { - kValue = items[k] + kValue = items[k]; if (mapFn) { - A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k) + A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); } else { - A[k] = kValue + A[k] = kValue; } - k += 1 + k += 1; } // 18. Let putStatus be Put(A, "length", len, true). - A.length = len + A.length = len; // 20. Return A. - return A - } - }()) + return A; + }; + }()); } if (typeof window !== 'undefined') { @@ -396,42 +396,42 @@ if (typeof window !== 'undefined') { // MIT license - let lastTime = 0 - let vendors = [ 'ms', 'moz', 'webkit', 'o' ] + let lastTime = 0; + let vendors = [ 'ms', 'moz', 'webkit', 'o' ]; for (let x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = ( (window as any)[ vendors[ x ] + 'RequestAnimationFrame' ] - ) + ); window.cancelAnimationFrame = ( (window as any)[ vendors[ x ] + 'CancelAnimationFrame' ] || (window as any)[ vendors[ x ] + 'CancelRequestAnimationFrame' ] - ) + ); } if (!window.requestAnimationFrame) { window.requestAnimationFrame = function (callback/* , element */) { - let currTime = new Date().getTime() - let timeToCall = Math.max(0, 16 - (currTime - lastTime)) + let currTime = new Date().getTime(); + let timeToCall = Math.max(0, 16 - (currTime - lastTime)); let id = window.setTimeout(function () { - let time = currTime + timeToCall - callback(time) - }, timeToCall) + let time = currTime + timeToCall; + callback(time); + }, timeToCall); - lastTime = currTime + timeToCall + lastTime = currTime + timeToCall; - return id - } + return id; + }; } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = function (id) { - clearTimeout(id) - } + clearTimeout(id); + }; } - }()) + }()); } if (Function.prototype.name === undefined && Object.defineProperty !== undefined) { @@ -442,26 +442,26 @@ if (Function.prototype.name === undefined && Object.defineProperty !== undefined Object.defineProperty(Function.prototype, 'name', { get: function () { - return this.toString().match(/^\s*function\s*(\S*)\s*\(/)[ 1 ] + return this.toString().match(/^\s*function\s*(\S*)\s*\(/)[ 1 ]; } - }) + }); } if (typeof window !== 'undefined') { if (window.performance === undefined) { /* global self */ - (window as any).performance = {} + (window as any).performance = {}; } if (window.performance.now === undefined) { (function () { - let start = Date.now() + let start = Date.now(); window.performance.now = function () { - return Date.now() - start - } - })() + return Date.now() - start; + }; + })(); } } @@ -476,7 +476,7 @@ if (Object.defineProperty !== undefined) { configurable: false, writable: false, value: Math.pow(2, 53) - 1 - }) + }); } if (Number.MIN_SAFE_INTEGER === undefined) { Object.defineProperty(Number, 'MIN_SAFE_INTEGER', { @@ -484,7 +484,7 @@ if (Object.defineProperty !== undefined) { configurable: false, writable: false, value: -(Math.pow(2, 53) - 1) - }) + }); } } @@ -663,33 +663,33 @@ if (!Array.prototype.copyWithin) { } if (!Int8Array.prototype.copyWithin) { - Object.defineProperty(Int8Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Int8Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Int16Array.prototype.copyWithin) { - Object.defineProperty(Int16Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Int16Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Int32Array.prototype.copyWithin) { - Object.defineProperty(Int32Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Int32Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Uint8Array.prototype.copyWithin) { - Object.defineProperty(Uint8Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Uint8Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Uint16Array.prototype.copyWithin) { - Object.defineProperty(Uint16Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Uint16Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Uint32Array.prototype.copyWithin) { - Object.defineProperty(Uint32Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Uint32Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Float32Array.prototype.copyWithin) { - Object.defineProperty(Float32Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Float32Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } if (!Float64Array.prototype.copyWithin) { - Object.defineProperty(Float64Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }) + Object.defineProperty(Float64Array.prototype, 'copyWithin', { value: Array.prototype.copyWithin }); } \ No newline at end of file diff --git a/src/mol-util/read.ts b/src/mol-util/read.ts index 7cf70c65d316abc6b8ef1b257d20645cd09fa3d0..1b5aec57fdf1ea32eba269e5ccb08bafb428a7bd 100644 --- a/src/mol-util/read.ts +++ b/src/mol-util/read.ts @@ -5,29 +5,29 @@ */ export function readFile (file: File, isBinary = false) { - const fileReader = new FileReader() + const fileReader = new FileReader(); return new Promise<string | Uint8Array>((resolve, reject) => { fileReader.onerror = () => { - fileReader.abort() - reject(new DOMException('Error parsing file.')) - } + fileReader.abort(); + reject(new DOMException('Error parsing file.')); + }; fileReader.onload = () => { - resolve(isBinary ? new Uint8Array(fileReader.result as ArrayBuffer) : fileReader.result as string) - } + resolve(isBinary ? new Uint8Array(fileReader.result as ArrayBuffer) : fileReader.result as string); + }; if (isBinary) { - fileReader.readAsArrayBuffer(file) + fileReader.readAsArrayBuffer(file); } else { - fileReader.readAsText(file) + fileReader.readAsText(file); } - }) + }); } export function readFileAsText(file: File) { - return readFile(file, false) as Promise<string> + return readFile(file, false) as Promise<string>; } export function readFileAsBuffer(file: File) { - return readFile(file, true) as Promise<Uint8Array> + return readFile(file, true) as Promise<Uint8Array>; } export async function readUrl(url: string, isBinary: boolean) { @@ -36,9 +36,9 @@ export async function readUrl(url: string, isBinary: boolean) { } export function readUrlAsText(url: string) { - return readUrl(url, false) as Promise<string> + return readUrl(url, false) as Promise<string>; } export function readUrlAsBuffer(url: string) { - return readUrl(url, true) as Promise<Uint8Array> + return readUrl(url, true) as Promise<Uint8Array>; } \ No newline at end of file diff --git a/src/mol-util/reference-cache.ts b/src/mol-util/reference-cache.ts index b1b7b04e5da38739005115c692a9487bec9cd95c..6a8646e0acb2140d5ad619541a5cf7660d3d53c8 100644 --- a/src/mol-util/reference-cache.ts +++ b/src/mol-util/reference-cache.ts @@ -7,7 +7,7 @@ export interface Reference<T> { readonly value: T, usageCount: number } export function createReference<T>(value: T, usageCount = 0) { - return { value, usageCount } + return { value, usageCount }; } export interface ReferenceItem<T> { @@ -18,10 +18,10 @@ export interface ReferenceItem<T> { export function createReferenceItem<T>(ref: Reference<T>) { return { free: () => { - ref.usageCount -= 1 + ref.usageCount -= 1; }, value: ref.value - } + }; } export interface ReferenceCache<T, P> { @@ -32,36 +32,36 @@ export interface ReferenceCache<T, P> { } export function createReferenceCache<T, P>(hashFn: (props: P) => string, ctor: (props: P) => T, deleteFn: (v: T) => void): ReferenceCache<T, P> { - const map: Map<string, Reference<T>> = new Map() + const map: Map<string, Reference<T>> = new Map(); return { get: (props: P) => { - const id = hashFn(props) - let ref = map.get(id) + const id = hashFn(props); + let ref = map.get(id); if (!ref) { - ref = createReference<T>(ctor(props)) - map.set(id, ref) + ref = createReference<T>(ctor(props)); + map.set(id, ref); } - ref.usageCount += 1 - return createReferenceItem(ref) + ref.usageCount += 1; + return createReferenceItem(ref); }, clear: () => { map.forEach((ref, id) => { if (ref.usageCount <= 0) { if (ref.usageCount < 0) { - console.warn('Reference usageCount below zero.') + console.warn('Reference usageCount below zero.'); } - deleteFn(ref.value) - map.delete(id) + deleteFn(ref.value); + map.delete(id); } - }) + }); }, get count () { - return map.size + return map.size; }, dispose: () => { - map.forEach(ref => deleteFn(ref.value)) - map.clear() + map.forEach(ref => deleteFn(ref.value)); + map.clear(); }, - } + }; } \ No newline at end of file diff --git a/src/mol-util/rx-event-helper.ts b/src/mol-util/rx-event-helper.ts index 586d2d3e002373bee454bd514e31f58fb988ce36..5b2ff57da92f59592719adf52391d2d5f9f684cc 100644 --- a/src/mol-util/rx-event-helper.ts +++ b/src/mol-util/rx-event-helper.ts @@ -6,7 +6,7 @@ import { Subject, BehaviorSubject } from 'rxjs'; -export { RxEventHelper } +export { RxEventHelper }; interface RxEventHelper { <T>(): Subject<T>, diff --git a/src/mol-util/set.ts b/src/mol-util/set.ts index 9e1f71738511e4ef34547c9aae44f375f635859b..e86346f80cf35e8032f8836b9545b75ca6523e6c 100644 --- a/src/mol-util/set.ts +++ b/src/mol-util/set.ts @@ -10,22 +10,22 @@ import { iterableToArray } from '../mol-data/util/array'; export namespace SetUtils { export function toArray<T>(set: ReadonlySet<T>) { - return iterableToArray(set.values()) + return iterableToArray(set.values()); } /** Test if set a contains all elements of set b. */ export function isSuperset<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>) { - let flag = true + let flag = true; setB.forEach(elem => { if (!setA.has(elem)) flag = false; - }) - return flag + }); + return flag; } /** Add all elements from `sets` to `out` */ export function add<T>(out: Set<T>, ...sets: ReadonlySet<T>[]): Set<T> { for (let i = 0; i < sets.length; i++) { - sets[i].forEach(elem => out.add(elem)) + sets[i].forEach(elem => out.add(elem)); } return out; } @@ -33,7 +33,7 @@ export namespace SetUtils { /** Create set containing elements of both set a and set b. */ export function union<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>): Set<T> { const union = new Set(setA); - setB.forEach(elem => union.add(elem)) + setB.forEach(elem => union.add(elem)); return union; } @@ -42,7 +42,7 @@ export namespace SetUtils { if (sets.length === 1) new Set(sets[0]); const union = new Set(sets[0]); for (let i = 1, il = sets.length; i < il; i++) { - sets[i].forEach(elem => union.add(elem)) + sets[i].forEach(elem => union.add(elem)); } return union; } @@ -61,30 +61,30 @@ export namespace SetUtils { const intersection = new Set<T>(); setB.forEach(elem => { if (setA.has(elem)) intersection.add(elem); - }) + }); return intersection; } export function areIntersecting<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>): boolean { - let flag = false + let flag = false; setB.forEach(elem => { if (setA.has(elem)) flag = true; - }) + }); return flag; } export function intersectionSize<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>): number { - let count = 0 + let count = 0; setB.forEach(elem => { if (setA.has(elem)) count += 1; - }) + }); return count; } /** Create set containing elements of set a that are not in set b. */ export function difference<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>): Set<T> { const difference = new Set(setA); - setB.forEach(elem => difference.delete(elem)) + setB.forEach(elem => difference.delete(elem)); return difference; } @@ -92,18 +92,18 @@ export namespace SetUtils { export function differenceSize<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>): number { let count = setA.size; setA.forEach(elem => { - if (setB.has(elem)) count -= 1 - }) + if (setB.has(elem)) count -= 1; + }); return count; } /** Test if set a and b contain the same elements. */ export function areEqual<T>(setA: ReadonlySet<T>, setB: ReadonlySet<T>) { - if (setA.size !== setB.size) return false - let flag = true + if (setA.size !== setB.size) return false; + let flag = true; setB.forEach(elem => { if (!setA.has(elem)) flag = false; - }) + }); return flag; } } \ No newline at end of file diff --git a/src/mol-util/sleep.ts b/src/mol-util/sleep.ts index 49981e34d37ee5d350a25228307e2affd469a8ef..30deadd9a9baf5b8bd2abe85ebd73b2e29bea2de 100644 --- a/src/mol-util/sleep.ts +++ b/src/mol-util/sleep.ts @@ -5,5 +5,5 @@ */ export function sleep(milliseconds: number) { - return new Promise(resolve => setTimeout(resolve, milliseconds)) + return new Promise(resolve => setTimeout(resolve, milliseconds)); } \ No newline at end of file diff --git a/src/mol-util/string-builder.ts b/src/mol-util/string-builder.ts index 30dd4cda1c0811119c46f84b299ad70fc3053f72..b108cfb60cd34a38e39c3d2a6fd3dee2ec6de058 100644 --- a/src/mol-util/string-builder.ts +++ b/src/mol-util/string-builder.ts @@ -140,7 +140,7 @@ namespace StringBuilder { * @example writeFloat(123.2123, 100) -- 2 decim */ export function writeFloat(builder: StringBuilder, val: number, precisionMultiplier: number) { - writeSafe(builder, '' + Math.round(precisionMultiplier * val) / precisionMultiplier) + writeSafe(builder, '' + Math.round(precisionMultiplier * val) / precisionMultiplier); } export function writeFloatPadLeft(builder: StringBuilder, val: number, precisionMultiplier: number, totalWidth: number) { @@ -158,4 +158,4 @@ namespace StringBuilder { } } -export default StringBuilder \ No newline at end of file +export default StringBuilder; \ No newline at end of file diff --git a/src/mol-util/string.ts b/src/mol-util/string.ts index 4ad2896f77123dd9e8cfadaf8d4687d9ecd7e630..090465280e8246743747b47ce82fa3429517dbbf 100644 --- a/src/mol-util/string.ts +++ b/src/mol-util/string.ts @@ -5,23 +5,23 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -const reLine = /^/mg +const reLine = /^/mg; export function indentString(str: string, count: number, indent: string) { - return count === 0 ? str : str.replace(reLine, indent.repeat(count)) + return count === 0 ? str : str.replace(reLine, indent.repeat(count)); } /** Add space between camelCase text. */ export function splitCamelCase(str: string, separator = ' ') { - return str.replace(/([a-z\xE0-\xFF])([A-Z\xC0\xDF])/g, `$1${separator}$2`) + return str.replace(/([a-z\xE0-\xFF])([A-Z\xC0\xDF])/g, `$1${separator}$2`); } /** Split camelCase text and capitalize. */ export function camelCaseToWords(str: string) { - return capitalize(splitCamelCase(str)) + return capitalize(splitCamelCase(str)); } -export const lowerCase = (str: string) => str.toLowerCase() -export const upperCase = (str: string) => str.toUpperCase() +export const lowerCase = (str: string) => str.toLowerCase(); +export const upperCase = (str: string) => str.toUpperCase(); /** Return upper case if string, otherwise return empty string */ export function upperCaseAny(value: any): string { @@ -35,23 +35,23 @@ export function capitalize(str: string) { } export function splitSnakeCase(str: string) { - return str.replace(/_/g, ' ') + return str.replace(/_/g, ' '); } export function snakeCaseToWords(str: string) { - return capitalize(splitSnakeCase(str)) + return capitalize(splitSnakeCase(str)); } export function splitKebabCase(str: string) { - return str.replace(/-/g, ' ') + return str.replace(/-/g, ' '); } export function kebabCaseToWords(str: string) { - return capitalize(splitKebabCase(str)) + return capitalize(splitKebabCase(str)); } export function stringToWords(str: string) { - return capitalize(splitCamelCase(splitSnakeCase(splitKebabCase(str)))) + return capitalize(splitCamelCase(splitSnakeCase(splitKebabCase(str)))); } export function substringStartsWith(str: string, start: number, end: number, target: string) { @@ -92,5 +92,5 @@ export function trimCharEnd(str: string, char: string) { /** Simple function to strip tags from a string */ export function stripTags(str: string) { - return str.replace(/<\/?[^>]+>/g, '') + return str.replace(/<\/?[^>]+>/g, ''); } \ No newline at end of file diff --git a/src/mol-util/type-helpers.ts b/src/mol-util/type-helpers.ts index 621a09203a95645b494df6c27b6b43f6ce7dce22..5831646d611b53ee8b71740ea62c3347cc21a6f5 100644 --- a/src/mol-util/type-helpers.ts +++ b/src/mol-util/type-helpers.ts @@ -23,6 +23,6 @@ export type AssignableArrayLike<T> = { [i: number]: T, length: number } export type NonNullableArray<T extends any[] | ReadonlyArray<any>> = T extends any[] ? NonNullable<T[0]>[] : ReadonlyArray<NonNullable<T[0]>> export function ObjectKeys<T extends object>(o: T) { - return Object.keys(o) as (keyof T)[] + return Object.keys(o) as (keyof T)[]; } export interface FiniteArray<T, L extends number = number> extends ReadonlyArray<T> { length: L }; \ No newline at end of file diff --git a/src/mol-util/url.ts b/src/mol-util/url.ts index 3234bdbaea7ff7565eb8f2542c057b314242fd02..c78dc107160e65f307016675b1c300450dc212e6 100644 --- a/src/mol-util/url.ts +++ b/src/mol-util/url.ts @@ -5,10 +5,10 @@ */ export function urlQueryParameter (id: string) { - if (typeof window === 'undefined') return undefined - const a = new RegExp(`${id}=([^&#=]*)`) - const m = a.exec(window.location.search) - return m ? decodeURIComponent(m[1]) : undefined + if (typeof window === 'undefined') return undefined; + const a = new RegExp(`${id}=([^&#=]*)`); + const m = a.exec(window.location.search); + return m ? decodeURIComponent(m[1]) : undefined; } export function urlCombine(base: string, query: string) { diff --git a/src/mol-util/uuid.ts b/src/mol-util/uuid.ts index e1dc052b87920f345d11ab9439d8a21605c0eedc..fff7897a9ab52a716c3862823943f44357817933 100644 --- a/src/mol-util/uuid.ts +++ b/src/mol-util/uuid.ts @@ -10,7 +10,7 @@ import { now } from '../mol-util/now'; type UUID = string & { '@type': 'uuid' } namespace UUID { - const _btoa = typeof btoa !== 'undefined' ? btoa : (s: string) => Buffer.from(s).toString('base64') + const _btoa = typeof btoa !== 'undefined' ? btoa : (s: string) => Buffer.from(s).toString('base64'); const chars: string[] = []; /** Creates a 22 characters 'base64' encoded UUID */ diff --git a/src/mol-util/value-cell.ts b/src/mol-util/value-cell.ts index 3edcbf2aa0a0eb2e7ab20b37987fb0488f415897..f0cc43bab65c739376b652a863d982ed46cdeb3e 100644 --- a/src/mol-util/value-cell.ts +++ b/src/mol-util/value-cell.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import { idFactory } from './id-factory' +import { idFactory } from './id-factory'; /** A mutable value reference. */ interface ValueRef<T> { ref: T } @@ -15,7 +15,7 @@ namespace ValueRef { export function set<T>(ref: ValueRef<T>, value: T) { ref.ref = value; return ref; } } -const getNextId = idFactory(0, 0x7FFFFFFF) +const getNextId = idFactory(0, 0x7FFFFFFF); /** * An immutable value box that also holds a version of the attribute. @@ -59,7 +59,7 @@ namespace ValueCell { /** Updates the cell if the value is has changed, comparing by reference */ export function updateIfChanged<T, D>(cell: ValueCell<T, D>, value: T): ValueCell<T, D> { - return cell.ref.value !== value ? update(cell, value) : cell + return cell.ref.value !== value ? update(cell, value) : cell; } } diff --git a/src/mol-util/zip/bin.ts b/src/mol-util/zip/bin.ts index c105a80db0c7dcce96a540a86a25742f7044fa77..ed36a8fe473cf47c096e14e29fe2dc0a5abad64f 100644 --- a/src/mol-util/zip/bin.ts +++ b/src/mol-util/zip/bin.ts @@ -8,10 +8,10 @@ */ export function toUint32(x: number) { - return x >>> 0 + return x >>> 0; } export function toInt32(x: number) { - return x >> 0 + return x >> 0; } export function readUshort(buff: Uint8Array, p: number) { @@ -59,7 +59,7 @@ export function readUTF8(buff: Uint8Array, p: number, l: number) { } export function writeUTF8(buff: Uint8Array, p: number, str: string) { - const strl = str.length + const strl = str.length; let i = 0; for(let ci = 0; ci < strl; ci++) { const code = str.charCodeAt(ci); @@ -87,7 +87,7 @@ export function writeUTF8(buff: Uint8Array, p: number, str: string) { } export function sizeUTF8(str: string) { - const strl = str.length + const strl = str.length; let i = 0; for(let ci = 0; ci < strl; ci++) { const code = str.charCodeAt(ci); diff --git a/src/mol-util/zip/checksum.ts b/src/mol-util/zip/checksum.ts index 380f4a0abd11c6dbea7e3ed319389034cd6536ff..591370aeb32cfaa66a2dc196ab4cfff04e5dd14c 100644 --- a/src/mol-util/zip/checksum.ts +++ b/src/mol-util/zip/checksum.ts @@ -18,7 +18,7 @@ const CrcTable = (function() { tab[n] = c; } return tab; -})() +})(); function _crc(c: number, buf: Uint8Array, off: number, len: number) { for (let i = 0; i < len; i++) { @@ -33,7 +33,7 @@ export function crc(b: Uint8Array, o: number, l: number) { export function adler(data: Uint8Array, o: number, len: number) { let a = 1, b = 0; - let off = o + let off = o; const end = o + len; while(off < end) { const eend = Math.min(off + 5552, end); diff --git a/src/mol-util/zip/deflate.ts b/src/mol-util/zip/deflate.ts index deaeaa3b1c557ebafb2e21b21a47e8661f6d85ee..b12ddb3e68f229cc18fe79bf7920cd9e29b5685a 100644 --- a/src/mol-util/zip/deflate.ts +++ b/src/mol-util/zip/deflate.ts @@ -30,11 +30,11 @@ export function _deflateRaw(data: Uint8Array, out: Uint8Array, opos: number, lvl /* 7 */ [ 8, 32, 128, 256, 0], /* 8 */ [32, 128, 258, 1024, 1], /* 9 */ [32, 258, 258, 4096, 1] /* max compression */ - ] + ]; const opt = opts[lvl]; - let i = 0, pos = opos << 3, cvrd = 0 + let i = 0, pos = opos << 3, cvrd = 0; const dlen = data.length; if(lvl === 0) { @@ -47,7 +47,7 @@ export function _deflateRaw(data: Uint8Array, out: Uint8Array, opos: number, lvl return pos >>> 3; } - const { lits, strt, prev } = U + const { lits, strt, prev } = U; let li = 0, lc = 0, bs = 0, ebits = 0, c = 0, nc = 0; // last_item, literal_count, block_start if(dlen > 2) { nc = _hash(data, 0); @@ -169,7 +169,7 @@ function _hash(data: Uint8Array, i: number) { function _writeBlock(BFINAL: number, lits: Uint32Array, li: number, ebits: number, data: Uint8Array, o0: number, l0: number, out: Uint8Array, pos: number) { U.lhst[256]++; - const [ ML, MD, MH, numl, numd, numh, lset, dset ] = getTrees() + const [ ML, MD, MH, numl, numd, numh, lset, dset ] = getTrees(); const cstSize = (((pos + 3) & 7) === 0 ? 0 : 8 - ((pos + 3) & 7)) + 32 + (l0 << 3); const fxdSize = ebits + contSize(U.fltree, U.lhst) + contSize(U.fdtree, U.dhst); @@ -209,7 +209,7 @@ function _writeBlock(BFINAL: number, lits: Uint32Array, li: number, ebits: numbe pos = _codeTiny(lset, U.itree, out, pos); pos = _codeTiny(dset, U.itree, out, pos); } else { - throw new Error(`unknown BTYPE ${BTYPE}`) + throw new Error(`unknown BTYPE ${BTYPE}`); } let off = o0; @@ -253,9 +253,9 @@ function _copyExact(data: Uint8Array, off: number, len: number, out: Uint8Array, function getTrees() { const ML = _hufTree(U.lhst, U.ltree, 15); const MD = _hufTree(U.dhst, U.dtree, 15); - const lset: number[] = [] + const lset: number[] = []; const numl = _lenCodes(U.ltree, lset); - const dset: number[] = [] + const dset: number[] = []; const numd = _lenCodes(U.dtree, dset); for(let i = 0; i < lset.length; i += 2) U.ihst[lset[i]]++; for(let i = 0; i < dset.length; i += 2) U.ihst[dset[i]]++; diff --git a/src/mol-util/zip/huffman.ts b/src/mol-util/zip/huffman.ts index 5d776c885fad239253e758ad2aabde10c3a2df58..be8b2f090372629f6f23169a2fd5a40b961e1c25 100644 --- a/src/mol-util/zip/huffman.ts +++ b/src/mol-util/zip/huffman.ts @@ -17,8 +17,8 @@ export type HufTree = { d: number } export function _hufTree(hst: NumberArray, tree: number[], MAXL: number) { - const list: HufTree[] = [] - const hl = hst.length, tl = tree.length + const list: HufTree[] = []; + const hl = hst.length, tl = tree.length; for(let i = 0; i < tl; i += 2) { tree[i] = 0; tree[i + 1] = 0; diff --git a/src/mol-util/zip/inflate.ts b/src/mol-util/zip/inflate.ts index e6dae79769fea9d301e994979e009ad65e27e387..bc0c397ee5186da5fd95b31777bc13e49adaba87 100644 --- a/src/mol-util/zip/inflate.ts +++ b/src/mol-util/zip/inflate.ts @@ -21,29 +21,29 @@ function InflateContext(data: Uint8Array, buf?: Uint8Array) { BFINAL: 0, off: 0, pos: 0 - } + }; } type InflateContext = ReturnType<typeof InflateContext> function inflateBlocks(ctx: InflateContext, count: number) { - const { data, noBuf } = ctx - let { buf, BFINAL, off, pos } = ctx + const { data, noBuf } = ctx; + let { buf, BFINAL, off, pos } = ctx; - let iBlock = 0 + let iBlock = 0; while(BFINAL === 0 && iBlock < count) { let lmap, dmap; let ML = 0, MD = 0; BFINAL = _bitsF(data, pos, 1); - iBlock += 1 + iBlock += 1; const BTYPE = _bitsF(data, pos + 1, 2); pos += 3; if(BTYPE === 0) { // uncompressed block if((pos & 7) !== 0) pos += 8 - (pos & 7); - const p8 = (pos >>> 3) + 4 + const p8 = (pos >>> 3) + 4; const len = data[p8 - 4] | (data[p8 - 3] << 8); if(noBuf) buf = _check(buf, off + len); buf.set(new Uint8Array(data.buffer, data.byteOffset + p8, len), off); @@ -96,7 +96,7 @@ function inflateBlocks(ctx: InflateContext, count: number) { makeCodes(U.dtree, mx1); codes2map(U.dtree, mx1, dmap); } else { - throw new Error(`unknown BTYPE ${BTYPE}`) + throw new Error(`unknown BTYPE ${BTYPE}`); } while(true) { @@ -118,7 +118,7 @@ function inflateBlocks(ctx: InflateContext, count: number) { const dcode = dmap[_get17(data, pos) & MD]; pos += dcode & 15; const dlit = dcode >>> 4; - const dbs = U.ddef[dlit] + const dbs = U.ddef[dlit]; const dst = (dbs >>> 4) + _bitsF(data, pos, dbs & 15); pos += dbs & 15; @@ -134,22 +134,22 @@ function inflateBlocks(ctx: InflateContext, count: number) { } } - ctx.buf = buf - ctx.BFINAL = BFINAL - ctx.off = off - ctx.pos = pos + ctx.buf = buf; + ctx.BFINAL = BFINAL; + ctx.off = off; + ctx.pos = pos; } // https://tools.ietf.org/html/rfc1951 export async function _inflate(runtime: RuntimeContext, data: Uint8Array, buf?: Uint8Array) { if(data[0] === 3 && data[1] === 0) return (buf ? buf : new Uint8Array(0)); - const ctx = InflateContext(data, buf) + const ctx = InflateContext(data, buf); while(ctx.BFINAL === 0) { if (runtime.shouldUpdate) { - await runtime.update({ message: 'Inflating blocks...', current: ctx.pos, max: data.length }) + await runtime.update({ message: 'Inflating blocks...', current: ctx.pos, max: data.length }); } - inflateBlocks(ctx, 100) + inflateBlocks(ctx, 100); } return ctx.buf.length === ctx.off ? ctx.buf : ctx.buf.slice(0, ctx.off); } @@ -195,7 +195,7 @@ function _decodeTiny(lmap: NumberArray, LL: number, len: number, data: Uint8Arra } function _copyOut(src: number[], off: number, len: number, tree: number[]) { - let mx = 0, i = 0 + let mx = 0, i = 0; const tl = tree.length >>> 1; while(i < len) { let v = src[i + off]; diff --git a/src/mol-util/zip/util.ts b/src/mol-util/zip/util.ts index a191ad3f1d2ca9db49c9da6a4f4b7610d2139b14..30cd5fddfeb2ad86bf03dec339fafc7eb6ecd782 100644 --- a/src/mol-util/zip/util.ts +++ b/src/mol-util/zip/util.ts @@ -66,13 +66,13 @@ export const U = (function(){ */ makeCodes(U.fltree, 9); codes2map(U.fltree, 9, U.flmap); - revCodes (U.fltree, 9) + revCodes (U.fltree, 9); pushV(U.fdtree, 32, 5); // for(i=0;i<32; i++) U.fdtree.push(0,5); makeCodes(U.fdtree, 5); codes2map(U.fdtree, 5, U.fdmap); - revCodes (U.fdtree, 5) + revCodes (U.fdtree, 5); pushV(U.itree, 19, 0); pushV(U.ltree, 286, 0); pushV(U.dtree, 30, 0); pushV(U.ttree, 320, 0); /* @@ -90,8 +90,8 @@ export function codes2map(tree: number[], MAX_BITS: number, map: Uint16Array) { if(tree[i + 1] !== 0) { const lit = i >> 1; const cl = tree[i + 1], val = (lit << 4) | cl; // : (0x8000 | (U.of0[lit-257]<<7) | (U.exb[lit-257]<<4) | cl); - const rest = (MAX_BITS - cl) - let i0 = tree[i] << rest + const rest = (MAX_BITS - cl); + let i0 = tree[i] << rest; const i1 = i0 + (1 << rest); // tree[i]=r15[i0]>>>(15-MAX_BITS); while(i0 !== i1) { diff --git a/src/mol-util/zip/zip.ts b/src/mol-util/zip/zip.ts index 25ca2ab06bb151cdc4053dd2aa34016acd5b55f1..2794aee27f02c185c020bc9c11a9654a5b37d181 100644 --- a/src/mol-util/zip/zip.ts +++ b/src/mol-util/zip/zip.ts @@ -49,8 +49,8 @@ export async function unzip(runtime: RuntimeContext, buf: ArrayBuffer, onlyNames const usize = readUint(data, o); o += 4; - const nl = readUshort(data, o) - const el = readUshort(data, o + 2) + const nl = readUshort(data, o); + const el = readUshort(data, o + 2); const cl = readUshort(data, o + 4); o += 6; // name, extra, comment o += 8; // disk, attribs @@ -128,55 +128,55 @@ export async function ungzip(runtime: RuntimeContext, file: Uint8Array, buf?: Ui // const id1 = file[0] // const id2 = file[1] // const cm = file[2] - const flg = file[3] + const flg = file[3]; // const mtime = readUint(file, 4) // const xfl = file[8] // const os = file[9] - let o = 10 + let o = 10; if (flg & 4) { // FEXTRA - const xlen = readUshort(file, o) + const xlen = readUshort(file, o); // console.log('FEXTRA', xlen) - o += xlen + o += xlen; } if (flg & 8) { // FNAME - let zero = o - while(file[zero] !== 0) ++zero + let zero = o; + while(file[zero] !== 0) ++zero; // const name = readUTF8(file, o, zero - o) // console.log('FNAME', name, zero - o) - o = zero + 1 + o = zero + 1; } if (flg & 16) { // FCOMMENT - let zero = o - while(file[zero] !== 0) ++zero + let zero = o; + while(file[zero] !== 0) ++zero; // const comment = readUTF8(file, o, zero - o) // console.log('FCOMMENT', comment) - o = zero + 1 + o = zero + 1; } if (flg & 1) { // FHCRC // const hcrc = readUshort(file, o) // console.log('FHCRC', hcrc) - o += 2 + o += 2; } - const crc32 = toInt32(readUint(file, file.length - 8)) - const isize = readUint(file, file.length - 4) - if (buf === undefined) buf = new Uint8Array(isize) + const crc32 = toInt32(readUint(file, file.length - 8)); + const isize = readUint(file, file.length - 4); + if (buf === undefined) buf = new Uint8Array(isize); - const blocks = new Uint8Array(file.buffer, file.byteOffset + o, file.length - o - 8) + const blocks = new Uint8Array(file.buffer, file.byteOffset + o, file.length - o - 8); const inflated = await inflateRaw(runtime, blocks, buf); - const crcValue = crc(inflated, 0, inflated.length) + const crcValue = crc(inflated, 0, inflated.length); if (crc32 !== crcValue) { - console.error("ungzip: checksums don't match") + console.error("ungzip: checksums don't match"); } - return inflated + return inflated; } export function deflate(data: Uint8Array, opts?: { level: number }/* , buf, off*/) { if(opts === undefined) opts = { level: 6 }; - let off = 0 + let off = 0; const buf = new Uint8Array(50 + Math.floor(data.length * 1.1)); buf[off] = 120; buf[off + 1] = 156; off += 2; off = _deflateRaw(data, buf, off, opts.level); @@ -199,7 +199,7 @@ export function zip(obj: { [k: string]: Uint8Array }, noCmpr = false) { let tot = 0; const zpd: { [k: string]: { cpr: boolean, usize: number, crc: number, file: Uint8Array } } = {}; for(const p in obj) { - const cpr = !_noNeed(p) && !noCmpr, buf = obj[p] + const cpr = !_noNeed(p) && !noCmpr, buf = obj[p]; const crcValue = crc(buf, 0, buf.length); zpd[p] = { cpr, @@ -212,9 +212,9 @@ export function zip(obj: { [k: string]: Uint8Array }, noCmpr = false) { for(const p in zpd) tot += zpd[p].file.length + 30 + 46 + 2 * sizeUTF8(p); tot += 22; - const data = new Uint8Array(tot) + const data = new Uint8Array(tot); let o = 0; - const fof = [] + const fof = []; for(const p in zpd) { const file = zpd[p]; fof.push(o); diff --git a/src/perf-tests/binary-search.ts b/src/perf-tests/binary-search.ts index 24b1ed6c51a6e1d75f1361f4b5e39dca5bc0d2cc..1f2a26dd441670f99fcf2c08c22cb7f78b43e8f4 100644 --- a/src/perf-tests/binary-search.ts +++ b/src/perf-tests/binary-search.ts @@ -137,7 +137,7 @@ function run(f: () => number, n: number) { console.log('set', testSet(set, queryPoints)); console.log('mask', testMask(mask, queryPoints)); - console.log('----------------------') + console.log('----------------------'); console.time('obj'); run(() => testObj(obj, queryPoints), 100); @@ -155,7 +155,7 @@ function run(f: () => number, n: number) { run(() => testMask(mask, queryPoints), 100); console.timeEnd('mask-search'); - console.log('----------------------') + console.log('----------------------'); console.time('prepare-obj'); run(() => prepareObj(list), 1); @@ -168,4 +168,4 @@ function run(f: () => number, n: number) { console.time('prepare-mask'); run(() => prepareMask(list).min, 1); console.timeEnd('prepare-mask'); -}()) +}()); diff --git a/src/perf-tests/chunked-array-vs-native.ts b/src/perf-tests/chunked-array-vs-native.ts index c49ed0b25ab1c273867b6b9418975697f56a2251..e71a154bfd8adf9ef7861689445b0b210f4525c4 100644 --- a/src/perf-tests/chunked-array-vs-native.ts +++ b/src/perf-tests/chunked-array-vs-native.ts @@ -1,5 +1,5 @@ -import * as B from 'benchmark' -import { ChunkedArray } from '../mol-data/util' +import * as B from 'benchmark'; +import { ChunkedArray } from '../mol-data/util'; function testNative(size: number) { const xs = new Array(size); diff --git a/src/perf-tests/cif-encoder.ts b/src/perf-tests/cif-encoder.ts index 50420f01c47120c5b683beaf828c114a3bcd9d7b..af30dcddee8e4b1fb0cf98b6026c1194ec1f73fe 100644 --- a/src/perf-tests/cif-encoder.ts +++ b/src/perf-tests/cif-encoder.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { CifWriter } from '../mol-io/writer/cif' -import * as fs from 'fs' +import { CifWriter } from '../mol-io/writer/cif'; +import * as fs from 'fs'; const category1fields: CifWriter.Field[] = [ CifWriter.Field.str('f1', i => 'v' + i), @@ -33,8 +33,8 @@ function testText() { const filter: CifWriter.Category.Filter = { includeCategory(cat) { return true; }, - includeField(cat, field) { return !(cat === 'cat2' && field === 'e2') } - } + includeField(cat, field) { return !(cat === 'cat2' && field === 'e2'); } + }; enc.startDataBlock('test'); enc.setFilter(filter); @@ -51,8 +51,8 @@ function testBinary() { const filter: CifWriter.Category.Filter = { includeCategory(cat) { return true; }, - includeField(cat, field) { return !(cat === 'cat2' && field === 'e2') } - } + includeField(cat, field) { return !(cat === 'cat2' && field === 'e2'); } + }; enc.startDataBlock('test'); enc.setFilter(filter); diff --git a/src/perf-tests/column.ts b/src/perf-tests/column.ts index 1a48a385c791b02b25dec0667c3edc76cf04a829..3cb781a2eee170198ed7fb46636188acffa8802c 100644 --- a/src/perf-tests/column.ts +++ b/src/perf-tests/column.ts @@ -1,5 +1,5 @@ -import * as B from 'benchmark' -import { Column as C } from '../mol-data/db' +import * as B from 'benchmark'; +import { Column as C } from '../mol-data/db'; export namespace Column { function createData(n: number) { diff --git a/src/perf-tests/iterators.ts b/src/perf-tests/iterators.ts index 8c1fd6f4266b5324e9cf51c2cc7dc1f89bd25643..d939fb3bf6adf9ec7efa6d46db020b2dd713d42e 100644 --- a/src/perf-tests/iterators.ts +++ b/src/perf-tests/iterators.ts @@ -1,5 +1,5 @@ -import * as B from 'benchmark' -import It from '../mol-data/iterator' +import * as B from 'benchmark'; +import It from '../mol-data/iterator'; function createData(n: number) { const data = []; // new Int32Array(n); @@ -32,13 +32,13 @@ export namespace Iterators { export function forEach() { const ctx = { sum: 0 }; - data.forEach(function (this: typeof ctx, v: number) { this.sum += v }, ctx); + data.forEach(function (this: typeof ctx, v: number) { this.sum += v; }, ctx); return ctx.sum; } export function forEachAllParams() { const ctx = { sum: 0 }; - data.forEach(function (this: typeof ctx, v: number, _: any, __: any) { this.sum += v }, ctx); + data.forEach(function (this: typeof ctx, v: number, _: any, __: any) { this.sum += v; }, ctx); return ctx.sum; } @@ -57,7 +57,7 @@ export namespace Iterators { export function forEachClosureAllFunction() { let sum = 0; - data.forEach(function (v, _, __) { sum += v }); + data.forEach(function (v, _, __) { sum += v; }); return sum; } @@ -77,7 +77,7 @@ export namespace Iterators { private index: number = -1; private length: number = 0; - [Symbol.iterator]() { return this }; + [Symbol.iterator]() { return this; }; next() { const index = ++this.index; @@ -104,7 +104,7 @@ export namespace Iterators { private index: number = -1; private length: number = 0; - [Symbol.iterator]() { return this }; + [Symbol.iterator]() { return this; }; next() { const index = ++this.index; diff --git a/src/perf-tests/lookup3d.ts b/src/perf-tests/lookup3d.ts index ea2e0bcb77c7d2f5607bfc758c193f4fd7a8ab4e..1c4c45af5af92796714493be07430b47eb6b393d 100644 --- a/src/perf-tests/lookup3d.ts +++ b/src/perf-tests/lookup3d.ts @@ -1,8 +1,8 @@ -import * as util from 'util' -import * as fs from 'fs' -import { CIF } from '../mol-io/reader/cif' +import * as util from 'util'; +import * as fs from 'fs'; +import { CIF } from '../mol-io/reader/cif'; -import { Structure } from '../mol-model/structure' +import { Structure } from '../mol-model/structure'; import { GridLookup3D } from '../mol-math/geometry'; // import { sortArray } from 'mol-data/util'; @@ -15,7 +15,7 @@ const readFileAsync = util.promisify(fs.readFile); async function readData(path: string) { if (path.match(/\.bcif$/)) { - const input = await readFileAsync(path) + const input = await readFileAsync(path); const data = new Uint8Array(input.byteLength); for (let i = 0; i < input.byteLength; i++) data[i] = input[i]; return data; @@ -26,7 +26,7 @@ async function readData(path: string) { export async function readCIF(path: string) { - const input = await readData(path) + const input = await readData(path); const comp = typeof input === 'string' ? CIF.parseText(input) : CIF.parseBinary(input); const parsed = await comp.run(); if (parsed.isError) { @@ -46,12 +46,12 @@ export async function test() { indices: OrderedSet.ofBounds(0, mmcif.db.atom_site._rowCount), // radius: [1, 1, 1, 1] // indices: [1] - } + }; const lookup = GridLookup3D(position, getBoundary(position)); console.log(lookup.boundary.box, lookup.boundary.sphere); const result = lookup.find(-30.07, 8.178, -13.897, 10); - console.log(result.count) // , sortArray(result.indices)); + console.log(result.count); // , sortArray(result.indices)); // const sl = structures[0].lookup3d; // const result1 = sl.find(-30.07, 8.178, -13.897, 10); diff --git a/src/perf-tests/mol-script.ts b/src/perf-tests/mol-script.ts index 57e5dcdc6da4f6660d4312b5b305ffbcfef6f15f..a840b606c6e61c9cf4ecbb9a0b929d75f38c57b5 100644 --- a/src/perf-tests/mol-script.ts +++ b/src/perf-tests/mol-script.ts @@ -5,7 +5,7 @@ import { readCifFile, getModelsAndStructure } from '../apps/structure-info/model import { CustomPropSymbol } from '../mol-script/language/symbol'; import Type from '../mol-script/language/type'; import { parseMolScript } from '../mol-script/language/parser'; -import * as util from 'util' +import * as util from 'util'; import { transpileMolScript } from '../mol-script/script/mol-script/symbols'; import { formatMolScript } from '../mol-script/language/expression-formatter'; import { StructureQualityReport, StructureQualityReportProvider } from '../mol-model-props/pdbe/structure-quality-report'; @@ -65,12 +65,12 @@ DefaultQueryRuntimeTable.addCustomProp(StructureQualityReportProvider.descriptor export async function testQ() { const frame = await readCifFile('e:/test/quick/1cbs_updated.cif'); const { structure } = await getModelsAndStructure(frame); - const model = structure.models[0] + const model = structure.models[0]; const rawData = await fetch(`https://www.ebi.ac.uk/pdbe/api/validation/residuewise_outlier_summary/entry/${model.entryId.toLowerCase()}`, { timeout: 1500 }); const data = StructureQualityReport.fromJson(model, await rawData.json()); - StructureQualityReportProvider.set(model, { serverUrl: '' }, data) + StructureQualityReportProvider.set(model, { serverUrl: '' }, data); let expr = MolScriptBuilder.struct.generator.atomGroups({ 'atom-test': MolScriptBuilder.core.rel.eq([ diff --git a/src/perf-tests/sets.ts b/src/perf-tests/sets.ts index 5e59c37d237d84628c3298e62b529b833d44599d..b3045312ec192ed2a568005bc554cff37f86ee63 100644 --- a/src/perf-tests/sets.ts +++ b/src/perf-tests/sets.ts @@ -1,5 +1,5 @@ -import * as B from 'benchmark' -import { Tuple, Segmentation, OrderedSet as OrdSet } from '../mol-data/int' +import * as B from 'benchmark'; +import { Tuple, Segmentation, OrderedSet as OrdSet } from '../mol-data/int'; // import { ElementSet } from 'mol-model/structure' // export namespace Iteration { @@ -87,7 +87,7 @@ export namespace Union { let c = (Math.random() * 100) | 0; for (let i = 0; i < n; i++) { data[i] = c; - c += 1 + (Math.random() * 100) | 0 + c += 1 + (Math.random() * 100) | 0; } return data; } @@ -109,7 +109,7 @@ export namespace Union { set.add(a); } - return { ordSet: OrdSet.ofSortedArray(array), obj, set } + return { ordSet: OrdSet.ofSortedArray(array), obj, set }; } function unionOS(a: OrdSet, b: OrdSet) { @@ -133,7 +133,7 @@ export namespace Union { return ret; } - function _setAdd(this: Set<number>, x: number) { this.add(x) } + function _setAdd(this: Set<number>, x: number) { this.add(x); } function unionS(a: Set<number>, b: Set<number>) { const ret = new Set<number>(); a.forEach(_setAdd, ret); @@ -141,7 +141,7 @@ export namespace Union { return ret; } - function _setInt(this: { set: Set<number>, other: Set<number> }, x: number) { if (this.other.has(x)) this.set.add(x) } + function _setInt(this: { set: Set<number>, other: Set<number> }, x: number) { if (this.other.has(x)) this.set.add(x); } function intS(a: Set<number>, b: Set<number>) { if (a.size < b.size) { const ctx = { set: new Set<number>(), other: b }; diff --git a/src/perf-tests/sort.ts b/src/perf-tests/sort.ts index 35d74414ddeed8f829cf29f3d3e100264714c6e4..262560ab3fc637b408f408ba5061e1dadc4e1a70 100644 --- a/src/perf-tests/sort.ts +++ b/src/perf-tests/sort.ts @@ -1,5 +1,5 @@ -import * as B from 'benchmark' -import * as Sort from '../mol-data/util' +import * as B from 'benchmark'; +import * as Sort from '../mol-data/util'; function shuffle(a: number[]) { for (let i = a.length - 1; i > 0; i--) { @@ -61,7 +61,7 @@ export function runTest(size: number) { function le(x: number, y: number) { return x - y; } - function name(n: string) { return `${n} (${size} elems)` } + function name(n: string) { return `${n} (${size} elems)`; } // TODO: the data copying skewes the benchmark -- write a simple benchmark util that allows for a preparation step. suite diff --git a/src/perf-tests/string-builder.ts b/src/perf-tests/string-builder.ts index 792fb40c19c508e2a97058c05af7aff5141e8d39..18f42a8efd1773b00c3521c1dcf99db6d56390aa 100644 --- a/src/perf-tests/string-builder.ts +++ b/src/perf-tests/string-builder.ts @@ -1,5 +1,5 @@ -import * as B from 'benchmark' -import SB from '../mol-util/string-builder' +import * as B from 'benchmark'; +import SB from '../mol-util/string-builder'; export namespace Test { function createData(n: number) { diff --git a/src/perf-tests/structure.ts b/src/perf-tests/structure.ts index 989e29c7f4df5bb9cef0ab3567fafd6d5390c99c..6275e214aea399eb9547840ade403c1cd5c7bcd7 100644 --- a/src/perf-tests/structure.ts +++ b/src/perf-tests/structure.ts @@ -4,17 +4,17 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as B from 'benchmark' +import * as B from 'benchmark'; -import * as util from 'util' -import * as fs from 'fs' -import fetch from 'node-fetch' -import { CIF } from '../mol-io/reader/cif' +import * as util from 'util'; +import * as fs from 'fs'; +import fetch from 'node-fetch'; +import { CIF } from '../mol-io/reader/cif'; -import { Structure, Model, Queries as Q, StructureElement, StructureSelection, StructureSymmetry, StructureQuery, StructureProperties as SP } from '../mol-model/structure' +import { Structure, Model, Queries as Q, StructureElement, StructureSelection, StructureSymmetry, StructureQuery, StructureProperties as SP } from '../mol-model/structure'; // import { Segmentation, OrderedSet } from '../mol-data/int' -import to_mmCIF from '../mol-model/structure/export/mmcif' +import to_mmCIF from '../mol-model/structure/export/mmcif'; import { Vec3 } from '../mol-math/linear-algebra'; import { trajectoryFromMmCIF, MmcifFormat } from '../mol-model-formats/structure/mmcif'; // import { printUnits } from '../apps/structure-info/model'; @@ -26,7 +26,7 @@ const writeFileAsync = util.promisify(fs.writeFile); async function readData(path: string) { if (path.match(/\.bcif$/)) { - const input = await readFileAsync(path) + const input = await readFileAsync(path); const data = new Uint8Array(input.byteLength); for (let i = 0; i < input.byteLength; i++) data[i] = input[i]; return data; @@ -58,7 +58,7 @@ async function readData(path: string) { export async function readCIF(path: string) { console.time('readData'); - const input = await readData(path) + const input = await readData(path); console.timeEnd('readData'); console.time('parse'); @@ -70,9 +70,9 @@ export async function readCIF(path: string) { } const data = parsed.result.blocks[0]; - console.time('buildModels') + console.time('buildModels'); const models = await trajectoryFromMmCIF(data).run(); - console.timeEnd('buildModels') + console.timeEnd('buildModels'); const structures = models.map(Structure.ofModel); return { mmcif: models[0].sourceData.data, models, structures }; @@ -82,20 +82,20 @@ const DATA_DIR = './build/data'; if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR); function getBcifUrl(pdbId: string) { - return `http://www.ebi.ac.uk/pdbe/coordinates/${pdbId.toLowerCase()}/full?encoding=bcif` + return `http://www.ebi.ac.uk/pdbe/coordinates/${pdbId.toLowerCase()}/full?encoding=bcif`; } function getBcifPath(pdbId: string) { - return `${DATA_DIR}/${pdbId.toLowerCase()}_full.bcif` + return `${DATA_DIR}/${pdbId.toLowerCase()}_full.bcif`; } async function ensureBcifAvailable(pdbId: string) { const bcifPath = getBcifPath(pdbId); if (!fs.existsSync(bcifPath)) { - console.log(`downloading ${pdbId} bcif...`) - const data = await fetch(getBcifUrl(pdbId)) - await writeFileAsync(bcifPath, await data.buffer()) - console.log(`done downloading ${pdbId} bcif`) + console.log(`downloading ${pdbId} bcif...`); + const data = await fetch(getBcifUrl(pdbId)); + await writeFileAsync(bcifPath, await data.buffer()); + console.log(`done downloading ${pdbId} bcif`); } } @@ -288,26 +288,26 @@ export namespace PropertyAccess { } export async function testAssembly(id: string, s: Structure) { - console.time('assembly') + console.time('assembly'); const a = await StructureSymmetry.buildAssembly(s, '1').run(); // const auth_comp_id = SP.residue.auth_comp_id; // const q1 = Query(Q.generators.atoms({ residueTest: l => auth_comp_id(l) === 'ALA' })); // const alas = await query(q1, a); - console.timeEnd('assembly') + console.timeEnd('assembly'); fs.writeFileSync(`${DATA_DIR}/${id}_assembly.bcif`, to_mmCIF(id, a, true)); // fs.writeFileSync(`${DATA_DIR}/${id}_assembly.bcif`, to_mmCIF(id, Selection.unionStructure(alas), true)); console.log('exported'); } export async function testSymmetry(id: string, s: Structure) { - console.time('symmetry') + console.time('symmetry'); const a = await StructureSymmetry.buildSymmetryRange(s, Vec3.create(-1, -1, -1), Vec3.create(1, 1, 1)).run(); // const auth_comp_id = SP.residue.auth_comp_id; // const q1 = Query(Q.generators.atoms({ residueTest: l => auth_comp_id(l) === 'ALA' })); // const alas = await query(q1, a); - console.timeEnd('symmetry') + console.timeEnd('symmetry'); fs.writeFileSync(`${DATA_DIR}/${id}_symm.bcif`, to_mmCIF(id, a, true)); // fs.writeFileSync(`${DATA_DIR}/${id}_assembly.bcif`, to_mmCIF(id, Selection.unionStructure(alas), true)); console.log('exported'); @@ -315,7 +315,7 @@ export namespace PropertyAccess { export async function testIncludeSurroundings(id: string, s: Structure) { // const a = s; - console.time('symmetry') + console.time('symmetry'); const a = await StructureSymmetry.buildSymmetryRange(s, Vec3.create(-2, -2, -2), Vec3.create(2, 2, 2)).run(); // console.log(printUnits(a)); @@ -329,7 +329,7 @@ export namespace PropertyAccess { wholeResidues: true }); const surr = StructureSelection.unionStructure(StructureQuery.run(q1, a)); - console.timeEnd('symmetry') + console.timeEnd('symmetry'); // for (const u of surr.units) { // const { atomId } = u.model.atomicConformation; @@ -375,7 +375,7 @@ export namespace PropertyAccess { export async function runBonds() { const { structures } = await readCIF('e:/test/quick/3j3q_full.bcif'); console.time('bonds'); - structures[0].interUnitBonds + structures[0].interUnitBonds; console.timeEnd('bonds'); } @@ -424,9 +424,9 @@ export namespace PropertyAccess { console.time('atom.x'); console.log('atom.x', sumProperty(structures[0], SP.atom.x)); console.timeEnd('atom.x'); - console.time('__x') + console.time('__x'); // console.log('__x', sumProperty(structures[0], l => l.unit.conformation.x[l.atom])); - console.timeEnd('__x') + console.timeEnd('__x'); // const authSeqId = Element.property(l => l.unit.hierarchy.residues.auth_seq_id.value(l.unit.residueIndex[l.atom])); @@ -436,7 +436,7 @@ export namespace PropertyAccess { // const set = new Set(['A', 'B', 'C', 'D']); // const q = Q.generators.atomGroups({ atomTest: l => auth_seq_id(l) < 3 }); const q = Q.generators.atoms({ atomTest: Q.pred.eq(l => SP.residue.auth_comp_id(l.element), 'ALA') }); - const P = SP + const P = SP; // const q0 = Q.generators.atoms({ atomTest: l => auth_comp_id(l) === 'ALA' }); const q1 = (Q.generators.atoms({ residueTest: l => auth_comp_id(l.element) === 'ALA' })); const q2 = (Q.generators.atoms({ residueTest: l => auth_comp_id(l.element) === 'ALA', groupBy: l => SP.residue.key(l.element) })); @@ -447,15 +447,15 @@ export namespace PropertyAccess { await query(q, structures[0]); // console.log(to_mmCIF('test', Selection.union(q0r))); - console.time('q1') + console.time('q1'); query(q1, structures[0]); - console.timeEnd('q1') - console.time('q1') + console.timeEnd('q1'); + console.time('q1'); query(q1, structures[0]); - console.timeEnd('q1') - console.time('q2') + console.timeEnd('q1'); + console.time('q2'); const q2r = query(q2, structures[0]); - console.timeEnd('q2') + console.timeEnd('q2'); console.log(StructureSelection.structureCount(q2r)); // console.log(q1(structures[0])); diff --git a/src/perf-tests/tasks.ts b/src/perf-tests/tasks.ts index 9cfc3e01f891a3a8ad9b6fce96a24a4cd278e7ec..f71ca23f23775770cac7279bd079e42557c8f1e0 100644 --- a/src/perf-tests/tasks.ts +++ b/src/perf-tests/tasks.ts @@ -1,6 +1,6 @@ -import * as B from 'benchmark' +import * as B from 'benchmark'; import { now } from '../mol-util/now'; -import { Scheduler } from '../mol-task/util/scheduler' +import { Scheduler } from '../mol-task/util/scheduler'; export namespace Tasks { export class Yielding { @@ -93,7 +93,7 @@ export namespace Tasks { export function run() { const suite = new B.Suite(); suite - .add(`yielding`, async () => { return await yielding() }) + .add(`yielding`, async () => { return await yielding(); }) // .add(`test yielding`, () => testYielding().then(() => { })) .on('cycle', (e: any) => console.log(String(e.target))) .run(); @@ -172,7 +172,7 @@ export namespace Tasks { // await Tasks.testYielding(); await Tasks.awaitF(); -}()) +}()); // console.time('test') // Tasks.yielding(); diff --git a/src/servers/common/swagger-ui/index.ts b/src/servers/common/swagger-ui/index.ts index fe93b0a0483adc081850a61db5111ee6a512da0e..1c0348a7c61a47bf8d4db60546f0af4b16ff4cbb 100644 --- a/src/servers/common/swagger-ui/index.ts +++ b/src/servers/common/swagger-ui/index.ts @@ -4,17 +4,17 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as express from 'express' -import * as fs from 'fs' -import { getAbsoluteFSPath } from 'swagger-ui-dist' +import * as express from 'express'; +import * as fs from 'fs'; +import { getAbsoluteFSPath } from 'swagger-ui-dist'; import { ServeStaticOptions } from 'serve-static'; import { interpolate } from '../../../mol-util/string'; import { Handler } from 'express-serve-static-core'; export function swaggerUiAssetsHandler(options?: ServeStaticOptions): Handler { - const opts = options || {} - opts.index = false - return express.static(getAbsoluteFSPath(), opts) + const opts = options || {}; + opts.index = false; + return express.static(getAbsoluteFSPath(), opts); } export interface SwaggerUIOptions { @@ -25,14 +25,14 @@ export interface SwaggerUIOptions { } function createHTML(options: SwaggerUIOptions) { - const htmlTemplate = fs.readFileSync(`${__dirname}/indexTemplate.html`).toString() - return interpolate(htmlTemplate, options) + const htmlTemplate = fs.readFileSync(`${__dirname}/indexTemplate.html`).toString(); + return interpolate(htmlTemplate, options); } export function swaggerUiIndexHandler(options: SwaggerUIOptions): express.Handler { - const html = createHTML(options) + const html = createHTML(options); return (req: express.Request, res: express.Response) => { res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(html); - } + }; } \ No newline at end of file diff --git a/src/servers/model/config.ts b/src/servers/model/config.ts index 993a41db23f380f57154b4a0c65e1a67186d4aae..ddba031699a3338d803ec096aaf8a42ed3fe9b88 100644 --- a/src/servers/model/config.ts +++ b/src/servers/model/config.ts @@ -4,10 +4,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as argparse from 'argparse' -import { ObjectKeys } from '../../mol-util/type-helpers' -import VERSION from './version' -import * as fs from 'fs' +import * as argparse from 'argparse'; +import { ObjectKeys } from '../../mol-util/type-helpers'; +import VERSION from './version'; +import * as fs from 'fs'; import { ModelPropertyProviderConfig } from './property-provider'; const DefaultModelServerConfig = { @@ -108,12 +108,12 @@ const DefaultModelServerConfig = { ] as ([string, string] | [string, string, ModelServerFetchFormats])[] }; -export const ModelServerFetchFormats = ['cif', 'bcif', 'cif.gz', 'bcif.gz'] as const +export const ModelServerFetchFormats = ['cif', 'bcif', 'cif.gz', 'bcif.gz'] as const; export type ModelServerFetchFormats = (typeof ModelServerFetchFormats)[number] export let mapSourceAndIdToFilename: (source: string, id: string) => [string, ModelServerFetchFormats] = () => { throw new Error('call setupConfig & validateConfigAndSetupSourceMap to initialize this function'); -} +}; function addServerArgs(parser: argparse.ArgumentParser) { parser.addArgument([ '--apiPrefix' ], { @@ -200,7 +200,7 @@ function addServerArgs(parser: argparse.ArgumentParser) { } export type ModelServerConfig = typeof DefaultModelServerConfig -export const ModelServerConfig = { ...DefaultModelServerConfig } +export const ModelServerConfig = { ...DefaultModelServerConfig }; export const ModelServerConfigTemplate: ModelServerConfig = { ...DefaultModelServerConfig, @@ -210,10 +210,10 @@ export const ModelServerConfigTemplate: ModelServerConfig = { ['pdb-cif', './path-to-text-cif/${id.substr(1, 2)}/${id}.cif'], ['pdb-updated', 'https://www.ebi.ac.uk/pdbe/entry-files/download/${id}_updated.cif', 'cif'] ] as [string, string][] -} +}; // TODO: include once properly supported -delete ModelServerConfigTemplate.customProperties +delete ModelServerConfigTemplate.customProperties; interface ServerJsonConfig { cfg?: string, @@ -276,7 +276,7 @@ export function configureServer() { } try { - setConfig(config) // sets the config for global use + setConfig(config); // sets the config for global use if (config.cfg) { const cfg = JSON.parse(fs.readFileSync(config.cfg, 'utf8')) as ModelServerConfig; diff --git a/src/servers/model/preprocess.ts b/src/servers/model/preprocess.ts index db06f797091855101e644f8cb37a6cff3dd891b1..6da907e4a6083cd40f2e0ece8e2b43e5ea7c93a3 100644 --- a/src/servers/model/preprocess.ts +++ b/src/servers/model/preprocess.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as cluster from 'cluster' +import * as cluster from 'cluster'; import { runChild } from './preprocess/parallel'; if (cluster.isMaster) { diff --git a/src/servers/model/preprocess/master.ts b/src/servers/model/preprocess/master.ts index 4c7068208838bd82a9e09ea9c00f9ad23255ad57..687b9fe41931fbc50c7bbd61af8d11c2b857944d 100644 --- a/src/servers/model/preprocess/master.ts +++ b/src/servers/model/preprocess/master.ts @@ -4,9 +4,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as fs from 'fs' -import * as path from 'path' -import * as argparse from 'argparse' +import * as fs from 'fs'; +import * as path from 'path'; +import * as argparse from 'argparse'; import { runMaster, PreprocessEntry } from './parallel'; import { ModelPropertyProviderConfig } from '../property-provider'; @@ -23,9 +23,9 @@ function description() { } } } - } + }; - return `Preprocess CIF files to include custom properties and convert them to BinaryCIF format.\n\nExample cfg.json: ${JSON.stringify(exampleCfg, null, 2)}` + return `Preprocess CIF files to include custom properties and convert them to BinaryCIF format.\n\nExample cfg.json: ${JSON.stringify(exampleCfg, null, 2)}`; } const cmdParser = new argparse.ArgumentParser({ @@ -68,8 +68,8 @@ if (Object.keys(cmdArgs).filter(k => (cmdArgs as any)[k] !== null).length === 0 process.exit(0); } -let entries: PreprocessEntry[] = [] -let config: PreprocessConfig = { numProcesses: cmdArgs.folderIn ? +(cmdArgs.folderNumProcesses || 1) : 1, customProperties: void 0 } +let entries: PreprocessEntry[] = []; +let config: PreprocessConfig = { numProcesses: cmdArgs.folderIn ? +(cmdArgs.folderNumProcesses || 1) : 1, customProperties: void 0 }; if (cmdArgs.input) entries.push({ source: cmdArgs.input, cif: cmdArgs.outCIF, bcif: cmdArgs.outBCIF }); // else if (cmdArgs.bulk) runBulk(cmdArgs.bulk); diff --git a/src/servers/model/preprocess/parallel.ts b/src/servers/model/preprocess/parallel.ts index 3d222242a968596affb630c34da06d767518aefc..399e06c920378a7b76d4df3abaaa207f46960d4d 100644 --- a/src/servers/model/preprocess/parallel.ts +++ b/src/servers/model/preprocess/parallel.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as path from 'path' -import * as cluster from 'cluster' +import * as path from 'path'; +import * as cluster from 'cluster'; import { now } from '../../../mol-util/now'; import { PerformanceMonitor } from '../../../mol-util/performance-monitor'; import { preprocessFile } from './preprocess'; @@ -28,9 +28,9 @@ export function runMaster(config: PreprocessConfig, entries: PreprocessEntry[]) const elapsed = now() - started; console.log(`[${progress}/${entries.length}] in ${PerformanceMonitor.format(elapsed)} (avg ${PerformanceMonitor.format(elapsed / progress)}).`); } else if (msg.type === 'error') { - console.error(`${msg.id}: ${msg.error}`) + console.error(`${msg.id}: ${msg.error}`); } - } + }; if (entries.length === 1) { runSingle(entries[0], config, onMessage); diff --git a/src/servers/model/properties/pdbe.ts b/src/servers/model/properties/pdbe.ts index 9512ae5fb196fc1b12533e640999487cdfa89c21..023c65f3c52d4c4bddb1344527f0c07840a3ebb7 100644 --- a/src/servers/model/properties/pdbe.ts +++ b/src/servers/model/properties/pdbe.ts @@ -16,4 +16,4 @@ export const attachModelProperties: AttachModelProperties = (args) => { PDBe_preferredAssembly(args), PDBe_structRefDomain(args) ]; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/servers/model/properties/providers/pdbe.ts b/src/servers/model/properties/providers/pdbe.ts index 4e4f314ee725363bacafc75f5d4523f5dee36690..87a20fce8ac6d1c476ae745d257e85af3c66f264 100644 --- a/src/servers/model/properties/providers/pdbe.ts +++ b/src/servers/model/properties/providers/pdbe.ts @@ -4,8 +4,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as fs from 'fs' -import * as path from 'path' +import * as fs from 'fs'; +import * as path from 'path'; import { Model } from '../../../../mol-model/structure'; import { StructureQualityReportProvider, StructureQualityReport } from '../../../../mol-model-props/pdbe/structure-quality-report'; import { fetchRetry } from '../../utils/fetch-retry'; @@ -20,19 +20,19 @@ export const PDBe_structureQualityReport: AttachModelProperty = async ({ model, const PDBe_apiSourceJson = useFileSource(params) ? residuewise_outlier_summary.getDataFromAggregateFile(getFilePrefix(params, 'residuewise_outlier_summary')) : apiQueryProvider(getApiUrl(params, 'residuewise_outlier_summary', StructureQualityReport.DefaultServerUrl), cache); - const data = StructureQualityReport.fromJson(model, await PDBe_apiSourceJson(model)) - return StructureQualityReportProvider.set(model, { serverUrl: StructureQualityReport.DefaultServerUrl }, data) -} + const data = StructureQualityReport.fromJson(model, await PDBe_apiSourceJson(model)); + return StructureQualityReportProvider.set(model, { serverUrl: StructureQualityReport.DefaultServerUrl }, data); +}; export const PDBe_preferredAssembly: AttachModelProperty = ({ model, params, cache }) => { const PDBe_apiSourceJson = apiQueryProvider(getApiUrl(params, 'preferred_assembly', 'https://www.ebi.ac.uk/pdbe/api/pdb/entry/summary'), cache); return PDBePreferredAssembly.attachFromCifOrApi(model, { PDBe_apiSourceJson }); -} +}; export const PDBe_structRefDomain: AttachModelProperty = ({ model, params, cache }) => { const PDBe_apiSourceJson = apiQueryProvider(getApiUrl(params, 'struct_ref_domain', 'https://www.ebi.ac.uk/pdbe/api/mappings/sequence_domains'), cache); return PDBeStructRefDomain.attachFromCifOrApi(model, { PDBe_apiSourceJson }); -} +}; namespace residuewise_outlier_summary { const json = new Map<string, any>(); @@ -48,7 +48,7 @@ namespace residuewise_outlier_summary { else json.set(key, JSON.parse(fs.readFileSync(fn, 'utf8'))); } return json.get(key)![model.entryId.toLowerCase()] || { }; - } + }; } } @@ -66,7 +66,7 @@ function getFilePrefix(params: any, name: string) { } function useFileSource(params: any) { - return !!getParam<boolean>(params, 'PDBe', 'UseFileSource') + return !!getParam<boolean>(params, 'PDBe', 'UseFileSource'); } function apiQueryProvider(urlPrefix: string, cache: any) { @@ -85,5 +85,5 @@ function apiQueryProvider(urlPrefix: string, cache: any) { ConsoleLogger.warn('Props', `Count not retrieve prop @${`${urlPrefix}/${model.entryId.toLowerCase()}`}`); return { }; } - } + }; } \ No newline at end of file diff --git a/src/servers/model/properties/providers/wwpdb.ts b/src/servers/model/properties/providers/wwpdb.ts index c35f991be4998bd07dfcabaee8434f8b2ae3d483..4d8bcdb14283dcbdab4d07c6174fecfddcc86a21 100644 --- a/src/servers/model/properties/providers/wwpdb.ts +++ b/src/servers/model/properties/providers/wwpdb.ts @@ -4,37 +4,37 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as fs from 'fs' -import * as util from 'util' +import * as fs from 'fs'; +import * as util from 'util'; import { AttachModelProperty } from '../../property-provider'; import { CIF } from '../../../../mol-io/reader/cif'; import { getParam } from '../../../common/util'; import { mmCIF_Database, mmCIF_Schema } from '../../../../mol-io/reader/cif/schema/mmcif'; import { ComponentBond } from '../../../../mol-model-formats/structure/property/bonds/comp'; -require('util.promisify').shim() -const readFile = util.promisify(fs.readFile) +require('util.promisify').shim(); +const readFile = util.promisify(fs.readFile); export const wwPDB_chemCompBond: AttachModelProperty = async ({ model, params }) => { - const table = await getChemCompBondTable(getTablePath(params)) - const data = ComponentBond.chemCompBondFromTable(model, table) - const entries = ComponentBond.getEntriesFromChemCompBond(data) - return ComponentBond.Provider.set(model, { entries, data }) -} + const table = await getChemCompBondTable(getTablePath(params)); + const data = ComponentBond.chemCompBondFromTable(model, table); + const entries = ComponentBond.getEntriesFromChemCompBond(data); + return ComponentBond.Provider.set(model, { entries, data }); +}; async function read(path: string) { return path.endsWith('.bcif') ? new Uint8Array(await readFile(path)) : readFile(path, 'utf8'); } -let chemCompBondTable: mmCIF_Database['chem_comp_bond'] +let chemCompBondTable: mmCIF_Database['chem_comp_bond']; async function getChemCompBondTable(path: string): Promise<mmCIF_Database['chem_comp_bond']> { if (!chemCompBondTable) { - const parsed = await CIF.parse(await read(path)).run() - if (parsed.isError) throw new Error(parsed.toString()) - const table = CIF.toDatabase(mmCIF_Schema, parsed.result.blocks[0]) - chemCompBondTable = table.chem_comp_bond + const parsed = await CIF.parse(await read(path)).run(); + if (parsed.isError) throw new Error(parsed.toString()); + const table = CIF.toDatabase(mmCIF_Schema, parsed.result.blocks[0]); + chemCompBondTable = table.chem_comp_bond; } - return chemCompBondTable + return chemCompBondTable; } function getTablePath(params: any) { diff --git a/src/servers/model/properties/wwpdb.ts b/src/servers/model/properties/wwpdb.ts index cb4040db1f7ac0ac78899f42d472e24113019bd9..ec6bef64e780f1c16757aae74a1ffb8468e6c6da 100644 --- a/src/servers/model/properties/wwpdb.ts +++ b/src/servers/model/properties/wwpdb.ts @@ -13,4 +13,4 @@ export const attachModelProperties: AttachModelProperties = (args) => { return [ wwPDB_chemCompBond(args) ]; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/servers/model/property-provider.ts b/src/servers/model/property-provider.ts index 92c5eb63798fa2c4177d8500d9da9d693ccc9f58..aead98a1b534adf99acb599ba10205a230d9f538 100644 --- a/src/servers/model/property-provider.ts +++ b/src/servers/model/property-provider.ts @@ -4,19 +4,19 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as fs from 'fs' +import * as fs from 'fs'; import { Model } from '../../mol-model/structure'; import { ModelServerConfig as Config } from './config'; import { ConsoleLogger } from '../../mol-util/console-logger'; // TODO enable dynamic imports again -import * as pdbeProps from './properties/pdbe' -import * as wwpdbProps from './properties/wwpdb' +import * as pdbeProps from './properties/pdbe'; +import * as wwpdbProps from './properties/wwpdb'; const attachModelProperties: { [k: string]: AttachModelProperties } = { pdbe: pdbeProps.attachModelProperties, wwpdb: wwpdbProps.attachModelProperties -} +}; export interface ModelPropertyProviderConfig { sources: string[], @@ -61,5 +61,5 @@ export function createModelPropertiesProvider(configOrPath: ModelPropertyProvide for (const e of p({ model, cache, params: config.params })) ret.push(e); } return ret; - } + }; } diff --git a/src/servers/model/query.ts b/src/servers/model/query.ts index 597f9f66785e2dcac595ee1d39a4d25c589c6470..556f497fcec2ae93a22feeff1c336865109cea8b 100644 --- a/src/servers/model/query.ts +++ b/src/servers/model/query.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as fs from 'fs' +import * as fs from 'fs'; import Version from './version'; import { LocalInput, runLocal } from './server/api-local'; diff --git a/src/servers/model/query/schemas.ts b/src/servers/model/query/schemas.ts index 521720d3be684056ce83ada77ac9429eb45769e8..f65175409296daf4c7dfb9f2e175038b70d51d80 100644 --- a/src/servers/model/query/schemas.ts +++ b/src/servers/model/query/schemas.ts @@ -59,4 +59,4 @@ export const QuerySchemas = { includeCategory(name) { return AssemblyCategories.has(name); }, includeField(cat, field) { return true; } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/servers/model/server.ts b/src/servers/model/server.ts index 1844c8ae2365a25572e4771822a017094fcf7b12..dae8c8583b9e73d9e35b343b81af11f3bf1b34ad 100644 --- a/src/servers/model/server.ts +++ b/src/servers/model/server.ts @@ -5,13 +5,13 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import compression from 'compression' -import express from 'express' -import { ConsoleLogger } from '../../mol-util/console-logger' -import { PerformanceMonitor } from '../../mol-util/performance-monitor' -import { configureServer, ModelServerConfig as ServerConfig } from './config' -import { initWebApi } from './server/api-web' -import Version from './version' +import compression from 'compression'; +import express from 'express'; +import { ConsoleLogger } from '../../mol-util/console-logger'; +import { PerformanceMonitor } from '../../mol-util/performance-monitor'; +import { configureServer, ModelServerConfig as ServerConfig } from './config'; +import { initWebApi } from './server/api-web'; +import Version from './version'; function setupShutdown() { if (ServerConfig.shutdownTimeoutVarianceMinutes > ServerConfig.shutdownTimeoutMinutes) { diff --git a/src/servers/model/server/api-schema.ts b/src/servers/model/server/api-schema.ts index 37de73f2a971a2528ba32284d38274896c007c60..e2071c4d7c5262afcafcb1d9ca340d58f272ddc0 100644 --- a/src/servers/model/server/api-schema.ts +++ b/src/servers/model/server/api-schema.ts @@ -4,12 +4,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import VERSION from '../version' +import VERSION from '../version'; import { QueryParamInfo, QueryParamType, QueryDefinition, CommonQueryParamsInfo, QueryList } from './api'; import { ModelServerConfig as ServerConfig } from '../config'; import { MultipleQuerySpec } from './api-web-multiple'; -export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />` +export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />`; export function getApiSchema() { return { @@ -39,7 +39,7 @@ export function getApiSchema() { }, } } - } + }; } function getPaths() { diff --git a/src/servers/model/server/api-web.ts b/src/servers/model/server/api-web.ts index d417d3629a07194f2a3a8a4790b47e77b118a0ac..3bf8c684781982b54f4df7e6015280917b4f0d8f 100644 --- a/src/servers/model/server/api-web.ts +++ b/src/servers/model/server/api-web.ts @@ -7,7 +7,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as express from 'express'; -import * as bodyParser from 'body-parser' +import * as bodyParser from 'body-parser'; import { ModelServerConfig as Config, ModelServerConfig, mapSourceAndIdToFilename } from '../config'; import { ConsoleLogger } from '../../../mol-util/console-logger'; import { resolveJob } from './query'; @@ -156,7 +156,7 @@ export function initWebApi(app: express.Express) { }); app.post(makePath('v1/query-many'), (req, res) => { const params = req.body; - req.setTimeout + req.setTimeout; createMultiJob(params, res); }); diff --git a/src/servers/model/server/api.ts b/src/servers/model/server/api.ts index 0eccd61a1762aeee32eb5f57fafc67756dfdb95b..e2a797be53d2fcf670349c7543ce4f5ec63e6468 100644 --- a/src/servers/model/server/api.ts +++ b/src/servers/model/server/api.ts @@ -68,7 +68,7 @@ export const AtomSiteSchemaElement = { label_atom_id: { type: QueryParamType.String, groupName: 'atom_site' }, auth_atom_id: { type: QueryParamType.String, groupName: 'atom_site' }, type_symbol: { type: QueryParamType.String, groupName: 'atom_site' } -} +}; export interface AtomSiteSchemaElement { label_entity_id?: string, @@ -203,7 +203,7 @@ export function getQueryByName(name: QueryName): QueryDefinition { export const QueryList = (function () { const list: { name: string, definition: QueryDefinition }[] = []; for (const k of Object.keys(QueryMap)) list.push({ name: k, definition: <QueryDefinition>QueryMap[k as QueryName] }); - list.sort(function (a, b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0 }); + list.sort(function (a, b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; }); return list; })(); diff --git a/src/servers/model/server/cache.ts b/src/servers/model/server/cache.ts index 365923c17bf1b093fd397f679f07ef9cbb279629..40083303139e3dd87a94215b29fbcdf412d8e39d 100644 --- a/src/servers/model/server/cache.ts +++ b/src/servers/model/server/cache.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { ConsoleLogger } from '../../../mol-util/console-logger' +import { ConsoleLogger } from '../../../mol-util/console-logger'; import { LinkedList } from '../../../mol-data/generic'; import { ModelServerConfig as ServerConfig } from '../config'; diff --git a/src/servers/model/server/jobs.ts b/src/servers/model/server/jobs.ts index 9a4960b39167a263a98593682ff28abefc3bbefe..62919e74704116b32b2c4576291c355031cc7645 100644 --- a/src/servers/model/server/jobs.ts +++ b/src/servers/model/server/jobs.ts @@ -66,7 +66,7 @@ export function JobEntry<Name extends QueryName>(definition: JobEntryDefinition< queryDefinition, normalizedParams, modelNums: definition.modelNums - } + }; } export function createJob(definition: JobDefinition): Job { diff --git a/src/servers/model/server/query.ts b/src/servers/model/server/query.ts index 0c7b76eeba168325cf61e258201246c4b3d52ca1..4b08c065bec5c1d48945f3fd44166bdac3eb590e 100644 --- a/src/servers/model/server/query.ts +++ b/src/servers/model/server/query.ts @@ -67,7 +67,7 @@ async function resolveSingleFile(job: Job) { headerMap.set(header, i); header += ' ' + i; } else { - headerMap.set(header, 0) + headerMap.set(header, 0); } encoder.startDataBlock(header); @@ -163,7 +163,7 @@ async function resolveJobEntry(entry: JobEntry, structure: StructureWrapper, enc const queries = structures.map(s => entry.queryDefinition.query(entry.normalizedParams, s)); const result: Structure[] = []; for (let i = 0; i < structures.length; i++) { - const s = await StructureSelection.unionStructure(StructureQuery.run(queries[i], structures[i], { timeoutMs: Config.queryTimeoutMs })) + const s = await StructureSelection.unionStructure(StructureQuery.run(queries[i], structures[i], { timeoutMs: Config.queryTimeoutMs })); if (s.elementCount > 0) result.push(s); } perf.end('query'); @@ -282,4 +282,4 @@ const _model_server_params: CifWriter.Category<JobEntry> = { const _model_server_stats: CifWriter.Category<Stats> = { name: 'model_server_stats', instance: (stats) => CifWriter.categoryInstance(_model_server_stats_fields, { data: stats, rowCount: 1 }) -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/servers/model/server/structure-wrapper.ts b/src/servers/model/server/structure-wrapper.ts index 62b8e3b3d1bda0bda42a1be81e4feb56a7574a69..9fdb746a2c087034d363798f9ce5451ee37cfdaa 100644 --- a/src/servers/model/server/structure-wrapper.ts +++ b/src/servers/model/server/structure-wrapper.ts @@ -8,10 +8,10 @@ import { Structure, Model } from '../../../mol-model/structure'; import { PerformanceMonitor } from '../../../mol-util/performance-monitor'; import { Cache } from './cache'; import { ModelServerConfig as Config, mapSourceAndIdToFilename, ModelServerFetchFormats } from '../config'; -import { CIF, CifFrame, CifBlock } from '../../../mol-io/reader/cif' -import * as util from 'util' -import * as fs from 'fs' -import * as zlib from 'zlib' +import { CIF, CifFrame, CifBlock } from '../../../mol-io/reader/cif'; +import * as util from 'util'; +import * as fs from 'fs'; +import * as zlib from 'zlib'; import { JobEntry } from './jobs'; import { ConsoleLogger } from '../../../mol-util/console-logger'; import { ModelPropertiesProvider } from '../property-provider'; @@ -70,7 +70,7 @@ const unzipAsync = util.promisify<zlib.InputType, Buffer>(zlib.unzip); async function readFile(filename: string) { const isGz = /\.gz$/i.test(filename); if (filename.match(/\.bcif/)) { - let input = await readFileAsync(filename) + let input = await readFileAsync(filename); if (isGz) input = await unzipAsync(input); const data = new Uint8Array(input.byteLength); for (let i = 0; i < input.byteLength; i++) data[i] = input[i]; diff --git a/src/servers/model/utils/fetch-props-pdbe.ts b/src/servers/model/utils/fetch-props-pdbe.ts index 047a955317e4f9562411463980379e031ec86ff5..a08094e07d2e51ab6eca43011b231f2e254ace3e 100644 --- a/src/servers/model/utils/fetch-props-pdbe.ts +++ b/src/servers/model/utils/fetch-props-pdbe.ts @@ -5,9 +5,9 @@ */ import fetch from 'node-fetch'; -import * as fs from 'fs' -import * as path from 'path' -import * as argparse from 'argparse' +import * as fs from 'fs'; +import * as path from 'path'; +import * as argparse from 'argparse'; import { makeDir } from '../../../mol-util/make-dir'; import { now } from '../../../mol-util/now'; import { PerformanceMonitor } from '../../../mol-util/performance-monitor'; @@ -53,7 +53,7 @@ function findEntries() { const ret: { key: string, entries: string[] }[] = []; for (const key of keys) { - ret.push({ key, entries: groups.get(key)! }) + ret.push({ key, entries: groups.get(key)! }); } return ret; @@ -67,7 +67,7 @@ async function process() { let prog = 0; for (const e of entries) { const ts = now(); - console.log(`${prog}/${entries.length} ${e.entries.length} entries.`) + console.log(`${prog}/${entries.length} ${e.entries.length} entries.`); const data = Object.create(null); for (let ee of e.entries) { diff --git a/src/servers/model/utils/tar.ts b/src/servers/model/utils/tar.ts index 700e3329d18c448682db7a2428c19cd9288437e5..05695d2cdf51a8ebce4c78381965cb34f19f900f 100644 --- a/src/servers/model/utils/tar.ts +++ b/src/servers/model/utils/tar.ts @@ -3,112 +3,112 @@ * Copyright (c) 2014 Mathias Buus, MIT License (MIT) */ -import { constants } from 'fs' +import { constants } from 'fs'; -let alloc = Buffer.alloc +let alloc = Buffer.alloc; -let ZEROS = '0000000000000000000' -let SEVENS = '7777777777777777777' -let ZERO_OFFSET = '0'.charCodeAt(0) -let USTAR_MAGIC = Buffer.from('ustar\x00', 'binary') -let USTAR_VER = Buffer.from('00', 'binary') -let MASK = parseInt('7777', 8) -let MAGIC_OFFSET = 257 -let VERSION_OFFSET = 263 +let ZEROS = '0000000000000000000'; +let SEVENS = '7777777777777777777'; +let ZERO_OFFSET = '0'.charCodeAt(0); +let USTAR_MAGIC = Buffer.from('ustar\x00', 'binary'); +let USTAR_VER = Buffer.from('00', 'binary'); +let MASK = parseInt('7777', 8); +let MAGIC_OFFSET = 257; +let VERSION_OFFSET = 263; let toTypeflag = function (flag: string) { switch (flag) { case 'file': - return 0 + return 0; case 'link': - return 1 + return 1; case 'symlink': - return 2 + return 2; case 'character-device': - return 3 + return 3; case 'block-device': - return 4 + return 4; case 'directory': - return 5 + return 5; case 'fifo': - return 6 + return 6; case 'contiguous-file': - return 7 + return 7; case 'pax-header': - return 72 + return 72; } - return 0 -} + return 0; +}; let indexOf = function (block: any, num: any, offset: any, end: any) { for (; offset < end; offset++) { - if (block[offset] === num) return offset + if (block[offset] === num) return offset; } - return end -} + return end; +}; let cksum = function (block: any) { - let sum = 8 * 32 - for (let i = 0; i < 148; i++) sum += block[i] - for (let j = 156; j < 512; j++) sum += block[j] - return sum -} + let sum = 8 * 32; + for (let i = 0; i < 148; i++) sum += block[i]; + for (let j = 156; j < 512; j++) sum += block[j]; + return sum; +}; let encodeOct = function (val: any, n: any) { - val = val.toString(8) - if (val.length > n) return SEVENS.slice(0, n) + ' ' - else return ZEROS.slice(0, n - val.length) + val + ' ' -} + val = val.toString(8); + if (val.length > n) return SEVENS.slice(0, n) + ' '; + else return ZEROS.slice(0, n - val.length) + val + ' '; +}; let decodeStr = function (val: any, offset: any, length: any, encoding?: any) { - return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding) -} + return val.slice(offset, indexOf(val, 0, offset, offset + length)).toString(encoding); +}; let addLength = function (str: any) { - let len = Buffer.byteLength(str) - let digits = Math.floor(Math.log(len) / Math.log(10)) + 1 - if (len + digits >= Math.pow(10, digits)) digits++ + let len = Buffer.byteLength(str); + let digits = Math.floor(Math.log(len) / Math.log(10)) + 1; + if (len + digits >= Math.pow(10, digits)) digits++; - return (len + digits) + str -} + return (len + digits) + str; +}; exports.decodeLongPath = function (buf: any, encoding: any) { - return decodeStr(buf, 0, buf.length, encoding) -} + return decodeStr(buf, 0, buf.length, encoding); +}; exports.encodePax = function (opts: any) { - let result = '' - if (opts.name) result += addLength(' path=' + opts.name + '\n') - if (opts.linkname) result += addLength(' linkpath=' + opts.linkname + '\n') - let pax = opts.pax + let result = ''; + if (opts.name) result += addLength(' path=' + opts.name + '\n'); + if (opts.linkname) result += addLength(' linkpath=' + opts.linkname + '\n'); + let pax = opts.pax; if (pax) { for (let key in pax) { - result += addLength(' ' + key + '=' + pax[key] + '\n') + result += addLength(' ' + key + '=' + pax[key] + '\n'); } } - return Buffer.from(result) -} + return Buffer.from(result); +}; exports.decodePax = function (buf: any) { - let result: any = {} + let result: any = {}; while (buf.length) { - let i = 0 - while (i < buf.length && buf[i] !== 32) i++ - let len = parseInt(buf.slice(0, i).toString(), 10) - if (!len) return result + let i = 0; + while (i < buf.length && buf[i] !== 32) i++; + let len = parseInt(buf.slice(0, i).toString(), 10); + if (!len) return result; - let b = buf.slice(i + 1, len - 1).toString() - let keyIndex = b.indexOf('=') - if (keyIndex === -1) return result - result[b.slice(0, keyIndex)] = b.slice(keyIndex + 1) + let b = buf.slice(i + 1, len - 1).toString(); + let keyIndex = b.indexOf('='); + if (keyIndex === -1) return result; + result[b.slice(0, keyIndex)] = b.slice(keyIndex + 1); - buf = buf.slice(len) + buf = buf.slice(len); } - return result -} + return result; +}; export interface Headers { name: string; @@ -141,71 +141,71 @@ export interface Headers { function modeToType(mode: number) { switch (mode & constants.S_IFMT) { - case constants.S_IFBLK: return 'block-device' - case constants.S_IFCHR: return 'character-device' - case constants.S_IFDIR: return 'directory' - case constants.S_IFIFO: return 'fifo' - case constants.S_IFLNK: return 'symlink' + case constants.S_IFBLK: return 'block-device'; + case constants.S_IFCHR: return 'character-device'; + case constants.S_IFDIR: return 'directory'; + case constants.S_IFIFO: return 'fifo'; + case constants.S_IFLNK: return 'symlink'; } - return 'file' + return 'file'; } -let DMODE = parseInt('755', 8) -let FMODE = parseInt('644', 8) +let DMODE = parseInt('755', 8); +let FMODE = parseInt('644', 8); function normalizeHeader(header: Headers) { - if (!header.size || header.type === 'symlink') header.size = 0 - if (!header.type) header.type = modeToType(header.mode || 0) - if (!header.mode) header.mode = header.type === 'directory' ? DMODE : FMODE - if (!header.uid) header.uid = 0 - if (!header.gid) header.gid = 0 - if (!header.mtime) header.mtime = new Date() + if (!header.size || header.type === 'symlink') header.size = 0; + if (!header.type) header.type = modeToType(header.mode || 0); + if (!header.mode) header.mode = header.type === 'directory' ? DMODE : FMODE; + if (!header.uid) header.uid = 0; + if (!header.gid) header.gid = 0; + if (!header.mtime) header.mtime = new Date(); } -export const END_OF_TAR = alloc(1024) +export const END_OF_TAR = alloc(1024); export function encodeTarHeader(opts: Headers) { normalizeHeader(opts); - let buf = alloc(512) - let name = opts.name - let prefix = '' + let buf = alloc(512); + let name = opts.name; + let prefix = ''; - if (opts.typeflag === 5 && name[name.length - 1] !== '/') name += '/' - if (Buffer.byteLength(name) !== name.length) return null // utf-8 + if (opts.typeflag === 5 && name[name.length - 1] !== '/') name += '/'; + if (Buffer.byteLength(name) !== name.length) return null; // utf-8 while (Buffer.byteLength(name) > 100) { - let i = name.indexOf('/') - if (i === -1) return null - prefix += prefix ? '/' + name.slice(0, i) : name.slice(0, i) - name = name.slice(i + 1) + let i = name.indexOf('/'); + if (i === -1) return null; + prefix += prefix ? '/' + name.slice(0, i) : name.slice(0, i); + name = name.slice(i + 1); } - if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null - if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null + if (Buffer.byteLength(name) > 100 || Buffer.byteLength(prefix) > 155) return null; + if (opts.linkname && Buffer.byteLength(opts.linkname) > 100) return null; - buf.write(name) - buf.write(encodeOct(opts.mode! & MASK, 6), 100) - buf.write(encodeOct(opts.uid, 6), 108) - buf.write(encodeOct(opts.gid, 6), 116) - buf.write(encodeOct(opts.size, 11), 124) - buf.write(encodeOct((opts.mtime?.getTime()! / 1000) | 0, 11), 136) + buf.write(name); + buf.write(encodeOct(opts.mode! & MASK, 6), 100); + buf.write(encodeOct(opts.uid, 6), 108); + buf.write(encodeOct(opts.gid, 6), 116); + buf.write(encodeOct(opts.size, 11), 124); + buf.write(encodeOct((opts.mtime?.getTime()! / 1000) | 0, 11), 136); - buf[156] = ZERO_OFFSET + toTypeflag(opts.type!) + buf[156] = ZERO_OFFSET + toTypeflag(opts.type!); - if (opts.linkname) buf.write(opts.linkname, 157) + if (opts.linkname) buf.write(opts.linkname, 157); - USTAR_MAGIC.copy(buf, MAGIC_OFFSET) - USTAR_VER.copy(buf, VERSION_OFFSET) - if (opts.uname) buf.write(opts.uname, 265) - if (opts.gname) buf.write(opts.gname, 297) - buf.write(encodeOct(opts.devmajor || 0, 6), 329) - buf.write(encodeOct(opts.devminor || 0, 6), 337) + USTAR_MAGIC.copy(buf, MAGIC_OFFSET); + USTAR_VER.copy(buf, VERSION_OFFSET); + if (opts.uname) buf.write(opts.uname, 265); + if (opts.gname) buf.write(opts.gname, 297); + buf.write(encodeOct(opts.devmajor || 0, 6), 329); + buf.write(encodeOct(opts.devminor || 0, 6), 337); - if (prefix) buf.write(prefix, 345) + if (prefix) buf.write(prefix, 345); - buf.write(encodeOct(cksum(buf), 6), 148) + buf.write(encodeOct(cksum(buf), 6), 148); - return buf + return buf; } \ No newline at end of file diff --git a/src/servers/model/utils/writer.ts b/src/servers/model/utils/writer.ts index 167c8761d0af76a00eecca32923cdda32cc0c80d..e92d0264044114df313bd6c8da0bbdadb865c123 100644 --- a/src/servers/model/utils/writer.ts +++ b/src/servers/model/utils/writer.ts @@ -9,7 +9,7 @@ import * as fs from 'fs'; import * as path from 'path'; import { makeDir } from '../../../mol-util/make-dir'; import { encodeTarHeader, END_OF_TAR } from './tar'; -import * as zlib from 'zlib' +import * as zlib from 'zlib'; export interface ResultWriter { beginEntry(name: string, size: number): void, diff --git a/src/servers/plugin-state/api-schema.ts b/src/servers/plugin-state/api-schema.ts index 207bfb539a102fea1cd9c254be87dacd353cc1a1..9e49cb48ba37a13fd09e2bd6da06b244a2edd2da 100644 --- a/src/servers/plugin-state/api-schema.ts +++ b/src/servers/plugin-state/api-schema.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import VERSION from './version' +import VERSION from './version'; import { Config } from './config'; export function getSchema(config: Config) { @@ -128,7 +128,7 @@ export function getSchema(config: Config) { } }, } - } + }; } -export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />` \ No newline at end of file +export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />`; \ No newline at end of file diff --git a/src/servers/plugin-state/config.ts b/src/servers/plugin-state/config.ts index 8cd474926259ddb5462d03e68cb04bd840c29b78..38ecd7667bf88590647b486621ff1d1a0d39770b 100644 --- a/src/servers/plugin-state/config.ts +++ b/src/servers/plugin-state/config.ts @@ -4,7 +4,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as argparse from 'argparse' +import * as argparse from 'argparse'; export interface Config { working_folder: string, diff --git a/src/servers/plugin-state/index.ts b/src/servers/plugin-state/index.ts index afe11ac06c4d9f095599a72f4a9b050baf7f6171..6655c03b64e269cda403ba6c201e423ee34ee64e 100644 --- a/src/servers/plugin-state/index.ts +++ b/src/servers/plugin-state/index.ts @@ -4,17 +4,17 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import express from 'express' -import compression from 'compression' -import cors from 'cors' -import * as bodyParser from 'body-parser' -import * as fs from 'fs' -import * as path from 'path' +import express from 'express'; +import compression from 'compression'; +import cors from 'cors'; +import * as bodyParser from 'body-parser'; +import * as fs from 'fs'; +import * as path from 'path'; import { swaggerUiIndexHandler, swaggerUiAssetsHandler } from '../common/swagger-ui'; -import { makeDir } from '../../mol-util/make-dir' -import { getConfig } from './config' -import { UUID } from '../../mol-util' -import { shortcutIconLink, getSchema } from './api-schema' +import { makeDir } from '../../mol-util/make-dir'; +import { getConfig } from './config'; +import { UUID } from '../../mol-util'; +import { shortcutIconLink, getSchema } from './api-schema'; const Config = getConfig(); @@ -59,7 +59,7 @@ function validateIndex(index: Index) { for (const d of deletes) { try { - fs.unlinkSync(path.join(Config.working_folder, d.id + '.json')) + fs.unlinkSync(path.join(Config.working_folder, d.id + '.json')); } catch { } } return newIndex; @@ -83,7 +83,7 @@ function remove(id: string) { writeIndex(index); } catch { } try { - fs.unlinkSync(path.join(Config.working_folder, e.id + '.json')) + fs.unlinkSync(path.join(Config.working_folder, e.id + '.json')); } catch { } return; } @@ -93,7 +93,7 @@ function clear() { let index = readIndex(); for (const e of index) { try { - fs.unlinkSync(path.join(Config.working_folder, e.id + '.json')) + fs.unlinkSync(path.join(Config.working_folder, e.id + '.json')); } catch { } } writeIndex([]); diff --git a/src/servers/plugin-state/version.ts b/src/servers/plugin-state/version.ts index 63248cf1ca2c5dc699e108a6af83464585df98b7..cbec7416b7fc7e9504dfd4b7d433d23338e29530 100644 --- a/src/servers/plugin-state/version.ts +++ b/src/servers/plugin-state/version.ts @@ -1 +1 @@ -export default '0.1.0' \ No newline at end of file +export default '0.1.0'; \ No newline at end of file diff --git a/src/servers/volume/common/binary-schema.ts b/src/servers/volume/common/binary-schema.ts index 8fb875e57e19e0efdc77e3a771bccf2bcbf58118..4922ab43dcbf9d72bd49bf0cf02489e86d455342 100644 --- a/src/servers/volume/common/binary-schema.ts +++ b/src/servers/volume/common/binary-schema.ts @@ -6,7 +6,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as UTF8 from '../../../mol-io/common/utf8' +import * as UTF8 from '../../../mol-io/common/utf8'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; export type Bool = { kind: 'bool' } diff --git a/src/servers/volume/common/data-format.ts b/src/servers/volume/common/data-format.ts index 61ea4688834603d54324f9a932313bd2ae97bbe4..25a0bfbbc6e850aae79c10d4a970ac6813322ff2 100644 --- a/src/servers/volume/common/data-format.ts +++ b/src/servers/volume/common/data-format.ts @@ -6,7 +6,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Schema from './binary-schema' +import * as Schema from './binary-schema'; import { FileHandle } from '../../../mol-io/common/file-handle'; import { TypedArrayValueType } from '../../../mol-io/common/typed-array'; @@ -61,7 +61,7 @@ export interface Header { } namespace _schema { - const { array, obj, int, bool, float, str } = Schema + const { array, obj, int, bool, float, str } = Schema; export const schema = obj<Header>([ ['formatVersion', str], diff --git a/src/servers/volume/common/file.ts b/src/servers/volume/common/file.ts index d522224b160e3394acf7f312dd9a0239002089c9..cf221346f018c6e34a82e5e7b672924391aef1af 100644 --- a/src/servers/volume/common/file.ts +++ b/src/servers/volume/common/file.ts @@ -6,8 +6,8 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as fs from 'fs' -import * as path from 'path' +import * as fs from 'fs'; +import * as path from 'path'; import { FileHandle } from '../../../mol-io/common/file-handle'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; @@ -24,7 +24,7 @@ export async function openRead(filename: string) { } catch (e) { fs.closeSync(file); } - }) + }); }); } @@ -54,7 +54,7 @@ export function createFile(filename: string) { fs.open(filename, 'w', (err, file) => { if (err) rej(err); else res(file); - }) + }); }); } diff --git a/src/servers/volume/config.ts b/src/servers/volume/config.ts index 28648370157b5f8f5e0bf12aeebca03f0e8c7f4e..b1ac9db61a63b6cb92b46253d432579a845fe8c1 100644 --- a/src/servers/volume/config.ts +++ b/src/servers/volume/config.ts @@ -5,10 +5,10 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as argparse from 'argparse' -import { ObjectKeys } from '../../mol-util/type-helpers' -import { VOLUME_SERVER_HEADER, VOLUME_SERVER_VERSION } from './server/version' -import * as fs from 'fs' +import * as argparse from 'argparse'; +import { ObjectKeys } from '../../mol-util/type-helpers'; +import { VOLUME_SERVER_HEADER, VOLUME_SERVER_VERSION } from './server/version'; +import * as fs from 'fs'; const DefaultServerConfig = { apiPrefix: '/VolumeServer', @@ -16,7 +16,7 @@ const DefaultServerConfig = { shutdownTimeoutMinutes: 24 * 60, /* a day */ shutdownTimeoutVarianceMinutes: 60, idMap: [] as [string, string][] -} +}; function addLimitsArgs(parser: argparse.ArgumentParser) { parser.addArgument([ '--maxRequestBlockCount' ], { @@ -102,7 +102,7 @@ export interface ServerJsonConfig { } export type ServerConfig = typeof DefaultServerConfig -export const ServerConfig = { ...DefaultServerConfig } +export const ServerConfig = { ...DefaultServerConfig }; function setServerConfig(config: ServerConfig) { for (const k of ObjectKeys(ServerConfig)) { @@ -128,9 +128,9 @@ const DefaultLimitsConfig = { 16 * 1024 * 1024, // ~ 256*256*256 24 * 1024 * 1024 ] -} +}; export type LimitsConfig = typeof DefaultLimitsConfig -export const LimitsConfig = { ...DefaultLimitsConfig } +export const LimitsConfig = { ...DefaultLimitsConfig }; function setLimitsConfig(config: LimitsConfig) { for (const k of ObjectKeys(LimitsConfig)) { @@ -141,8 +141,8 @@ function setLimitsConfig(config: LimitsConfig) { type FullServerConfig = ServerConfig & LimitsConfig function setConfig(config: FullServerConfig) { - setServerConfig(config) - setLimitsConfig(config) + setServerConfig(config); + setLimitsConfig(config); } const ServerConfigTemplate: FullServerConfig = { @@ -152,7 +152,7 @@ const ServerConfigTemplate: FullServerConfig = { ['em', './path-to-em-data/emd-${id}.mdb'] ] as [string, string][], ...DefaultLimitsConfig -} +}; export function configureServer() { const parser = new argparse.ArgumentParser({ @@ -171,7 +171,7 @@ export function configureServer() { } try { - setConfig(config) // sets the config for global use + setConfig(config); // sets the config for global use if (config.cfg) { const cfg = JSON.parse(fs.readFileSync(config.cfg, 'utf8')) as FullServerConfig; @@ -209,7 +209,7 @@ export function configureLocal() { } try { - setLimitsConfig(config) // sets the config for global use + setLimitsConfig(config); // sets the config for global use if (config.cfg) { const cfg = JSON.parse(fs.readFileSync(config.cfg, 'utf8')) as FullServerConfig; diff --git a/src/servers/volume/pack.ts b/src/servers/volume/pack.ts index e96126c6bdebb7e1bf8179bd748dfb7af213f3d3..25cb7b7a436a80821aa5f8e5baed065afe367d56 100644 --- a/src/servers/volume/pack.ts +++ b/src/servers/volume/pack.ts @@ -8,9 +8,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as argparse from 'argparse' -import pack from './pack/main' -import VERSION from './pack/version' +import * as argparse from 'argparse'; +import pack from './pack/main'; +import VERSION from './pack/version'; type FileFormat = 'ccp4' | 'dsn6' @@ -27,23 +27,23 @@ function getConfig(args: Args) { blockSizeInMB: args.blockSizeInMB, format: args.format, outputFilename: args.output - } + }; switch (args.mode) { case 'em': config.input = [ { name: 'em', filename: args.inputEm } ]; config.isPeriodic = false; - break + break; case 'xray': config.input = [ { name: '2Fo-Fc', filename: args.input2fofc }, { name: 'Fo-Fc', filename: args.inputFofc } ]; config.isPeriodic = true; - break + break; } - return config as Config + return config as Config; } interface GeneralArgs { @@ -73,21 +73,21 @@ const subparsers = parser.addSubparsers({ }); function addGeneralArgs(parser: argparse.ArgumentParser) { - parser.addArgument(['output'], { help: `Output path.` }) - parser.addArgument(['--blockSizeInMB'], { defaultValue: 96, help: `Maximum block size.`, metavar: 'SIZE' }) - parser.addArgument(['--format'], { defaultValue: 'ccp4', help: `Input file format.` }) + parser.addArgument(['output'], { help: `Output path.` }); + parser.addArgument(['--blockSizeInMB'], { defaultValue: 96, help: `Maximum block size.`, metavar: 'SIZE' }); + parser.addArgument(['--format'], { defaultValue: 'ccp4', help: `Input file format.` }); } -const xrayParser = subparsers.addParser('xray', { addHelp: true }) -xrayParser.addArgument(['input2fofc'], { help: `Path to 2fofc file.`, metavar: '2FOFC' }) -xrayParser.addArgument(['inputFofc'], { help: `Path to fofc file.`, metavar: 'FOFC' }) -addGeneralArgs(xrayParser) +const xrayParser = subparsers.addParser('xray', { addHelp: true }); +xrayParser.addArgument(['input2fofc'], { help: `Path to 2fofc file.`, metavar: '2FOFC' }); +xrayParser.addArgument(['inputFofc'], { help: `Path to fofc file.`, metavar: 'FOFC' }); +addGeneralArgs(xrayParser); -const emParser = subparsers.addParser('em', { addHelp: true }) -emParser.addArgument(['inputEm'], { help: `Path to EM density file.`, metavar: 'EM' }) -addGeneralArgs(emParser) +const emParser = subparsers.addParser('em', { addHelp: true }); +emParser.addArgument(['inputEm'], { help: `Path to EM density file.`, metavar: 'EM' }); +addGeneralArgs(emParser); const args: Args = parser.parseArgs(); -const config = getConfig(args) +const config = getConfig(args); pack(config.input, config.blockSizeInMB, config.isPeriodic, config.outputFilename, config.format); diff --git a/src/servers/volume/pack/data-model.ts b/src/servers/volume/pack/data-model.ts index f3d6bbdef4c0e605ee5435b5026664df04731ace..20d518adc9ca6cfb5946fc77f6055a8a574acfbd 100644 --- a/src/servers/volume/pack/data-model.ts +++ b/src/servers/volume/pack/data-model.ts @@ -5,8 +5,8 @@ * * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Format from './format' -import * as DataFormat from '../common/data-format' +import * as Format from './format'; +import * as DataFormat from '../common/data-format'; import { FileHandle } from '../../../mol-io/common/file-handle'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; import { TypedArrayValueArray, TypedArrayValueType } from '../../../mol-io/common/typed-array'; @@ -122,7 +122,7 @@ export function createHeader(ctx: Context): DataFormat.Header { rate: s.rate, valuesInfo, sampleCount: s.sampleCount, - } + }; }) }; } diff --git a/src/servers/volume/pack/downsampling.ts b/src/servers/volume/pack/downsampling.ts index 47397b6bbdfb8a9aaa35d6f6de0a77d0e29d602b..d3d4bb43f2363dc72d1989bf914d48068cc4a232 100644 --- a/src/servers/volume/pack/downsampling.ts +++ b/src/servers/volume/pack/downsampling.ts @@ -6,7 +6,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Data from './data-model' +import * as Data from './data-model'; import { TypedArrayValueArray } from '../../../mol-io/common/typed-array'; /** @@ -121,7 +121,7 @@ function downsampleHK(kernel: Data.Kernel, dimsX: number[], buffer: Data.Downsam /** Calls downsampleH and downsampleHk for each input channel separately. */ function downsampleSlice(ctx: Data.Context, sampling: Data.Sampling) { - const dimsU = [sampling.sampleCount[1], Math.floor((sampling.sampleCount[0] + 1) / 2)] + const dimsU = [sampling.sampleCount[1], Math.floor((sampling.sampleCount[0] + 1) / 2)]; for (let i = 0, _ii = sampling.blocks.values.length; i < _ii; i++) { downsampleH(ctx.kernel, sampling.sampleCount, sampling.blocks.values[i], sampling.blocks.slicesWritten - 1, sampling.downsampling![i]); downsampleHK(ctx.kernel, dimsU, sampling.downsampling![i]); diff --git a/src/servers/volume/pack/format.ts b/src/servers/volume/pack/format.ts index 8988a37ef1c24b22c7fb8b36f3fb2d007af52383..3e478f7b2288bcb8ac6c4d43cf8e17659d289e33 100644 --- a/src/servers/volume/pack/format.ts +++ b/src/servers/volume/pack/format.ts @@ -5,7 +5,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as File from '../common/file' +import * as File from '../common/file'; import { FileHandle } from '../../../mol-io/common/file-handle'; import { Ccp4Provider } from './format/ccp4'; import { TypedArrayBufferContext, TypedArrayValueArray, TypedArrayValueType, getElementByteSize, createTypedArrayBufferContext } from '../../../mol-io/common/typed-array'; @@ -58,7 +58,7 @@ export interface Context { export function assignSliceBuffer(data: Data, blockSizeInMB: number) { const { extent, valueType } = data.header; - const maxBlockBytes = blockSizeInMB * 1024 * 1024 + const maxBlockBytes = blockSizeInMB * 1024 * 1024; const sliceSize = extent[0] * extent[1] * getElementByteSize(valueType); const sliceCapacity = Math.max(1, Math.floor(Math.min(maxBlockBytes, sliceSize * extent[2]) / sliceSize)); const buffer = createTypedArrayBufferContext(sliceCapacity * extent[0] * extent[1], valueType); @@ -95,16 +95,16 @@ export type Type = 'ccp4' | 'dsn6' export function getProviderFromType(type: Type): Provider { switch (type) { - case 'ccp4': return Ccp4Provider - case 'dsn6': return Dsn6Provider + case 'ccp4': return Ccp4Provider; + case 'dsn6': return Dsn6Provider; } } export async function open(name: string, filename: string, type: Type): Promise<Context> { - const provider = getProviderFromType(type) + const provider = getProviderFromType(type); const descriptor = await File.openRead(filename); - const file = FileHandle.fromDescriptor(descriptor) + const file = FileHandle.fromDescriptor(descriptor); const header = await provider.readHeader(name, file); - const data = { header, file, slices: void 0 as any } + const data = { header, file, slices: void 0 as any }; return { data, provider }; } \ No newline at end of file diff --git a/src/servers/volume/pack/format/ccp4.ts b/src/servers/volume/pack/format/ccp4.ts index 721ee99eb1db4fb7f2c158e2dc4d77488fa8f389..5c748a007dee8b6ea1a15c24f3ed9eac5c6dae23 100644 --- a/src/servers/volume/pack/format/ccp4.ts +++ b/src/servers/volume/pack/format/ccp4.ts @@ -12,7 +12,7 @@ import { getCcp4Origin } from '../../../../mol-model-formats/volume/ccp4'; import { Ccp4Header } from '../../../../mol-io/reader/ccp4/schema'; async function readHeader(name: string, file: FileHandle) { - const { header: ccp4Header, littleEndian } = await readCcp4Header(file) + const { header: ccp4Header, littleEndian } = await readCcp4Header(file); const header: Header = { name, @@ -54,4 +54,4 @@ export async function readSlices(data: Data) { } } -export const Ccp4Provider: Provider = { readHeader, readSlices } \ No newline at end of file +export const Ccp4Provider: Provider = { readHeader, readSlices }; \ No newline at end of file diff --git a/src/servers/volume/pack/format/dsn6.ts b/src/servers/volume/pack/format/dsn6.ts index 93817a7b4ed0511ef78946fbfdbbeed92a4ec03d..8f6a3b5c5ebc17e513742a692a02ef884a114126 100644 --- a/src/servers/volume/pack/format/dsn6.ts +++ b/src/servers/volume/pack/format/dsn6.ts @@ -11,7 +11,7 @@ import { TypedArrayValueType } from '../../../../mol-io/common/typed-array'; import { Dsn6Header } from '../../../../mol-io/reader/dsn6/schema'; async function readHeader(name: string, file: FileHandle) { - const { header: dsn6Header, littleEndian } = await readDsn6Header(file) + const { header: dsn6Header, littleEndian } = await readDsn6Header(file); const header: Header = { name, @@ -42,18 +42,18 @@ export async function readSlices(data: Data) { } const { extent, dataOffset, originalHeader } = header; - const sliceCount = extent[2] + const sliceCount = extent[2]; - const { byteCount } = getDsn6Counts(originalHeader as Dsn6Header) + const { byteCount } = getDsn6Counts(originalHeader as Dsn6Header); if (byteCount > slices.maxBlockBytes) { - throw new Error(`dsn6 file to large, can't read ${byteCount} bytes at once, increase block size or use another file format`) + throw new Error(`dsn6 file to large, can't read ${byteCount} bytes at once, increase block size or use another file format`); } - const { buffer } = await file.readBuffer(dataOffset, byteCount) + const { buffer } = await file.readBuffer(dataOffset, byteCount); if (!(slices.values instanceof Float32Array)) { - throw new Error(`dsn6 reader only supports Float32Array for output values`) + throw new Error(`dsn6 reader only supports Float32Array for output values`); } - await parseDsn6Values(originalHeader as Dsn6Header, buffer, slices.values, header.littleEndian) + await parseDsn6Values(originalHeader as Dsn6Header, buffer, slices.values, header.littleEndian); slices.slicesRead += sliceCount; slices.sliceCount = sliceCount; @@ -63,4 +63,4 @@ export async function readSlices(data: Data) { } } -export const Dsn6Provider: Provider = { readHeader, readSlices } \ No newline at end of file +export const Dsn6Provider: Provider = { readHeader, readSlices }; \ No newline at end of file diff --git a/src/servers/volume/pack/main.ts b/src/servers/volume/pack/main.ts index a6b9ec27c34e3050dfbf0ede52c6f220653911b5..9aa44989b430f5c31f101cf289cef01c9066975d 100644 --- a/src/servers/volume/pack/main.ts +++ b/src/servers/volume/pack/main.ts @@ -6,11 +6,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Format from './format' -import * as File from '../common/file' -import * as Data from './data-model' -import * as Sampling from './sampling' -import * as DataFormat from '../common/data-format' +import * as Format from './format'; +import * as File from '../common/file'; +import * as Data from './data-model'; +import * as Sampling from './sampling'; +import * as DataFormat from '../common/data-format'; import { FileHandle } from '../../../mol-io/common/file-handle'; export default async function pack(input: { name: string, filename: string }[], blockSizeInMB: number, isPeriodic: boolean, outputFilename: string, format: Format.Type) { diff --git a/src/servers/volume/pack/sampling.ts b/src/servers/volume/pack/sampling.ts index 356286a3e2d545fcaf9a032419b0e7f8a4497981..6b97309f33c95fee8ddeb4a4e377c189b0587b70 100644 --- a/src/servers/volume/pack/sampling.ts +++ b/src/servers/volume/pack/sampling.ts @@ -6,12 +6,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Format from './format' -import * as Data from './data-model' -import * as File from '../common/file' -import * as Downsampling from './downsampling' -import * as Writer from './writer' -import * as DataFormat from '../common/data-format' +import * as Format from './format'; +import * as Data from './data-model'; +import * as File from '../common/file'; +import * as Downsampling from './downsampling'; +import * as Writer from './writer'; +import * as DataFormat from '../common/data-format'; import { FileHandle } from '../../../mol-io/common/file-handle'; import { getElementByteSize, createTypedArray, TypedArrayValueType } from '../../../mol-io/common/typed-array'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; @@ -113,7 +113,7 @@ function createDownsamplingBuffer(valueType: TypedArrayValueType, sourceSampleCo downsampleHK: createTypedArray(valueType, 5 * targetSampleCount[0] * targetSampleCount[1]), slicesWritten: 0, startSliceIndex: 0 - } + }; } return ret; } @@ -127,7 +127,7 @@ function createSampling(index: number, valueType: TypedArrayValueType, numChanne sqSum: 0.0, max: Number.NEGATIVE_INFINITY, min: Number.POSITIVE_INFINITY - } + }; } return { rate: 1 << index, @@ -139,7 +139,7 @@ function createSampling(index: number, valueType: TypedArrayValueType, numChanne byteOffset: 0, byteSize: numChannels * sampleCount[0] * sampleCount[1] * sampleCount[2] * getElementByteSize(valueType), writeByteOffset: 0 - } + }; } function copyLayer(ctx: Data.Context, sliceIndex: number) { diff --git a/src/servers/volume/pack/version.ts b/src/servers/volume/pack/version.ts index 1cf1a6adbf2f9cf88e9a6f9364c148f81fd9ebd9..b0a9ab600594334d03242b8d1eed0e85dd81b921 100644 --- a/src/servers/volume/pack/version.ts +++ b/src/servers/volume/pack/version.ts @@ -1 +1 @@ -export default '0.9.2' \ No newline at end of file +export default '0.9.2'; \ No newline at end of file diff --git a/src/servers/volume/pack/writer.ts b/src/servers/volume/pack/writer.ts index eb46d5fb48072efbdb293bf15136d980e746763b..5525346a5a8519b9851cca55bd5fe16fec010473 100644 --- a/src/servers/volume/pack/writer.ts +++ b/src/servers/volume/pack/writer.ts @@ -6,7 +6,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Data from './data-model' +import * as Data from './data-model'; import { getElementByteSize } from '../../../mol-io/common/typed-array'; import { SimpleBuffer } from '../../../mol-io/common/simple-buffer'; diff --git a/src/servers/volume/server.ts b/src/servers/volume/server.ts index e9420b2589907073892a14407bc2570a5fe1b58d..e9a7e7c04cfd9787c06a2a5122896533daaa2053 100644 --- a/src/servers/volume/server.ts +++ b/src/servers/volume/server.ts @@ -8,13 +8,13 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import compression from 'compression' -import express from 'express' -import { ConsoleLogger } from '../../mol-util/console-logger' -import { configureServer, ServerConfig } from './config' -import { State } from './server/state' -import { VOLUME_SERVER_HEADER } from './server/version' -import init from './server/web-api' +import compression from 'compression'; +import express from 'express'; +import { ConsoleLogger } from '../../mol-util/console-logger'; +import { configureServer, ServerConfig } from './config'; +import { State } from './server/state'; +import { VOLUME_SERVER_HEADER } from './server/version'; +import init from './server/web-api'; function setupShutdown() { diff --git a/src/servers/volume/server/algebra/box.ts b/src/servers/volume/server/algebra/box.ts index 8f0e5e252d0feb66e8a7d879cd18b682799d7ce5..579afe852cd28665d5965fd06680030338b2d1b0 100644 --- a/src/servers/volume/server/algebra/box.ts +++ b/src/servers/volume/server/algebra/box.ts @@ -2,7 +2,7 @@ * Copyright (c) 2016 - now, David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. */ -import * as Coords from './coordinate' +import * as Coords from './coordinate'; import { SpacegroupCell } from '../../../../mol-math/geometry'; export interface Box<C extends Coords.Coord<Coords.Space>> { a: C, b: C } @@ -29,11 +29,11 @@ export function cartesianToFractional(box: Cartesian, spacegroup: SpacegroupCell } export function fractionalToGrid<K>(box: Fractional, domain: Coords.GridDomain<K>): Grid<K> { - return { a: Coords.fractionalToGrid(box.a, domain, 'bottom'), b: Coords.fractionalToGrid(box.b, domain, 'top') } + return { a: Coords.fractionalToGrid(box.a, domain, 'bottom'), b: Coords.fractionalToGrid(box.b, domain, 'top') }; } export function gridToFractional<K>(box: Grid<K>): Fractional { - return { a: Coords.gridToFractional(box.a), b: Coords.gridToFractional(box.b) } + return { a: Coords.gridToFractional(box.a), b: Coords.gridToFractional(box.b) }; } export function fractionalBoxReorderAxes(box: Fractional, axisOrder: number[]) { @@ -41,7 +41,7 @@ export function fractionalBoxReorderAxes(box: Fractional, axisOrder: number[]) { return { a: Coords.withCoord(a, a[axisOrder[0]], a[axisOrder[1]], a[axisOrder[2]]), b: Coords.withCoord(b, b[axisOrder[0]], b[axisOrder[1]], b[axisOrder[2]]) - } + }; } export function expandGridBox<K>(box: Grid<K>, by: number) { @@ -49,7 +49,7 @@ export function expandGridBox<K>(box: Grid<K>, by: number) { return { a: Coords.withCoord(a, a[0] - by, a[1] - by, a[2] - by), b: Coords.withCoord(b, b[0] + by, b[1] + by, b[2] + by) - } + }; } // MISC @@ -79,7 +79,7 @@ export function fractionalFromBlock(block: Coords.Grid<'Block'>): Fractional { for (let i = 0; i < 3; i++) { b[i] = Math.min(b[i], domain.origin[i] + domain.dimensions[i]); } - return { a, b } + return { a, b }; } export function bounding<C extends Coords.Coord<Coords.Space>>(xs: C[]): Box<C> { @@ -92,7 +92,7 @@ export function bounding<C extends Coords.Coord<Coords.Space>>(xs: C[]): Box<C> b[i] = Math.max(b[i], x[i]); } } - return { a, b } + return { a, b }; } export function areIntersecting<C extends Coords.Coord<S>, S extends Coords.Space>(box1: Box<C>, box2: Box<C>) { diff --git a/src/servers/volume/server/algebra/coordinate.ts b/src/servers/volume/server/algebra/coordinate.ts index 4c8bc5703251b4ac8d557efb52b812fe2a4e387e..1c693a0781966d5abaca0350a3c247faef045c38 100644 --- a/src/servers/volume/server/algebra/coordinate.ts +++ b/src/servers/volume/server/algebra/coordinate.ts @@ -2,8 +2,8 @@ * Copyright (c) 2016 - now, David Sehnal, licensed under Apache 2.0, See LICENSE file for more info. */ -import { Mat4, Vec3 } from '../../../../mol-math/linear-algebra' -import { SpacegroupCell } from '../../../../mol-math/geometry' +import { Mat4, Vec3 } from '../../../../mol-math/linear-algebra'; +import { SpacegroupCell } from '../../../../mol-math/geometry'; /** Information about a region sampled in fractional coordinates */ export interface GridInfo { diff --git a/src/servers/volume/server/api.ts b/src/servers/volume/server/api.ts index 85562c436f15f5dad6fc3f2d6f5d176ddc595063..5c96536cd6a2fe387f2f1fc587d27555f73c8a4d 100644 --- a/src/servers/volume/server/api.ts +++ b/src/servers/volume/server/api.ts @@ -6,16 +6,16 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as File from '../common/file' -import execute from './query/execute' -import * as Data from './query/data-model' -import { ConsoleLogger } from '../../../mol-util/console-logger' -import * as DataFormat from '../common/data-format' +import * as File from '../common/file'; +import execute from './query/execute'; +import * as Data from './query/data-model'; +import { ConsoleLogger } from '../../../mol-util/console-logger'; +import * as DataFormat from '../common/data-format'; import { FileHandle } from '../../../mol-io/common/file-handle'; import { LimitsConfig } from '../config'; export function getOutputFilename(source: string, id: string, { asBinary, box, detail, forcedSamplingLevel }: Data.QueryParams) { - function n(s: string) { return (s || '').replace(/[ \n\t]/g, '').toLowerCase() } + function n(s: string) { return (s || '').replace(/[ \n\t]/g, '').toLowerCase(); } function r(v: number) { return Math.round(10 * v) / 10; } const det = forcedSamplingLevel !== void 0 ? `l${forcedSamplingLevel}` diff --git a/src/servers/volume/server/local-api.ts b/src/servers/volume/server/local-api.ts index 930aa0c33a3d2b532d770267fe7770aa0151a215..52c1fef954dcfd5b30d54a7cd5fe2ab9f9608ef9 100644 --- a/src/servers/volume/server/local-api.ts +++ b/src/servers/volume/server/local-api.ts @@ -6,12 +6,12 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Api from './api' -import * as Data from './query/data-model' -import * as Coordinate from './algebra/coordinate' +import * as Api from './api'; +import * as Data from './query/data-model'; +import * as Coordinate from './algebra/coordinate'; -import * as fs from 'fs' -import * as path from 'path' +import * as fs from 'fs'; +import * as path from 'path'; export interface JobEntry { source: { @@ -71,13 +71,13 @@ async function query(job: JobEntry) { kind: 'Fractional', a: Coordinate.fractional(job.query.bottomLeft![0], job.query.bottomLeft![1], job.query.bottomLeft![2]), b: Coordinate.fractional(job.query.topRight![0], job.query.topRight![1], job.query.topRight![2]), - } + }; } else { box = { kind: 'Cartesian', a: Coordinate.cartesian(job.query.bottomLeft![0], job.query.bottomLeft![1], job.query.bottomLeft![2]), b: Coordinate.cartesian(job.query.topRight![0], job.query.topRight![1], job.query.topRight![2]), - } + }; } const params: Data.QueryParams = { @@ -93,9 +93,9 @@ async function query(job: JobEntry) { makeDir(job.outputFolder); } - const filename = path.join(job.outputFolder, Api.getOutputFilename(job.source.name, job.source.id, params)) + const filename = path.join(job.outputFolder, Api.getOutputFilename(job.source.name, job.source.id, params)); const res = () => wrapFile(filename); - await Api.queryBox(params, res) + await Api.queryBox(params, res); } function makeDir(path: string, root?: string): boolean { diff --git a/src/servers/volume/server/query/compose.ts b/src/servers/volume/server/query/compose.ts index ef842706e8bccbe0eb8b3a83d3318cc7f030c687..3ea7a43d10209e7d635ab5d0dbb6979f53718863 100644 --- a/src/servers/volume/server/query/compose.ts +++ b/src/servers/volume/server/query/compose.ts @@ -6,9 +6,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Data from './data-model' -import * as Box from '../algebra/box' -import * as Coords from '../algebra/coordinate' +import * as Data from './data-model'; +import * as Box from '../algebra/box'; +import * as Coords from '../algebra/coordinate'; import { createTypedArrayBufferContext, getElementByteSize, readTypedArray } from '../../../../mol-io/common/typed-array'; export default async function compose(query: Data.QueryContext.Data) { @@ -19,11 +19,11 @@ export default async function compose(query: Data.QueryContext.Data) { async function readBlock(query: Data.QueryContext.Data, coord: Coords.Grid<'Block'>, blockBox: Box.Fractional): Promise<Data.BlockData> { const { valueType, blockSize } = query.data.header; - const elementByteSize = getElementByteSize(valueType) + const elementByteSize = getElementByteSize(valueType); const numChannels = query.data.header.channels.length; const blockSampleCount = Box.dimensions(Box.fractionalToGrid(blockBox, query.samplingInfo.sampling.dataDomain)); const size = numChannels * blockSampleCount[0] * blockSampleCount[1] * blockSampleCount[2]; - const byteSize = elementByteSize * size + const byteSize = elementByteSize * size; const dataSampleCount = query.data.header.sampling[query.samplingInfo.sampling.index].sampleCount; const buffer = createTypedArrayBufferContext(size, valueType); const byteOffset = query.samplingInfo.sampling.byteOffset diff --git a/src/servers/volume/server/query/data-model.ts b/src/servers/volume/server/query/data-model.ts index 95d77403c69ac22d88709e643d5793460e8fa482..4fd67dcde70e05b3414c8b41d8c9196a1a14598d 100644 --- a/src/servers/volume/server/query/data-model.ts +++ b/src/servers/volume/server/query/data-model.ts @@ -6,10 +6,10 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as DataFormat from '../../common/data-format' -import * as Coords from '../algebra/coordinate' -import * as Box from '../algebra/box' -import Writer from '../../../../mol-io/writer/writer' +import * as DataFormat from '../../common/data-format'; +import * as Coords from '../algebra/coordinate'; +import * as Box from '../algebra/box'; +import Writer from '../../../../mol-io/writer/writer'; import { SpacegroupCell } from '../../../../mol-math/geometry'; import { FileHandle } from '../../../../mol-io/common/file-handle'; import { TypedArrayValueArray } from '../../../../mol-io/common/typed-array'; diff --git a/src/servers/volume/server/query/encode.ts b/src/servers/volume/server/query/encode.ts index b89691f180ea4e1f46f687d0010f2ac571c0f28a..b718c91e21ec2da7226e043c4dc6059712353f86 100644 --- a/src/servers/volume/server/query/encode.ts +++ b/src/servers/volume/server/query/encode.ts @@ -6,11 +6,11 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { CifWriter } from '../../../../mol-io/writer/cif' -import * as Data from './data-model' -import * as Coords from '../algebra/coordinate' -import { VOLUME_SERVER_VERSION as VERSION } from '../version' -import * as DataFormat from '../../common/data-format' +import { CifWriter } from '../../../../mol-io/writer/cif'; +import * as Data from './data-model'; +import * as Coords from '../algebra/coordinate'; +import { VOLUME_SERVER_VERSION as VERSION } from '../version'; +import * as DataFormat from '../../common/data-format'; import { Column } from '../../../../mol-data/db'; import { ArrayEncoding, ArrayEncoder } from '../../../../mol-io/common/binary-cif'; import { TypedArrayValueType, TypedArrayValueArray } from '../../../../mol-io/common/typed-array'; @@ -103,7 +103,7 @@ const _volume_data_3d_info: CifWriter.Category<ResultContext> = { sampledValuesInfo: result.query.data.header.sampling[result.query.samplingInfo.sampling.index].valuesInfo[result.channelIndex] }; - return { fields: _volume_data_3d_info_fields, source: [{ data: ctx, rowCount: 1 }] } + return { fields: _volume_data_3d_info_fields, source: [{ data: ctx, rowCount: 1 }] }; } }; @@ -133,13 +133,13 @@ const _volume_data_3d: CifWriter.Category<ResultContext> = { } else { typedArray = Int8Array; // just encode the bytes - encoder = E.by(E.byteArray) + encoder = E.by(E.byteArray); } const fields = [CifWriter.Field.float('values', _volume_data_3d_number, { encoder, typedArray, digitCount: 6 })]; return CifWriter.categoryInstance(fields, { data, rowCount: data.length }); } -} +}; function pickQueryBoxDimension(ctx: Data.QueryContext, e: 'a' | 'b', d: number) { const box = ctx.params.box; @@ -171,12 +171,12 @@ const _density_server_result_fields = [ queryBoxDimension('b', 0), queryBoxDimension('b', 1), queryBoxDimension('b', 2) -] +]; const _density_server_result: CifWriter.Category<Data.QueryContext> = { name: 'density_server_result', instance: ctx => CifWriter.categoryInstance(_density_server_result_fields, { data: ctx, rowCount: 1 }) -} +}; function write(encoder: CifWriter.Encoder, query: Data.QueryContext) { encoder.startDataBlock('SERVER'); diff --git a/src/servers/volume/server/query/execute.ts b/src/servers/volume/server/query/execute.ts index a7fa850e28889fc2f008699d2f862143cc13a673..6a5e4115b407161a2d34f11de8877ffd1c813091 100644 --- a/src/servers/volume/server/query/execute.ts +++ b/src/servers/volume/server/query/execute.ts @@ -6,17 +6,17 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as DataFormat from '../../common/data-format' -import * as File from '../../common/file' -import * as Data from './data-model' -import * as Coords from '../algebra/coordinate' -import * as Box from '../algebra/box' -import { ConsoleLogger } from '../../../../mol-util/console-logger' -import { State } from '../state' - -import identify from './identify' -import compose from './compose' -import encode from './encode' +import * as DataFormat from '../../common/data-format'; +import * as File from '../../common/file'; +import * as Data from './data-model'; +import * as Coords from '../algebra/coordinate'; +import * as Box from '../algebra/box'; +import { ConsoleLogger } from '../../../../mol-util/console-logger'; +import { State } from '../state'; + +import identify from './identify'; +import compose from './compose'; +import encode from './encode'; import { SpacegroupCell } from '../../../../mol-math/geometry'; import { Vec3 } from '../../../../mol-math/linear-algebra'; import { UUID } from '../../../../mol-util'; @@ -79,7 +79,7 @@ function createSampling(header: DataFormat.Header, index: number, dataOffset: nu byteOffset: sampling.byteOffset + dataOffset, dataDomain, blockDomain: blockDomain(dataDomain, header.blockSize) - } + }; } async function createDataContext(file: FileHandle): Promise<Data.DataContext> { @@ -94,7 +94,7 @@ async function createDataContext(file: FileHandle): Promise<Data.DataContext> { spacegroup: SpacegroupCell.create(header.spacegroup.number, Vec3.ofArray(header.spacegroup.size), Vec3.scale(Vec3.zero(), Vec3.ofArray(header.spacegroup.angles), Math.PI / 180)), dataBox: { a: origin, b: Coords.add(origin, dimensions) }, sampling: header.sampling.map((s, i) => createSampling(header, i, dataOffset)) - } + }; } function createQuerySampling(data: Data.DataContext, sampling: Data.Sampling, queryBox: Box.Fractional): Data.QuerySamplingInfo { @@ -132,7 +132,7 @@ function pickSampling(data: Data.DataContext, queryBox: Box.Fractional, forcedLe } function emptyQueryContext(data: Data.DataContext, params: Data.QueryParams, guid: string): Data.QueryContext { - return { kind: 'Empty', guid, params, data } + return { kind: 'Empty', guid, params, data }; } function getQueryBox(data: Data.DataContext, queryBox: Data.QueryParamsBox) { @@ -183,7 +183,7 @@ function createQueryContext(data: Data.DataContext, params: Data.QueryParams, gu params, samplingInfo, values: allocateValues(samplingInfo.gridDomain, data.header.channels.length, data.header.valueType) - } + }; } @@ -206,7 +206,7 @@ async function _execute(file: FileHandle, params: Data.QueryParams, guid: string encode(query, output); output.end(); } catch (e) { - const query: Data.QueryContext = { kind: 'Error', guid, params, message: `${e}` } + const query: Data.QueryContext = { kind: 'Error', guid, params, message: `${e}` }; try { if (!output) output = outputProvider(); encode(query, output); diff --git a/src/servers/volume/server/query/identify.ts b/src/servers/volume/server/query/identify.ts index 85b276c30da12e548096a1074c9acbec3578b130..caed1039bbc0ec5543342ef5126cbe041475d699 100644 --- a/src/servers/volume/server/query/identify.ts +++ b/src/servers/volume/server/query/identify.ts @@ -6,9 +6,9 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import * as Coords from '../algebra/coordinate' -import * as Box from '../algebra/box' -import * as Data from './data-model' +import * as Coords from '../algebra/coordinate'; +import * as Box from '../algebra/box'; +import * as Data from './data-model'; // import { FastMap } from '../utils/collections' /** Find a list of unique blocks+offsets that overlap with the query region. */ @@ -25,7 +25,7 @@ export default function findUniqueBlocks(data: Data.DataContext, sampling: Data. } const blockList = [] as Data.QueryBlock[]; - blocks.forEach(function (this: Data.QueryBlock[], b) { this.push(b) }, blockList); + blocks.forEach(function (this: Data.QueryBlock[], b) { this.push(b); }, blockList); // sort the data so that the first coodinate changes the fastest // this is because that's how the data is laid out in the underlaying diff --git a/src/servers/volume/server/state.ts b/src/servers/volume/server/state.ts index 83299501da1299927d4d0c332851bba83594e302..3dd8ae27aa880a46e59833d6e7d2e1e345fe13c5 100644 --- a/src/servers/volume/server/state.ts +++ b/src/servers/volume/server/state.ts @@ -10,4 +10,4 @@ export const State = { pendingQueries: 0, shutdownOnZeroPending: false, querySerial: 0 -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/servers/volume/server/version.ts b/src/servers/volume/server/version.ts index 806aa778ef648eb7ea2212600271d4247d2649fd..24ad9feab0cdd9b8a1356af6aa6d937ecee8e2d7 100644 --- a/src/servers/volume/server/version.ts +++ b/src/servers/volume/server/version.ts @@ -1,2 +1,2 @@ -export const VOLUME_SERVER_VERSION = '0.9.5' -export const VOLUME_SERVER_HEADER = `VolumeServer ${VOLUME_SERVER_VERSION}, (c) 2018-2020, Mol* contributors` \ No newline at end of file +export const VOLUME_SERVER_VERSION = '0.9.5'; +export const VOLUME_SERVER_HEADER = `VolumeServer ${VOLUME_SERVER_VERSION}, (c) 2018-2020, Mol* contributors`; \ No newline at end of file diff --git a/src/servers/volume/server/web-api.ts b/src/servers/volume/server/web-api.ts index 8b8d1a165c7e8b0dcb61f854f50087e77c7b59dd..f28c81d3db06878b422c117df24ebb632ae9edbc 100644 --- a/src/servers/volume/server/web-api.ts +++ b/src/servers/volume/server/web-api.ts @@ -7,20 +7,20 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import * as express from 'express' +import * as express from 'express'; -import * as Api from './api' -import * as Data from './query/data-model' -import * as Coords from './algebra/coordinate' -import { ConsoleLogger } from '../../../mol-util/console-logger' -import { State } from './state' +import * as Api from './api'; +import * as Data from './query/data-model'; +import * as Coords from './algebra/coordinate'; +import { ConsoleLogger } from '../../../mol-util/console-logger'; +import { State } from './state'; import { LimitsConfig, ServerConfig } from '../config'; import { interpolate } from '../../../mol-util/string'; import { getSchema, shortcutIconLink } from './web-schema'; import { swaggerUiIndexHandler, swaggerUiAssetsHandler } from '../../common/swagger-ui'; export default function init(app: express.Express) { - app.locals.mapFile = getMapFileFn() + app.locals.mapFile = getMapFileFn(); function makePath(p: string) { return `${ServerConfig.apiPrefix}/${p}`; } @@ -55,13 +55,13 @@ function getMapFileFn() { 'id = id.toLowerCase()', 'switch (type.toLowerCase()) {', ...ServerConfig.idMap.map(mapping => { - const [type, path] = mapping - return ` case '${type}': return interpolate('${path}', { id });` + const [type, path] = mapping; + return ` case '${type}': return interpolate('${path}', { id });`; }), ' default: return void 0;', '}' - ].join('\n')) - return (type: string, id: string) => map(type, id, interpolate) + ].join('\n')); + return (type: string, id: string) => map(type, id, interpolate); } function wrapResponse(fn: string, res: express.Response) { @@ -153,7 +153,7 @@ function getQueryParams(req: express.Request, isCell: boolean): Data.QueryParams const a = [+req.params.a1, +req.params.a2, +req.params.a3]; const b = [+req.params.b1, +req.params.b2, +req.params.b3]; - const detail = Math.min(Math.max(0, (+req.query.detail) | 0), LimitsConfig.maxOutputSizeInVoxelCountByPrecisionLevel.length - 1) + const detail = Math.min(Math.max(0, (+req.query.detail) | 0), LimitsConfig.maxOutputSizeInVoxelCountByPrecisionLevel.length - 1); const isCartesian = (req.query.space || '').toLowerCase() !== 'fractional'; const box: Data.QueryParamsBox = isCell diff --git a/src/servers/volume/server/web-schema.ts b/src/servers/volume/server/web-schema.ts index e9a1d4684b1380d809eb82092fda45ffdd50674b..fc2a7b222d5cabc05759641dc3276fac133ca9dd 100644 --- a/src/servers/volume/server/web-schema.ts +++ b/src/servers/volume/server/web-schema.ts @@ -5,7 +5,7 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { VOLUME_SERVER_VERSION } from './version' +import { VOLUME_SERVER_VERSION } from './version'; import { LimitsConfig, ServerConfig } from '../config'; export function getSchema() { @@ -13,7 +13,7 @@ export function getSchema() { return `${i} (${Math.round(100 * LimitsConfig.maxOutputSizeInVoxelCountByPrecisionLevel[i] / 1000 / 1000) / 100 }M voxels)`; } const detailMax = LimitsConfig.maxOutputSizeInVoxelCountByPrecisionLevel.length - 1; - const sources = ServerConfig.idMap.map(m => m[0]) + const sources = ServerConfig.idMap.map(m => m[0]); return { openapi: '3.0.0', @@ -255,7 +255,7 @@ export function getSchema() { } } } - } + }; } -export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />` \ No newline at end of file +export const shortcutIconLink = `<link rel='shortcut icon' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAnUExURQAAAMIrHrspHr0oH7soILonHrwqH7onILsoHrsoH7soH7woILwpIKgVokoAAAAMdFJOUwAQHzNxWmBHS5XO6jdtAmoAAACZSURBVDjLxZNRCsQgDAVNXmwb9f7nXZEaLRgXloXOhwQdjMYYwpOLw55fBT46KhbOKhmRR2zLcFJQj8UR+HxFgArIF5BKJbEncC6NDEdI5SatBRSDJwGAoiFDONrEJXWYhGMIcRJGCrb1TOtDahfUuQXd10jkFYq0ViIrbUpNcVT6redeC1+b9tH2WLR93Sx2VCzkv/7NjfABxjQHksGB7lAAAAAASUVORK5CYII=' />`; \ No newline at end of file diff --git a/src/tests/browser/font-atlas.ts b/src/tests/browser/font-atlas.ts index 7ec02880bc90707aedacad6e3bd660c590d15d2c..26b847276ae37e7de65cf134233ae096466349cd 100644 --- a/src/tests/browser/font-atlas.ts +++ b/src/tests/browser/font-atlas.ts @@ -4,37 +4,37 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { FontAtlas } from '../../mol-geo/geometry/text/font-atlas'; import { printTextureImage } from '../../mol-gl/renderable/util'; function test() { - console.time('FontAtlas init') - const fontAtlas = new FontAtlas({ fontQuality: 3 }) - console.timeEnd('FontAtlas init') + console.time('FontAtlas init'); + const fontAtlas = new FontAtlas({ fontQuality: 3 }); + console.timeEnd('FontAtlas init'); - console.time('Basic Latin (subset)') - for (let i = 0x0020; i <= 0x007E; ++i) fontAtlas.get(String.fromCharCode(i)) - console.timeEnd('Basic Latin (subset)') + console.time('Basic Latin (subset)'); + for (let i = 0x0020; i <= 0x007E; ++i) fontAtlas.get(String.fromCharCode(i)); + console.timeEnd('Basic Latin (subset)'); - console.time('Latin-1 Supplement (subset)') - for (let i = 0x00A1; i <= 0x00FF; ++i) fontAtlas.get(String.fromCharCode(i)) - console.timeEnd('Latin-1 Supplement (subset)') + console.time('Latin-1 Supplement (subset)'); + for (let i = 0x00A1; i <= 0x00FF; ++i) fontAtlas.get(String.fromCharCode(i)); + console.timeEnd('Latin-1 Supplement (subset)'); - console.time('Greek and Coptic (subset)') - for (let i = 0x0391; i <= 0x03C9; ++i) fontAtlas.get(String.fromCharCode(i)) - console.timeEnd('Greek and Coptic (subset)') + console.time('Greek and Coptic (subset)'); + for (let i = 0x0391; i <= 0x03C9; ++i) fontAtlas.get(String.fromCharCode(i)); + console.timeEnd('Greek and Coptic (subset)'); - console.time('Cyrillic (subset)') - for (let i = 0x0400; i <= 0x044F; ++i) fontAtlas.get(String.fromCharCode(i)) - console.timeEnd('Cyrillic (subset)') + console.time('Cyrillic (subset)'); + for (let i = 0x0400; i <= 0x044F; ++i) fontAtlas.get(String.fromCharCode(i)); + console.timeEnd('Cyrillic (subset)'); - console.time('Angstrom Sign') - fontAtlas.get(String.fromCharCode(0x212B)) - console.timeEnd('Angstrom Sign') + console.time('Angstrom Sign'); + fontAtlas.get(String.fromCharCode(0x212B)); + console.timeEnd('Angstrom Sign'); - printTextureImage(fontAtlas.texture, 0.5) - console.log(`${Object.keys(fontAtlas.mapped).length} chars prepared`) + printTextureImage(fontAtlas.texture, 0.5); + console.log(`${Object.keys(fontAtlas.mapped).length} chars prepared`); } test(); \ No newline at end of file diff --git a/src/tests/browser/marching-cubes.ts b/src/tests/browser/marching-cubes.ts index 0a01df80d2136759a93587c3f217e0e247a546d3..db1f2440c12ddae44f1f444072a9fe28ac47240a 100644 --- a/src/tests/browser/marching-cubes.ts +++ b/src/tests/browser/marching-cubes.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { resizeCanvas } from '../../mol-canvas3d/util'; import { Canvas3DParams } from '../../mol-canvas3d/canvas3d'; import { ColorNames } from '../../mol-util/color/names'; @@ -23,124 +23,124 @@ import { computeMarchingCubesMesh } from '../../mol-geo/util/marching-cubes/algo import { Mesh } from '../../mol-geo/geometry/mesh/mesh'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); const canvas3d = PD.merge(Canvas3DParams, PD.getDefaultValues(Canvas3DParams), { renderer: { backgroundColor: ColorNames.white }, camera: { mode: 'orthographic' } -}) -canvas3d.animate() +}); +canvas3d.animate(); async function init() { - const { webgl } = canvas3d + const { webgl } = canvas3d; const position: PositionData = { x: [0, 2], y: [0, 2], z: [0, 2], indices: OrderedSet.ofSortedArray([0, 1]), - } - const box = Box3D.create(Vec3.create(0, 0, 0), Vec3.create(2, 2, 2)) - const radius = () => 1.8 + }; + const box = Box3D.create(Vec3.create(0, 0, 0), Vec3.create(2, 2, 2)); + const radius = () => 1.8; const props = { resolution: 0.1, radiusOffset: 0, smoothness: 1.5 - } - const isoValue = Math.exp(-props.smoothness) + }; + const isoValue = Math.exp(-props.smoothness); if (true) { - console.time('gpu gaussian2') - const densityTextureData2 = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run() - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu gaussian2') - - console.time('gpu mc2') - console.time('gpu mc active2') - const activeVoxelsTex2 = calcActiveVoxels(webgl, densityTextureData2.texture, densityTextureData2.gridDim, densityTextureData2.gridTexDim, isoValue, densityTextureData2.gridTexScale) - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu mc active2') - - console.time('gpu mc pyramid2') - const compacted2 = createHistogramPyramid(webgl, activeVoxelsTex2, densityTextureData2.gridTexScale) - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu mc pyramid2') - - console.time('gpu mc vert2') - createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue) - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu mc vert2') - console.timeEnd('gpu mc2') + console.time('gpu gaussian2'); + const densityTextureData2 = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run(); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu gaussian2'); + + console.time('gpu mc2'); + console.time('gpu mc active2'); + const activeVoxelsTex2 = calcActiveVoxels(webgl, densityTextureData2.texture, densityTextureData2.gridDim, densityTextureData2.gridTexDim, isoValue, densityTextureData2.gridTexScale); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu mc active2'); + + console.time('gpu mc pyramid2'); + const compacted2 = createHistogramPyramid(webgl, activeVoxelsTex2, densityTextureData2.gridTexScale); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu mc pyramid2'); + + console.time('gpu mc vert2'); + createIsosurfaceBuffers(webgl, activeVoxelsTex2, densityTextureData2.texture, compacted2, densityTextureData2.gridDim, densityTextureData2.gridTexDim, densityTextureData2.transform, isoValue); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu mc vert2'); + console.timeEnd('gpu mc2'); } - console.time('gpu gaussian') - const densityTextureData = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run() - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu gaussian') - - console.time('gpu mc') - console.time('gpu mc active') - const activeVoxelsTex = calcActiveVoxels(webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, isoValue, densityTextureData.gridTexScale) - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu mc active') - - console.time('gpu mc pyramid') - const compacted = createHistogramPyramid(webgl, activeVoxelsTex, densityTextureData.gridTexScale) - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu mc pyramid') - - console.time('gpu mc vert') - const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue) - webgl.waitForGpuCommandsCompleteSync() - console.timeEnd('gpu mc vert') - console.timeEnd('gpu mc') - - console.log({ ...webgl.stats, programCount: webgl.stats.resourceCounts.program, shaderCount: webgl.stats.resourceCounts.shader }) - - const mcBoundingSphere = Sphere3D.fromBox3D(Sphere3D(), densityTextureData.bbox) - const mcIsosurface = TextureMesh.create(gv.vertexCount, 1, gv.vertexGroupTexture, gv.normalTexture, mcBoundingSphere) - const mcIsoSurfaceProps = { doubleSided: true, flatShaded: true, alpha: 1.0 } - const mcIsoSurfaceValues = TextureMesh.Utils.createValuesSimple(mcIsosurface, mcIsoSurfaceProps, Color(0x112299), 1) + console.time('gpu gaussian'); + const densityTextureData = await computeGaussianDensityTexture2d(position, box, radius, props, webgl).run(); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu gaussian'); + + console.time('gpu mc'); + console.time('gpu mc active'); + const activeVoxelsTex = calcActiveVoxels(webgl, densityTextureData.texture, densityTextureData.gridDim, densityTextureData.gridTexDim, isoValue, densityTextureData.gridTexScale); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu mc active'); + + console.time('gpu mc pyramid'); + const compacted = createHistogramPyramid(webgl, activeVoxelsTex, densityTextureData.gridTexScale); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu mc pyramid'); + + console.time('gpu mc vert'); + const gv = createIsosurfaceBuffers(webgl, activeVoxelsTex, densityTextureData.texture, compacted, densityTextureData.gridDim, densityTextureData.gridTexDim, densityTextureData.transform, isoValue); + webgl.waitForGpuCommandsCompleteSync(); + console.timeEnd('gpu mc vert'); + console.timeEnd('gpu mc'); + + console.log({ ...webgl.stats, programCount: webgl.stats.resourceCounts.program, shaderCount: webgl.stats.resourceCounts.shader }); + + const mcBoundingSphere = Sphere3D.fromBox3D(Sphere3D(), densityTextureData.bbox); + const mcIsosurface = TextureMesh.create(gv.vertexCount, 1, gv.vertexGroupTexture, gv.normalTexture, mcBoundingSphere); + const mcIsoSurfaceProps = { doubleSided: true, flatShaded: true, alpha: 1.0 }; + const mcIsoSurfaceValues = TextureMesh.Utils.createValuesSimple(mcIsosurface, mcIsoSurfaceProps, Color(0x112299), 1); // console.log('mcIsoSurfaceValues', mcIsoSurfaceValues) - const mcIsoSurfaceState = TextureMesh.Utils.createRenderableState(mcIsoSurfaceProps) - const mcIsoSurfaceRenderObject = createRenderObject('texture-mesh', mcIsoSurfaceValues, mcIsoSurfaceState, -1) - const mcIsoSurfaceRepr = Representation.fromRenderObject('texture-mesh', mcIsoSurfaceRenderObject) + const mcIsoSurfaceState = TextureMesh.Utils.createRenderableState(mcIsoSurfaceProps); + const mcIsoSurfaceRenderObject = createRenderObject('texture-mesh', mcIsoSurfaceValues, mcIsoSurfaceState, -1); + const mcIsoSurfaceRepr = Representation.fromRenderObject('texture-mesh', mcIsoSurfaceRenderObject); - canvas3d.add(mcIsoSurfaceRepr) - canvas3d.requestCameraReset() + canvas3d.add(mcIsoSurfaceRepr); + canvas3d.requestCameraReset(); // - console.time('cpu gaussian') - const densityData = await computeGaussianDensity(position, box, radius, { ...props, useGpu: false }, webgl).run() - console.timeEnd('cpu gaussian') - console.log({ densityData }) + console.time('cpu gaussian'); + const densityData = await computeGaussianDensity(position, box, radius, { ...props, useGpu: false }, webgl).run(); + console.timeEnd('cpu gaussian'); + console.log({ densityData }); const params = { isoLevel: isoValue, scalarField: densityData.field, idField: densityData.idField - } - - console.time('cpu mc') - const surface = await computeMarchingCubesMesh(params).run() - console.timeEnd('cpu mc') - console.log('surface', surface) - Mesh.transform(surface, densityData.transform) - const meshProps = { doubleSided: true, flatShaded: false, alpha: 1.0 } - const meshValues = Mesh.Utils.createValuesSimple(surface, meshProps, Color(0x995511), 1) - const meshState = Mesh.Utils.createRenderableState(meshProps) - const meshRenderObject = createRenderObject('mesh', meshValues, meshState, -1) - const meshRepr = Representation.fromRenderObject('mesh', meshRenderObject) - - canvas3d.add(meshRepr) - canvas3d.requestCameraReset() + }; + + console.time('cpu mc'); + const surface = await computeMarchingCubesMesh(params).run(); + console.timeEnd('cpu mc'); + console.log('surface', surface); + Mesh.transform(surface, densityData.transform); + const meshProps = { doubleSided: true, flatShaded: false, alpha: 1.0 }; + const meshValues = Mesh.Utils.createValuesSimple(surface, meshProps, Color(0x995511), 1); + const meshState = Mesh.Utils.createRenderableState(meshProps); + const meshRenderObject = createRenderObject('mesh', meshValues, meshState, -1); + const meshRepr = Representation.fromRenderObject('mesh', meshRenderObject); + + canvas3d.add(meshRepr); + canvas3d.requestCameraReset(); } -init() \ No newline at end of file +init(); \ No newline at end of file diff --git a/src/tests/browser/render-lines.ts b/src/tests/browser/render-lines.ts index d782b92aa7540d53169f57741fcebf8b7767ca3a..514a8b923d00cfb33c67defabbc4b1ef6645b48b 100644 --- a/src/tests/browser/render-lines.ts +++ b/src/tests/browser/render-lines.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { resizeCanvas } from '../../mol-canvas3d/util'; import { Canvas3D } from '../../mol-canvas3d/canvas3d'; import { LinesBuilder } from '../../mol-geo/geometry/lines/lines-builder'; @@ -15,30 +15,30 @@ import { Color } from '../../mol-util/color'; import { createRenderObject } from '../../mol-gl/render-object'; import { Representation } from '../../mol-repr/representation'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); -const canvas3d = Canvas3D.fromCanvas(canvas) -canvas3d.animate() +const canvas3d = Canvas3D.fromCanvas(canvas); +canvas3d.animate(); function linesRepr() { - const linesBuilder = LinesBuilder.create() - const t = Mat4.identity() - const dodecahedronCage = DodecahedronCage() - linesBuilder.addCage(t, dodecahedronCage, 0) - const lines = linesBuilder.getLines() + const linesBuilder = LinesBuilder.create(); + const t = Mat4.identity(); + const dodecahedronCage = DodecahedronCage(); + linesBuilder.addCage(t, dodecahedronCage, 0); + const lines = linesBuilder.getLines(); - const values = Lines.Utils.createValuesSimple(lines, {}, Color(0xFF0000), 3) - const state = Lines.Utils.createRenderableState({}) - const renderObject = createRenderObject('lines', values, state, -1) - const repr = Representation.fromRenderObject('cage-lines', renderObject) - return repr + const values = Lines.Utils.createValuesSimple(lines, {}, Color(0xFF0000), 3); + const state = Lines.Utils.createRenderableState({}); + const renderObject = createRenderObject('lines', values, state, -1); + const repr = Representation.fromRenderObject('cage-lines', renderObject); + return repr; } -canvas3d.add(linesRepr()) -canvas3d.requestCameraReset() \ No newline at end of file +canvas3d.add(linesRepr()); +canvas3d.requestCameraReset(); \ No newline at end of file diff --git a/src/tests/browser/render-mesh.ts b/src/tests/browser/render-mesh.ts index f5358bf9f6d54ff5d208a854a8b5dd34a8939cd2..f7aa6bc296baf0cb485e0ab332e56bf450ce0fe3 100644 --- a/src/tests/browser/render-mesh.ts +++ b/src/tests/browser/render-mesh.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { resizeCanvas } from '../../mol-canvas3d/util'; import { Canvas3D } from '../../mol-canvas3d/canvas3d'; import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder'; @@ -16,35 +16,35 @@ import { Color } from '../../mol-util/color'; import { createRenderObject } from '../../mol-gl/render-object'; import { Representation } from '../../mol-repr/representation'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); -const canvas3d = Canvas3D.fromCanvas(canvas) -canvas3d.animate() +const canvas3d = Canvas3D.fromCanvas(canvas); +canvas3d.animate(); function meshRepr() { - const builderState = MeshBuilder.createState() + const builderState = MeshBuilder.createState(); - const t = Mat4.identity() - MeshBuilder.addCage(builderState, t, HexagonalPrismCage(), 0.005, 2, 20) + const t = Mat4.identity(); + MeshBuilder.addCage(builderState, t, HexagonalPrismCage(), 0.005, 2, 20); - const t2 = Mat4.identity() - Mat4.scaleUniformly(t2, t2, 0.1) - MeshBuilder.addPrimitive(builderState, t2, SpikedBall(3)) + const t2 = Mat4.identity(); + Mat4.scaleUniformly(t2, t2, 0.1); + MeshBuilder.addPrimitive(builderState, t2, SpikedBall(3)); - const mesh = MeshBuilder.getMesh(builderState) + const mesh = MeshBuilder.getMesh(builderState); - const values = Mesh.Utils.createValuesSimple(mesh, {}, Color(0xFF0000), 1) - const state = Mesh.Utils.createRenderableState({}) - const renderObject = createRenderObject('mesh', values, state, -1) - const repr = Representation.fromRenderObject('mesh', renderObject) - return repr + const values = Mesh.Utils.createValuesSimple(mesh, {}, Color(0xFF0000), 1); + const state = Mesh.Utils.createRenderableState({}); + const renderObject = createRenderObject('mesh', values, state, -1); + const repr = Representation.fromRenderObject('mesh', renderObject); + return repr; } -canvas3d.add(meshRepr()) -canvas3d.requestCameraReset() \ No newline at end of file +canvas3d.add(meshRepr()); +canvas3d.requestCameraReset(); \ No newline at end of file diff --git a/src/tests/browser/render-shape.ts b/src/tests/browser/render-shape.ts index f191858dcad3a672578b38483bdce22f7d2bf6d6..856293a4aa7f23046a84b76b817b412bf3dc50aa 100644 --- a/src/tests/browser/render-shape.ts +++ b/src/tests/browser/render-shape.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { resizeCanvas } from '../../mol-canvas3d/util'; import { Representation } from '../../mol-repr/representation'; import { Canvas3D } from '../../mol-canvas3d/canvas3d'; @@ -20,43 +20,43 @@ import { ColorNames } from '../../mol-util/color/names'; import { Shape } from '../../mol-model/shape'; import { ShapeRepresentation } from '../../mol-repr/shape/representation'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); -const info = document.createElement('div') -info.style.position = 'absolute' -info.style.fontFamily = 'sans-serif' -info.style.fontSize = '24pt' -info.style.bottom = '20px' -info.style.right = '20px' -info.style.color = 'white' -parent.appendChild(info) +const info = document.createElement('div'); +info.style.position = 'absolute'; +info.style.fontFamily = 'sans-serif'; +info.style.fontSize = '24pt'; +info.style.bottom = '20px'; +info.style.right = '20px'; +info.style.color = 'white'; +parent.appendChild(info); -let prevReprLoci = Representation.Loci.Empty -const canvas3d = Canvas3D.fromCanvas(canvas) -canvas3d.animate() +let prevReprLoci = Representation.Loci.Empty; +const canvas3d = Canvas3D.fromCanvas(canvas); +canvas3d.animate(); canvas3d.input.move.subscribe(({x, y}) => { - const pickingId = canvas3d.identify(x, y) - let label = '' + const pickingId = canvas3d.identify(x, y); + let label = ''; if (pickingId) { - const reprLoci = canvas3d.getLoci(pickingId) - label = lociLabel(reprLoci.loci) + const reprLoci = canvas3d.getLoci(pickingId); + label = lociLabel(reprLoci.loci); if (!Representation.Loci.areEqual(prevReprLoci, reprLoci)) { - canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight) - canvas3d.mark(reprLoci, MarkerAction.Highlight) - prevReprLoci = reprLoci + canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight); + canvas3d.mark(reprLoci, MarkerAction.Highlight); + prevReprLoci = reprLoci; } } else { - canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight) - prevReprLoci = Representation.Loci.Empty + canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight); + prevReprLoci = Representation.Loci.Empty; } - info.innerText = label -}) + info.innerText = label; +}); /** * Create a mesh of spheres at given centers @@ -65,19 +65,19 @@ canvas3d.input.move.subscribe(({x, y}) => { * - re-use storage from an existing mesh if given */ async function getSphereMesh(ctx: RuntimeContext, centers: number[], mesh?: Mesh) { - const builderState = MeshBuilder.createState(centers.length * 128, centers.length * 128 / 2, mesh) - const t = Mat4.identity() - const v = Vec3.zero() - const sphere = Sphere(3) - builderState.currentGroup = 0 + const builderState = MeshBuilder.createState(centers.length * 128, centers.length * 128 / 2, mesh); + const t = Mat4.identity(); + const v = Vec3.zero(); + const sphere = Sphere(3); + builderState.currentGroup = 0; for (let i = 0, il = centers.length / 3; i < il; ++i) { // for production, calls to update should be guarded by `if (ctx.shouldUpdate)` - await ctx.update({ current: i, max: il, message: `adding sphere ${i}` }) - builderState.currentGroup = i - Mat4.setTranslation(t, Vec3.fromArray(v, centers, i * 3)) - MeshBuilder.addPrimitive(builderState, t, sphere) + await ctx.update({ current: i, max: il, message: `adding sphere ${i}` }); + builderState.currentGroup = i; + Mat4.setTranslation(t, Vec3.fromArray(v, centers, i * 3)); + MeshBuilder.addPrimitive(builderState, t, sphere); } - return MeshBuilder.getMesh(builderState) + return MeshBuilder.getMesh(builderState); } const myData = { @@ -85,40 +85,40 @@ const myData = { colors: [ColorNames.tomato, ColorNames.springgreen, ColorNames.springgreen], labels: ['Sphere 0, Instance A', 'Sphere 1, Instance A', 'Sphere 0, Instance B', 'Sphere 1, Instance B'], transforms: [Mat4.identity(), Mat4.fromTranslation(Mat4.zero(), Vec3.create(3, 0, 0))] -} +}; type MyData = typeof myData /** * Get shape from `MyData` object */ async function getShape(ctx: RuntimeContext, data: MyData, props: {}, shape?: Shape<Mesh>) { - await ctx.update('async creation of shape from myData') - const { centers, colors, labels, transforms } = data - const mesh = await getSphereMesh(ctx, centers, shape && shape.geometry) - const groupCount = centers.length / 3 + await ctx.update('async creation of shape from myData'); + const { centers, colors, labels, transforms } = data; + const mesh = await getSphereMesh(ctx, centers, shape && shape.geometry); + const groupCount = centers.length / 3; return Shape.create( 'test', data, mesh, (groupId: number) => colors[groupId], // color: per group, same for instances () => 1, // size: constant (groupId: number, instanceId: number) => labels[instanceId * groupCount + groupId], // label: per group and instance transforms - ) + ); } // Init ShapeRepresentation container -const repr = ShapeRepresentation(getShape, Mesh.Utils) +const repr = ShapeRepresentation(getShape, Mesh.Utils); export async function init() { // Create shape from myData and add to canvas3d - await repr.createOrUpdate({}, myData).run((p: Progress) => console.log(Progress.format(p))) - canvas3d.add(repr) - canvas3d.requestCameraReset() + await repr.createOrUpdate({}, myData).run((p: Progress) => console.log(Progress.format(p))); + canvas3d.add(repr); + canvas3d.requestCameraReset(); // Change color after 1s setTimeout(async () => { - myData.colors[0] = ColorNames.darkmagenta + myData.colors[0] = ColorNames.darkmagenta; // Calling `createOrUpdate` with `data` will trigger color and transform update - await repr.createOrUpdate({}, myData).run() - }, 1000) + await repr.createOrUpdate({}, myData).run(); + }, 1000); } -init() \ No newline at end of file +init(); \ No newline at end of file diff --git a/src/tests/browser/render-spheres.ts b/src/tests/browser/render-spheres.ts index 094e48585b429ddcee036a1ad64fe65b1239532b..2862abfb23597b5ef9d61bcb83574e90db5bea53 100644 --- a/src/tests/browser/render-spheres.ts +++ b/src/tests/browser/render-spheres.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { resizeCanvas } from '../../mol-canvas3d/util'; import { Canvas3D } from '../../mol-canvas3d/canvas3d'; import { SpheresBuilder } from '../../mol-geo/geometry/spheres/spheres-builder'; @@ -13,31 +13,31 @@ import { Color } from '../../mol-util/color'; import { createRenderObject } from '../../mol-gl/render-object'; import { Representation } from '../../mol-repr/representation'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); -const canvas3d = Canvas3D.fromCanvas(canvas) -canvas3d.animate() +const canvas3d = Canvas3D.fromCanvas(canvas); +canvas3d.animate(); function spheresRepr() { - const spheresBuilder = SpheresBuilder.create(3, 1) - spheresBuilder.add(0, 0, 0, 0) - spheresBuilder.add(5, 0, 0, 0) - spheresBuilder.add(-4, 1, 0, 0) - const spheres = spheresBuilder.getSpheres() + const spheresBuilder = SpheresBuilder.create(3, 1); + spheresBuilder.add(0, 0, 0, 0); + spheresBuilder.add(5, 0, 0, 0); + spheresBuilder.add(-4, 1, 0, 0); + const spheres = spheresBuilder.getSpheres(); - const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xFF0000), 1) - const state = Spheres.Utils.createRenderableState({}) - const renderObject = createRenderObject('spheres', values, state, -1) - console.log(renderObject) - const repr = Representation.fromRenderObject('spheres', renderObject) - return repr + const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xFF0000), 1); + const state = Spheres.Utils.createRenderableState({}); + const renderObject = createRenderObject('spheres', values, state, -1); + console.log(renderObject); + const repr = Representation.fromRenderObject('spheres', renderObject); + return repr; } -canvas3d.add(spheresRepr()) -canvas3d.requestCameraReset() \ No newline at end of file +canvas3d.add(spheresRepr()); +canvas3d.requestCameraReset(); \ No newline at end of file diff --git a/src/tests/browser/render-structure.ts b/src/tests/browser/render-structure.ts index e19dbb44e12c0505c21816c5173bd05893396f3c..4969c910fc8e81f1a811c4826934dbf2acdf4b67 100644 --- a/src/tests/browser/render-structure.ts +++ b/src/tests/browser/render-structure.ts @@ -4,9 +4,9 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { Canvas3D } from '../../mol-canvas3d/canvas3d'; -import { CIF, CifFrame } from '../../mol-io/reader/cif' +import { CIF, CifFrame } from '../../mol-io/reader/cif'; import { Model, Structure } from '../../mol-model/structure'; import { ColorTheme } from '../../mol-theme/color'; import { SizeTheme } from '../../mol-theme/size'; @@ -27,44 +27,44 @@ import { SecondaryStructureProvider } from '../../mol-model-props/computed/secon import { SyncRuntimeContext } from '../../mol-task/execution/synchronous'; import { ajaxGet } from '../../mol-util/data-source'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); -const canvas3d = Canvas3D.fromCanvas(canvas) -canvas3d.animate() +const canvas3d = Canvas3D.fromCanvas(canvas); +canvas3d.animate(); -const info = document.createElement('div') -info.style.position = 'absolute' -info.style.fontFamily = 'sans-serif' -info.style.fontSize = '16pt' -info.style.bottom = '20px' -info.style.right = '20px' -info.style.color = 'white' -parent.appendChild(info) +const info = document.createElement('div'); +info.style.position = 'absolute'; +info.style.fontFamily = 'sans-serif'; +info.style.fontSize = '16pt'; +info.style.bottom = '20px'; +info.style.right = '20px'; +info.style.color = 'white'; +parent.appendChild(info); -let prevReprLoci = Representation.Loci.Empty +let prevReprLoci = Representation.Loci.Empty; canvas3d.input.move.pipe(throttleTime(100)).subscribe(({x, y}) => { - const pickingId = canvas3d.identify(x, y) - let label = '' + const pickingId = canvas3d.identify(x, y); + let label = ''; if (pickingId) { - const reprLoci = canvas3d.getLoci(pickingId) - label = lociLabel(reprLoci.loci) + const reprLoci = canvas3d.getLoci(pickingId); + label = lociLabel(reprLoci.loci); if (!Representation.Loci.areEqual(prevReprLoci, reprLoci)) { - canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight) - canvas3d.mark(reprLoci, MarkerAction.Highlight) - prevReprLoci = reprLoci + canvas3d.mark(prevReprLoci, MarkerAction.RemoveHighlight); + canvas3d.mark(reprLoci, MarkerAction.Highlight); + prevReprLoci = reprLoci; } } else { - canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight) - prevReprLoci = Representation.Loci.Empty + canvas3d.mark({ loci: EveryLoci }, MarkerAction.RemoveHighlight); + prevReprLoci = Representation.Loci.Empty; } - info.innerHTML = label -}) + info.innerHTML = label; +}); async function parseCif(data: string|Uint8Array) { const comp = CIF.parse(data); @@ -95,42 +95,42 @@ const reprCtx = { webgl: canvas3d.webgl, colorThemeRegistry: ColorTheme.createRegistry(), sizeThemeRegistry: SizeTheme.createRegistry() -} +}; function getCartoonRepr() { - return CartoonRepresentationProvider.factory(reprCtx, CartoonRepresentationProvider.getParams) + return CartoonRepresentationProvider.factory(reprCtx, CartoonRepresentationProvider.getParams); } function getInteractionRepr() { - return InteractionsRepresentationProvider.factory(reprCtx, InteractionsRepresentationProvider.getParams) + return InteractionsRepresentationProvider.factory(reprCtx, InteractionsRepresentationProvider.getParams); } function getBallAndStickRepr() { - return BallAndStickRepresentationProvider.factory(reprCtx, BallAndStickRepresentationProvider.getParams) + return BallAndStickRepresentationProvider.factory(reprCtx, BallAndStickRepresentationProvider.getParams); } function getMolecularSurfaceRepr() { - return MolecularSurfaceRepresentationProvider.factory(reprCtx, MolecularSurfaceRepresentationProvider.getParams) + return MolecularSurfaceRepresentationProvider.factory(reprCtx, MolecularSurfaceRepresentationProvider.getParams); } function getGaussianSurfaceRepr() { - return GaussianSurfaceRepresentationProvider.factory(reprCtx, GaussianSurfaceRepresentationProvider.getParams) + return GaussianSurfaceRepresentationProvider.factory(reprCtx, GaussianSurfaceRepresentationProvider.getParams); } async function init() { - const ctx = { runtime: SyncRuntimeContext, fetch: ajaxGet } + const ctx = { runtime: SyncRuntimeContext, fetch: ajaxGet }; - const cif = await downloadFromPdb('3pqr') - const models = await getModels(cif) - const structure = await getStructure(models[0]) + const cif = await downloadFromPdb('3pqr'); + const models = await getModels(cif); + const structure = await getStructure(models[0]); - console.time('compute SecondaryStructure') - await SecondaryStructureProvider.attach(ctx, structure) + console.time('compute SecondaryStructure'); + await SecondaryStructureProvider.attach(ctx, structure); console.timeEnd('compute SecondaryStructure'); - console.time('compute Interactions') - await InteractionsProvider.attach(ctx, structure) + console.time('compute Interactions'); + await InteractionsProvider.attach(ctx, structure); console.timeEnd('compute Interactions'); - console.log(InteractionsProvider.get(structure).value) + console.log(InteractionsProvider.get(structure).value); const show = { cartoon: true, @@ -138,65 +138,65 @@ async function init() { ballAndStick: true, molecularSurface: false, gaussianSurface: false, - } + }; - const cartoonRepr = getCartoonRepr() - const interactionRepr = getInteractionRepr() - const ballAndStickRepr = getBallAndStickRepr() - const molecularSurfaceRepr = getMolecularSurfaceRepr() - const gaussianSurfaceRepr = getGaussianSurfaceRepr() + const cartoonRepr = getCartoonRepr(); + const interactionRepr = getInteractionRepr(); + const ballAndStickRepr = getBallAndStickRepr(); + const molecularSurfaceRepr = getMolecularSurfaceRepr(); + const gaussianSurfaceRepr = getGaussianSurfaceRepr(); if (show.cartoon) { cartoonRepr.setTheme({ color: reprCtx.colorThemeRegistry.create('element-symbol', { structure }), size: reprCtx.sizeThemeRegistry.create('uniform', { structure }) - }) - await cartoonRepr.createOrUpdate({ ...CartoonRepresentationProvider.defaultValues, quality: 'auto' }, structure).run() + }); + await cartoonRepr.createOrUpdate({ ...CartoonRepresentationProvider.defaultValues, quality: 'auto' }, structure).run(); } if (show.interaction) { interactionRepr.setTheme({ color: reprCtx.colorThemeRegistry.create('interaction-type', { structure }), size: reprCtx.sizeThemeRegistry.create('uniform', { structure }) - }) - await interactionRepr.createOrUpdate({ ...InteractionsRepresentationProvider.defaultValues, quality: 'auto' }, structure).run() + }); + await interactionRepr.createOrUpdate({ ...InteractionsRepresentationProvider.defaultValues, quality: 'auto' }, structure).run(); } if (show.ballAndStick) { ballAndStickRepr.setTheme({ color: reprCtx.colorThemeRegistry.create('element-symbol', { structure }), size: reprCtx.sizeThemeRegistry.create('uniform', { structure }, { value: 1 }) - }) - await ballAndStickRepr.createOrUpdate({ ...BallAndStickRepresentationProvider.defaultValues, quality: 'auto' }, structure).run() + }); + await ballAndStickRepr.createOrUpdate({ ...BallAndStickRepresentationProvider.defaultValues, quality: 'auto' }, structure).run(); } if (show.molecularSurface) { molecularSurfaceRepr.setTheme({ color: reprCtx.colorThemeRegistry.create('secondary-structure', { structure }), size: reprCtx.sizeThemeRegistry.create('physical', { structure }) - }) - console.time('molecular surface') - await molecularSurfaceRepr.createOrUpdate({ ...MolecularSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 0.5, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run() - console.timeEnd('molecular surface') + }); + console.time('molecular surface'); + await molecularSurfaceRepr.createOrUpdate({ ...MolecularSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 0.5, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run(); + console.timeEnd('molecular surface'); } if (show.gaussianSurface) { gaussianSurfaceRepr.setTheme({ color: reprCtx.colorThemeRegistry.create('secondary-structure', { structure }), size: reprCtx.sizeThemeRegistry.create('physical', { structure }) - }) - console.time('gaussian surface') - await gaussianSurfaceRepr.createOrUpdate({ ...GaussianSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 1.0, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run() - console.timeEnd('gaussian surface') + }); + console.time('gaussian surface'); + await gaussianSurfaceRepr.createOrUpdate({ ...GaussianSurfaceRepresentationProvider.defaultValues, quality: 'custom', alpha: 1.0, flatShaded: true, doubleSided: true, resolution: 0.3 }, structure).run(); + console.timeEnd('gaussian surface'); } - if (show.cartoon) canvas3d.add(cartoonRepr) - if (show.interaction) canvas3d.add(interactionRepr) - if (show.ballAndStick) canvas3d.add(ballAndStickRepr) - if (show.molecularSurface) canvas3d.add(molecularSurfaceRepr) - if (show.gaussianSurface) canvas3d.add(gaussianSurfaceRepr) - canvas3d.requestCameraReset() + if (show.cartoon) canvas3d.add(cartoonRepr); + if (show.interaction) canvas3d.add(interactionRepr); + if (show.ballAndStick) canvas3d.add(ballAndStickRepr); + if (show.molecularSurface) canvas3d.add(molecularSurfaceRepr); + if (show.gaussianSurface) canvas3d.add(gaussianSurfaceRepr); + canvas3d.requestCameraReset(); // canvas3d.setProps({ trackball: { ...canvas3d.props.trackball, spin: true } }) } -init() \ No newline at end of file +init(); \ No newline at end of file diff --git a/src/tests/browser/render-text.ts b/src/tests/browser/render-text.ts index 0c11067311cc7733651a443cf00cb2921df955ed..d1c20a791ec8413779820897a9f9ebe3b5011285 100644 --- a/src/tests/browser/render-text.ts +++ b/src/tests/browser/render-text.ts @@ -4,7 +4,7 @@ * @author Alexander Rose <alexander.rose@weirdbyte.de> */ -import './index.html' +import './index.html'; import { Canvas3D } from '../../mol-canvas3d/canvas3d'; import { TextBuilder } from '../../mol-geo/geometry/text/text-builder'; import { Text } from '../../mol-geo/geometry/text/text'; @@ -16,16 +16,16 @@ import { createRenderObject } from '../../mol-gl/render-object'; import { Spheres } from '../../mol-geo/geometry/spheres/spheres'; import { resizeCanvas } from '../../mol-canvas3d/util'; -const parent = document.getElementById('app')! -parent.style.width = '100%' -parent.style.height = '100%' +const parent = document.getElementById('app')!; +parent.style.width = '100%'; +parent.style.height = '100%'; -const canvas = document.createElement('canvas') -parent.appendChild(canvas) -resizeCanvas(canvas, parent) +const canvas = document.createElement('canvas'); +parent.appendChild(canvas); +resizeCanvas(canvas, parent); -const canvas3d = Canvas3D.fromCanvas(canvas) -canvas3d.animate() +const canvas3d = Canvas3D.fromCanvas(canvas); +canvas3d.animate(); function textRepr() { const props: PD.Values<Text.Params> = { @@ -39,39 +39,39 @@ function textRepr() { tether: true, tetherLength: 1.5, tetherBaseWidth: 0.5, - } + }; - const textBuilder = TextBuilder.create(props, 1, 1) - textBuilder.add('Hello world', 0, 0, 0, 1, 1, 0) + const textBuilder = TextBuilder.create(props, 1, 1); + textBuilder.add('Hello world', 0, 0, 0, 1, 1, 0); // textBuilder.add('Добрый день', 0, 1, 0, 0, 0) // textBuilder.add('美好的一天', 0, 2, 0, 0, 0) // textBuilder.add('¿Cómo estás?', 0, -1, 0, 0, 0) // textBuilder.add('αβγ Å', 0, -2, 0, 0, 0) - const text = textBuilder.getText() + const text = textBuilder.getText(); - const values = Text.Utils.createValuesSimple(text, props, Color(0xFFDD00), 1) - const state = Text.Utils.createRenderableState(props) - const renderObject = createRenderObject('text', values, state, -1) - console.log('text', renderObject, props) - const repr = Representation.fromRenderObject('text', renderObject) - return repr + const values = Text.Utils.createValuesSimple(text, props, Color(0xFFDD00), 1); + const state = Text.Utils.createRenderableState(props); + const renderObject = createRenderObject('text', values, state, -1); + console.log('text', renderObject, props); + const repr = Representation.fromRenderObject('text', renderObject); + return repr; } function spheresRepr() { - const spheresBuilder = SpheresBuilder.create(1, 1) - spheresBuilder.add(0, 0, 0, 0) - spheresBuilder.add(5, 0, 0, 0) - spheresBuilder.add(-4, 1, 0, 0) - const spheres = spheresBuilder.getSpheres() + const spheresBuilder = SpheresBuilder.create(1, 1); + spheresBuilder.add(0, 0, 0, 0); + spheresBuilder.add(5, 0, 0, 0); + spheresBuilder.add(-4, 1, 0, 0); + const spheres = spheresBuilder.getSpheres(); - const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xFF0000), 0.2) - const state = Spheres.Utils.createRenderableState({}) - const renderObject = createRenderObject('spheres', values, state, -1) - console.log('spheres', renderObject) - const repr = Representation.fromRenderObject('spheres', renderObject) - return repr + const values = Spheres.Utils.createValuesSimple(spheres, {}, Color(0xFF0000), 0.2); + const state = Spheres.Utils.createRenderableState({}); + const renderObject = createRenderObject('spheres', values, state, -1); + console.log('spheres', renderObject); + const repr = Representation.fromRenderObject('spheres', renderObject); + return repr; } -canvas3d.add(textRepr()) -canvas3d.add(spheresRepr()) -canvas3d.requestCameraReset() \ No newline at end of file +canvas3d.add(textRepr()); +canvas3d.add(spheresRepr()); +canvas3d.requestCameraReset(); \ No newline at end of file