diff --git a/CHANGELOG.md b/CHANGELOG.md index 283c8880f0c16cacafc258e6bca603c17d806384..954678f09fe71926ceb95cca4db4ffd1e2883ab8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Note that since we don't clearly distinguish between a public and private interf ## [Unreleased] - Fix VolumeServer/query CLI +- Support automatic iso-value adjustment for VolumeServer data in ``Viewer.loadVolumeFromUrl`` ## [v3.0.0] - 2022-01-23 diff --git a/src/apps/viewer/app.ts b/src/apps/viewer/app.ts index b399d04bc9f6570004484e9652c05244a8d1f20c..af6afd97b418dca8dfa28700a82a40b53c80296a 100644 --- a/src/apps/viewer/app.ts +++ b/src/apps/viewer/app.ts @@ -17,6 +17,7 @@ import { ModelExport } from '../../extensions/model-export'; import { Mp4Export } from '../../extensions/mp4-export'; import { PDBeStructureQualityReport } from '../../extensions/pdbe'; import { RCSBAssemblySymmetry, RCSBValidationReport } from '../../extensions/rcsb'; +import { Volume } from '../../mol-model/volume'; import { DownloadStructure, PdbDownloadProvider } from '../../mol-plugin-state/actions/structure'; import { DownloadDensity } from '../../mol-plugin-state/actions/volume'; import { PresetTrajectoryHierarchy } from '../../mol-plugin-state/builder/structure/hierarchy-preset'; @@ -366,11 +367,13 @@ export class Viewer { const repr = plugin.build(); for (const iso of isovalues) { + const volume: StateObjectSelector<PluginStateObject.Volume.Data> = parsed.volumes?.[iso.volumeIndex ?? 0] ?? parsed.volume; + const volumeData = volume.cell!.obj!.data; repr - .to(parsed.volumes?.[iso.volumeIndex ?? 0] ?? parsed.volume) + .to(volume) .apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(this.plugin, firstVolume.data!, { type: 'isosurface', - typeParams: { alpha: iso.alpha ?? 1, isoValue: iso.type === 'absolute' ? { kind: 'absolute', absoluteValue: iso.value } : { kind: 'relative', relativeValue: iso.value } }, + typeParams: { alpha: iso.alpha ?? 1, isoValue: Volume.adjustedIsoValue(volumeData, iso.value, iso.type) }, color: 'uniform', colorParams: { value: iso.color } })); diff --git a/src/mol-model/volume/volume.ts b/src/mol-model/volume/volume.ts index 280a32d7e26e9f2a3f455b3c77e84677b488ebf5..8a322563ae06817f174312c55f413357baded5a1 100644 --- a/src/mol-model/volume/volume.ts +++ b/src/mol-model/volume/volume.ts @@ -15,6 +15,7 @@ import { ModelFormat } from '../../mol-model-formats/format'; import { CustomProperties } from '../custom-property'; import { ParamDefinition as PD } from '../../mol-util/param-definition'; import { toPrecision } from '../../mol-util/number'; +import { DscifFormat } from '../../mol-model-formats/volume/density-server'; export interface Volume { readonly label?: string @@ -84,6 +85,23 @@ export namespace Volume { } } + // Converts iso value to relative if using downsample VolumeServer data + export function adjustedIsoValue(volume: Volume, value: number, kind: 'absolute' | 'relative') { + if (kind === 'relative') return IsoValue.relative(value); + + const absolute = IsoValue.absolute(value); + if (DscifFormat.is(volume.sourceData)) { + const stats = { + min: volume.sourceData.data.volume_data_3d_info.min_source.value(0), + max: volume.sourceData.data.volume_data_3d_info.max_source.value(0), + mean: volume.sourceData.data.volume_data_3d_info.mean_source.value(0), + sigma: volume.sourceData.data.volume_data_3d_info.sigma_source.value(0), + }; + return Volume.IsoValue.toRelative(absolute, stats); + } + return absolute; + } + const defaultStats: Grid['stats'] = { min: -1, max: 1, mean: 0, sigma: 0.1 }; export function createIsoValueParam(defaultValue: Volume.IsoValue, stats?: Grid['stats']) { const sts = stats || defaultStats; diff --git a/src/mol-plugin-state/formats/volume.ts b/src/mol-plugin-state/formats/volume.ts index d3701364f2018e11e37cabf0576a52f0c88850b5..f2c527738c53323a48191cb2906ffa764e67e247 100644 --- a/src/mol-plugin-state/formats/volume.ts +++ b/src/mol-plugin-state/formats/volume.ts @@ -18,7 +18,6 @@ import { objectForEach } from '../../mol-util/object'; import { RecommendedIsoValue } from '../../mol-model-formats/volume/property'; import { getContourLevelEmdb } from '../../mol-plugin/behavior/dynamic/volume-streaming/util'; import { Task } from '../../mol-task'; -import { DscifFormat } from '../../mol-model-formats/volume/density-server'; export const VolumeFormatCategory = 'Volume'; type Params = { entryId?: string }; @@ -42,19 +41,9 @@ async function tryObtainRecommendedIsoValue(plugin: PluginContext, volume?: Volu function tryGetRecomendedIsoValue(volume: Volume) { const recommendedIsoValue = RecommendedIsoValue.Provider.get(volume); if (!recommendedIsoValue) return; - if (recommendedIsoValue.kind === 'relative') return recommendedIsoValue; - let stats = volume.grid.stats; - if (DscifFormat.is(volume.sourceData)) { - stats = { - min: volume.sourceData.data.volume_data_3d_info.min_source.value(0), - max: volume.sourceData.data.volume_data_3d_info.max_source.value(0), - mean: volume.sourceData.data.volume_data_3d_info.mean_source.value(0), - sigma: volume.sourceData.data.volume_data_3d_info.sigma_source.value(0), - }; - } - return Volume.IsoValue.toRelative(recommendedIsoValue, stats); + return Volume.adjustedIsoValue(volume, recommendedIsoValue.absoluteValue, 'absolute'); } async function defaultVisuals(plugin: PluginContext, data: { volume: StateObjectSelector<PluginStateObject.Volume.Data> }) {