Files
enviPy-bayer/static/js/ketcher2/script/ui/structconv.js
2025-06-23 20:13:54 +02:00

278 lines
6.4 KiB
JavaScript

/****************************************************************************
* Copyright 2017 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***************************************************************************/
import { capitalize } from 'lodash/fp';
import Struct from '../chem/struct';
import element from '../chem/element';
export function fromElement(selem) {
if (selem.label === 'R#')
return {
type: 'rlabel',
values: fromRlabel(selem.rglabel)
};
if (selem.label === 'L#')
return fromAtomList(selem);
if (element.map[selem.label])
return fromAtom(selem);
if (!selem.label && 'attpnt' in selem)
return { ap: fromApoint(selem.attpnt) };
return selem; // probably generic
}
export function toElement(elem) {
if (elem.type === 'rlabel')
return {
label: elem.values.length ? 'R#' : 'C',
rglabel: toRlabel(elem.values)
};
if (elem.type === 'list' || elem.type === 'not-list')
return toAtomList(elem);
if (!elem.label && 'ap' in elem)
return { attpnt: toApoint(elem.ap) };
if (element.map[capitalize(elem.label)])
return toAtom(elem);
if (elem.label === 'A' || elem.label === '*' || elem.label === 'Q' ||
elem.label === 'X' || elem.label === 'R') {
elem.pseudo = elem.label;
return toAtom(elem);
}
return elem;
}
function fromAtom(satom) {
const alias = satom.alias || '';
return {
alias: alias,
label: satom.label,
charge: satom.charge,
isotope: satom.isotope,
explicitValence: satom.explicitValence,
radical: satom.radical,
invRet: satom.invRet,
exactChangeFlag: !!satom.exactChangeFlag,
ringBondCount: satom.ringBondCount,
substitutionCount: satom.substitutionCount,
unsaturatedAtom: !!satom.unsaturatedAtom,
hCount: satom.hCount
};
}
function toAtom(atom) {
// TODO merge this to Struct.Atom.attrlist?
// see ratomtool
return Object.assign({}, atom, {
label: capitalize(atom.label)
});
}
function fromAtomList(satom) {
return {
type: satom.atomList.notList ? 'not-list' : 'list',
values: satom.atomList.ids.map(i => element[i].label)
};
}
function toAtomList(atom) {
return {
pseudo: null,
label: 'L#',
atomList: new Struct.AtomList({
notList: atom.type === 'not-list',
ids: atom.values.map(el => element.map[el])
})
};
}
function fromApoint(sap) {
return {
primary: ((sap || 0) & 1) > 0,
secondary: ((sap || 0) & 2) > 0
};
}
function toApoint(ap) {
return (ap.primary && 1) + (ap.secondary && 2);
}
function fromRlabel(rg) {
var res = [];
for (var rgi = 0; rgi < 32; rgi++) {
if (rg & (1 << rgi)) {
var val = rgi + 1;
res.push(val); // push the string
}
}
return res;
}
function toRlabel(values) {
var res = 0;
values.forEach(function (val) {
var rgi = val - 1;
res |= 1 << rgi;
});
return res;
}
export function fromBond(sbond) {
const type = sbond.type;
const stereo = sbond.stereo;
return {
type: fromBondType(type, stereo),
topology: sbond.topology || 0,
center: sbond.reactingCenterStatus || 0
};
}
export function toBond(bond) {
return {
topology: bond.topology,
reactingCenterStatus: bond.center,
...toBondType(bond.type)
};
}
export function toBondType(caption) {
return Object.assign({}, bondCaptionMap[caption]);
}
function fromBondType(type, stereo) {
for (let caption in bondCaptionMap) {
if (bondCaptionMap[caption].type === type &&
bondCaptionMap[caption].stereo === stereo)
return caption;
}
throw 'No such bond caption';
}
const bondCaptionMap = {
single: {
type: Struct.Bond.PATTERN.TYPE.SINGLE,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
up: {
type: Struct.Bond.PATTERN.TYPE.SINGLE,
stereo: Struct.Bond.PATTERN.STEREO.UP
},
down: {
type: Struct.Bond.PATTERN.TYPE.SINGLE,
stereo: Struct.Bond.PATTERN.STEREO.DOWN
},
updown: {
type: Struct.Bond.PATTERN.TYPE.SINGLE,
stereo: Struct.Bond.PATTERN.STEREO.EITHER
},
double: {
type: Struct.Bond.PATTERN.TYPE.DOUBLE,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
crossed: {
type: Struct.Bond.PATTERN.TYPE.DOUBLE,
stereo: Struct.Bond.PATTERN.STEREO.CIS_TRANS
},
triple: {
type: Struct.Bond.PATTERN.TYPE.TRIPLE,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
aromatic: {
type: Struct.Bond.PATTERN.TYPE.AROMATIC,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
singledouble: {
type: Struct.Bond.PATTERN.TYPE.SINGLE_OR_DOUBLE,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
singlearomatic: {
type: Struct.Bond.PATTERN.TYPE.SINGLE_OR_AROMATIC,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
doublearomatic: {
type: Struct.Bond.PATTERN.TYPE.DOUBLE_OR_AROMATIC,
stereo: Struct.Bond.PATTERN.STEREO.NONE
},
any: {
type: Struct.Bond.PATTERN.TYPE.ANY,
stereo: Struct.Bond.PATTERN.STEREO.NONE
}
};
import { sdataSchema } from './data/sdata-schema'
export function fromSgroup(ssgroup) {
const type = ssgroup.type || 'GEN';
const { context, fieldName, fieldValue, absolute, attached } = ssgroup.attrs;
if (absolute === false && attached === false)
ssgroup.attrs.radiobuttons = 'Relative';
else ssgroup.attrs.radiobuttons = attached ? 'Attached' : 'Absolute';
if (sdataSchema[context][fieldName] && sdataSchema[context][fieldName].properties.fieldValue.items) {
ssgroup.attrs.fieldValue = fieldValue.split('\n');
}
return Object.assign({ type: type }, ssgroup.attrs);
}
export function toSgroup(sgroup) {
const { type, radiobuttons, ...props } = sgroup;
const attrs = { ...props };
const absolute = 'absolute';
const attached = 'attached';
switch (radiobuttons) {
case 'Absolute':
attrs[absolute] = true;
attrs[attached] = false;
break;
case 'Attached':
attrs[absolute] = false;
attrs[attached] = true;
break;
case 'Relative':
attrs[absolute] = false;
attrs[attached] = false;
break;
default:
break;
}
if (attrs.fieldName)
attrs.fieldName = attrs.fieldName.trim();
if (attrs.fieldValue) {
attrs.fieldValue = typeof (attrs.fieldValue) === 'string' ?
attrs.fieldValue.trim() :
attrs.fieldValue;
}
return {
type,
attrs
};
}