UNPKG

pdbe-molstar

Version:
158 lines (157 loc) 12.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AfSuperpositionControls = exports.AlphafoldSuperpositionParams = exports.AlphafoldSuperpositionControls = exports.AlphafoldPaeControls = void 0; const tslib_1 = require("tslib"); const jsx_runtime_1 = require("react/jsx-runtime"); const d3_axis_1 = require("d3-axis"); const d3_scale_1 = require("d3-scale"); const d3_selection_1 = require("d3-selection"); const base_1 = require("molstar/lib/mol-plugin-ui/base"); const common_1 = require("molstar/lib/mol-plugin-ui/controls/common"); const icons_1 = require("molstar/lib/mol-plugin-ui/controls/icons"); const parameters_1 = require("molstar/lib/mol-plugin-ui/controls/parameters"); const param_definition_1 = require("molstar/lib/mol-util/param-definition"); const react_1 = tslib_1.__importDefault(require("react")); const plugin_custom_state_1 = require("../plugin-custom-state"); const superposition_1 = require("../superposition"); const icons_2 = require("./icons"); class AlphafoldPaeControls extends base_1.CollapsableControls { defaultState() { return { isCollapsed: false, header: 'AlphaFold PAE', brand: { accent: 'gray', svg: icons_1.SuperpositionSvg }, isHidden: true, }; } constructor(props, context) { super(props, context); this.axisBoxRef = react_1.default.createRef(); } componentDidMount() { this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, sel => { const superpositionState = (0, plugin_custom_state_1.PluginCustomState)(this.plugin).superpositionState; if (superpositionState && superpositionState.alphafold.ref && superpositionState.alphafold.apiData.pae && superpositionState.alphafold.apiData.pae !== '' && superpositionState.alphafold.apiData.pae !== '') { this.setState({ isHidden: false }); const domainMax = superpositionState.alphafold.apiData.length; const x = (0, d3_scale_1.scaleLinear)().domain([0, domainMax]).range([0, 200]); const xAxis = (0, d3_axis_1.axisBottom)(x).ticks(6).tickFormat(this.formatTicks).tickSizeOuter(0); const yAxis = (0, d3_axis_1.axisLeft)(x).ticks(6).tickFormat(this.formatTicks).tickSizeOuter(0); const axisContainer = (0, d3_selection_1.select)(this.axisBoxRef.current); axisContainer.append('svg:svg') .attr('width', 220) .attr('height', 30) .attr('class', 'pae-x-axis') .style('z-index', '1') .style('position', 'absolute') .attr('transform', `translate(-93,202)`) .append('g') .attr('transform', `translate(6,0)`) .call(xAxis); axisContainer.append('svg:svg') .attr('width', 50) .attr('height', 220) .attr('class', 'pae-y-axis') .style('z-index', '1') .style('position', 'absolute') .attr('transform', `translate(-123,0)`) .append('g') .attr('transform', `translate(36,4)`) .call(yAxis); } }); } formatTicks(d) { return d > 999 ? d / 1000 + 'k' : d; } renderControls() { const superpositionState = (0, plugin_custom_state_1.PluginCustomState)(this.plugin).superpositionState; if (!superpositionState || !superpositionState.alphafold) return null; const errorScale = [0, 5, 10, 15, 20, 25, 30]; return (0, jsx_runtime_1.jsxs)("div", { className: 'msp-flex-row', style: { height: 'auto', textAlign: 'center', justifyContent: 'center', padding: '15px 0', position: 'relative', fontSize: '12px' }, children: [(0, jsx_runtime_1.jsx)("div", { ref: this.axisBoxRef, className: 'pae-axis-box', style: { position: 'absolute', width: '100%', height: '100%' } }), (0, jsx_runtime_1.jsx)("span", { style: { transform: 'rotate(270deg)', position: 'absolute', transformOrigin: '0 0', left: '10px', top: '165px', fontWeight: 500 }, children: "Aligned residue" }), (0, jsx_runtime_1.jsxs)("div", { className: 'msp-flex-row', style: { height: 'auto', flexDirection: 'column' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { width: '200px', height: '200px', border: '1px solid #6a635a', margin: '2px 0 25px 25px', position: 'relative' }, children: (0, jsx_runtime_1.jsx)("img", { style: { width: '100%', height: '100%', position: 'absolute', left: 0, top: 0 }, src: `${superpositionState.alphafold.apiData.pae}`, alt: "PAE" }) }), (0, jsx_runtime_1.jsx)("div", { style: { textAlign: 'center', paddingLeft: '30px', marginBottom: '20px', fontWeight: 500 }, children: "Scored residue" }), (0, jsx_runtime_1.jsx)("img", { style: { width: '200px', height: '10px', border: '1px solid #6a635a', margin: '2px 0 25px 25px', transform: 'rotate(180deg)' }, src: 'https://alphafold.ebi.ac.uk/assets/img/horizontal_colorbar.png', alt: "PAE Scale" }), (0, jsx_runtime_1.jsx)("ul", { style: { listStyleType: 'none', fontWeight: 500, margin: 0, display: 'inline-block', position: 'absolute', top: '292px', marginLeft: '24px' }, children: errorScale.map((errValue) => (0, jsx_runtime_1.jsx)("li", { style: { float: 'left', marginRight: '18px' }, children: errValue }, errValue)) }), (0, jsx_runtime_1.jsx)("div", { style: { textAlign: 'center', paddingLeft: '20px', fontWeight: 500 }, children: "Expected position error (\u00C5ngstr\u00F6ms)" })] })] }); } } exports.AlphafoldPaeControls = AlphafoldPaeControls; class AlphafoldSuperpositionControls extends base_1.CollapsableControls { defaultState() { return { isCollapsed: false, header: 'AlphaFold Superposition', brand: { accent: 'gray', svg: icons_1.SuperpositionSvg }, isHidden: true, }; } componentDidMount() { this.subscribe(this.plugin.managers.structure.hierarchy.behaviors.selection, sel => { const superpositionState = (0, plugin_custom_state_1.PluginCustomState)(this.plugin).superpositionState; if ((superpositionState === null || superpositionState === void 0 ? void 0 : superpositionState.alphafold.apiData.cif) && (superpositionState === null || superpositionState === void 0 ? void 0 : superpositionState.alphafold.apiData.bcif)) { this.setState({ isHidden: false }); } }); } rmsdTable() { const spData = (0, plugin_custom_state_1.PluginCustomState)(this.plugin).superpositionState; if (!spData) throw new Error('customState.superpositionState has not been initialized'); const { activeSegment } = spData; const { rmsds } = spData.alphafold; return (0, jsx_runtime_1.jsxs)("div", { className: 'msp-control-offset', children: [(rmsds.length === 0 || !rmsds[activeSegment - 1]) && (0, jsx_runtime_1.jsx)("div", { className: 'msp-flex-row', style: { padding: '5px 0 0 10px' }, children: (0, jsx_runtime_1.jsx)("strong", { children: "No overlap found!" }) }), rmsds[activeSegment - 1] && (0, jsx_runtime_1.jsxs)("div", { className: 'msp-flex-row', children: [(0, jsx_runtime_1.jsx)("div", { style: { width: '40%', borderRight: '1px solid rgb(213 206 196)', padding: '5px 0 0 5px' }, children: (0, jsx_runtime_1.jsx)("strong", { children: "Entry" }) }), (0, jsx_runtime_1.jsx)("div", { style: { padding: '5px 0 0 5px' }, children: (0, jsx_runtime_1.jsx)("strong", { children: "RMSD (\u212B)" }) })] }), rmsds[activeSegment - 1] && rmsds[activeSegment - 1].map((d) => { const details = d.split(':'); return details[1] !== '-' ? (0, jsx_runtime_1.jsxs)("div", { className: 'msp-flex-row', children: [(0, jsx_runtime_1.jsx)("div", { className: 'msp-control-row-label', style: { width: '40%', borderRight: '1px solid rgb(213 206 196)', padding: '5px 0 0 5px' }, children: details[0] }), (0, jsx_runtime_1.jsx)("div", { style: { padding: '5px 0 0 5px' }, children: details[1] })] }, d) : null; })] }); } renderControls() { const superpositionState = (0, plugin_custom_state_1.PluginCustomState)(this.plugin).superpositionState; if (!superpositionState) throw new Error('customState.superpositionState has not been initialized'); return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [superpositionState.alphafold.ref !== '' && this.rmsdTable(), superpositionState.alphafold.ref === '' && (0, jsx_runtime_1.jsx)(AfSuperpositionControls, {})] }); } } exports.AlphafoldSuperpositionControls = AlphafoldSuperpositionControls; exports.AlphafoldSuperpositionParams = { // alignSequences: PD.Boolean(true, { isEssential: true, description: 'For Chain-based 3D superposition, perform a sequence alignment and use the aligned residue pairs to guide the 3D superposition.' }), traceOnly: param_definition_1.ParamDefinition.Boolean(true, { description: 'For Chain- and Uniprot-based 3D superposition, base superposition only on CA (and equivalent) atoms.' }), }; const DefaultAlphafoldSuperpositionOptions = param_definition_1.ParamDefinition.getDefaultValues(exports.AlphafoldSuperpositionParams); class AfSuperpositionControls extends base_1.PurePluginUIComponent { constructor() { super(...arguments); this.state = { isBusy: false, canUseDb: true, action: undefined, options: DefaultAlphafoldSuperpositionOptions, }; this.superposeDb = () => tslib_1.__awaiter(this, void 0, void 0, function* () { this.setState({ isBusy: true }); const spData = this.customState.superpositionState; if (!spData) throw new Error('customState.superpositionState has not been initialized'); spData.alphafold.traceOnly = this.state.options.traceOnly; (0, superposition_1.superposeAf)(this.plugin, this.state.options.traceOnly); }); this.toggleOptions = () => this.setState({ action: this.state.action === 'options' ? undefined : 'options' }); this.setOptions = (values) => { this.setState({ options: values }); }; } componentDidMount() { this.subscribe(this.plugin.behaviors.state.isBusy, v => { this.setState({ isBusy: v }); }); } get selection() { return this.plugin.managers.structure.selection; } get customState() { return (0, plugin_custom_state_1.PluginCustomState)(this.plugin); } superposeByDbMapping() { return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(common_1.Button, { icon: icons_1.SuperposeChainsSvg, title: 'Superpose AlphaFold structure using intersection of residues from SIFTS UNIPROT mapping.', className: 'msp-btn msp-btn-block', onClick: this.superposeDb, style: { marginTop: '1px', textAlign: 'left' }, disabled: this.state.isBusy, children: "Load AlphaFold structure" }) }); } render() { return (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { style: { backgroundColor: '#dce54e', fontWeight: 500, padding: '5px 12px' }, children: "New Feature!" }), (0, jsx_runtime_1.jsx)("div", { className: 'msp-help-text', style: { margin: '2px 0' }, children: (0, jsx_runtime_1.jsxs)("div", { className: 'msp-help-description', children: [(0, jsx_runtime_1.jsx)(icons_1.Icon, { svg: icons_2.InfoIconSvg, inline: true }), "Load and superpose AlphaFold structure against representative chains."] }) }), (0, jsx_runtime_1.jsxs)("div", { className: 'msp-flex-row', children: [this.state.canUseDb && this.superposeByDbMapping(), (0, jsx_runtime_1.jsx)(common_1.ToggleButton, { icon: icons_1.TuneSvg, label: '', title: 'Options', toggle: this.toggleOptions, isSelected: this.state.action === 'options', disabled: this.state.isBusy, style: { flex: '0 0 40px', padding: 0 } })] }), this.state.action === 'options' && (0, jsx_runtime_1.jsx)("div", { className: 'msp-control-offset', children: (0, jsx_runtime_1.jsx)(parameters_1.ParameterControls, { params: exports.AlphafoldSuperpositionParams, values: this.state.options, onChangeValues: this.setOptions, isDisabled: this.state.isBusy }) })] }); } } exports.AfSuperpositionControls = AfSuperpositionControls;