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

wip isovalue param

parent 82401b4d
No related branches found
No related tags found
No related merge requests found
...@@ -47,6 +47,7 @@ function controlFor(param: PD.Any): ParamControl | undefined { ...@@ -47,6 +47,7 @@ function controlFor(param: PD.Any): ParamControl | undefined {
case 'number': return typeof param.min !== 'undefined' && typeof param.max !== 'undefined' case 'number': return typeof param.min !== 'undefined' && typeof param.max !== 'undefined'
? NumberRangeControl : NumberInputControl; ? NumberRangeControl : NumberInputControl;
case 'converted': return ConvertedControl; case 'converted': return ConvertedControl;
case 'conditioned': return ConditionedControl;
case 'multi-select': return MultiSelectControl; case 'multi-select': return MultiSelectControl;
case 'color': return ColorControl; case 'color': return ColorControl;
case 'color-scale': return ColorScaleControl; case 'color-scale': return ColorScaleControl;
...@@ -456,6 +457,41 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any> ...@@ -456,6 +457,41 @@ export class MappedControl extends React.PureComponent<ParamProps<PD.Mapped<any>
} }
} }
export class ConditionedControl extends React.PureComponent<ParamProps<PD.Conditioned<any, any, any>>> {
change(value: PD.Conditioned<any, any, any>['defaultValue'] ) {
this.props.onChange({ name: this.props.name, param: this.props.param, value });
}
onChangeCondition: ParamOnChange = e => {
this.change(this.props.param.conditionedValue(this.props.value, e.value));
}
onChangeParam: ParamOnChange = e => {
this.change(e.value);
}
render() {
const value = this.props.value;
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} />
if (!Conditioned) {
return select;
}
return <div>
{select}
<Conditioned param={param} value={value} name={label} onChange={this.onChangeParam} onEnter={this.props.onEnter} isDisabled={this.props.isDisabled} />
</div>
}
}
export class ConvertedControl extends React.PureComponent<ParamProps<PD.Converted<any, any>>> { export class ConvertedControl extends React.PureComponent<ParamProps<PD.Converted<any, any>>> {
onChange: ParamOnChange = e => { onChange: ParamOnChange = e => {
this.props.onChange({ this.props.onChange({
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
import { VolumeData } from 'mol-model/volume' import { VolumeData, VolumeIsoValue } from 'mol-model/volume'
import { VolumeVisual, VolumeRepresentation, VolumeRepresentationProvider } from './representation'; import { VolumeVisual, VolumeRepresentation, VolumeRepresentationProvider } from './representation';
import { EmptyLoci } from 'mol-model/loci'; import { EmptyLoci } from 'mol-model/loci';
import { ParamDefinition as PD } from 'mol-util/param-definition'; import { ParamDefinition as PD } from 'mol-util/param-definition';
...@@ -19,9 +19,30 @@ import { VisualContext } from 'mol-repr/visual'; ...@@ -19,9 +19,30 @@ import { VisualContext } from 'mol-repr/visual';
import { NullLocation } from 'mol-model/location'; import { NullLocation } from 'mol-model/location';
import { Lines } from 'mol-geo/geometry/lines/lines'; import { Lines } from 'mol-geo/geometry/lines/lines';
interface VolumeIsosurfaceProps { const IsoValueParam = PD.Conditioned(
isoValue: number VolumeIsoValue.relative(VolumeData.Empty.dataStats, 2),
{
'absolute': PD.Converted(
(v: VolumeIsoValue) => VolumeIsoValue.toAbsolute(v).absoluteValue,
(v: number) => VolumeIsoValue.absolute(VolumeData.Empty.dataStats, v),
PD.Numeric(0, { min: -1, max: 1, step: 0.01 })
),
'relative': PD.Converted(
(v: VolumeIsoValue) => VolumeIsoValue.toRelative(v).relativeValue,
(v: number) => VolumeIsoValue.relative(VolumeData.Empty.dataStats, v),
PD.Numeric(0, { min: -1, max: 1, step: 0.01 })
)
},
(v: VolumeIsoValue) => v.kind === 'absolute' ? 'absolute' : 'relative',
(v: VolumeIsoValue, c: 'absolute' | 'relative') => c === 'absolute' ? VolumeIsoValue.toAbsolute(v) : VolumeIsoValue.toRelative(v)
)
type IsoValueParam = typeof IsoValueParam
export const VolumeIsosurfaceParams = {
isoValue: IsoValueParam
} }
export type VolumeIsosurfaceParams = typeof VolumeIsosurfaceParams
export type VolumeIsosurfaceProps = PD.Values<VolumeIsosurfaceParams>
// //
...@@ -29,7 +50,7 @@ export async function createVolumeIsosurfaceMesh(ctx: VisualContext, volume: Vol ...@@ -29,7 +50,7 @@ export async function createVolumeIsosurfaceMesh(ctx: VisualContext, volume: Vol
ctx.runtime.update({ message: 'Marching cubes...' }); ctx.runtime.update({ message: 'Marching cubes...' });
const surface = await computeMarchingCubesMesh({ const surface = await computeMarchingCubesMesh({
isoLevel: props.isoValue, isoLevel: VolumeIsoValue.toAbsolute(props.isoValue).absoluteValue,
scalarField: volume.data scalarField: volume.data
}, mesh).runAsChild(ctx.runtime); }, mesh).runAsChild(ctx.runtime);
...@@ -43,7 +64,7 @@ export async function createVolumeIsosurfaceMesh(ctx: VisualContext, volume: Vol ...@@ -43,7 +64,7 @@ export async function createVolumeIsosurfaceMesh(ctx: VisualContext, volume: Vol
export const IsosurfaceMeshParams = { export const IsosurfaceMeshParams = {
...Mesh.Params, ...Mesh.Params,
isoValue: PD.Numeric(0.22, { min: -1, max: 1, step: 0.01 }), ...VolumeIsosurfaceParams
} }
export type IsosurfaceMeshParams = typeof IsosurfaceMeshParams export type IsosurfaceMeshParams = typeof IsosurfaceMeshParams
...@@ -66,11 +87,10 @@ export function IsosurfaceMeshVisual(): VolumeVisual<IsosurfaceMeshParams> { ...@@ -66,11 +87,10 @@ export function IsosurfaceMeshVisual(): VolumeVisual<IsosurfaceMeshParams> {
export async function createVolumeIsosurfaceWireframe(ctx: VisualContext, volume: VolumeData, theme: Theme, props: VolumeIsosurfaceProps, lines?: Lines) { export async function createVolumeIsosurfaceWireframe(ctx: VisualContext, volume: VolumeData, theme: Theme, props: VolumeIsosurfaceProps, lines?: Lines) {
ctx.runtime.update({ message: 'Marching cubes...' }); ctx.runtime.update({ message: 'Marching cubes...' });
const params = { const wireframe = await computeMarchingCubesLines({
isoLevel: props.isoValue, isoLevel: VolumeIsoValue.toAbsolute(props.isoValue).absoluteValue,
scalarField: volume.data scalarField: volume.data
} }, lines).runAsChild(ctx.runtime)
const wireframe = await computeMarchingCubesLines(params, lines).runAsChild(ctx.runtime)
const transform = VolumeData.getGridToCartesianTransform(volume); const transform = VolumeData.getGridToCartesianTransform(volume);
Lines.transformImmediate(wireframe, transform) Lines.transformImmediate(wireframe, transform)
...@@ -80,7 +100,7 @@ export async function createVolumeIsosurfaceWireframe(ctx: VisualContext, volume ...@@ -80,7 +100,7 @@ export async function createVolumeIsosurfaceWireframe(ctx: VisualContext, volume
export const IsosurfaceWireframeParams = { export const IsosurfaceWireframeParams = {
...Lines.Params, ...Lines.Params,
isoValue: PD.Numeric(0.22, { min: -1, max: 1, step: 0.01 }), ...VolumeIsosurfaceParams
} }
export type IsosurfaceWireframeParams = typeof IsosurfaceWireframeParams export type IsosurfaceWireframeParams = typeof IsosurfaceWireframeParams
...@@ -114,7 +134,26 @@ export const IsosurfaceParams = { ...@@ -114,7 +134,26 @@ export const IsosurfaceParams = {
} }
export type IsosurfaceParams = typeof IsosurfaceParams export type IsosurfaceParams = typeof IsosurfaceParams
export function getIsosurfaceParams(ctx: ThemeRegistryContext, volume: VolumeData) { export function getIsosurfaceParams(ctx: ThemeRegistryContext, volume: VolumeData) {
return PD.clone(IsosurfaceParams) const p = PD.clone(IsosurfaceParams)
const { min, max, mean, sigma } = volume.dataStats
p.isoValue = PD.Conditioned(
VolumeIsoValue.relative(volume.dataStats, 2),
{
'absolute': PD.Converted(
(v: VolumeIsoValue) => VolumeIsoValue.toAbsolute(v).absoluteValue,
(v: number) => VolumeIsoValue.absolute(volume.dataStats, v),
PD.Numeric(mean, { min, max, step: sigma / 100 })
),
'relative': PD.Converted(
(v: VolumeIsoValue) => VolumeIsoValue.toRelative(v).relativeValue,
(v: number) => VolumeIsoValue.relative(volume.dataStats, v),
PD.Numeric(2, { min: -10, max: 10, step: 0.001 })
)
},
(v: VolumeIsoValue) => v.kind === 'absolute' ? 'absolute' : 'relative',
(v: VolumeIsoValue, c: 'absolute' | 'relative') => c === 'absolute' ? VolumeIsoValue.toAbsolute(v) : VolumeIsoValue.toRelative(v)
)
return p
} }
export type IsosurfaceRepresentation = VolumeRepresentation<IsosurfaceParams> export type IsosurfaceRepresentation = VolumeRepresentation<IsosurfaceParams>
......
...@@ -205,7 +205,6 @@ export type VolumeRepresentationProvider<P extends VolumeParams> = Representatio ...@@ -205,7 +205,6 @@ export type VolumeRepresentationProvider<P extends VolumeParams> = Representatio
export const VolumeParams = { export const VolumeParams = {
...BaseGeometry.Params, ...BaseGeometry.Params,
isoValue: PD.Numeric(0.22, { min: -1, max: 1, step: 0.01 }),
} }
export type VolumeParams = typeof VolumeParams export type VolumeParams = typeof VolumeParams
......
...@@ -190,7 +190,7 @@ export namespace ParamDefinition { ...@@ -190,7 +190,7 @@ export namespace ParamDefinition {
export interface Converted<T, C> extends Base<T> { export interface Converted<T, C> extends Base<T> {
type: 'converted', type: 'converted',
converted: Any, converted: Any,
/** converts from props value to display value */ /** converts from prop value to display value */
fromValue(v: T): C, fromValue(v: T): C,
/** converts from display value to prop value */ /** converts from display value to prop value */
toValue(v: C): T toValue(v: C): T
...@@ -199,7 +199,19 @@ export namespace ParamDefinition { ...@@ -199,7 +199,19 @@ export namespace ParamDefinition {
return { type: 'converted', defaultValue: toValue(converted.defaultValue), converted, fromValue, toValue }; return { type: 'converted', defaultValue: toValue(converted.defaultValue), converted, fromValue, toValue };
} }
export type Any = Value<any> | Select<any> | MultiSelect<any> | Boolean | Text | Color | Vec3 | Numeric | FileParam | Interval | LineGraph | ColorScale<any> | Group<any> | Mapped<any> | Converted<any, any> export interface Conditioned<T, P extends Base<T>, C = { [k: string]: P }> extends Base<T> {
type: 'conditioned',
select: Select<string>,
conditionParams: C
conditionForValue(v: T): keyof C
conditionedValue(v: T, condition: keyof C): T,
}
export function Conditioned<T, P extends Base<T>, C = { [k: string]: P }>(defaultValue: T, conditionParams: C, conditionForValue: (v: T) => keyof C, conditionedValue: (v: T, condition: keyof C) => T): Conditioned<T, P, C> {
const options = Object.keys(conditionParams).map(k => [k, k]) as [string, string][];
return { type: 'conditioned', select: Select<string>(conditionForValue(defaultValue) as string, options), defaultValue, conditionParams, conditionForValue, conditionedValue };
}
export type Any = Value<any> | Select<any> | MultiSelect<any> | Boolean | Text | Color | Vec3 | Numeric | FileParam | Interval | LineGraph | ColorScale<any> | Group<any> | Mapped<any> | Converted<any, any> | Conditioned<any, any, any>
export type Params = { [k: string]: Any } export type Params = { [k: string]: Any }
export type Values<T extends Params> = { [k in keyof T]: T[k]['defaultValue'] } export type Values<T extends Params> = { [k in keyof T]: T[k]['defaultValue'] }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment