Skip to content
Snippets Groups Projects
Commit 3532b0d7 authored by Alexander Rose's avatar Alexander Rose
Browse files

Merge branch 'master' into graphics

parents baf0ceb6 71a44e51
Branches
Tags
No related merge requests found
...@@ -13,6 +13,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition'; ...@@ -13,6 +13,7 @@ import { ParamDefinition as PD } from 'mol-util/param-definition';
import { Ccp4Provider, Dsn6Provider, DscifProvider } from './volume'; import { Ccp4Provider, Dsn6Provider, DscifProvider } from './volume';
import { StateTransforms } from '../transforms'; import { StateTransforms } from '../transforms';
import { MmcifProvider, PdbProvider, GroProvider } from './structure'; import { MmcifProvider, PdbProvider, GroProvider } from './structure';
import msgpackDecode from 'mol-io/common/msgpack/decode'
export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | PluginStateObject.Data.String> { export class DataFormatRegistry<D extends PluginStateObject.Data.Binary | PluginStateObject.Data.String> {
private _list: { name: string, provider: DataFormatProvider<D> }[] = [] private _list: { name: string, provider: DataFormatProvider<D> }[] = []
...@@ -140,3 +141,17 @@ export const OpenFile = StateAction.build({ ...@@ -140,3 +141,17 @@ export const OpenFile = StateAction.build({
// need to await the 2nd update the so that the enclosing Task finishes after the update is done. // need to await the 2nd update the so that the enclosing Task finishes after the update is done.
await provider.getDefaultBuilder(ctx, b, state).runInContext(taskCtx) await provider.getDefaultBuilder(ctx, b, state).runInContext(taskCtx)
})); }));
//
type cifVariants = 'dscif' | -1
export function guessCifVariant(info: FileInfo, data: Uint8Array | string): cifVariants {
if (info.ext === 'bcif') {
try {
if (msgpackDecode(data as Uint8Array).encoder.startsWith('VolumeServer')) return 'dscif'
} catch { }
} else if (info.ext === 'cif') {
if ((data as string).startsWith('data_SERVER\n#\n_density_server_result')) return 'dscif'
}
return -1
}
\ No newline at end of file
...@@ -13,7 +13,7 @@ import { StateTransforms } from '../transforms'; ...@@ -13,7 +13,7 @@ import { StateTransforms } from '../transforms';
import { Download } from '../transforms/data'; import { Download } from '../transforms/data';
import { StructureRepresentation3DHelpers } from '../transforms/representation'; import { StructureRepresentation3DHelpers } from '../transforms/representation';
import { CustomModelProperties, StructureSelection } from '../transforms/model'; import { CustomModelProperties, StructureSelection } from '../transforms/model';
import { DataFormatProvider } from './data-format'; import { DataFormatProvider, guessCifVariant } from './data-format';
import { FileInfo } from 'mol-util/file-info'; import { FileInfo } from 'mol-util/file-info';
import { Task } from 'mol-task'; import { Task } from 'mol-task';
import { StructureElement } from 'mol-model/structure'; import { StructureElement } from 'mol-model/structure';
...@@ -24,7 +24,10 @@ export const MmcifProvider: DataFormatProvider<any> = { ...@@ -24,7 +24,10 @@ export const MmcifProvider: DataFormatProvider<any> = {
stringExtensions: ['cif', 'mmcif', 'mcif'], stringExtensions: ['cif', 'mmcif', 'mcif'],
binaryExtensions: ['bcif'], binaryExtensions: ['bcif'],
isApplicable: (info: FileInfo, data: Uint8Array | string) => { isApplicable: (info: FileInfo, data: Uint8Array | string) => {
return info.ext === 'cif' || info.ext === 'mmcif' || info.ext === 'mcif' || info.ext === 'bcif' if (info.ext === 'mmcif' || info.ext === 'mcif') return true
// assume cif/bcif files that are not DensityServer CIF are mmCIF
if (info.ext === 'cif' || info.ext === 'bcif') return guessCifVariant(info, data) !== 'dscif'
return false
}, },
getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, state: State) => { getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, state: State) => {
return Task.create('mmCIF default builder', async taskCtx => { return Task.create('mmCIF default builder', async taskCtx => {
......
...@@ -16,7 +16,7 @@ import { PluginStateObject } from '../objects'; ...@@ -16,7 +16,7 @@ import { PluginStateObject } from '../objects';
import { StateTransforms } from '../transforms'; import { StateTransforms } from '../transforms';
import { Download } from '../transforms/data'; import { Download } from '../transforms/data';
import { VolumeRepresentation3DHelpers } from '../transforms/representation'; import { VolumeRepresentation3DHelpers } from '../transforms/representation';
import { DataFormatProvider } from './data-format'; import { DataFormatProvider, guessCifVariant } from './data-format';
export const Ccp4Provider: DataFormatProvider<any> = { export const Ccp4Provider: DataFormatProvider<any> = {
label: 'CCP4/MRC/BRIX', label: 'CCP4/MRC/BRIX',
...@@ -59,10 +59,10 @@ export const DscifProvider: DataFormatProvider<any> = { ...@@ -59,10 +59,10 @@ export const DscifProvider: DataFormatProvider<any> = {
description: 'DensityServer CIF', description: 'DensityServer CIF',
stringExtensions: ['cif'], stringExtensions: ['cif'],
binaryExtensions: ['bcif'], binaryExtensions: ['bcif'],
isApplicable: (info: FileInfo, data: Uint8Array) => { isApplicable: (info: FileInfo, data: Uint8Array | string) => {
return info.ext === 'cif' || info.ext === 'bcif' return guessCifVariant(info, data) === 'dscif' ? true : false
}, },
getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary>, state: State) => { getDefaultBuilder: (ctx: PluginContext, data: StateBuilder.To<PluginStateObject.Data.Binary | PluginStateObject.Data.String>, state: State) => {
return Task.create('DensityServer CIF default builder', async taskCtx => { return Task.create('DensityServer CIF default builder', async taskCtx => {
const cifBuilder = data.apply(StateTransforms.Data.ParseCif) const cifBuilder = data.apply(StateTransforms.Data.ParseCif)
const cifStateObject = await state.updateTree(cifBuilder).runInContext(taskCtx) const cifStateObject = await state.updateTree(cifBuilder).runInContext(taskCtx)
......
...@@ -11,7 +11,7 @@ import { OrderedSet, SortedArray } from 'mol-data/int'; ...@@ -11,7 +11,7 @@ import { OrderedSet, SortedArray } from 'mol-data/int';
import { EmptyLoci, Loci } from 'mol-model/loci'; import { EmptyLoci, Loci } from 'mol-model/loci';
/** Return a Loci for the elements of a whole residue the elementIndex belongs to. */ /** Return a Loci for the elements of a whole residue the elementIndex belongs to. */
export function getResidueLoci(structure: Structure, unit: Unit, elementIndex: ElementIndex): Loci { 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) { if (OrderedSet.indexOf(elements, elementIndex) !== -1) {
const { index, offsets } = model.atomicHierarchy.residueAtomSegments const { index, offsets } = model.atomicHierarchy.residueAtomSegments
......
...@@ -72,12 +72,25 @@ export function getPolymerElementLoci(pickingId: PickingId, structureGroup: Stru ...@@ -72,12 +72,25 @@ export function getPolymerElementLoci(pickingId: PickingId, structureGroup: Stru
if (id === objectId) { if (id === objectId) {
const { structure, group } = structureGroup const { structure, group } = structureGroup
const unit = group.units[instanceId] 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
if (unitIndex !== -1) {
const indices = OrderedSet.ofSingleton(unitIndex)
return StructureElement.Loci(structure, [{ unit, indices }])
}
}
} }
return EmptyLoci return EmptyLoci
} }
/** Mark a polymer element (e.g. part of a cartoon trace) when all its residue's elements are in a loci. */ /**
* Mark a polymer element (e.g. part of a cartoon trace)
* - for atomic units mark only when all its residue's elements are in a loci
*/
export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) { export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, apply: (interval: Interval) => boolean) {
let changed = false let changed = false
if (!StructureElement.isLoci(loci)) return false if (!StructureElement.isLoci(loci)) return false
...@@ -90,6 +103,7 @@ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, a ...@@ -90,6 +103,7 @@ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, a
for (const e of loci.elements) { 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 (unitIdx !== undefined) {
if (Unit.isAtomic(e.unit)) {
// TODO optimized implementation for intervals // TODO optimized implementation for intervals
OrderedSet.forEach(e.indices, v => { OrderedSet.forEach(e.indices, v => {
const rI = index[elements[v]] const rI = index[elements[v]]
...@@ -103,6 +117,18 @@ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, a ...@@ -103,6 +117,18 @@ export function eachPolymerElement(loci: Loci, structureGroup: StructureGroup, a
if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true if (apply(Interval.ofSingleton(unitIdx * groupCount + idx))) changed = true
} }
}) })
} else {
if (Interval.is(e.indices)) {
const start = unitIdx * groupCount + Interval.start(e.indices);
const end = unitIdx * groupCount + 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 = unitIdx * groupCount + e.indices[i];
if (apply(Interval.ofSingleton(idx))) changed = true
}
}
}
} }
} }
return changed return changed
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment